blob: da3a29449f55fbeea8c5f50c9418d8e6ba9894d3 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnsond9f08602016-12-02 11:31:30 -08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053039#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#include <linux/etherdevice.h>
41#include <linux/firmware.h>
42#include <wlan_hdd_tx_rx.h>
43#include <wni_api.h>
44#include <wlan_hdd_cfg.h>
45#include <wlan_ptt_sock_svc.h>
46#include <dbglog_host.h>
47#include <wlan_logging_sock_svc.h>
48#include <wlan_hdd_wowl.h>
49#include <wlan_hdd_misc.h>
50#include <wlan_hdd_wext.h>
51#include "wlan_hdd_trace.h"
52#include "wlan_hdd_ioctl.h"
53#include "wlan_hdd_ftm.h"
54#include "wlan_hdd_power.h"
55#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070056#include "wlan_hdd_scan.h"
Jeff Johnsonce0032c2017-01-20 07:18:27 -080057#include "wlan_hdd_request_manager.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053058#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053059#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070060#include <cdp_txrx_peer_ops.h>
Dhanashri Atrea8f82f22017-01-23 12:58:24 -080061#include <cdp_txrx_misc.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062
63#include <net/addrconf.h>
64#include <linux/wireless.h>
65#include <net/cfg80211.h>
66#include <linux/inetdevice.h>
67#include <net/addrconf.h>
68#include "wlan_hdd_cfg80211.h"
69#include "wlan_hdd_ext_scan.h"
70#include "wlan_hdd_p2p.h"
71#include <linux/rtnetlink.h>
72#include "sap_api.h"
73#include <linux/semaphore.h>
74#include <linux/ctype.h>
75#include <linux/compat.h>
76#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include <soc/qcom/subsystem_restart.h>
78#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079#include <wlan_hdd_hostapd.h>
80#include <wlan_hdd_softap_tx_rx.h>
81#include "cfg_api.h"
82#include "qwlan_version.h"
83#include "wma_types.h"
84#include "wlan_hdd_tdls.h"
85#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053086#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080087#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070089#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080090#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091#include "wlan_hdd_nan.h"
92#include "wlan_hdd_debugfs.h"
93#include "wlan_hdd_driver_ops.h"
94#include "epping_main.h"
95#include "wlan_hdd_memdump.h"
96
97#include <wlan_hdd_ipa.h>
98#include "hif.h"
99#include "wma.h"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -0800100#include "wlan_policy_mgr_api.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700101#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800102#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530103#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700104#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700105#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530106#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700107#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530108#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800109#include <dispatcher_init_deinit.h>
Rajeev Kumar699debf2017-01-06 14:17:00 -0800110#include "wlan_hdd_object_manager.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530111#include "cds_utils.h"
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -0800112#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800113#include <qca_vendor.h>
Mukul Sharma9d797a02017-01-05 20:26:03 +0530114#include "wlan_pmo_ucfg_api.h"
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +0530115#include "sir_api.h"
Naveen Rawat910726a2017-03-06 11:42:51 -0800116#include "os_if_wifi_pos.h"
117#include "wifi_pos_api.h"
118#include "wlan_hdd_oemdata.h"
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800119#include "wlan_hdd_he.h"
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700120#include "os_if_nan.h"
121#include "nan_public_structs.h"
Kiran Kumar Lokere3beeb952017-05-02 18:40:24 -0700122#include "wlan_reg_ucfg_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800123
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +0530124#ifdef CNSS_GENL
125#include <net/cnss_nl.h>
126#endif
Amar Singhal5cccafe2017-02-15 12:42:58 -0800127#include "wlan_reg_ucfg_api.h"
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +0530128
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800129#ifdef MODULE
130#define WLAN_MODULE_NAME module_name(THIS_MODULE)
131#else
132#define WLAN_MODULE_NAME "wlan"
133#endif
134
135#ifdef TIMER_MANAGER
136#define TIMER_MANAGER_STR " +TIMER_MANAGER"
137#else
138#define TIMER_MANAGER_STR ""
139#endif
140
141#ifdef MEMORY_DEBUG
142#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
143#else
144#define MEMORY_DEBUG_STR ""
145#endif
146
Sachin Ahujadddd2632017-03-07 19:07:24 +0530147int wlan_start_ret_val;
148static DECLARE_COMPLETION(wlan_start_comp);
149static unsigned int dev_num = 1;
150static struct cdev wlan_hdd_state_cdev;
151static struct class *class;
152static dev_t device;
Arun Khandavallifae92942016-08-01 13:31:08 +0530153#ifndef MODULE
154static struct gwlan_loader *wlan_loader;
155static ssize_t wlan_boot_cb(struct kobject *kobj,
156 struct kobj_attribute *attr,
157 const char *buf, size_t count);
158struct gwlan_loader {
159 bool loaded_state;
160 struct kobject *boot_wlan_obj;
161 struct attribute_group *attr_group;
162};
163
164static struct kobj_attribute wlan_boot_attribute =
165 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
166
167static struct attribute *attrs[] = {
168 &wlan_boot_attribute.attr,
169 NULL,
170};
171
172#define MODULE_INITIALIZED 1
173#endif
174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800175/* the Android framework expects this param even though we don't use it */
176#define BUF_LEN 20
177static char fwpath_buffer[BUF_LEN];
178static struct kparam_string fwpath = {
179 .string = fwpath_buffer,
180 .maxlen = BUF_LEN,
181};
182
183static char *country_code;
184static int enable_11d = -1;
185static int enable_dfs_chan_scan = -1;
186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187/*
188 * spinlock for synchronizing asynchronous request/response
189 * (full description of use in wlan_hdd_main.h)
190 */
191DEFINE_SPINLOCK(hdd_context_lock);
192
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800193#define WLAN_NLINK_CESIUM 30
194
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530195static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196
197#define WOW_MAX_FILTER_LISTS 1
198#define WOW_MAX_FILTERS_PER_LIST 4
199#define WOW_MIN_PATTERN_SIZE 6
200#define WOW_MAX_PATTERN_SIZE 64
201
202#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
203static const struct wiphy_wowlan_support wowlan_support_reg_init = {
204 .flags = WIPHY_WOWLAN_ANY |
205 WIPHY_WOWLAN_MAGIC_PKT |
206 WIPHY_WOWLAN_DISCONNECT |
207 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
208 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
209 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
210 WIPHY_WOWLAN_4WAY_HANDSHAKE |
211 WIPHY_WOWLAN_RFKILL_RELEASE,
212 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
213 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
214 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
215};
216#endif
217
218/* internal function declaration */
219
220struct sock *cesium_nl_srv_sock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700222static void wlan_hdd_auto_shutdown_cb(void);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223#endif
224
Sachin Ahujadddd2632017-03-07 19:07:24 +0530225void hdd_start_complete(int ret)
226{
227 wlan_start_ret_val = ret;
228
229 complete(&wlan_start_comp);
230}
231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530233 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
234 * @hdd_ctx: pointer to hdd_context_t
235 *
236 * Return: none
237 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700238static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530239{
240 hdd_adapter_t *adapter;
241 hdd_adapter_list_node_t *adapter_node, *next;
242 QDF_STATUS status = QDF_STATUS_SUCCESS;
243
244 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
245 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
246 adapter = adapter_node->pAdapter;
247 if (NULL != adapter)
248 hdd_send_rps_ind(adapter);
249 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
250 adapter_node = next;
251 }
252}
253
254/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800255 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
256 * @vdev_id: vdev_id
257 * @action: action type
258 * @reason: reason type
259 *
260 * Return: none
261 */
262void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
263 enum netif_action_type action, enum netif_reason_type reason)
264{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530265 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 hdd_adapter_t *adapter;
267
268 if (!hdd_ctx) {
269 hdd_err("hdd ctx is NULL");
270 return;
271 }
272 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
273
274 wlan_hdd_netif_queue_control(adapter, action, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275}
276
277/*
Dustin Brownab482ac2017-06-09 17:00:44 -0700278 * Store WLAN driver version and timestamp info in global variables such that
279 * crash debugger can extract them from driver debug symbol and crashdump for
280 * post processing
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 */
282uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
Dustin Brownab482ac2017-06-09 17:00:44 -0700283uint8_t g_wlan_driver_timestamp[] = BUILD_TIMESTAMP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284
285/**
286 * hdd_device_mode_to_string() - return string conversion of device mode
287 * @device_mode: device mode
288 *
289 * This utility function helps log string conversion of device mode.
290 *
291 * Return: string conversion of device mode, if match found;
292 * "Unknown" otherwise.
293 */
294const char *hdd_device_mode_to_string(uint8_t device_mode)
295{
296 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800297 CASE_RETURN_STRING(QDF_STA_MODE);
298 CASE_RETURN_STRING(QDF_SAP_MODE);
299 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
300 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
301 CASE_RETURN_STRING(QDF_FTM_MODE);
302 CASE_RETURN_STRING(QDF_IBSS_MODE);
303 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
304 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700305 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800306 default:
307 return "Unknown";
308 }
309}
310
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530311/**
312 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
313 * @adapter: HDD adapter
314 * @chan_number: Channel number
315 * @chan_bw: Bandwidth
316 *
317 * Checks if the given bandwidth is valid for the given channel number.
318 *
319 * Return: 0 for success, non-zero for failure
320 */
321int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
322 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800323 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530324{
325 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
326 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
327 bool found = false;
328 tHalHandle hal;
329
330 hal = WLAN_HDD_GET_HAL_CTX(adapter);
331 if (!hal) {
332 hdd_err("Invalid HAL context");
333 return -EINVAL;
334 }
335
336 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
337 hdd_err("No valid channel list");
338 return -EOPNOTSUPP;
339 }
340
341 for (i = 0; i < len; i++) {
342 if (chan[i] == chan_number) {
343 found = true;
344 break;
345 }
346 }
347
348 if (found == false) {
349 hdd_err("Channel not in driver's valid channel list");
350 return -EOPNOTSUPP;
351 }
352
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -0700353 if ((!WLAN_REG_IS_24GHZ_CH(chan_number)) &&
354 (!WLAN_REG_IS_5GHZ_CH(chan_number))) {
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530355 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
356 return -EINVAL;
357 }
358
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -0700359 if (WLAN_REG_IS_24GHZ_CH(chan_number)) {
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530360 if (chan_bw == CH_WIDTH_80MHZ) {
361 hdd_err("BW80 not possible in 2.4GHz band");
362 return -EINVAL;
363 }
364 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
365 (chan_bw != CH_WIDTH_MAX)) {
366 hdd_err("Only BW20 possible on channel 14");
367 return -EINVAL;
368 }
369 }
370
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -0700371 if (WLAN_REG_IS_5GHZ_CH(chan_number)) {
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530372 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
373 (chan_bw != CH_WIDTH_MAX)) {
374 hdd_err("Only BW20 possible on channel 165");
375 return -EINVAL;
376 }
377 }
378
379 return 0;
380}
381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800382static int __hdd_netdev_notifier_call(struct notifier_block *nb,
383 unsigned long state, void *data)
384{
385#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
386 struct netdev_notifier_info *dev_notif_info = data;
387 struct net_device *dev = dev_notif_info->dev;
388#else
389 struct net_device *dev = data;
390#endif
391 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
392 hdd_context_t *hdd_ctx;
393
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800394 ENTER_DEV(dev);
395
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800396 /* Make sure that this callback corresponds to our device. */
397 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
398 return NOTIFY_DONE;
399
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530400 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700402 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800403 return NOTIFY_DONE;
404 }
405
406 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700407 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 return NOTIFY_DONE;
409 }
410
411 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
412 if (NULL == hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800413 hdd_err("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530414 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 return NOTIFY_DONE;
416 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800417 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 return NOTIFY_DONE;
419
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800420 hdd_debug("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 dev->name, state);
422
423 switch (state) {
424 case NETDEV_REGISTER:
425 break;
426
427 case NETDEV_UNREGISTER:
428 break;
429
430 case NETDEV_UP:
431 sme_ch_avoid_update_req(hdd_ctx->hHal);
432 break;
433
434 case NETDEV_DOWN:
435 break;
436
437 case NETDEV_CHANGE:
438 if (true == adapter->isLinkUpSvcNeeded)
439 complete(&adapter->linkup_event_var);
440 break;
441
442 case NETDEV_GOING_DOWN:
443 if (adapter->scan_info.mScanPending != false) {
Abhishek Singh69ccb512017-04-25 11:58:16 +0530444 wlan_abort_scan(hdd_ctx->hdd_pdev, INVAL_PDEV_ID,
445 adapter->sessionId, INVALID_SCAN_ID, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800446 } else {
hqueaa33ee2017-05-04 17:56:35 +0800447 cds_flush_work(&adapter->scan_block_work);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800448 hdd_debug("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800449 }
450 break;
451
452 default:
453 break;
454 }
455
456 return NOTIFY_DONE;
457}
458
459/**
460 * hdd_netdev_notifier_call() - netdev notifier callback function
461 * @nb: pointer to notifier block
462 * @state: state
463 * @ndev: ndev pointer
464 *
465 * Return: 0 on success, error number otherwise.
466 */
467static int hdd_netdev_notifier_call(struct notifier_block *nb,
468 unsigned long state,
469 void *ndev)
470{
471 int ret;
472
473 cds_ssr_protect(__func__);
474 ret = __hdd_netdev_notifier_call(nb, state, ndev);
475 cds_ssr_unprotect(__func__);
476
477 return ret;
478}
479
480struct notifier_block hdd_netdev_notifier = {
481 .notifier_call = hdd_netdev_notifier_call,
482};
483
484/* variable to hold the insmod parameters */
485static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800486
487/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800489
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530490/**
491 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
492 * @ch_width: NL channel width
493 *
494 * Converts the NL channel width to the driver's internal representation
495 *
496 * Return: Converted channel width. In case of non matching NL channel width,
497 * CH_WIDTH_MAX will be returned.
498 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800499enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530500{
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800501 uint8_t fw_ch_bw;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700502
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800503 fw_ch_bw = wma_get_vht_ch_width();
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530504 switch (ch_width) {
505 case NL80211_CHAN_WIDTH_20_NOHT:
506 case NL80211_CHAN_WIDTH_20:
507 return CH_WIDTH_20MHZ;
508 case NL80211_CHAN_WIDTH_40:
509 return CH_WIDTH_40MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530510 case NL80211_CHAN_WIDTH_80:
511 return CH_WIDTH_80MHZ;
512 case NL80211_CHAN_WIDTH_80P80:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800513 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
514 return CH_WIDTH_80P80MHZ;
515 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
516 return CH_WIDTH_160MHZ;
517 else
518 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530519 case NL80211_CHAN_WIDTH_160:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800520 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
521 return CH_WIDTH_160MHZ;
522 else
523 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530524 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800525 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530526 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800527 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530528 default:
529 hdd_err("Invalid channel width %d, setting to default",
530 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800531 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530532 }
533}
534
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530535/* wlan_hdd_find_opclass() - Find operating class for a channel
536 * @hal: handler to HAL
537 * @channel: channel id
538 * @bw_offset: bandwidth offset
539 *
540 * Function invokes sme api to find the operating class
541 *
542 * Return: operating class
543 */
544uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
545 uint8_t bw_offset)
546{
547 uint8_t opclass = 0;
548
549 sme_get_opclass(hal, channel, bw_offset, &opclass);
550 return opclass;
551}
552
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530554 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530555 * @module_id: Module whose trace level is being configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 * @bitmask: Bitmask of log levels to be enabled
557 *
558 * Called immediately after the cfg.ini is read in order to configure
559 * the desired trace levels.
560 *
561 * Return: None
562 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530563int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530565 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530566 int qdf_print_idx = -1;
567 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 /*
569 * if the bitmask is the default value, then a bitmask was not
570 * specified in cfg.ini, so leave the logging level alone (it
571 * will remain at the "compiled in" default value)
572 */
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700573 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530574 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530576 qdf_print_idx = qdf_get_pidx();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530578 /* a mask was specified. start by disabling all logging */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530579 status = qdf_print_set_category_verbose(qdf_print_idx, module_id,
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530580 QDF_TRACE_LEVEL_NONE, 0);
581
582 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530583 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530585 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586 while (0 != bitmask) {
587 if (bitmask & 1) {
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530588 status = qdf_print_set_category_verbose(qdf_print_idx,
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530589 module_id, level, 1);
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530590 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530591 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700593
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594 level++;
595 bitmask >>= 1;
596 }
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530597 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598}
599
600/**
601 * wlan_hdd_validate_context() - check the HDD context
602 * @hdd_ctx: HDD context pointer
603 *
604 * Return: 0 if the context is valid. Error code otherwise
605 */
606int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
607{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530609 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 return -ENODEV;
611 }
612
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800613 if (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800614 hdd_debug("%pS Recovery in Progress. State: 0x%x Ignore!!!",
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530615 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 return -EAGAIN;
617 }
618
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800619 if (cds_is_load_or_unload_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 return -EAGAIN;
621 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530622
623 if (hdd_ctx->start_modules_in_progress ||
624 hdd_ctx->stop_modules_in_progress) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800625 hdd_debug("%pS Start/Stop Modules in progress. Ignore!!!",
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530626 (void *)_RET_IP_);
627 return -EAGAIN;
628 }
629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630 return 0;
631}
632
Dustin Brownf13b8c32017-05-19 17:23:08 -0700633int hdd_validate_adapter(hdd_adapter_t *adapter)
634{
635 if (!adapter) {
636 hdd_err("adapter is null");
637 return -EINVAL;
638 }
639
640 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
641 hdd_err("bad adapter magic: 0x%x (should be 0x%x)",
642 adapter->magic, WLAN_HDD_ADAPTER_MAGIC);
643 return -EINVAL;
644 }
645
646 if (!adapter->dev) {
647 hdd_err("adapter net_device is null");
648 return -EINVAL;
649 }
650
651 if (!(adapter->dev->flags & IFF_UP)) {
652 hdd_info("adapter net_device is not up");
653 return -EAGAIN;
654 }
655
656 if (adapter->sessionId == HDD_SESSION_ID_INVALID) {
657 hdd_info("adapter session is not open");
658 return -EAGAIN;
659 }
660
661 if (adapter->sessionId >= MAX_NUMBER_OF_ADAPTERS) {
662 hdd_err("bad adapter session Id: %u", adapter->sessionId);
663 return -EINVAL;
664 }
665
666 return 0;
667}
668
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669/**
Arun Khandavallica892f62017-05-26 14:25:50 +0530670 * wlan_hdd_validate_modules_state() - Check modules status
671 * @hdd_ctx: HDD context pointer
672 *
673 * Check's the driver module's state and returns true if the
674 * modules are enabled returns false if modules are closed.
675 *
676 * Return: True if modules are enabled or false.
677 */
678bool wlan_hdd_validate_modules_state(hdd_context_t *hdd_ctx)
679{
680 mutex_lock(&hdd_ctx->iface_change_lock);
681 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
682 mutex_unlock(&hdd_ctx->iface_change_lock);
683 hdd_notice("Modules not enabled, Present status: %d",
684 hdd_ctx->driver_status);
685 return false;
686 }
687 mutex_unlock(&hdd_ctx->iface_change_lock);
688 return true;
689}
690
691/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
693 * @hdd_adapter_t Hdd adapter.
694 *
695 * This function sets the IBSS power save config parameters to WMA
696 * which will send it to firmware if FW supports IBSS power save
697 * before vdev start.
698 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 * on failure.
701 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530702QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703{
704 int ret;
705 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
706
707 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700708 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530709 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 }
711
712 ret = wma_cli_set_command(adapter->sessionId,
713 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
714 hdd_ctx->config->ibssATIMWinSize,
715 VDEV_CMD);
716 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700717 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530718 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 }
720
721 ret = wma_cli_set_command(adapter->sessionId,
722 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
723 hdd_ctx->config->isIbssPowerSaveAllowed,
724 VDEV_CMD);
725 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700726 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
727 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530728 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729 }
730
731 ret = wma_cli_set_command(adapter->sessionId,
732 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
733 hdd_ctx->config->
734 isIbssPowerCollapseAllowed, VDEV_CMD);
735 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700736 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
737 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530738 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800739 }
740
741 ret = wma_cli_set_command(adapter->sessionId,
742 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
743 hdd_ctx->config->isIbssAwakeOnTxRx,
744 VDEV_CMD);
745 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700746 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530747 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800748 }
749
750 ret = wma_cli_set_command(adapter->sessionId,
751 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
752 hdd_ctx->config->ibssInactivityCount,
753 VDEV_CMD);
754 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700755 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530756 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800757 }
758
759 ret = wma_cli_set_command(adapter->sessionId,
760 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
761 hdd_ctx->config->ibssTxSpEndInactivityTime,
762 VDEV_CMD);
763 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700764 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
765 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 }
768
769 ret = wma_cli_set_command(adapter->sessionId,
770 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
771 hdd_ctx->config->ibssPsWarmupTime,
772 VDEV_CMD);
773 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700774 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
775 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530776 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 }
778
779 ret = wma_cli_set_command(adapter->sessionId,
780 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
781 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
782 VDEV_CMD);
783 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700784 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
785 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530786 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787 }
788
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530789 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790}
791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792#define INTF_MACADDR_MASK 0x7
793
794/**
795 * hdd_update_macaddr() - update mac address
796 * @config: hdd configuration
797 * @hw_macaddr: mac address
798 *
799 * Mac address for multiple virtual interface is found as following
800 * i) The mac address of the first interface is just the actual hw mac address.
801 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
802 * define the mac address for the remaining interfaces and locally
803 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
804 * supported virtual interfaces, right now this is 0x07 (meaning 8
805 * interface).
806 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
807 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
808 *
809 * Return: None
810 */
811void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530812 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813{
814 int8_t i;
815 uint8_t macaddr_b3, tmp_br3;
816
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530817 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530818 QDF_MAC_ADDR_SIZE);
819 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530820 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530821 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 macaddr_b3 = config->intfMacAddr[i].bytes[3];
823 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
824 INTF_MACADDR_MASK;
825 macaddr_b3 += tmp_br3;
826
827 /* XOR-ing bit-24 of the mac address. This will give enough
828 * mac address range before collision
829 */
830 macaddr_b3 ^= (1 << 7);
831
832 /* Set locally administered bit */
833 config->intfMacAddr[i].bytes[0] |= 0x02;
834 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800835 hdd_debug("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800836 MAC_ADDRESS_STR, i,
837 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
838 }
839}
840
841static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
842 struct wma_tgt_services *cfg)
843{
844 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845
846 /* Set up UAPSD */
847 config->apUapsdEnabled &= cfg->uapsd;
848
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800849 /* 11AX mode support */
850 if ((config->dot11Mode == eHDD_DOT11_MODE_11ax ||
851 config->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY) && !cfg->en_11ax)
852 config->dot11Mode = eHDD_DOT11_MODE_11ac;
853
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854 /* 11AC mode support */
855 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
856 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
857 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858
859 /* ARP offload: override user setting if invalid */
860 config->fhostArpOffload &= cfg->arp_offload;
861
862#ifdef FEATURE_WLAN_SCAN_PNO
863 /* PNO offload */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800864 hdd_debug("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800865 if (cfg->pno_offload)
866 config->PnoOffload = true;
867#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868#ifdef FEATURE_WLAN_TDLS
869 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530870 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
871 cfg->en_tdls_offchan;
872 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
873 cfg->en_tdls_uapsd_buf_sta;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700874 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800875 config->fEnableTDLSSleepSta = true;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700876 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800877 config->fEnableTDLSSleepSta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879#ifdef WLAN_FEATURE_ROAM_OFFLOAD
880 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
881#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700882 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883
884}
885
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700886/**
887 * hdd_update_vdev_nss() - sets the vdev nss
888 * @hdd_ctx: HDD context
889 *
890 * Sets the Nss per vdev type based on INI
891 *
892 * Return: None
893 */
894static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
895{
896 struct hdd_config *cfg_ini = hdd_ctx->config;
897 uint8_t max_supp_nss = 1;
898
Naveen Rawat10b1c152017-01-18 11:16:06 -0800899 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700900 max_supp_nss = 2;
901
902 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
903 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
904
905 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
906 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
907}
908
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530909/**
910 * hdd_update_hw_dbs_capable() - sets the dbs capability of the device
911 * @hdd_ctx: HDD context
912 *
913 * Sets the DBS capability as per INI and firmware capability
914 *
915 * Return: None
916 */
917static void hdd_update_hw_dbs_capable(hdd_context_t *hdd_ctx)
918{
919 struct hdd_config *cfg_ini = hdd_ctx->config;
920 uint8_t hw_dbs_capable = 0;
921
922 if ((!cfg_ini->dual_mac_feature_disable)
Archana Ramachandran62886ce2017-03-24 14:46:32 -0700923 && policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc))
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530924 hw_dbs_capable = 1;
925
926 sme_update_hw_dbs_capable(hdd_ctx->hHal, hw_dbs_capable);
927}
928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
930 struct wma_tgt_ht_cap *cfg)
931{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530932 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800933 uint32_t value, val32;
934 uint16_t val16;
935 struct hdd_config *pconfig = hdd_ctx->config;
936 tSirMacHTCapabilityInfo *phtCapInfo;
937 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
938 uint8_t enable_tx_stbc;
939
940 /* check and update RX STBC */
941 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
942 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
943
944 /* get the MPDU density */
945 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
946
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530947 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700948 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 value = 0;
950 }
951
952 /*
953 * MPDU density:
954 * override user's setting if value is larger
955 * than the one supported by target
956 */
957 if (value > cfg->mpdu_density) {
958 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
959 cfg->mpdu_density);
960
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800962 hdd_err("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 }
964
965 /* get the HT capability info */
966 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530967 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700968 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969 return;
970 }
971 val16 = (uint16_t) val32;
972 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
973
974 /* Set the LDPC capability */
975 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
976
977 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
978 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
979
980 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
981 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
982
983 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
984 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
985
986 enable_tx_stbc = pconfig->enableTxSTBC;
987
988 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
989 pconfig->enable2x2 = 1;
990 } else {
991 pconfig->enable2x2 = 0;
992 enable_tx_stbc = 0;
993
994 /* 1x1 */
995 /* Update Rx Highest Long GI data Rate */
996 if (sme_cfg_set_int(hdd_ctx->hHal,
997 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700998 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530999 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001000 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001 }
1002
1003 /* Update Tx Highest Long GI data Rate */
1004 if (sme_cfg_set_int
1005 (hdd_ctx->hHal,
1006 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001007 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301008 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001009 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010 }
1011 }
1012 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
1013 enable_tx_stbc = 0;
1014 phtCapInfo->txSTBC = enable_tx_stbc;
1015
1016 val32 = val16;
1017 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301018 if (status != QDF_STATUS_SUCCESS)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001019 hdd_err("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001020#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
1021 value = SIZE_OF_SUPPORTED_MCS_SET;
1022 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301023 &value) == QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001024 hdd_debug("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025
1026 if (pconfig->enable2x2) {
1027 for (value = 0; value < cfg->num_rf_chains; value++)
1028 mcs_set[value] =
1029 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
1030
1031 status =
1032 sme_cfg_set_str(hdd_ctx->hHal,
1033 WNI_CFG_SUPPORTED_MCS_SET,
1034 mcs_set,
1035 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301036 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001037 hdd_err("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 }
1039 }
1040#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
1041}
1042
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
1044 struct wma_tgt_vht_cap *cfg)
1045{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301046 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001047 uint32_t value = 0;
1048 struct hdd_config *pconfig = hdd_ctx->config;
1049 struct wiphy *wiphy = hdd_ctx->wiphy;
1050 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -07001051 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001052 uint32_t temp = 0;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001053 uint32_t ch_width = eHT_CHANNEL_WIDTH_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001054
Dustin Brown5e06bd32016-10-04 12:49:10 -07001055 if (!band_5g) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001056 hdd_debug("5GHz band disabled, skipping capability population");
Dustin Brown5e06bd32016-10-04 12:49:10 -07001057 return;
1058 }
1059
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 /* Get the current MPDU length */
1061 status =
1062 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1063 &value);
1064
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301065 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001066 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067 value = 0;
1068 }
1069
1070 /*
1071 * VHT max MPDU length:
1072 * override if user configured value is too high
1073 * that the target cannot support
1074 */
1075 if (value > cfg->vht_max_mpdu) {
1076 status = sme_cfg_set_int(hdd_ctx->hHal,
1077 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1078 cfg->vht_max_mpdu);
1079
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001080 if (status == QDF_STATUS_E_FAILURE)
1081 hdd_err("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 }
1083
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001084 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1085 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1086
1087 if (pconfig->enable2x2)
1088 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1089
1090 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1091 QDF_STATUS_E_FAILURE) {
1092 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1093 }
1094
1095 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1096 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1097 if (pconfig->enable2x2)
1098 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1099
1100 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1101 QDF_STATUS_E_FAILURE) {
1102 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1103 }
1104
1105 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1106 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1107 if (pconfig->enable2x2)
1108 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1109
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001110 hdd_debug("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001111 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1112
1113 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1114 QDF_STATUS_E_FAILURE) {
1115 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1116 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001118 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001119 &value);
1120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301121 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001122 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001123 value = 0;
1124 }
1125
1126 /* Set the LDPC capability */
1127 if (value && !cfg->vht_rx_ldpc) {
1128 status = sme_cfg_set_int(hdd_ctx->hHal,
1129 WNI_CFG_VHT_LDPC_CODING_CAP,
1130 cfg->vht_rx_ldpc);
1131
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001132 if (status == QDF_STATUS_E_FAILURE)
1133 hdd_err("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 }
1135
1136 /* Get current GI 80 value */
1137 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1138 &value);
1139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301140 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001141 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 value = 0;
1143 }
1144
1145 /* set the Guard interval 80MHz */
1146 if (value && !cfg->vht_short_gi_80) {
1147 status = sme_cfg_set_int(hdd_ctx->hHal,
1148 WNI_CFG_VHT_SHORT_GI_80MHZ,
1149 cfg->vht_short_gi_80);
1150
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001151 if (status == QDF_STATUS_E_FAILURE)
1152 hdd_err("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153 }
1154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 /* Get VHT TX STBC cap */
1156 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301158 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001159 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 value = 0;
1161 }
1162
1163 /* VHT TX STBC cap */
1164 if (value && !cfg->vht_tx_stbc) {
1165 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1166 cfg->vht_tx_stbc);
1167
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001168 if (status == QDF_STATUS_E_FAILURE)
1169 hdd_err("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001170 }
1171
1172 /* Get VHT RX STBC cap */
1173 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1174
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301175 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001176 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001177 value = 0;
1178 }
1179
1180 /* VHT RX STBC cap */
1181 if (value && !cfg->vht_rx_stbc) {
1182 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1183 cfg->vht_rx_stbc);
1184
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001185 if (status == QDF_STATUS_E_FAILURE)
1186 hdd_err("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001187 }
1188
1189 /* Get VHT SU Beamformer cap */
1190 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1191 &value);
1192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301193 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001194 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 value = 0;
1196 }
1197
1198 /* set VHT SU Beamformer cap */
1199 if (value && !cfg->vht_su_bformer) {
1200 status = sme_cfg_set_int(hdd_ctx->hHal,
1201 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1202 cfg->vht_su_bformer);
1203
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001204 if (status == QDF_STATUS_E_FAILURE)
1205 hdd_err("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 }
1207
1208 /* check and update SU BEAMFORMEE capabality */
1209 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1210 pconfig->enableTxBF = cfg->vht_su_bformee;
1211
1212 status = sme_cfg_set_int(hdd_ctx->hHal,
1213 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1214 pconfig->enableTxBF);
1215
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001216 if (status == QDF_STATUS_E_FAILURE)
1217 hdd_err("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218
1219 /* Get VHT MU Beamformer cap */
1220 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1221 &value);
1222
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301223 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001224 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 value = 0;
1226 }
1227
1228 /* set VHT MU Beamformer cap */
1229 if (value && !cfg->vht_mu_bformer) {
1230 status = sme_cfg_set_int(hdd_ctx->hHal,
1231 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1232 cfg->vht_mu_bformer);
1233
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001234 if (status == QDF_STATUS_E_FAILURE)
1235 hdd_err("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 }
1237
1238 /* Get VHT MU Beamformee cap */
1239 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1240 &value);
1241
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301242 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001243 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 value = 0;
1245 }
1246
1247 /* set VHT MU Beamformee cap */
1248 if (value && !cfg->vht_mu_bformee) {
1249 status = sme_cfg_set_int(hdd_ctx->hHal,
1250 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1251 cfg->vht_mu_bformee);
1252
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001253 if (status == QDF_STATUS_E_FAILURE)
1254 hdd_err("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 }
1256
1257 /* Get VHT MAX AMPDU Len exp */
1258 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1259 &value);
1260
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301261 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001262 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 value = 0;
1264 }
1265
1266 /*
1267 * VHT max AMPDU len exp:
1268 * override if user configured value is too high
1269 * that the target cannot support.
1270 * Even though Rome publish ampdu_len=7, it can
1271 * only support 4 because of some h/w bug.
1272 */
1273
1274 if (value > cfg->vht_max_ampdu_len_exp) {
1275 status = sme_cfg_set_int(hdd_ctx->hHal,
1276 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1277 cfg->vht_max_ampdu_len_exp);
1278
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001279 if (status == QDF_STATUS_E_FAILURE)
1280 hdd_err("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281 }
1282
1283 /* Get VHT TXOP PS CAP */
1284 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1285
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301286 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001287 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001288 value = 0;
1289 }
1290
1291 /* set VHT TXOP PS cap */
1292 if (value && !cfg->vht_txop_ps) {
1293 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1294 cfg->vht_txop_ps);
1295
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001296 if (status == QDF_STATUS_E_FAILURE)
1297 hdd_err("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 }
1299
1300 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1301 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1302 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1303 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1304 else
1305 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1306
1307
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001308 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1309 status = sme_cfg_set_int(hdd_ctx->hHal,
1310 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1311 VHT_CAP_160_AND_80P80_SUPP);
1312 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001313 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001314 band_5g->vht_cap.cap |=
1315 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001316 ch_width = eHT_CHANNEL_WIDTH_80P80MHZ;
1317 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1318 status = sme_cfg_set_int(hdd_ctx->hHal,
1319 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1320 VHT_CAP_160_SUPP);
1321 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001322 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 band_5g->vht_cap.cap |=
1324 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001325 ch_width = eHT_CHANNEL_WIDTH_160MHZ;
1326 }
1327 pconfig->vhtChannelWidth = QDF_MIN(pconfig->vhtChannelWidth,
1328 ch_width);
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301329 /* Get the current GI 160 value */
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001330 status = sme_cfg_get_int(hdd_ctx->hHal,
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301331 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001332 &value);
1333 if (status != QDF_STATUS_SUCCESS) {
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301334 hdd_err("could not get GI 80 & 160");
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001335 value = 0;
1336 }
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301337 /* set the Guard interval 160MHz */
1338 if (value && !cfg->vht_short_gi_160) {
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001339 status = sme_cfg_set_int(hdd_ctx->hHal,
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301340 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1341 cfg->vht_short_gi_160);
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001342
1343 if (status == QDF_STATUS_E_FAILURE)
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301344 hdd_err("failed to set SHORT GI 160MHZ");
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001345 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346
1347 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1348 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1349
1350 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1351 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1352 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1353 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1354
1355 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1356 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1357
1358 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1359 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1360 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1361 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1362 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1363 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1364
1365 band_5g->vht_cap.cap |=
1366 (cfg->vht_max_ampdu_len_exp <<
1367 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1368
1369 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1370 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1371 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1372 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1373 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1374 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1375 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1376 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1377
1378 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1379 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1380
1381}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001383/**
1384 * hdd_generate_macaddr_auto() - Auto-generate mac address
1385 * @hdd_ctx: Pointer to the HDD context
1386 *
1387 * Auto-generate mac address using device serial number.
1388 * Keep the first 3 bytes of OUI as before and replace
1389 * the last 3 bytes with the lower 3 bytes of serial number.
1390 *
1391 * Return: 0 for success
1392 * Non zero failure code for errors
1393 */
1394static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1395{
1396 unsigned int serialno = 0;
1397 struct qdf_mac_addr mac_addr = {
1398 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1399 };
1400
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001401 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001402 if (serialno == 0)
1403 return -EINVAL;
1404
1405 serialno &= 0x00ffffff;
1406
1407 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1408 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1409 mac_addr.bytes[5] = serialno & 0xff;
1410
1411 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1412 return 0;
1413}
1414
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301415/**
1416 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1417 * configuration to cfg_ini in HDD
1418 * @hdd_ctx: Pointer to hdd_ctx
1419 * @cfg: target configuration
1420 *
1421 * Return: None
1422 */
1423#ifdef FEATURE_WLAN_RA_FILTERING
1424static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1425 struct wma_tgt_cfg *cfg)
1426{
1427 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1428}
1429#else
1430static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1431 struct wma_tgt_cfg *cfg)
1432{
1433}
1434#endif
1435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436void hdd_update_tgt_cfg(void *context, void *param)
1437{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001438 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001439 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1440 struct wma_tgt_cfg *cfg = param;
1441 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001442 struct cds_config_info *cds_cfg = cds_get_ini_config();
Nitesh Shahe50711f2017-04-26 16:30:45 +05301443 uint8_t antenna_mode;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301444
Yue Mae3e86ab2017-05-08 10:48:24 -07001445 /* Reuse same pdev for module start/stop or SSR */
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07001446 if ((hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) ||
Yue Mae3e86ab2017-05-08 10:48:24 -07001447 !cds_is_driver_loading()) {
1448 hdd_err("Reuse pdev for module start/stop or SSR");
1449 /* Restore pdev to MAC/WMA contexts */
1450 sme_store_pdev(hdd_ctx->hHal, hdd_ctx->hdd_pdev);
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07001451 } else {
1452 ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
1453 if (ret) {
1454 hdd_err("pdev creation fails!");
1455 QDF_BUG(0);
1456 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301457 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001458
Naveen Rawat64e477e2016-05-20 10:34:56 -07001459 if (cds_cfg) {
1460 if (hdd_ctx->config->enable_sub_20_channel_width !=
1461 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1462 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1463 cds_cfg->sub_20_channel_width =
1464 WLAN_SUB_20_CH_WIDTH_NONE;
1465 } else {
1466 cds_cfg->sub_20_channel_width =
1467 hdd_ctx->config->enable_sub_20_channel_width;
1468 }
1469 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470
1471 /* first store the INI band capability */
1472 temp_band_cap = hdd_ctx->config->nBandCapability;
1473
1474 hdd_ctx->config->nBandCapability = cfg->band_cap;
1475
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001476 /*
1477 * now overwrite the target band capability with INI
1478 * setting if INI setting is a subset
1479 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001480
1481 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1482 (temp_band_cap != eCSR_BAND_ALL))
1483 hdd_ctx->config->nBandCapability = temp_band_cap;
1484 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1485 (temp_band_cap != eCSR_BAND_ALL) &&
1486 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001487 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488 }
1489
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001490 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1492 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1493 }
1494
1495 /* This can be extended to other configurations like ht, vht cap... */
1496
Anurag Chouhanc5548422016-02-24 18:33:27 +05301497 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001499 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001501 static struct qdf_mac_addr default_mac_addr = {
1502 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1503 };
1504 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1505 &default_mac_addr)) {
1506 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1507 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1508 MAC_ADDRESS_STR,
1509 MAC_ADDR_ARRAY(hdd_ctx->config->
1510 intfMacAddr[0].bytes));
1511 } else {
1512 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1513 MAC_ADDRESS_STR,
1514 MAC_ADDR_ARRAY(hdd_ctx->config->
1515 intfMacAddr[0].bytes));
1516 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001517 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 }
1519
1520 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001521 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522
1523 hdd_ctx->max_intf_count = cfg->max_intf_count;
1524
Jeff Johnsonc875e242016-09-23 18:12:34 -07001525 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001526 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001527
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001528 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1529 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1530
1531 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajaned1efd92016-09-24 18:05:47 -07001534 if (cfg->services.en_11ax) {
1535 hdd_info("11AX: 11ax is enabled - update HDD config");
1536 hdd_update_tgt_he_cap(hdd_ctx, cfg);
1537 }
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001538
1539 hdd_update_vdev_nss(hdd_ctx);
1540
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +05301541 hdd_update_hw_dbs_capable(hdd_ctx);
1542
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001543 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001544 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001545 hdd_debug("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001546 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001547
Nitesh Shahe50711f2017-04-26 16:30:45 +05301548 antenna_mode = (hdd_ctx->config->enable2x2 == 0x01) ?
1549 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1550 hdd_update_smps_antenna_mode(hdd_ctx, antenna_mode);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001551 hdd_debug("Init current antenna mode: %d",
Archana Ramachandran393f3792015-11-13 17:13:21 -08001552 hdd_ctx->current_antenna_mode);
1553
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001554 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1555 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301556 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301557
Nachiket Kukade8b4bfd82017-05-25 18:34:48 +05301558 if ((hdd_ctx->config->txBFCsnValue >
1559 WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF) &&
1560 !cfg->tx_bfee_8ss_enabled)
1561 hdd_ctx->config->txBFCsnValue =
1562 WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF;
1563
1564 if (sme_cfg_set_int(hdd_ctx->hHal,
1565 WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED,
1566 hdd_ctx->config->txBFCsnValue) == QDF_STATUS_E_FAILURE)
1567 hdd_err("fw update WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED to CFG fails");
1568
1569
1570 hdd_debug("Target BPF %d Host BPF %d 8ss fw support %d txBFCsnValue %d",
1571 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable,
1572 cfg->tx_bfee_8ss_enabled, hdd_ctx->config->txBFCsnValue);
Arun Khandavallid454d422016-08-17 12:47:05 +05301573 /*
1574 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1575 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1576 * configure the STA mode wow pattern.
1577 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301578 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301579 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301580
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301581 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1582
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001583 /* Configure NAN datapath features */
1584 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Arif Hussain759a0232017-03-20 13:17:18 -07001585 hdd_ctx->dfs_cac_offload = cfg->dfs_cac_offload;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001586}
1587
Arif Hussaincd151632017-02-11 16:57:19 -08001588bool hdd_dfs_indicate_radar(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001589{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001590 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1591 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301592 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301593 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001594
Arif Hussaincd151632017-02-11 16:57:19 -08001595 if (!hdd_ctx || hdd_ctx->config->disableDFSChSwitch) {
1596 hdd_info("skip tx block hdd_ctx=%p, disableDFSChSwitch=%d",
1597 hdd_ctx, hdd_ctx->config->disableDFSChSwitch);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301598 return true;
Arif Hussaincd151632017-02-11 16:57:19 -08001599 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001600
Arif Hussaincd151632017-02-11 16:57:19 -08001601 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
1602 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
1603 adapter = adapterNode->pAdapter;
1604 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1605
1606 if ((QDF_SAP_MODE == adapter->device_mode ||
1607 QDF_P2P_GO_MODE == adapter->device_mode) &&
1608 (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
1609 ap_ctx->operatingChannel))) {
1610 WLAN_HDD_GET_AP_CTX_PTR(adapter)->dfs_cac_block_tx =
1611 true;
1612 hdd_info("tx blocked for session: %d",
1613 adapter->sessionId);
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301614 }
Arif Hussaincd151632017-02-11 16:57:19 -08001615 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
1616 adapterNode = pNext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001617 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301618
1619 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001620}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001621
1622/**
1623 * hdd_is_valid_mac_address() - validate MAC address
1624 * @pMacAddr: Pointer to the input MAC address
1625 *
1626 * This function validates whether the given MAC address is valid or not
1627 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1628 * where X is the hexa decimal digit character and separated by ':'
1629 * This algorithm works even if MAC address is not separated by ':'
1630 *
1631 * This code checks given input string mac contains exactly 12 hexadecimal
1632 * digits and a separator colon : appears in the input string only after
1633 * an even number of hex digits.
1634 *
1635 * Return: 1 for valid and 0 for invalid
1636 */
1637bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1638{
1639 int xdigit = 0;
1640 int separator = 0;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07001641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001642 while (*pMacAddr) {
1643 if (isxdigit(*pMacAddr)) {
1644 xdigit++;
1645 } else if (':' == *pMacAddr) {
1646 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1647 break;
1648
1649 ++separator;
1650 } else {
1651 /* Invalid MAC found */
1652 return 0;
1653 }
1654 ++pMacAddr;
1655 }
1656 return xdigit == 12 && (separator == 5 || separator == 0);
1657}
1658
1659/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301660 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1661 * @dev: Handle to struct net_device to be updated.
1662 *
1663 * Return: None
1664 */
1665static void hdd_mon_mode_ether_setup(struct net_device *dev)
1666{
1667 dev->header_ops = NULL;
1668 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1669 dev->hard_header_len = ETH_HLEN;
1670 dev->mtu = ETH_DATA_LEN;
1671 dev->addr_len = ETH_ALEN;
1672 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1673 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1674 dev->priv_flags |= IFF_TX_SKB_SHARING;
1675
1676 memset(dev->broadcast, 0xFF, ETH_ALEN);
1677}
1678
1679/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001680 * __hdd__mon_open() - HDD Open function
1681 * @dev: Pointer to net_device structure
1682 *
1683 * This is called in response to ifconfig up
1684 *
1685 * Return: 0 for success; non-zero for failure
1686 */
1687static int __hdd_mon_open(struct net_device *dev)
1688{
1689 int ret;
1690
1691 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301692 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001693 ret = hdd_set_mon_rx_cb(dev);
1694 return ret;
1695}
1696
1697/**
1698 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1699 * @dev: Pointer to net_device structure
1700 *
1701 * This is called in response to ifconfig up
1702 *
1703 * Return: 0 for success; non-zero for failure
1704 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001705static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001706{
1707 int ret;
1708
1709 cds_ssr_protect(__func__);
1710 ret = __hdd_mon_open(dev);
1711 cds_ssr_unprotect(__func__);
1712
1713 return ret;
1714}
1715
1716/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301717 * hdd_start_adapter() - Wrapper function for device specific adapter
1718 * @adapter: pointer to HDD adapter
1719 *
1720 * This function is called to start the device specific adapter for
1721 * the mode passed in the adapter's device_mode.
1722 *
1723 * Return: 0 for success; non-zero for failure
1724 */
1725int hdd_start_adapter(hdd_adapter_t *adapter)
1726{
1727
1728 int ret;
1729 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1730
1731 ENTER_DEV(adapter->dev);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001732 hdd_debug("Start_adapter for mode : %d", adapter->device_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05301733
1734 switch (device_mode) {
1735 case QDF_P2P_CLIENT_MODE:
1736 case QDF_P2P_DEVICE_MODE:
1737 case QDF_OCB_MODE:
1738 case QDF_STA_MODE:
1739 case QDF_MONITOR_MODE:
1740 ret = hdd_start_station_adapter(adapter);
1741 if (ret)
1742 goto err_start_adapter;
1743 break;
1744 case QDF_P2P_GO_MODE:
1745 case QDF_SAP_MODE:
1746 ret = hdd_start_ap_adapter(adapter);
1747 if (ret)
1748 goto err_start_adapter;
1749 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301750 case QDF_IBSS_MODE:
1751 /*
1752 * For IBSS interface is initialized as part of
1753 * hdd_init_station_mode()
1754 */
1755 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301756 case QDF_FTM_MODE:
1757 ret = hdd_start_ftm_adapter(adapter);
1758 if (ret)
1759 goto err_start_adapter;
1760 break;
1761 default:
1762 hdd_err("Invalid session type %d", device_mode);
1763 QDF_ASSERT(0);
1764 goto err_start_adapter;
1765 }
1766 if (hdd_set_fw_params(adapter))
1767 hdd_err("Failed to set the FW params for the adapter!");
1768
1769 /*
1770 * Action frame registered in one adapter which will
1771 * applicable to all interfaces
1772 */
1773 wlan_hdd_cfg80211_register_frames(adapter);
1774 EXIT();
1775 return 0;
1776err_start_adapter:
1777 return -EINVAL;
1778}
1779
1780/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301781 * hdd_enable_power_management() - API to Enable Power Management
1782 *
1783 * API invokes Bus Interface Layer power management functionality
1784 *
1785 * Return: None
1786 */
1787static void hdd_enable_power_management(void)
1788{
1789 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1790
1791 if (!hif_ctx) {
1792 hdd_err("Bus Interface Context is Invalid");
1793 return;
1794 }
1795
1796 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1797}
1798
1799/**
1800 * hdd_disable_power_management() - API to disable Power Management
1801 *
1802 * API disable Bus Interface Layer Power management functionality
1803 *
1804 * Return: None
1805 */
1806static void hdd_disable_power_management(void)
1807{
1808 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1809
1810 if (!hif_ctx) {
1811 hdd_err("Bus Interface Context is Invalid");
1812 return;
1813 }
1814
1815 hif_disable_power_management(hif_ctx);
1816}
1817
1818/**
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301819 * hdd_update_hw_sw_info() - API to update the HW/SW information
1820 *
1821 * API to update the HW and SW information in the driver
1822 *
1823 * Return: None
1824 */
1825static void hdd_update_hw_sw_info(hdd_context_t *hdd_ctx)
1826{
1827 void *hif_sc;
1828
1829 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
1830 if (!hif_sc) {
1831 hdd_err("HIF context is NULL");
1832 return;
1833 }
1834
1835 /*
1836 * target hw version/revision would only be retrieved after firmware
1837 * download
1838 */
1839 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
1840 &hdd_ctx->target_hw_revision,
1841 &hdd_ctx->target_hw_name);
1842
1843 /* Get the wlan hw/fw version */
1844 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
1845
1846 return;
1847}
1848
1849/**
gbian62edd7e2017-03-07 13:12:13 +08001850 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
1851 * @hdd_ctx: Pointer to hdd context
1852 *
1853 * Return: none
1854 */
1855static void
1856hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
1857{
1858 uint8_t num_entries = 0;
1859 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
1860 uint8_t *tx_sched_wrr_ac;
1861 int i;
1862 cds_context_type *cds_ctx;
1863
1864 if (NULL == hdd_ctx)
1865 return;
1866
1867 if (NULL == hdd_ctx->config) {
1868 /* Do nothing if hdd_ctx is invalid */
1869 hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
1870 return;
1871 }
1872
1873 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1874
1875 if (!cds_ctx) {
1876 hdd_err("Invalid CDS Context");
1877 return;
1878 }
1879
1880 for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
1881 switch (i) {
1882 case OL_TX_WMM_AC_BE:
1883 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
1884 break;
1885 case OL_TX_WMM_AC_BK:
1886 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
1887 break;
1888 case OL_TX_WMM_AC_VI:
1889 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
1890 break;
1891 case OL_TX_WMM_AC_VO:
1892 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
1893 break;
1894 default:
1895 tx_sched_wrr_ac = NULL;
1896 break;
1897 }
1898
1899 hdd_string_to_u8_array(tx_sched_wrr_ac,
1900 tx_sched_wrr_param,
1901 &num_entries,
1902 sizeof(tx_sched_wrr_param));
1903
1904 if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
1905 cds_ctx->ac_specs[i].wrr_skip_weight =
1906 tx_sched_wrr_param[0];
1907 cds_ctx->ac_specs[i].credit_threshold =
1908 tx_sched_wrr_param[1];
1909 cds_ctx->ac_specs[i].send_limit =
1910 tx_sched_wrr_param[2];
1911 cds_ctx->ac_specs[i].credit_reserve =
1912 tx_sched_wrr_param[3];
1913 cds_ctx->ac_specs[i].discard_weight =
1914 tx_sched_wrr_param[4];
1915 }
1916
1917 num_entries = 0;
1918 }
1919}
1920
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001921#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001922static enum policy_mgr_con_mode wlan_hdd_get_mode_for_non_connected_vdev(
1923 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
1924{
1925 hdd_adapter_t *adapter = NULL;
1926 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1927
1928 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
1929 if (!adapter) {
1930 hdd_err("Adapter is NULL");
1931 return PM_MAX_NUM_OF_MODE;
1932 }
1933
1934 return policy_mgr_convert_device_mode_to_qdf_type(
1935 adapter->device_mode);
1936}
1937
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001938static void hdd_register_policy_manager_callback(
1939 struct wlan_objmgr_psoc *psoc)
1940{
1941 struct policy_mgr_hdd_cbacks hdd_cbacks;
1942 hdd_cbacks.sap_restart_chan_switch_cb =
1943 sap_restart_chan_switch_cb;
1944 hdd_cbacks.wlan_hdd_get_channel_for_sap_restart =
1945 wlan_hdd_get_channel_for_sap_restart;
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001946 hdd_cbacks.get_mode_for_non_connected_vdev =
1947 wlan_hdd_get_mode_for_non_connected_vdev;
1948
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001949 if (QDF_STATUS_SUCCESS !=
1950 policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {
1951 hdd_err("HDD callback registration with policy manager failed");
1952 }
1953}
1954#else
1955static void hdd_register_policy_manager_callback(
1956 struct wlan_objmgr_psoc *psoc)
1957{
1958}
1959#endif
1960
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001961#ifdef WLAN_FEATURE_NAN_CONVERGENCE
1962static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1963{
1964 struct nan_callbacks cb_obj = {0};
1965
1966 cb_obj.ndi_open = hdd_ndi_open;
1967 cb_obj.ndi_close = hdd_ndi_close;
1968 cb_obj.ndi_start = hdd_ndi_start;
1969 cb_obj.ndi_delete = hdd_ndi_delete;
1970 cb_obj.drv_ndi_create_rsp_handler = hdd_ndi_drv_ndi_create_rsp_handler;
1971 cb_obj.drv_ndi_delete_rsp_handler = hdd_ndi_drv_ndi_delete_rsp_handler;
1972
Naveen Rawat37f62c82017-03-26 22:24:43 -07001973 cb_obj.new_peer_ind = hdd_ndp_new_peer_handler;
1974 cb_obj.get_peer_idx = hdd_ndp_get_peer_idx;
Naveen Rawatb3143ea2017-03-26 22:25:46 -07001975 cb_obj.peer_departed_ind = hdd_ndp_peer_departed_handler;
Naveen Rawat37f62c82017-03-26 22:24:43 -07001976
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001977 os_if_nan_register_hdd_callbacks(hdd_ctx->hdd_psoc, &cb_obj);
1978}
1979#else
1980static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1981{
1982}
1983#endif
1984
gbian62edd7e2017-03-07 13:12:13 +08001985/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301986 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1987 * @hdd_ctx: HDD context
1988 * @adapter: HDD adapter
1989 * @reinit: flag to indicate from SSR or normal path
1990 *
1991 * This function maintains the driver state machine it will be invoked from
1992 * startup, reinit and change interface. Depending on the driver state shall
1993 * perform the opening of the modules.
1994 *
1995 * Return: 0 for success; non-zero for failure
1996 */
1997int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1998 bool reinit)
1999{
2000 int ret;
2001 qdf_device_t qdf_dev;
2002 QDF_STATUS status;
2003 p_cds_contextType p_cds_context;
2004 bool unint = false;
2005 void *hif_ctx;
2006
2007 ENTER();
2008
2009 p_cds_context = cds_get_global_context();
2010 if (!p_cds_context) {
2011 hdd_err("Global Context is NULL");
2012 QDF_ASSERT(0);
2013 return -EINVAL;
2014 }
2015
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002016 hdd_debug("start modules called in state! :%d reinit: %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05302017 hdd_ctx->driver_status, reinit);
2018
2019 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
2020 if (!qdf_dev) {
2021 hdd_err("QDF Device Context is Invalid return");
2022 return -EINVAL;
2023 }
2024
2025 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302026 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05302027
2028 if (QDF_TIMER_STATE_RUNNING ==
2029 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
2030
2031 hdd_set_idle_ps_config(hdd_ctx, false);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002032 hdd_debug("Interface change Timer running Stop timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05302033 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
2034 }
2035
2036 switch (hdd_ctx->driver_status) {
2037 case DRIVER_MODULES_UNINITIALIZED:
2038 unint = true;
2039 /* Fall through dont add break here */
2040 case DRIVER_MODULES_CLOSED:
2041 if (!reinit && !unint) {
2042 ret = pld_power_on(qdf_dev->dev);
2043 if (ret) {
2044 hdd_err("Failed to Powerup the device: %d", ret);
2045 goto release_lock;
2046 }
2047 }
2048 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
2049 qdf_dev->bus_type,
2050 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
2051 HIF_ENABLE_TYPE_PROBE);
2052 if (ret) {
2053 hdd_err("Failed to open hif: %d", ret);
2054 goto power_down;
2055 }
2056
2057 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05302058 if (!hif_ctx) {
2059 hdd_err("hif context is null!!");
2060 goto power_down;
2061 }
2062
Arun Khandavallifae92942016-08-01 13:31:08 +05302063 status = ol_cds_init(qdf_dev, hif_ctx);
2064 if (status != QDF_STATUS_SUCCESS) {
2065 hdd_err("No Memory to Create BMI Context :%d", status);
2066 goto hif_close;
2067 }
2068
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002069 ret = hdd_update_config(hdd_ctx);
2070 if (ret) {
2071 hdd_err("Failed to update configuration :%d", ret);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302072 goto ol_cds_free;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002073 }
2074
gbian62edd7e2017-03-07 13:12:13 +08002075 hdd_update_cds_ac_specs_params(hdd_ctx);
2076
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302077 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05302078 if (!QDF_IS_STATUS_SUCCESS(status)) {
2079 hdd_err("Failed to Open CDS: %d", status);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302080 goto ol_cds_free;
Arun Khandavallifae92942016-08-01 13:31:08 +05302081 }
2082
Mukul Sharma9d797a02017-01-05 20:26:03 +05302083 /* initalize components configurations after psoc open */
2084 ret = hdd_update_components_config(hdd_ctx);
2085 if (ret) {
2086 hdd_err("Failed to update components configs :%d",
2087 ret);
2088 goto close;
2089 }
2090
Naveen Rawatcb5c5402017-03-22 10:12:19 -07002091 /*
2092 * NAN compoenet requires certian operations like, open adapter,
2093 * close adapter, etc. to be initiated by HDD, for those
2094 * register HDD callbacks with UMAC's NAN componenet.
2095 */
2096 hdd_nan_register_callbacks(hdd_ctx);
2097
Arun Khandavallifae92942016-08-01 13:31:08 +05302098 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
2099
2100 status = cds_pre_enable(hdd_ctx->pcds_context);
2101 if (!QDF_IS_STATUS_SUCCESS(status)) {
2102 hdd_err("Failed to pre-enable CDS: %d", status);
2103 goto close;
2104 }
2105
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07002106 hdd_register_policy_manager_callback(
2107 hdd_ctx->hdd_psoc);
2108
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302109 hdd_update_hw_sw_info(hdd_ctx);
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05302110 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302111
Arun Khandavallifae92942016-08-01 13:31:08 +05302112 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2113 sme_register_ftm_msg_processor(hdd_ctx->hHal,
2114 hdd_ftm_mc_process_msg);
2115 break;
2116 }
2117 if (unint) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002118 hdd_debug("In phase-1 initialization don't enable modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05302119 break;
2120 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302121
2122 if (reinit) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08002123 if (hdd_ipa_uc_ssr_reinit(hdd_ctx)) {
2124 hdd_err("HDD IPA UC reinit failed");
Rajeev Kumara3f672f2017-02-16 13:59:37 -08002125 goto post_disable;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08002126 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302127 }
2128
Arun Khandavallifae92942016-08-01 13:31:08 +05302129 /* Fall through dont add break here */
2130 case DRIVER_MODULES_OPENED:
2131 if (!adapter) {
Rajeev Kumara3f672f2017-02-16 13:59:37 -08002132 hdd_alert("adapter is Null");
2133 goto post_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05302134 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05302135 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2136 hdd_err("in ftm mode, no need to configure cds modules");
2137 break;
2138 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302139 if (hdd_configure_cds(hdd_ctx, adapter)) {
2140 hdd_err("Failed to Enable cds modules");
Rajeev Kumara3f672f2017-02-16 13:59:37 -08002141 goto post_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05302142 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05302143 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05302144 hdd_info("Driver Modules Successfully Enabled");
2145 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
2146 break;
2147 case DRIVER_MODULES_ENABLED:
2148 hdd_info("Driver modules already Enabled");
2149 break;
2150 default:
2151 hdd_err("WLAN start invoked in wrong state! :%d\n",
2152 hdd_ctx->driver_status);
2153 goto release_lock;
2154 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302155 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302156 mutex_unlock(&hdd_ctx->iface_change_lock);
2157 EXIT();
2158 return 0;
2159
Rajeev Kumara3f672f2017-02-16 13:59:37 -08002160post_disable:
Rajeev Kumarbe021242017-02-16 16:12:23 -08002161 cds_post_disable();
Rajeev Kumara3f672f2017-02-16 13:59:37 -08002162
Arun Khandavallifae92942016-08-01 13:31:08 +05302163close:
Rajeev Kumara3f672f2017-02-16 13:59:37 -08002164 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302165 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05302166
2167ol_cds_free:
2168 ol_cds_free();
2169
2170hif_close:
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05302171 hdd_hif_close(hdd_ctx, p_cds_context->pHIFContext);
Arun Khandavallifae92942016-08-01 13:31:08 +05302172power_down:
2173 if (!reinit && !unint)
2174 pld_power_off(qdf_dev->dev);
2175release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302176 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302177 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302178 EXIT();
Rajeev Kumara3f672f2017-02-16 13:59:37 -08002179
Arun Khandavallifae92942016-08-01 13:31:08 +05302180 return -EINVAL;
2181}
2182
Naveen Rawat910726a2017-03-06 11:42:51 -08002183#ifdef WIFI_POS_CONVERGED
2184static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2185{
2186 int ret = os_if_wifi_pos_register_nl();
2187
2188 if (ret)
2189 hdd_err("os_if_wifi_pos_register_nl failed");
2190
2191 return ret;
2192}
2193
2194static int hdd_deactivate_wifi_pos(void)
2195{
2196 int ret = os_if_wifi_pos_deregister_nl();
2197
2198 if (ret)
2199 hdd_err("os_if_wifi_pos_deregister_nl failed");
2200
2201 return ret;
2202}
2203
2204/**
2205 * hdd_populate_wifi_pos_cfg - populates wifi_pos parameters
2206 * @hdd_ctx: hdd context
2207 *
2208 * Return: status of operation
2209 */
2210static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2211{
2212 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2213 struct hdd_config *cfg = hdd_ctx->config;
2214
2215 wifi_pos_set_oem_target_type(psoc, hdd_ctx->target_type);
2216 wifi_pos_set_oem_fw_version(psoc, hdd_ctx->target_fw_version);
2217 wifi_pos_set_drv_ver_major(psoc, QWLAN_VERSION_MAJOR);
2218 wifi_pos_set_drv_ver_minor(psoc, QWLAN_VERSION_MINOR);
2219 wifi_pos_set_drv_ver_patch(psoc, QWLAN_VERSION_PATCH);
2220 wifi_pos_set_drv_ver_build(psoc, QWLAN_VERSION_BUILD);
2221 wifi_pos_set_dwell_time_min(psoc, cfg->nNeighborScanMinChanTime);
2222 wifi_pos_set_dwell_time_max(psoc, cfg->nNeighborScanMaxChanTime);
2223}
2224#else
2225static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2226{
2227 return oem_activate_service(hdd_ctx);
2228}
2229
2230static int hdd_deactivate_wifi_pos(void)
2231{
2232 return 0;
2233}
2234
2235static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2236{
2237}
2238#endif
2239
Arun Khandavallifae92942016-08-01 13:31:08 +05302240/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 * __hdd_open() - HDD Open function
2242 * @dev: Pointer to net_device structure
2243 *
2244 * This is called in response to ifconfig up
2245 *
2246 * Return: 0 for success; non-zero for failure
2247 */
2248static int __hdd_open(struct net_device *dev)
2249{
2250 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2251 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2252 int ret;
2253
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002254 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302255 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05302256 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257
2258 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302259 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302261
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262
Arun Khandavallifae92942016-08-01 13:31:08 +05302263 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
2264 if (ret) {
2265 hdd_err("Failed to start WLAN modules return");
2266 return -ret;
2267 }
2268
2269
2270 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2271 ret = hdd_start_adapter(adapter);
2272 if (ret) {
2273 hdd_err("Failed to start adapter :%d",
2274 adapter->device_mode);
2275 return ret;
2276 }
2277 }
2278
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2280 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302281 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282 /* Enable TX queues only when we are connected */
2283 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05302284 WLAN_START_ALL_NETIF_QUEUE,
2285 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 }
2287
Naveen Rawat286def52016-09-23 15:38:02 -07002288 /* Enable carrier and transmit queues for NDI */
2289 if (WLAN_HDD_IS_NDI(adapter)) {
2290 hdd_notice("Enabling Tx Queues");
2291 wlan_hdd_netif_queue_control(adapter,
2292 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
2293 WLAN_CONTROL_PATH);
2294 }
2295
Naveen Rawat910726a2017-03-06 11:42:51 -08002296 hdd_populate_wifi_pos_cfg(hdd_ctx);
2297
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002298 return ret;
2299}
2300
Arun Khandavallifae92942016-08-01 13:31:08 +05302301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302/**
2303 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
2304 * @dev: Pointer to net_device structure
2305 *
2306 * This is called in response to ifconfig up
2307 *
2308 * Return: 0 for success; non-zero for failure
2309 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002310static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311{
2312 int ret;
2313
2314 cds_ssr_protect(__func__);
2315 ret = __hdd_open(dev);
2316 cds_ssr_unprotect(__func__);
2317
2318 return ret;
2319}
2320
2321/**
2322 * __hdd_stop() - HDD stop function
2323 * @dev: Pointer to net_device structure
2324 *
2325 * This is called in response to ifconfig down
2326 *
2327 * Return: 0 for success; non-zero for failure
2328 */
2329static int __hdd_stop(struct net_device *dev)
2330{
2331 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2332 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2333 int ret;
2334
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002335 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302337 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 adapter->sessionId, adapter->device_mode));
2339
2340 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302341 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002342 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343
2344 /* Nothing to be done if the interface is not opened */
2345 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002346 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 return -ENODEV;
2348 }
2349
2350 /* Make sure the interface is marked as closed */
2351 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002352 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002353
2354 /*
2355 * Disable TX on the interface, after this hard_start_xmit() will not
2356 * be called on that interface
2357 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002358 hdd_notice("Disabling queues");
Himanshu Agarwal865201d2017-04-12 15:45:31 +05302359 wlan_hdd_netif_queue_control(adapter,
2360 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
2361 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362
2363 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002364 * NAN data interface is different in some sense. The traffic on NDI is
2365 * bursty in nature and depends on the need to transfer. The service
2366 * layer may down the interface after the usage and up again when
2367 * required. In some sense, the NDI is expected to be available
2368 * (like SAP) iface until NDI delete request is issued by the service
2369 * layer. Skip BSS termination and adapter deletion for NAN Data
2370 * interface (NDI).
2371 */
2372 if (WLAN_HDD_IS_NDI(adapter))
2373 return 0;
2374
2375 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 * The interface is marked as down for outside world (aka kernel)
2377 * But the driver is pretty much alive inside. The driver needs to
2378 * tear down the existing connection on the netdev (session)
2379 * cleanup the data pipes and wait until the control plane is stabilized
2380 * for this interface. The call also needs to wait until the above
2381 * mentioned actions are completed before returning to the caller.
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002382 * Notice that hdd_stop_adapter is requested not to close the session
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 * That is intentional to be able to scan if it is a STA/P2P interface
2384 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302385 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386
2387 /* DeInit the adapter. This ensures datapath cleanup as well */
2388 hdd_deinit_adapter(hdd_ctx, adapter, true);
2389
Arun Khandavallifae92942016-08-01 13:31:08 +05302390
2391 /*
2392 * Find if any iface is up. If any iface is up then can't put device to
2393 * sleep/power save mode
2394 */
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05302395 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002396 hdd_debug("Closing all modules from the hdd_stop");
Arun Khandavallifae92942016-08-01 13:31:08 +05302397 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
Hanumanth Reddy Pothula42e714a2016-12-21 19:33:57 +05302398 hdd_ctx->config->iface_change_wait_time);
Arun Khandavallifae92942016-08-01 13:31:08 +05302399 }
2400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 EXIT();
2402 return 0;
2403}
2404
2405/**
2406 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2407 * @dev: pointer to net_device structure
2408 *
2409 * This is called in response to ifconfig down
2410 *
2411 * Return: 0 for success and error number for failure
2412 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002413static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414{
2415 int ret;
2416
2417 cds_ssr_protect(__func__);
2418 ret = __hdd_stop(dev);
2419 cds_ssr_unprotect(__func__);
2420
2421 return ret;
2422}
2423
2424/**
2425 * __hdd_uninit() - HDD uninit function
2426 * @dev: Pointer to net_device structure
2427 *
2428 * This is called during the netdev unregister to uninitialize all data
2429 * associated with the device
2430 *
2431 * Return: None
2432 */
2433static void __hdd_uninit(struct net_device *dev)
2434{
2435 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2436
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002437 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438
2439 do {
2440 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002441 hdd_err("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 break;
2443 }
2444
2445 if (NULL == adapter->pHddCtx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002446 hdd_err("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 break;
2448 }
2449
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002450 if (dev != adapter->dev)
2451 hdd_err("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452
2453 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2454
2455 /* after uninit our adapter structure will no longer be valid */
2456 adapter->dev = NULL;
2457 adapter->magic = 0;
2458 } while (0);
2459
2460 EXIT();
2461}
2462
2463/**
2464 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2465 * @dev: pointer to net_device structure
2466 *
2467 * This is called during the netdev unregister to uninitialize all data
2468 * associated with the device
2469 *
2470 * Return: none
2471 */
2472static void hdd_uninit(struct net_device *dev)
2473{
2474 cds_ssr_protect(__func__);
2475 __hdd_uninit(dev);
2476 cds_ssr_unprotect(__func__);
2477}
2478
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002479static int hdd_open_cesium_nl_sock(void)
2480{
2481#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2482 struct netlink_kernel_cfg cfg = {
2483 .groups = WLAN_NLINK_MCAST_GRP_ID,
2484 .input = NULL
2485 };
2486#endif
2487 int ret = 0;
2488
2489#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2490 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2491#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2492 THIS_MODULE,
2493#endif
2494 &cfg);
2495#else
2496 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2497 WLAN_NLINK_MCAST_GRP_ID,
2498 NULL, NULL, THIS_MODULE);
2499#endif
2500
2501 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002502 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002503 ret = -ECONNREFUSED;
2504 }
2505
2506 return ret;
2507}
2508
2509static void hdd_close_cesium_nl_sock(void)
2510{
2511 if (NULL != cesium_nl_srv_sock) {
2512 netlink_kernel_release(cesium_nl_srv_sock);
2513 cesium_nl_srv_sock = NULL;
2514 }
2515}
2516
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517/**
2518 * __hdd_set_mac_address() - set the user specified mac address
2519 * @dev: Pointer to the net device.
2520 * @addr: Pointer to the sockaddr.
2521 *
2522 * This function sets the user specified mac address using
2523 * the command ifconfig wlanX hw ether <mac adress>.
2524 *
2525 * Return: 0 for success, non zero for failure
2526 */
2527static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2528{
2529 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2530 hdd_context_t *hdd_ctx;
2531 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302532 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 int ret;
2534
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002535 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536
2537 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2538 ret = wlan_hdd_validate_context(hdd_ctx);
2539 if (0 != ret)
2540 return ret;
2541
2542 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2543 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2544
2545 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302546 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547}
2548
2549/**
2550 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2551 * function from SSR
2552 * @dev: pointer to net_device structure
2553 * @addr: Pointer to the sockaddr
2554 *
2555 * This function sets the user specified mac address using
2556 * the command ifconfig wlanX hw ether <mac adress>.
2557 *
2558 * Return: 0 for success.
2559 */
2560static int hdd_set_mac_address(struct net_device *dev, void *addr)
2561{
2562 int ret;
2563
2564 cds_ssr_protect(__func__);
2565 ret = __hdd_set_mac_address(dev, addr);
2566 cds_ssr_unprotect(__func__);
2567
2568 return ret;
2569}
2570
2571uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2572{
2573 int i;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002574
Anurag Chouhan6d760662016-02-20 16:05:43 +05302575 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002576 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2577 break;
2578 }
2579
Anurag Chouhan6d760662016-02-20 16:05:43 +05302580 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 return NULL;
2582
2583 hdd_ctx->config->intfAddrMask |= (1 << i);
2584 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2585}
2586
2587void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2588{
2589 int i;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002590
Anurag Chouhan6d760662016-02-20 16:05:43 +05302591 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 if (!memcmp(releaseAddr,
2593 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2594 6)) {
2595 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2596 break;
2597 }
2598 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599}
2600
2601#ifdef WLAN_FEATURE_PACKET_FILTERING
2602/**
2603 * __hdd_set_multicast_list() - set the multicast address list
2604 * @dev: Pointer to the WLAN device.
2605 * @skb: Pointer to OS packet (sk_buff).
2606 *
2607 * This funciton sets the multicast address list.
2608 *
2609 * Return: None
2610 */
2611static void __hdd_set_multicast_list(struct net_device *dev)
2612{
2613 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614 int i = 0, status;
2615 struct netdev_hw_addr *ha;
2616 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302617 struct pmo_mc_addr_list_params *mc_list_request = NULL;
2618 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2619 int mc_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002621 ENTER_DEV(dev);
Anurag Chouhan6d760662016-02-20 16:05:43 +05302622 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302623 goto out;
Mukul Sharma51c44942015-10-30 19:30:19 +05302624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302626 if (0 != status)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302627 goto out;
2628
2629 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
2630 if (!mc_list_request) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002631 hdd_err("Cannot allocate mc_list_request");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302632 goto out;
2633 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002634
2635 if (dev->flags & IFF_ALLMULTI) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002636 hdd_debug("allow all multicast frames");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302637 hdd_disable_and_flush_mc_addr_list(adapter,
2638 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639 } else {
2640 mc_count = netdev_mc_count(dev);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302641 if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002642 hdd_debug("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302643 pmo_ucfg_max_mc_addr_supported(psoc));
2644 hdd_disable_and_flush_mc_addr_list(adapter,
2645 pmo_mc_list_change_notify);
2646 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002648 netdev_for_each_mc_addr(ha, dev) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002649 hdd_debug("ha_addr[%d] "MAC_ADDRESS_STR,
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302650 i, MAC_ADDR_ARRAY(ha->addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651 if (i == mc_count)
2652 break;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302653 memset(&(mc_list_request->mc_addr[i].bytes),
2654 0, ETH_ALEN);
2655 memcpy(&(mc_list_request->mc_addr[i].bytes),
2656 ha->addr, ETH_ALEN);
2657 hdd_info("mlist[%d] = %pM", i,
2658 mc_list_request->mc_addr[i].bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002659 i++;
2660 }
2661 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302662
2663 mc_list_request->psoc = psoc;
2664 mc_list_request->vdev_id = adapter->sessionId;
2665 mc_list_request->count = mc_count;
2666 status = hdd_cache_mc_addr_list(mc_list_request);
2667 if (status == 0) {
2668 hdd_enable_mc_addr_filtering(adapter,
2669 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 } else {
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302671 hdd_err("error while caching mc list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302673out:
2674 if (mc_list_request)
2675 qdf_mem_free(mc_list_request);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302676 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677}
2678
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680/**
2681 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2682 * @dev: pointer to net_device
2683 *
2684 * Return: none
2685 */
2686static void hdd_set_multicast_list(struct net_device *dev)
2687{
2688 cds_ssr_protect(__func__);
2689 __hdd_set_multicast_list(dev);
2690 cds_ssr_unprotect(__func__);
2691}
2692#endif
2693
2694/**
2695 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2696 * @dev: Pointer to the WLAN device.
2697 * @skb: Pointer to OS packet (sk_buff).
2698 *
2699 * This function is registered with the Linux OS for network
2700 * core to decide which queue to use first.
2701 *
2702 * Return: ac, Queue Index/access category corresponding to UP in IP header
2703 */
2704static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2705#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2706 , void *accel_priv
2707#endif
2708#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2709 , select_queue_fallback_t fallback
2710#endif
2711)
2712{
2713 return hdd_wmm_select_queue(dev, skb);
2714}
2715
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002716static const struct net_device_ops wlan_drv_ops = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717 .ndo_open = hdd_open,
2718 .ndo_stop = hdd_stop,
2719 .ndo_uninit = hdd_uninit,
2720 .ndo_start_xmit = hdd_hard_start_xmit,
2721 .ndo_tx_timeout = hdd_tx_timeout,
2722 .ndo_get_stats = hdd_get_stats,
2723 .ndo_do_ioctl = hdd_ioctl,
2724 .ndo_set_mac_address = hdd_set_mac_address,
2725 .ndo_select_queue = hdd_select_queue,
2726#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728#endif
2729};
2730
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002731/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002732static const struct net_device_ops wlan_mon_drv_ops = {
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002733 .ndo_open = hdd_mon_open,
2734 .ndo_stop = hdd_stop,
2735 .ndo_get_stats = hdd_get_stats,
2736};
2737
2738/**
2739 * hdd_set_station_ops() - update net_device ops for monitor mode
2740 * @pWlanDev: Handle to struct net_device to be updated.
2741 * Return: None
2742 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743void hdd_set_station_ops(struct net_device *pWlanDev)
2744{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002745 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2746 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2747 else
2748 pWlanDev->netdev_ops = &wlan_drv_ops;
2749}
2750
Komal Seelama89be8d2016-09-29 11:09:26 +05302751#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302752/**
2753 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2754 * @hdd_ctx: HDD context
2755 *
2756 * Return: None
2757 */
2758static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2759{
2760 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2761
Komal Seelamaa75f262016-09-29 12:32:13 +05302762 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302763 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302764}
2765
2766/**
2767 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2768 * @hdd_ctx: HDD Context
2769 *
2770 * Return: None
2771 */
2772static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2773{
2774 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2775
Komal Seelamaa75f262016-09-29 12:32:13 +05302776 qdf_runtime_lock_deinit(ctx->roc);
2777 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302778 qdf_runtime_lock_deinit(ctx->dfs);
2779 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302780}
2781
Komal Seelama89be8d2016-09-29 11:09:26 +05302782static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2783{
2784 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2785
2786 ctx->connect = qdf_runtime_lock_init("connect");
2787}
2788
2789static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2790{
2791 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2792
2793 qdf_runtime_lock_deinit(ctx->connect);
2794 ctx->connect = NULL;
2795}
2796#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302797static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2798static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302799static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2800static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2801#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002802/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002803 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2804 * @hdd_ctx: global hdd context
2805 * @macAddr: mac address to assign to the interface
2806 * @name: User-visible name of the interface
2807 *
2808 * hdd adapter pointer would point to the netdev->priv space, this function
2809 * would retrive the pointer, and setup the hdd adapter configuration.
2810 *
2811 * Return: the pointer to hdd adapter, otherwise NULL
2812 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2814 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002815 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 const char *name)
2817{
2818 struct net_device *pWlanDev = NULL;
2819 hdd_adapter_t *adapter = NULL;
2820 /*
2821 * cfg80211 initialization and registration....
2822 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002823 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2824#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2825 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002827 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2828 hdd_mon_mode_ether_setup : ether_setup),
2829 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830
2831 if (pWlanDev != NULL) {
2832
2833 /* Save the pointer to the net_device in the HDD adapter */
2834 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2835
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302836 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837
2838 adapter->dev = pWlanDev;
2839 adapter->pHddCtx = hdd_ctx;
2840 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302841 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002842
2843 init_completion(&adapter->session_open_comp_var);
2844 init_completion(&adapter->session_close_comp_var);
2845 init_completion(&adapter->disconnect_comp_var);
2846 init_completion(&adapter->linkup_event_var);
2847 init_completion(&adapter->cancel_rem_on_chan_var);
2848 init_completion(&adapter->rem_on_chan_ready_event);
2849 init_completion(&adapter->sta_authorized_event);
2850 init_completion(&adapter->offchannel_tx_event);
2851 init_completion(&adapter->tx_action_cnf_event);
2852#ifdef FEATURE_WLAN_TDLS
2853 init_completion(&adapter->tdls_add_station_comp);
2854 init_completion(&adapter->tdls_del_station_comp);
2855 init_completion(&adapter->tdls_mgmt_comp);
2856 init_completion(&adapter->tdls_link_establish_req_comp);
2857#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002858 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002859 init_completion(&adapter->change_country_code);
2860
2861
2862 init_completion(&adapter->scan_info.abortscan_event_var);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302863 init_completion(&adapter->lfr_fw_status.disable_lfr_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002864
2865 adapter->offloads_configured = false;
2866 adapter->isLinkUpSvcNeeded = false;
2867 adapter->higherDtimTransition = true;
2868 /* Init the net_device structure */
2869 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2870
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302871 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302873 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874 sizeof(tSirMacAddr));
2875 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876
2877 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2878 pWlanDev->features |=
2879 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2880 pWlanDev->features |= NETIF_F_RXCSUM;
2881
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002882 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2883
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 hdd_set_station_ops(adapter->dev);
2885
2886 pWlanDev->destructor = free_netdev;
2887 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002888 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 adapter->wdev.wiphy = hdd_ctx->wiphy;
2890 adapter->wdev.netdev = pWlanDev;
2891 /* set pWlanDev's parent to underlying device */
2892 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2893 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302894 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302896 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 }
2898
2899 return adapter;
2900}
2901
Jeff Johnson590e2012016-10-05 16:16:24 -07002902static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2903 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904{
2905 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002907 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2909 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002910 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302911 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 }
2913 }
2914 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002915 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302916 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 }
2918 } else {
2919 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002920 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302921 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 }
2923 }
2924 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2925
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302926 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927}
2928
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002929QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930{
2931 hdd_adapter_t *adapter = pContext;
2932
2933 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002934 hdd_err("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302935 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 }
2937
2938 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002939 hdd_err("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302940 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 }
2942
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002943 /*
2944 * For NAN Data interface, the close session results in the final
2945 * indication to the userspace
2946 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002947 if (adapter->device_mode == QDF_NDI_MODE)
2948 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2951
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 /*
2953 * We can be blocked while waiting for scheduled work to be
2954 * flushed, and the adapter structure can potentially be freed, in
2955 * which case the magic will have been reset. So make sure the
2956 * magic is still good, and hence the adapter structure is still
2957 * valid, before signaling completion
2958 */
2959 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2960 complete(&adapter->session_close_comp_var);
2961
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302962 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963}
2964
Krunal Soni8c37e322016-02-03 16:08:37 -08002965/**
2966 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2967 * @adapter: pointer to device adapter
Krunal Soni8c37e322016-02-03 16:08:37 -08002968 *
2969 * This routine will check the mode of adapter and if it is required then it
2970 * will initialize the TDLS operations
2971 *
2972 * Return: QDF_STATUS
2973 */
2974#ifdef FEATURE_WLAN_TDLS
Dustin Brownd28772b2017-03-17 14:16:07 -07002975static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002976{
Dustin Brownd28772b2017-03-17 14:16:07 -07002977 if (adapter->device_mode == QDF_IBSS_MODE)
2978 return QDF_STATUS_SUCCESS;
2979
2980 if (wlan_hdd_tdls_init(adapter)) {
2981 hdd_err("wlan_hdd_tdls_init failed");
2982 return QDF_STATUS_E_FAILURE;
Krunal Soni8c37e322016-02-03 16:08:37 -08002983 }
Dustin Brownd28772b2017-03-17 14:16:07 -07002984 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2985
Krunal Soni8c37e322016-02-03 16:08:37 -08002986 return QDF_STATUS_SUCCESS;
2987}
2988#else
Dustin Brownd28772b2017-03-17 14:16:07 -07002989static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002990{
2991 return QDF_STATUS_SUCCESS;
2992}
2993#endif
2994
Dustin Brownd28772b2017-03-17 14:16:07 -07002995int hdd_vdev_ready(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002996{
Dustin Brownd28772b2017-03-17 14:16:07 -07002997 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998
Dustin Brownd28772b2017-03-17 14:16:07 -07002999 status = pmo_vdev_ready(adapter->hdd_vdev);
Kiran Kumar Lokere3beeb952017-05-02 18:40:24 -07003000 status = ucfg_reg_11d_vdev_created_update(adapter->hdd_vdev);
Dustin Brownd28772b2017-03-17 14:16:07 -07003001
3002 return qdf_status_to_os_return(status);
3003}
3004
3005int hdd_vdev_destroy(hdd_adapter_t *adapter)
3006{
3007 QDF_STATUS status;
3008 int errno;
3009 hdd_context_t *hdd_ctx;
3010 unsigned long rc;
3011
3012 hdd_info("destroying vdev %d", adapter->sessionId);
3013
3014 /* vdev created sanity check */
3015 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3016 hdd_err("vdev for Id %d does not exist", adapter->sessionId);
3017 return -EINVAL;
3018 }
Kiran Kumar Lokere3beeb952017-05-02 18:40:24 -07003019 status = ucfg_reg_11d_vdev_delete_update(adapter->hdd_vdev);
Dustin Brown0d2eeae2017-03-24 15:21:32 -07003020 /* do vdev logical destroy via objmgr */
3021 errno = hdd_objmgr_destroy_vdev(adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07003022 if (errno) {
3023 hdd_err("failed to destroy objmgr vdev: %d", errno);
3024 return errno;
3025 }
3026
Yue Maf9782842017-05-08 12:49:49 -07003027 /*
3028 * In SSR case, there is no need to destroy vdev in firmware since
3029 * it has already asserted. vdev can be released directly.
3030 */
3031 if (cds_is_driver_recovering())
3032 goto release_vdev;
3033
Dustin Brownd28772b2017-03-17 14:16:07 -07003034 /* close sme session (destroy vdev in firmware via legacy API) */
3035 INIT_COMPLETION(adapter->session_close_comp_var);
3036 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3037 status = sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3038 hdd_sme_close_session_callback, adapter);
3039 if (QDF_IS_STATUS_ERROR(status)) {
3040 hdd_err("failed to close sme session: %d", status);
3041 return qdf_status_to_os_return(status);
3042 }
3043
3044 /* block on a completion variable until sme session is closed */
3045 rc = wait_for_completion_timeout(
3046 &adapter->session_close_comp_var,
3047 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3048 if (!rc) {
3049 hdd_err("timed out waiting for close sme session: %ld", rc);
3050 if (adapter->device_mode == QDF_NDI_MODE)
3051 hdd_ndp_session_end_handler(adapter);
3052 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
3053 return -ETIMEDOUT;
3054 }
3055
Yue Maf9782842017-05-08 12:49:49 -07003056release_vdev:
Dustin Brown0d2eeae2017-03-24 15:21:32 -07003057 /* now that sme session is closed, allow physical vdev destroy */
3058 errno = hdd_objmgr_release_vdev(adapter);
3059 if (errno) {
3060 hdd_err("failed to release objmgr vdev: %d", errno);
3061 return errno;
3062 }
3063
Dustin Brownd28772b2017-03-17 14:16:07 -07003064 hdd_info("vdev destroyed successfully");
3065
3066 return 0;
3067}
3068
3069int hdd_vdev_create(hdd_adapter_t *adapter)
3070{
3071 QDF_STATUS status;
3072 int errno;
3073 hdd_context_t *hdd_ctx;
3074 uint32_t type;
3075 uint32_t sub_type;
3076 unsigned long rc;
3077
3078 hdd_info("creating new vdev");
3079
3080 /* determine vdev (sub)type */
3081 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303082 if (QDF_STATUS_SUCCESS != status) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003083 hdd_err("failed to get vdev type: %d", status);
3084 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003085 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003086
3087 /* do vdev create via objmgr */
3088 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown7d043f62017-03-27 12:07:36 -07003089 errno = hdd_objmgr_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07003090 if (errno) {
3091 hdd_err("failed to create objmgr vdev: %d", errno);
3092 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003094
3095 /* Open a SME session (prepare vdev in firmware via legacy API) */
3096 INIT_COMPLETION(adapter->session_open_comp_var);
3097 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
3098 (uint8_t *)&adapter->macAddressCurrent,
3099 adapter->sessionId, type, sub_type);
3100 if (QDF_IS_STATUS_ERROR(status)) {
3101 hdd_err("failed to open sme session: %d", status);
3102 errno = qdf_status_to_os_return(status);
3103 goto objmgr_vdev_destroy;
3104 }
3105
3106 /* block on a completion variable until sme session is opened */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107 rc = wait_for_completion_timeout(
3108 &adapter->session_open_comp_var,
3109 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3110 if (!rc) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003111 hdd_err("timed out waiting for open sme session: %ld", rc);
3112 errno = -ETIMEDOUT;
3113 goto objmgr_vdev_destroy;
3114 }
3115
3116 /* firmware ready for component communication, raise vdev_ready event */
3117 errno = hdd_vdev_ready(adapter);
3118 if (errno) {
3119 hdd_err("failed to dispatch vdev ready event: %d", errno);
3120 goto hdd_vdev_destroy;
3121 }
3122
3123 hdd_info("vdev %d created successfully", adapter->sessionId);
3124
3125 return 0;
3126
3127 /*
3128 * Due to legacy constraints, we need to destroy in the same order as
3129 * create. So, split error handling into 2 cases to accommodate.
3130 */
3131
3132objmgr_vdev_destroy:
Dustin Brown7d043f62017-03-27 12:07:36 -07003133 QDF_BUG(!hdd_objmgr_release_and_destroy_vdev(adapter));
Dustin Brownd28772b2017-03-17 14:16:07 -07003134
3135 return errno;
3136
3137hdd_vdev_destroy:
3138 QDF_BUG(!hdd_vdev_destroy(adapter));
3139
3140 return errno;
3141}
3142
3143QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
3144{
3145 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
3146 hdd_context_t *hdd_ctx;
3147 QDF_STATUS status;
3148 int ret_val;
3149
3150 ret_val = hdd_vdev_create(adapter);
3151 if (ret_val) {
3152 hdd_err("failed to create vdev: %d", ret_val);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303153 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 }
3155
Dustin Brownd28772b2017-03-17 14:16:07 -07003156 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3157 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
3158 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Naveen Rawata410c5a2016-09-19 14:22:33 -07003159 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Dustin Brownd28772b2017-03-17 14:16:07 -07003160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003161 /* Register wireless extensions */
Dustin Brownd28772b2017-03-17 14:16:07 -07003162 status = hdd_register_wext(adapter->dev);
3163 if (QDF_IS_STATUS_ERROR(status)) {
3164 hdd_err("failed to register wireless extensions: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165 goto error_register_wext;
3166 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 /* Set the Connection State to Not Connected */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003169 hdd_debug("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3171
Deepak Dhamdherea2785822016-11-17 01:17:45 -08003172 /* set fast roaming capability in sme session */
3173 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
3174 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 /* Set the default operation channel */
3176 pHddStaCtx->conn_info.operationChannel =
3177 hdd_ctx->config->OperatingChannel;
3178
3179 /* Make the default Auth Type as OPEN */
3180 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3181
3182 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303183 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003184 hdd_err("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 status, status);
3186 goto error_init_txrx;
3187 }
3188
3189 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3190
3191 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303192 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003193 hdd_err("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 status, status);
3195 goto error_wmm_init;
3196 }
3197
3198 set_bit(WMM_INIT_DONE, &adapter->event_flags);
3199
3200 ret_val = wma_cli_set_command(adapter->sessionId,
3201 WMI_PDEV_PARAM_BURST_ENABLE,
3202 hdd_ctx->config->enableSifsBurst,
3203 PDEV_CMD);
Dustin Brownd28772b2017-03-17 14:16:07 -07003204 if (ret_val)
3205 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206
Dustin Brownd28772b2017-03-17 14:16:07 -07003207 status = hdd_check_and_init_tdls(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08003208 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210
Dhanashri Atre1a6a4ce2017-05-03 19:40:33 -07003211 adapter->dev->features |= NETIF_F_LRO;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303212 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214error_tdls_init:
3215 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3216 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217error_wmm_init:
3218 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3219 hdd_deinit_tx_rx(adapter);
3220error_init_txrx:
Dustin Brownd28772b2017-03-17 14:16:07 -07003221 hdd_unregister_wext(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222error_register_wext:
Dustin Brownd28772b2017-03-17 14:16:07 -07003223 QDF_BUG(!hdd_vdev_destroy(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 return status;
3226}
3227
3228void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
3229{
3230 hdd_cfg80211_state_t *cfgState;
3231
3232 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3233
3234 if (NULL != cfgState->buf) {
3235 unsigned long rc;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003236
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 rc = wait_for_completion_timeout(
3238 &adapter->tx_action_cnf_event,
3239 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3240 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003241 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05303242 /*
3243 * Inform tx status as FAILURE to upper layer and free
3244 * cfgState->buf
3245 */
3246 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 }
3248 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249}
3250
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303251/**
3252 * hdd_station_adapter_deinit() - De-initialize the station adapter
3253 * @hdd_ctx: global hdd context
3254 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07003255 * @rtnl_held: Used to indicate whether or not the caller is holding
3256 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303257 *
3258 * This function De-initializes the STA/P2P/OCB adapter.
3259 *
3260 * Return: None.
3261 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003262static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
3263 hdd_adapter_t *adapter,
3264 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303265{
3266 ENTER_DEV(adapter->dev);
3267
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303268 if (adapter->dev) {
3269 if (rtnl_held)
3270 adapter->dev->wireless_handlers = NULL;
3271 else {
3272 rtnl_lock();
3273 adapter->dev->wireless_handlers = NULL;
3274 rtnl_unlock();
3275 }
3276 }
3277
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303278 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
3279 hdd_deinit_tx_rx(adapter);
3280 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3281 }
3282
3283 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3284 hdd_wmm_adapter_close(adapter);
3285 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3286 }
3287
3288 hdd_cleanup_actionframe(hdd_ctx, adapter);
3289 wlan_hdd_tdls_exit(adapter);
3290
3291 EXIT();
3292}
3293
3294/**
3295 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
3296 * @hdd_ctx: global hdd context
3297 * @adapter: HDD adapter
3298 * @rtnl_held: the rtnl lock hold flag
3299 * This function De-initializes the AP/P2PGo adapter.
3300 *
3301 * Return: None.
3302 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003303static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
3304 hdd_adapter_t *adapter,
3305 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303306{
3307 ENTER_DEV(adapter->dev);
3308
3309 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3310 hdd_wmm_adapter_close(adapter);
3311 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3312 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003313 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303314
3315 hdd_cleanup_actionframe(hdd_ctx, adapter);
3316
3317 hdd_unregister_hostapd(adapter, rtnl_held);
3318
3319 EXIT();
3320}
3321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003322void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3323 bool rtnl_held)
3324{
3325 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003328 case QDF_STA_MODE:
3329 case QDF_P2P_CLIENT_MODE:
3330 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303332 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333 break;
3334 }
3335
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003336 case QDF_SAP_MODE:
3337 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 {
3339
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303340 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 break;
3342 }
3343
3344 default:
3345 break;
3346 }
3347
3348 EXIT();
3349}
3350
Jeff Johnson590e2012016-10-05 16:16:24 -07003351static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3352 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353{
3354 struct net_device *pWlanDev = NULL;
3355
3356 if (adapter)
3357 pWlanDev = adapter->dev;
3358 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003359 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360 return;
3361 }
3362
Rajeev Kumardca5f812016-02-04 17:28:06 -08003363 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303364
3365 if (adapter->scan_info.default_scan_ies) {
3366 qdf_mem_free(adapter->scan_info.default_scan_ies);
3367 adapter->scan_info.default_scan_ies = NULL;
3368 }
3369
Komal Seelama89be8d2016-09-29 11:09:26 +05303370 hdd_adapter_runtime_suspend_denit(adapter);
3371
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372 /*
3373 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
3374 * the driver is almost closed and cannot handle either control
3375 * messages or data. However, unregister_netdevice() call above will
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003376 * eventually invoke hdd_stop(ndo_close) driver callback, which attempts
3377 * to close the active connections(basically excites control path) which
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003378 * is not right. Setting this flag helps hdd_stop() to recognize that
3379 * the interface is closed and restricts any operations on that
3380 */
3381 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3382
3383 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003384 if (rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003385 unregister_netdevice(pWlanDev);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003386 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387 unregister_netdev(pWlanDev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 /*
3389 * Note that the adapter is no longer valid at this point
3390 * since the memory has been reclaimed
3391 */
3392 }
3393}
3394
Jeff Johnson590e2012016-10-05 16:16:24 -07003395static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
3396 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003397{
3398 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3399 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303400 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303403 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404 adapter = adapterNode->pAdapter;
3405 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303406 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303408 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409 }
3410 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3411 adapterNode = pNext;
3412 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303413 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414}
Ryan Hsu07495ea2016-01-21 15:25:39 -08003415
Arun Khandavalli2358d522016-05-16 18:05:37 +05303416#ifdef CONFIG_FW_LOGS_BASED_ON_INI
3417/**
3418 * hdd_set_fw_log_params() - Set log parameters to FW
3419 * @hdd_ctx: HDD Context
3420 * @adapter: HDD Adapter
3421 *
3422 * This function set the FW Debug log level based on the INI.
3423 *
3424 * Return: None
3425 */
3426static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3427 hdd_adapter_t *adapter)
3428{
3429 uint8_t count = 0, numentries = 0,
3430 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3431 uint32_t value = 0;
3432 int ret;
3433
Arun Khandavallifae92942016-08-01 13:31:08 +05303434 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3435 (!hdd_ctx->config->enable_fw_log)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003436 hdd_debug("enable_fw_log not enabled in INI or in FTM mode return");
Arun Khandavalli2358d522016-05-16 18:05:37 +05303437 return;
3438 }
3439
Arun Khandavallifae92942016-08-01 13:31:08 +05303440 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303441 hdd_ctx->fw_log_settings.dl_type =
3442 hdd_ctx->config->enableFwLogType;
3443 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303444 WMI_DBGLOG_TYPE,
3445 hdd_ctx->config->enableFwLogType,
3446 DBG_CMD);
3447 if (ret != 0)
3448 hdd_err("Failed to enable FW log type ret %d",
3449 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303450
3451 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303452 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303453 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303454 WMI_DBGLOG_LOG_LEVEL,
3455 hdd_ctx->config->enableFwLogLevel,
3456 DBG_CMD);
3457 if (ret != 0)
3458 hdd_err("Failed to enable FW log level ret %d",
3459 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303460
3461 hdd_string_to_u8_array(
3462 hdd_ctx->config->enableFwModuleLogLevel,
3463 moduleloglevel,
3464 &numentries,
3465 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3466
3467 while (count < numentries) {
3468 /*
3469 * FW module log level input string looks like
3470 * below:
3471 * gFwDebugModuleLoglevel=<FW Module ID>,
3472 * <Log Level>,...
3473 * For example:
3474 * gFwDebugModuleLoglevel=
3475 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3476 * Above input string means :
3477 * For FW module ID 1 enable log level 0
3478 * For FW module ID 2 enable log level 1
3479 * For FW module ID 3 enable log level 2
3480 * For FW module ID 4 enable log level 3
3481 * For FW module ID 5 enable log level 4
3482 * For FW module ID 6 enable log level 5
3483 * For FW module ID 7 enable log level 6
3484 */
3485
Nishank Aggarwale239d962017-03-03 12:26:02 +05303486 if ((moduleloglevel[count] > WLAN_MODULE_ID_MAX)
3487 || (moduleloglevel[count + 1] > DBGLOG_LVL_MAX)) {
3488 hdd_err("Module id %d and dbglog level %d input length is more than max",
3489 moduleloglevel[count],
3490 moduleloglevel[count + 1]);
3491 return;
3492 }
3493
3494 value = moduleloglevel[count] << 16;
3495 value |= moduleloglevel[count + 1];
Arun Khandavalli2358d522016-05-16 18:05:37 +05303496 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303497 WMI_DBGLOG_MOD_LOG_LEVEL,
3498 value, DBG_CMD);
3499 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303500 hdd_err("Failed to enable FW module log level %d ret %d",
3501 value, ret);
3502
3503 count += 2;
3504 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303505
Arun Khandavalli2358d522016-05-16 18:05:37 +05303506}
3507#else
3508static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3509 hdd_adapter_t *adapter)
3510{
3511}
3512
3513#endif
3514
3515/**
3516 * hdd_set_fw_params() - Set parameters to firmware
3517 * @adapter: HDD adapter
3518 *
3519 * This function Sets various parameters to fw once the
3520 * adapter is started.
3521 *
3522 * Return: 0 on success or errno on failure
3523 */
3524int hdd_set_fw_params(hdd_adapter_t *adapter)
3525{
3526 int ret;
3527 hdd_context_t *hdd_ctx;
3528
3529 ENTER_DEV(adapter->dev);
3530
3531 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3532 if (!hdd_ctx)
3533 return -EINVAL;
3534
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003535 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303536 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303537#define HDD_DTIM_1CHAIN_RX_ID 0x5
3538#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003539 /*
3540 * Disable DTIM 1 chain Rx when in 1x1,
3541 * we are passing two value
3542 * as param_id << 29 | param_value.
3543 * Below param_value = 0(disable)
3544 */
3545 ret = wma_cli_set_command(adapter->sessionId,
3546 WMI_STA_SMPS_PARAM_CMDID,
3547 HDD_DTIM_1CHAIN_RX_ID <<
3548 HDD_SMPS_PARAM_VALUE_S,
3549 VDEV_CMD);
3550 if (ret) {
3551 hdd_err("DTIM 1 chain set failed %d", ret);
3552 goto error;
3553 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303554
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003555 ret = wma_cli_set_command(adapter->sessionId,
3556 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3557 hdd_ctx->config->txchainmask1x1,
3558 PDEV_CMD);
3559 if (ret) {
3560 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3561 ret);
3562 goto error;
3563 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303564
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003565 ret = wma_cli_set_command(adapter->sessionId,
3566 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3567 hdd_ctx->config->rxchainmask1x1,
3568 PDEV_CMD);
3569 if (ret) {
3570 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3571 ret);
3572 goto error;
3573 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303574#undef HDD_DTIM_1CHAIN_RX_ID
3575#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003576 } else {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003577 hdd_debug("FTM Mode or 2x2 mode - Do not set 1x1 params");
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003578 }
3579
Arun Khandavallifae92942016-08-01 13:31:08 +05303580 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3581 ret = wma_cli_set_command(adapter->sessionId,
3582 WMI_PDEV_PARAM_HYST_EN,
3583 hdd_ctx->config->enableMemDeepSleep,
3584 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303585
Arun Khandavallifae92942016-08-01 13:31:08 +05303586 if (ret) {
3587 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3588 ret);
3589 goto error;
3590 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303591
3592 ret = wma_cli_set_command(adapter->sessionId,
3593 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3594 hdd_ctx->config->rts_profile,
3595 VDEV_CMD);
3596 if (ret) {
3597 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3598 goto error;
3599 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303600 }
3601
3602 hdd_set_fw_log_params(hdd_ctx, adapter);
3603
3604 EXIT();
3605 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303606
Arun Khandavalli2358d522016-05-16 18:05:37 +05303607error:
3608 return -EINVAL;
3609}
3610
Ryan Hsu07495ea2016-01-21 15:25:39 -08003611/**
3612 * hdd_open_adapter() - open and setup the hdd adatper
3613 * @hdd_ctx: global hdd context
3614 * @session_type: type of the interface to be created
3615 * @iface_name: User-visible name of the interface
3616 * @macAddr: MAC address to assign to the interface
3617 * @name_assign_type: the name of assign type of the netdev
3618 * @rtnl_held: the rtnl lock hold flag
3619 *
3620 * This function open and setup the hdd adpater according to the device
3621 * type request, assign the name, the mac address assigned, and then prepared
3622 * the hdd related parameters, queue, lock and ready to start.
3623 *
3624 * Return: the pointer of hdd adapter, otherwise NULL.
3625 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3627 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003628 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003629 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003630{
3631 hdd_adapter_t *adapter = NULL;
3632 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303633 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08003636 hdd_info("%s interface created. iftype: %d", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637
3638 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3639 /*
3640 * Max limit reached on the number of vdevs configured by the
3641 * host. Return error
3642 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303643 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3644 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003645 return NULL;
3646 }
3647
3648 if (macAddr == NULL) {
3649 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303650 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003651 return NULL;
3652 }
3653 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303654 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303655 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3656 " already exists",
3657 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003658 return NULL;
3659 }
3660
3661 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003662 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003663 /* Reset locally administered bit if the device mode is STA */
3664 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3665 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003666 case QDF_P2P_CLIENT_MODE:
3667 case QDF_P2P_DEVICE_MODE:
3668 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003669 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303670 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003671 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3672 name_assign_type,
3673 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674
3675 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303676 hdd_err("failed to allocate adapter for session %d",
3677 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678 return NULL;
3679 }
3680
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003681 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003683 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003684 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303685 else if (QDF_MONITOR_MODE == session_type)
3686 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687 else
3688 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3689
3690 adapter->device_mode = session_type;
3691
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303692 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003693 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303694 if (QDF_STATUS_SUCCESS != status)
3695 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303696 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 /*
3699 * Workqueue which gets scheduled in IPv4 notification
3700 * callback
3701 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3703 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704
3705#ifdef WLAN_NS_OFFLOAD
3706 /*
3707 * Workqueue which gets scheduled in IPv6
3708 * notification callback.
3709 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003710 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3711 hdd_ipv6_notifier_work_queue);
3712#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303714 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303716 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003717 }
3718
3719 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303720 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003721 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303722 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3723 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003724 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303725
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003727 case QDF_P2P_GO_MODE:
3728 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003729 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3730 name_assign_type,
3731 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003733 hdd_err("failed to allocate adapter for session %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05303734 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735 return NULL;
3736 }
3737
3738 adapter->wdev.iftype =
3739 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003740 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741 NL80211_IFTYPE_P2P_GO;
3742 adapter->device_mode = session_type;
3743
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003744 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303745 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003746 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3747 goto err_free_netdev;
3748 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303749 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303751 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3752 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003753 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303754 case QDF_FTM_MODE:
3755 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3756 name_assign_type,
3757 "wlan0");
3758 if (NULL == adapter) {
3759 hdd_err("Failed to allocate adapter for FTM mode");
3760 return NULL;
3761 }
3762 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3763 adapter->device_mode = session_type;
3764 status = hdd_register_interface(adapter, rtnl_held);
3765 if (QDF_STATUS_SUCCESS != status) {
3766 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3767 goto err_free_netdev;
3768 }
3769 /* Stop the Interface TX queue. */
3770 hdd_info("Disabling queues");
3771 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303772 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3773 WLAN_CONTROL_PATH);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303774 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003776 hdd_err("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303777 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 return NULL;
3779 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780
hqueaa33ee2017-05-04 17:56:35 +08003781 INIT_WORK(&adapter->scan_block_work, wlan_hdd_cfg80211_scan_block_cb);
3782
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3784 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3785
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303786 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 /* Add it to the hdd's session list. */
3788 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303789 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003790 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303791 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 } else {
3793 pHddAdapterNode->pAdapter = adapter;
3794 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3795 }
3796 }
3797
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303798 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003799 if (NULL != adapter) {
3800 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3801 adapter = NULL;
3802 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003803 if (NULL != pHddAdapterNode)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303804 qdf_mem_free(pHddAdapterNode);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806 return NULL;
3807 }
3808
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303809 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003810 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
3811 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 /* Adapter successfully added. Increment the vdev count */
3814 hdd_ctx->current_intf_count++;
3815
Jeff Johnson5880d792016-08-15 13:32:30 -07003816 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 hdd_ctx->current_intf_count);
3818
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003819 hdd_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003820 }
3821
Rajeev Kumardca5f812016-02-04 17:28:06 -08003822 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3823 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003824
3825 return adapter;
3826
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303829 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830
3831 return NULL;
3832}
3833
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303834QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003835 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836{
3837 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303838 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839
3840 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303841 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003842 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843 status);
3844 return status;
3845 }
3846
3847 while (pCurrent->pAdapter != adapter) {
3848 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303849 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850 break;
3851
3852 pCurrent = pNext;
3853 }
3854 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303855 if (QDF_STATUS_SUCCESS == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003856 hdd_debug("wait for bus bw work to flush");
Dustin Brown5ec6b552017-03-31 12:11:40 -07003857 hdd_bus_bw_compute_timer_stop(hdd_ctx);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303858 cancel_work_sync(&hdd_ctx->bus_bw_work);
Dustin Brown5ec6b552017-03-31 12:11:40 -07003859
3860 /* cleanup adapter */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003861 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
3862 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003863 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303865 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 adapterNode = NULL;
3867
Dustin Brown5ec6b552017-03-31 12:11:40 -07003868 /* conditionally restart the bw timer */
3869 hdd_bus_bw_compute_timer_try_start(hdd_ctx);
3870
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003871 /* Adapter removed. Decrement vdev count */
3872 if (hdd_ctx->current_intf_count != 0)
3873 hdd_ctx->current_intf_count--;
3874
3875 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303876 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303878
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303879 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880}
3881
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003882/**
3883 * hdd_close_all_adapters - Close all open adapters
3884 * @hdd_ctx: Hdd context
3885 * rtnl_held: True if RTNL lock held
3886 *
3887 * Close all open adapters.
3888 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303889 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003890 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303891QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892{
3893 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303894 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895
3896 ENTER();
3897
3898 do {
3899 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303900 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303901 wlan_hdd_release_intf_addr(hdd_ctx,
3902 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003904 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303905 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303906 /* Adapter removed. Decrement vdev count */
3907 if (hdd_ctx->current_intf_count != 0)
3908 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303910 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003911
3912 EXIT();
3913
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303914 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915}
3916
3917void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3918{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303919 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920 tSirUpdateIE updateIE;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003923 case QDF_STA_MODE:
3924 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925 {
3926 hdd_station_ctx_t *pHddStaCtx =
3927 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003928 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 break;
3930 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003931 case QDF_SAP_MODE:
3932 case QDF_P2P_GO_MODE:
3933 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003935 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936 break;
3937 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003938 case QDF_FTM_MODE:
3939 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003940 default:
3941 /*
3942 * wlan_hdd_reset_prob_rspies should not have been called
3943 * for these kind of devices
3944 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003945 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003946 pHostapdAdapter->device_mode);
3947 return;
3948 }
3949
Anurag Chouhanc5548422016-02-24 18:33:27 +05303950 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3952 updateIE.ieBufferlength = 0;
3953 updateIE.pAdditionIEBuffer = NULL;
3954 updateIE.append = true;
3955 updateIE.notify = false;
3956 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3957 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303958 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003959 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960 }
3961}
3962
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303963QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003964 const bool bCloseSession)
3965{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303966 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003967 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3968 union iwreq_data wrqu;
3969 tSirUpdateIE updateIE;
3970 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303971 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003972
3973 ENTER();
3974
Sachin Ahuja988fd102016-09-15 17:16:25 +05303975 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003976 hdd_notice("Disabling queues");
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303977 wlan_hdd_netif_queue_control(adapter,
3978 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3979 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003980 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003981 case QDF_STA_MODE:
3982 case QDF_P2P_CLIENT_MODE:
3983 case QDF_IBSS_MODE:
3984 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003985 case QDF_NDI_MODE:
3986 if ((QDF_NDI_MODE == adapter->device_mode) ||
3987 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3989 hdd_is_connecting(
3990 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003991 INIT_COMPLETION(adapter->disconnect_comp_var);
3992 /*
3993 * For NDI do not use pWextState from sta_ctx, if needed
3994 * extract from ndi_ctx.
3995 */
3996 if (QDF_NDI_MODE == adapter->device_mode)
3997 qdf_ret_status = sme_roam_disconnect(
3998 hdd_ctx->hHal,
3999 adapter->sessionId,
4000 eCSR_DISCONNECT_REASON_NDI_DELETE);
4001 else if (pWextState->roamProfile.BSSType ==
4002 eCSR_BSS_TYPE_START_IBSS)
4003 qdf_ret_status = sme_roam_disconnect(
4004 hdd_ctx->hHal,
4005 adapter->sessionId,
4006 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Varun Reddy Yeturu96dced72017-03-29 18:03:54 -07004007 else if (QDF_STA_MODE == adapter->device_mode)
4008 qdf_ret_status =
4009 wlan_hdd_try_disconnect(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07004011 qdf_ret_status = sme_roam_disconnect(
4012 hdd_ctx->hHal,
4013 adapter->sessionId,
4014 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004015 /* success implies disconnect command got
4016 * queued up successfully
4017 */
Varun Reddy Yeturu96dced72017-03-29 18:03:54 -07004018 if (qdf_ret_status == QDF_STATUS_SUCCESS &&
4019 QDF_STA_MODE != adapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 rc = wait_for_completion_timeout(
4021 &adapter->disconnect_comp_var,
4022 msecs_to_jiffies
4023 (WLAN_WAIT_TIME_DISCONNECT));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004024 if (!rc)
Varun Reddy Yeturu96dced72017-03-29 18:03:54 -07004025 hdd_warn("disconn_comp_var wait fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 }
Varun Reddy Yeturu96dced72017-03-29 18:03:54 -07004027 if (qdf_ret_status != QDF_STATUS_SUCCESS)
4028 hdd_warn("failed to post disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029 memset(&wrqu, '\0', sizeof(wrqu));
4030 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4031 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4032 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
4033 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05304034 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004035 if (scan_info != NULL && scan_info->mScanPending)
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05304036 wlan_hdd_scan_abort(adapter);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004037
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05304038 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039
4040#ifdef WLAN_OPEN_SOURCE
4041 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
4042#endif
4043
4044 hdd_deregister_tx_flow_control(adapter);
4045
4046#ifdef WLAN_NS_OFFLOAD
4047#ifdef WLAN_OPEN_SOURCE
4048 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
4049#endif
4050#endif
4051
4052 /*
4053 * It is possible that the caller of this function does not
4054 * wish to close the session
4055 */
Krunal Soni985b8132017-02-10 18:49:08 -08004056 if (true == bCloseSession) {
4057 if (0 != wlan_hdd_try_disconnect(adapter)) {
4058 hdd_err("Error: Can't disconnect adapter");
4059 return QDF_STATUS_E_FAILURE;
4060 }
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004061 hdd_vdev_destroy(adapter);
Krunal Soni985b8132017-02-10 18:49:08 -08004062 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063 break;
4064
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004065 case QDF_SAP_MODE:
4066 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004068 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
4070
4071 hdd_deregister_tx_flow_control(adapter);
4072
4073 mutex_lock(&hdd_ctx->sap_lock);
4074 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304075 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05304076 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077
4078 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079 status = wlansap_stop_bss(
4080 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304082 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 hdd_hostapd_state_t *hostapd_state =
4084 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304085 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304086 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304087 qdf_status =
4088 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08004089 qdf_stop_bss_event,
4090 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091
Anurag Chouhance0dc992016-02-16 18:18:03 +05304092 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004093 hdd_err("failure waiting for wlansap_stop_bss %d",
4094 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004095 }
4096 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07004097 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098 }
4099 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004100 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4101 adapter->device_mode,
4102 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004103
Anurag Chouhanc5548422016-02-24 18:33:27 +05304104 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08004105 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106 updateIE.smeSessionId = adapter->sessionId;
4107 updateIE.ieBufferlength = 0;
4108 updateIE.pAdditionIEBuffer = NULL;
4109 updateIE.append = false;
4110 updateIE.notify = false;
4111 /* Probe bcn reset */
4112 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4113 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304114 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004115 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 }
4117 /* Assoc resp reset */
4118 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4119 &updateIE,
4120 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304121 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004122 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123 }
4124 /* Reset WNI_CFG_PROBE_RSP Flags */
4125 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304126 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127 adapter->sessionCtx.ap.beacon = NULL;
4128 }
Ajit Pal Singh747b6802017-05-24 15:42:03 +05304129
4130 /*
4131 * If Do_Not_Break_Stream was enabled clear avoid channel list.
4132 */
4133 if (policy_mgr_is_dnsc_set(adapter->hdd_vdev))
4134 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0);
4135
Peng Xu66162de2016-02-11 17:01:20 -08004136 if (true == bCloseSession)
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004137 hdd_vdev_destroy(adapter);
Manikandan Mohan5df78272017-03-22 16:28:50 -07004138 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004140 case QDF_OCB_MODE:
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -08004141 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004142 (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
Leo Changfdb45c32016-10-28 11:09:23 -07004143 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144 break;
4145 default:
4146 break;
4147 }
4148
4149 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304150 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151}
4152
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05304153/**
4154 * hdd_deinit_all_adapters - deinit all adapters
4155 * @hdd_ctx: HDD context
4156 * @rtnl_held: True if RTNL lock held
4157 *
4158 */
4159void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
4160{
4161 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4162 QDF_STATUS status;
4163 hdd_adapter_t *adapter;
4164
4165 ENTER();
4166
4167 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4168
4169 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4170 adapter = adapter_node->pAdapter;
4171 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
4172 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4173 adapter_node = next;
4174 }
4175
4176 EXIT();
4177}
4178
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304179QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180{
4181 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304182 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 hdd_adapter_t *adapter;
4184
4185 ENTER();
4186
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304187 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4188
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4190
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304191 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192 adapter = adapterNode->pAdapter;
4193 hdd_stop_adapter(hdd_ctx, adapter, true);
4194 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4195 adapterNode = pNext;
4196 }
4197
4198 EXIT();
4199
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304200 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004201}
4202
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304203QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204{
4205 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304206 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 hdd_adapter_t *adapter;
Yue Mad5b4b9f2017-05-26 16:23:40 -07004208 hdd_station_ctx_t *pHddStaCtx;
4209 struct qdf_mac_addr peerMacAddr;
Ganesh Kondabattini9e4fbbb2017-05-24 16:53:02 +05304210 tdlsCtx_t *tdls_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211
4212 ENTER();
4213
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304214 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4217
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304218 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219 adapter = adapterNode->pAdapter;
Yue Mad5b4b9f2017-05-26 16:23:40 -07004220 hdd_notice("Disabling queues for adapter type: %d",
4221 adapter->device_mode);
Ganesh Kondabattini9e4fbbb2017-05-24 16:53:02 +05304222
4223 if ((adapter->device_mode == QDF_STA_MODE) ||
4224 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
4225 /* Stop tdls timers */
4226 tdls_ctx = WLAN_HDD_GET_TDLS_CTX_PTR(adapter);
4227 if (tdls_ctx)
4228 wlan_hdd_tdls_timers_stop(tdls_ctx);
4229 }
4230
Arun Khandavallicc544b32017-01-30 19:52:16 +05304231 if (hdd_ctx->config->sap_internal_restart &&
4232 adapter->device_mode == QDF_SAP_MODE) {
4233 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05304234 WLAN_STOP_ALL_NETIF_QUEUE,
Arun Khandavallicc544b32017-01-30 19:52:16 +05304235 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004236 if (test_bit(SOFTAP_BSS_STARTED,
4237 &adapter->event_flags)) {
4238 hdd_sap_indicate_disconnect_for_sta(adapter);
4239 hdd_cleanup_actionframe(hdd_ctx, adapter);
4240 hdd_sap_destroy_events(adapter);
4241 }
4242 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
4243 } else {
Arun Khandavallicc544b32017-01-30 19:52:16 +05304244 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05304245 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004247 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248
4249 adapter->sessionCtx.station.hdd_ReassocScenario = false;
4250
4251 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004252 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4253 adapter->device_mode, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
4255 hdd_wmm_adapter_close(adapter);
4256 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
4257 }
4258
Wu Gao36717432016-11-21 15:09:48 +08004259 /*
4260 * If adapter is SAP, set session ID to invalid since SAP
4261 * session will be cleanup during SSR.
4262 */
4263 if (adapter->device_mode == QDF_SAP_MODE)
4264 wlansap_set_invalid_session(
4265 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
4266
Yue Mad5b4b9f2017-05-26 16:23:40 -07004267 /* Delete peers if any for STA and P2P client modes */
4268 if (adapter->device_mode == QDF_STA_MODE ||
4269 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
4270 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4271 qdf_copy_macaddr(&peerMacAddr,
4272 &pHddStaCtx->conn_info.bssId);
4273
4274 hdd_objmgr_remove_peer_object(adapter->hdd_vdev,
4275 peerMacAddr.bytes);
4276 }
4277
Yue Maf9782842017-05-08 12:49:49 -07004278 /* Destroy vdev which will be recreated during reinit. */
4279 hdd_vdev_destroy(adapter);
4280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004281 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4282 adapterNode = pNext;
4283 }
4284
4285 EXIT();
4286
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304287 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288}
4289
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304290bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
4291{
4292 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4293 QDF_STATUS status;
4294 bool close_modules = true;
4295
4296 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4297 while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
4298 if (test_bit(DEVICE_IFACE_OPENED,
4299 &adapter_node->pAdapter->event_flags)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004300 hdd_debug("Still other ifaces are up cannot close modules");
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304301 close_modules = false;
4302 break;
4303 }
4304 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4305 adapter_node = next;
4306 }
4307
4308 return close_modules;
4309}
4310
Arun Khandavallifae92942016-08-01 13:31:08 +05304311/**
4312 * hdd_is_interface_up()- Checkfor interface up before ssr
4313 * @hdd_ctx: HDD context
4314 *
4315 * check if there are any wlan interfaces before SSR accordingly start
4316 * the interface.
4317 *
4318 * Return: 0 if interface was opened else false
4319 */
4320static bool hdd_is_interface_up(hdd_adapter_t *adapter)
4321{
4322 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
4323 return true;
4324 else
4325 return false;
4326}
4327
Anurag Chouhanc4092922016-09-08 15:56:11 +05304328#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05304329 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304330struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4331 struct ieee80211_channel *channel,
4332 const u8 *bssid, const u8 *ssid,
4333 size_t ssid_len)
4334{
4335 return cfg80211_get_bss(wiphy, channel, bssid,
4336 ssid, ssid_len,
4337 WLAN_CAPABILITY_ESS,
4338 WLAN_CAPABILITY_ESS);
4339}
4340#else
4341struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4342 struct ieee80211_channel *channel,
4343 const u8 *bssid, const u8 *ssid,
4344 size_t ssid_len)
4345{
4346 return cfg80211_get_bss(wiphy, channel, bssid,
4347 ssid, ssid_len,
4348 IEEE80211_BSS_TYPE_ESS,
4349 IEEE80211_PRIVACY_ANY);
4350}
4351#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304352
Abhishek Singha84d3952016-09-13 13:45:05 +05304353#if defined CFG80211_CONNECT_BSS
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304354#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
4355 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
4356/**
4357 * hdd_convert_timeout_reason() - Convert to kernel specific enum
4358 * @timeout_reason: reason for connect timeout
4359 *
4360 * This function is used to convert host timeout
4361 * reason enum to kernel specific enum.
4362 *
4363 * Return: nl timeout enum
4364 */
4365static enum nl80211_timeout_reason hdd_convert_timeout_reason(
4366 tSirResultCodes timeout_reason)
4367{
4368 switch (timeout_reason) {
4369 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
4370 return NL80211_TIMEOUT_SCAN;
4371 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
4372 return NL80211_TIMEOUT_AUTH;
4373 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
4374 return NL80211_TIMEOUT_ASSOC;
4375 default:
4376 return NL80211_TIMEOUT_UNSPECIFIED;
4377 }
4378}
4379
4380/**
4381 * hdd_cfg80211_connect_timeout() - API to send connection timeout reason
4382 * @dev: network device
4383 * @bssid: bssid to which we want to associate
4384 * @timeout_reason: reason for connect timeout
4385 *
4386 * This API is used to send connection timeout reason to supplicant
4387 *
4388 * Return: void
4389 */
4390static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4391 const u8 *bssid,
4392 tSirResultCodes timeout_reason)
4393{
4394 enum nl80211_timeout_reason nl_timeout_reason;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004395
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304396 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4397
4398 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
4399 nl_timeout_reason);
4400}
4401
4402/**
4403 * __hdd_connect_bss() - API to send connection status to supplicant
4404 * @dev: network device
4405 * @bssid: bssid to which we want to associate
4406 * @req_ie: Request Information Element
4407 * @req_ie_len: len of the req IE
4408 * @resp_ie: Response IE
4409 * @resp_ie_len: len of ht response IE
4410 * @status: status
4411 * @gfp: Kernel Flag
4412 * @timeout_reason: reason for connect timeout
4413 *
4414 * Return: void
4415 */
4416static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4417 struct cfg80211_bss *bss, const u8 *req_ie,
4418 size_t req_ie_len, const u8 *resp_ie,
4419 size_t resp_ie_len, int status, gfp_t gfp,
4420 tSirResultCodes timeout_reason)
4421{
4422 enum nl80211_timeout_reason nl_timeout_reason;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004423
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304424 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4425
4426 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4427 resp_ie, resp_ie_len, status, gfp,
4428 nl_timeout_reason);
4429}
4430#else
4431#if defined CFG80211_CONNECT_TIMEOUT
4432static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4433 const u8 *bssid,
4434 tSirResultCodes timeout_reason)
4435{
4436 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
4437}
4438#endif
4439
4440static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4441 struct cfg80211_bss *bss, const u8 *req_ie,
4442 size_t req_ie_len, const u8 *resp_ie,
4443 size_t resp_ie_len, int status, gfp_t gfp,
4444 tSirResultCodes timeout_reason)
4445{
4446 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4447 resp_ie, resp_ie_len, status, gfp);
4448}
4449#endif
4450
Abhishek Singha84d3952016-09-13 13:45:05 +05304451/**
4452 * hdd_connect_bss() - API to send connection status to supplicant
4453 * @dev: network device
4454 * @bssid: bssid to which we want to associate
4455 * @req_ie: Request Information Element
4456 * @req_ie_len: len of the req IE
4457 * @resp_ie: Response IE
4458 * @resp_ie_len: len of ht response IE
4459 * @status: status
4460 * @gfp: Kernel Flag
4461 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304462 * @timeout_reason: reason for connect timeout
Abhishek Singha84d3952016-09-13 13:45:05 +05304463 *
4464 * The API is a wrapper to send connection status to supplicant
4465 *
4466 * Return: Void
4467 */
4468#if defined CFG80211_CONNECT_TIMEOUT
4469static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4470 struct cfg80211_bss *bss, const u8 *req_ie,
4471 size_t req_ie_len, const u8 *resp_ie,
4472 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304473 bool connect_timeout,
4474 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304475{
4476 if (connect_timeout)
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304477 hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304478 else
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304479 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4480 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304481}
4482#else
4483static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4484 struct cfg80211_bss *bss, const u8 *req_ie,
4485 size_t req_ie_len, const u8 *resp_ie,
4486 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304487 bool connect_timeout,
4488 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304489{
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304490 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4491 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304492}
4493#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304494
4495/**
4496 * hdd_connect_result() - API to send connection status to supplicant
4497 * @dev: network device
4498 * @bssid: bssid to which we want to associate
4499 * @roam_info: information about connected bss
4500 * @req_ie: Request Information Element
4501 * @req_ie_len: len of the req IE
4502 * @resp_ie: Response IE
4503 * @resp_ie_len: len of ht response IE
4504 * @status: status
4505 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05304506 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304507 * @timeout_reason: reason for connect timeout
Anurag Chouhanc4092922016-09-08 15:56:11 +05304508 *
4509 * The API is a wrapper to send connection status to supplicant
4510 * and allow runtime suspend
4511 *
4512 * Return: Void
4513 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304514void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4515 tCsrRoamInfo *roam_info, const u8 *req_ie,
4516 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304517 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304518 bool connect_timeout,
4519 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304520{
4521 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4522 struct cfg80211_bss *bss = NULL;
4523
4524 if (WLAN_STATUS_SUCCESS == status) {
4525 struct ieee80211_channel *chan;
4526 int freq;
4527 int chan_no = roam_info->pBssDesc->channelId;
4528
4529 if (chan_no <= 14)
4530 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004531 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304532 else
4533 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004534 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304535
4536 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
4537 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
4538 roam_info->u.pConnectedProfile->SSID.ssId,
4539 roam_info->u.pConnectedProfile->SSID.length);
4540 }
Komal Seelama89be8d2016-09-29 11:09:26 +05304541
Abhishek Singha84d3952016-09-13 13:45:05 +05304542 hdd_connect_bss(dev, bssid, bss, req_ie,
4543 req_ie_len, resp_ie, resp_ie_len,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304544 status, gfp, connect_timeout, timeout_reason);
Komal Seelama89be8d2016-09-29 11:09:26 +05304545
4546 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -07004547 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304548}
4549#else
4550void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4551 tCsrRoamInfo *roam_info, const u8 *req_ie,
4552 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304553 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304554 bool connect_timeout,
4555 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304556{
Komal Seelama89be8d2016-09-29 11:09:26 +05304557 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4558
Anurag Chouhanc4092922016-09-08 15:56:11 +05304559 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4560 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304561 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -07004562 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304563}
4564#endif
4565
4566
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304567QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568{
4569 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304570 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 hdd_adapter_t *adapter;
4572#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304573 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574#endif
4575 eConnectionState connState;
4576
4577 ENTER();
4578
4579 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304580 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 adapter = adapterNode->pAdapter;
4582
Arun Khandavallifae92942016-08-01 13:31:08 +05304583 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304584 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586 hdd_wmm_init(adapter);
4587
4588 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004589 case QDF_STA_MODE:
4590 case QDF_P2P_CLIENT_MODE:
4591 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592
4593 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4594 ->conn_info.connState;
4595
4596 hdd_init_station_mode(adapter);
4597 /* Open the gates for HDD to receive Wext commands */
4598 adapter->isLinkUpSvcNeeded = false;
4599 adapter->scan_info.mScanPending = false;
4600
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004601 /* Indicate disconnect event to supplicant
4602 * if associated previously
4603 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004604 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004605 eConnectionState_IbssConnected == connState ||
4606 eConnectionState_NotConnected == connState ||
4607 eConnectionState_IbssDisconnected == connState ||
4608 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 union iwreq_data wrqu;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004610
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004611 memset(&wrqu, '\0', sizeof(wrqu));
4612 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4613 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4614 wireless_send_event(adapter->dev, SIOCGIWAP,
4615 &wrqu, NULL);
4616 adapter->sessionCtx.station.
4617 hdd_ReassocScenario = false;
4618
4619 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304620 wlan_hdd_cfg80211_indicate_disconnect(
4621 adapter->dev, false,
4622 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004623 } else if (eConnectionState_Connecting == connState) {
4624 /*
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004625 * Indicate connect failure to supplicant if we
4626 * were in the process of connecting
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004627 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304628 hdd_connect_result(adapter->dev, NULL, NULL,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304629 NULL, 0, NULL, 0,
4630 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004631 GFP_KERNEL, false, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004632 }
4633
4634 hdd_register_tx_flow_control(adapter,
4635 hdd_tx_resume_timer_expired_handler,
4636 hdd_tx_resume_cb);
4637
4638 break;
4639
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004640 case QDF_SAP_MODE:
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004641 if (hdd_ctx->config->sap_internal_restart)
Arun Khandavallicc544b32017-01-30 19:52:16 +05304642 hdd_init_ap_mode(adapter, true);
4643
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644 break;
4645
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004646 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004647#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004648 hdd_debug("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4650#else
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004651 hdd_debug("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 /* event supplicant to restart */
4653 cfg80211_del_sta(adapter->dev,
4654 (const u8 *)&bcastMac.bytes[0],
4655 GFP_KERNEL);
4656#endif
4657 break;
4658
4659 default:
4660 break;
4661 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304662get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4664 adapterNode = pNext;
4665 }
4666
4667 EXIT();
4668
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304669 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004670}
4671
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304672QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 hdd_adapter_list_node_t **padapterNode)
4674{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304675 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004676
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004677 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304678 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4679 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004680 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 return status;
4682}
4683
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304684QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685 hdd_adapter_list_node_t *adapterNode,
4686 hdd_adapter_list_node_t **pNextAdapterNode)
4687{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304688 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004689
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004690 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304691 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4692 (qdf_list_node_t *) adapterNode,
4693 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004694
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004695 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 return status;
4697}
4698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304699QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700 hdd_adapter_list_node_t *adapterNode)
4701{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304702 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004703
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004704 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304705 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004707 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708 return status;
4709}
4710
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304711QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712 hdd_adapter_list_node_t **padapterNode)
4713{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304714 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004715
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004716 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304717 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4718 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004719 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 return status;
4721}
4722
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304723QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724 hdd_adapter_list_node_t *adapterNode)
4725{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304726 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004727
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004728 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304729 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4730 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004731 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004732 return status;
4733}
4734
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304735QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004736 hdd_adapter_list_node_t *adapterNode)
4737{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304738 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004739
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004740 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304741 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4742 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004743 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004744 return status;
4745}
4746
4747hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4748 tSirMacAddr macAddr)
4749{
4750 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4751 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304752 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753
4754 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4755
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304756 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004757 adapter = adapterNode->pAdapter;
4758
4759 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304760 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004761 macAddr, sizeof(tSirMacAddr)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 return adapter;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4765 adapterNode = pNext;
4766 }
4767
4768 return NULL;
4769
4770}
4771
4772hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4773 uint32_t vdev_id)
4774{
4775 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4776 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304777 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004778
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304779 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004780
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304781 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004782 adapter = adapterNode->pAdapter;
4783
4784 if (adapter->sessionId == vdev_id)
4785 return adapter;
4786
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304787 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004788 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4789 adapterNode = pNext;
4790 }
4791
Jeff Johnson5880d792016-08-15 13:32:30 -07004792 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793
4794 return NULL;
4795}
4796
Abhishek Singh7996eb72015-12-30 17:24:02 +05304797/**
4798 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4799 * the sessionid
4800 * @hdd_ctx: hdd context.
4801 * @sme_session_id: sme session is for the adapter to get.
4802 *
4803 * This function is used to get the adapter with provided session id
4804 *
4805 * Return: adapter pointer if found
4806 *
4807 */
4808hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4809 uint32_t sme_session_id)
4810{
4811 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4812 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304813 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304814
4815
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304816 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304817
4818 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304819 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304820 adapter = adapter_node->pAdapter;
4821
4822 if (adapter &&
4823 adapter->sessionId == sme_session_id)
4824 return adapter;
4825
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304826 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304827 hdd_get_next_adapter(hdd_ctx,
4828 adapter_node, &next);
4829 adapter_node = next;
4830 }
4831 return NULL;
4832}
4833
Naveen Rawat4edb6822017-04-12 10:09:17 -07004834hdd_adapter_t *hdd_get_adapter_by_iface_name(hdd_context_t *hdd_ctx,
4835 const char *iface_name)
4836{
4837 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4838 hdd_adapter_t *adapter;
4839 QDF_STATUS qdf_status;
4840
4841 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4842
4843 while ((NULL != adapter_node) &&
4844 (QDF_STATUS_SUCCESS == qdf_status)) {
4845 adapter = adapter_node->pAdapter;
4846
4847 if (adapter &&
4848 !qdf_str_cmp(adapter->dev->name, iface_name))
4849 return adapter;
4850
4851 qdf_status =
4852 hdd_get_next_adapter(hdd_ctx,
4853 adapter_node, &next);
4854 adapter_node = next;
4855 }
4856 return NULL;
4857}
4858
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004859/**
4860 * hdd_get_adapter() - to get adapter matching the mode
4861 * @hdd_ctx: hdd context
4862 * @mode: adapter mode
4863 *
4864 * This routine will return the pointer to adapter matching
4865 * with the passed mode.
4866 *
4867 * Return: pointer to adapter or null
4868 */
4869hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4870 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871{
4872 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4873 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304874 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875
4876 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4877
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304878 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004879 adapter = adapterNode->pAdapter;
4880
4881 if (adapter && (mode == adapter->device_mode))
4882 return adapter;
4883
4884 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4885 adapterNode = pNext;
4886 }
4887
4888 return NULL;
4889
4890}
4891
4892/**
4893 * hdd_get_operating_channel() - return operating channel of the device mode
4894 * @hdd_ctx: Pointer to the HDD context.
4895 * @mode: Device mode for which operating channel is required.
4896 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004897 * QDF_STA_MODE,
4898 * QDF_P2P_CLIENT_MODE,
4899 * QDF_SAP_MODE,
4900 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 *
4902 * This API returns the operating channel of the requested device mode
4903 *
4904 * Return: channel number. "0" id the requested device is not found OR it is
4905 * not connected.
4906 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004907uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4908 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004909{
4910 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304911 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 hdd_adapter_t *adapter;
4913 uint8_t operatingChannel = 0;
4914
4915 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4916
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304917 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 adapter = adapterNode->pAdapter;
4919
4920 if (mode == adapter->device_mode) {
4921 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004922 case QDF_STA_MODE:
4923 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924 if (hdd_conn_is_connected
4925 (WLAN_HDD_GET_STATION_CTX_PTR
4926 (adapter))) {
4927 operatingChannel =
4928 (WLAN_HDD_GET_STATION_CTX_PTR
4929 (adapter))->conn_info.
4930 operationChannel;
4931 }
4932 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004933 case QDF_SAP_MODE:
4934 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 /* softap connection info */
4936 if (test_bit
4937 (SOFTAP_BSS_STARTED,
4938 &adapter->event_flags))
4939 operatingChannel =
4940 (WLAN_HDD_GET_AP_CTX_PTR
4941 (adapter))->operatingChannel;
4942 break;
4943 default:
4944 break;
4945 }
4946
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004947 /* Found the device of interest. break the loop */
4948 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 }
4950
4951 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4952 adapterNode = pNext;
4953 }
4954 return operatingChannel;
4955}
4956
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304957static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004958 hdd_ctx)
4959{
4960 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304961 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962 hdd_adapter_t *adapter;
4963
4964 ENTER();
4965
4966 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4967
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304968 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004969 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004970 if ((adapter->device_mode == QDF_STA_MODE) ||
4971 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4972 (adapter->device_mode == QDF_IBSS_MODE) ||
4973 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4974 (adapter->device_mode == QDF_SAP_MODE) ||
4975 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 wlan_hdd_cfg80211_deregister_frames(adapter);
4977 hdd_unregister_wext(adapter->dev);
4978 }
4979 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4980 adapterNode = pNext;
4981 }
4982
4983 EXIT();
4984
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304985 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004986}
4987
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304988QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004989{
4990 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304991 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004992 hdd_adapter_t *adapter;
4993
4994 ENTER();
4995
4996 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4997
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304998 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005000 if ((adapter->device_mode == QDF_STA_MODE) ||
5001 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
5002 (adapter->device_mode == QDF_IBSS_MODE) ||
5003 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
5004 (adapter->device_mode == QDF_SAP_MODE) ||
5005 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Abhishek Singh69ccb512017-04-25 11:58:16 +05305006 wlan_abort_scan(hdd_ctx->hdd_pdev, INVAL_PDEV_ID,
5007 adapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008 }
5009 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
5010 adapterNode = pNext;
5011 }
5012
5013 EXIT();
5014
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305015 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005016}
5017
Dustin Brownf27bce82016-11-03 12:52:27 -07005018/**
5019 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
5020 * adapters
5021 * @hdd_ctx: The HDD context containing the adapters to operate on
5022 *
5023 * return: QDF_STATUS_SUCCESS
5024 */
5025static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
5026{
5027 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
5028 QDF_STATUS status;
5029 hdd_adapter_t *adapter;
5030 int err;
5031
5032 ENTER();
5033
5034 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
5035
5036 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5037 adapter = adapter_node->pAdapter;
5038 if ((adapter->device_mode == QDF_STA_MODE) ||
5039 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
5040 (adapter->device_mode == QDF_IBSS_MODE) ||
5041 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
5042 (adapter->device_mode == QDF_SAP_MODE) ||
5043 (adapter->device_mode == QDF_P2P_GO_MODE)) {
5044 err = wlan_hdd_sched_scan_stop(adapter->dev);
5045 if (err)
5046 hdd_err("Unable to stop scheduled scan");
5047 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005048 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
5049 &next_node);
Dustin Brownf27bce82016-11-03 12:52:27 -07005050 adapter_node = next_node;
5051 }
5052
5053 EXIT();
5054
5055 return QDF_STATUS_SUCCESS;
5056}
5057
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058#ifdef WLAN_NS_OFFLOAD
5059/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005060 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005061 * @hdd_ctx: Pointer to hdd context
5062 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005063 * Unregister for IPv6 address change notifications.
5064 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065 * Return: None
5066 */
5067static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
5068{
5069 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005070}
5071
5072/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005073 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074 * @hdd_ctx: Pointer to hdd context
5075 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005076 * Register for IPv6 address change notifications.
5077 *
5078 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005079 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005080static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081{
5082 int ret;
5083
5084 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
5085 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005086 if (ret) {
5087 hdd_err("Failed to register IPv6 notifier: %d", ret);
5088 goto out;
5089 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005090
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005091 hdd_debug("Registered IPv6 notifier");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005092out:
5093 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005094}
5095#else
5096/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005097 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098 * @hdd_ctx: Pointer to hdd context
5099 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005100 * Unregister for IPv6 address change notifications.
5101 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005102 * Return: None
5103 */
5104static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
5105{
5106}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005108/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005109 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005110 * @hdd_ctx: Pointer to hdd context
5111 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005112 * Register for IPv6 address change notifications.
5113 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005114 * Return: None
5115 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005116static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005118 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005119}
5120#endif
5121
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305122#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
5123/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005124 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305125 * @hdd_ctx: HDD context
5126 *
5127 * Activates the logging service
5128 *
5129 * Return: Zero in case of success, negative value otherwise
5130 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005131static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305132{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005133 int ret;
5134 struct hdd_config *config = hdd_ctx->config;
5135
5136 if (!config->wlanLoggingEnable)
5137 return 0;
5138
Srinivas Girigowda8187e792017-03-03 11:50:59 -08005139 ret = wlan_logging_sock_activate_svc(config->wlanLoggingToConsole,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005140 config->wlanLoggingNumBuf);
5141 if (ret)
5142 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
5143 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305144}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005145
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305146/**
5147 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
5148 * @hdd_ctx: HDD context
5149 *
5150 * Deactivates the logging service
5151 *
5152 * Return: 0 on deactivating the logging service
5153 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005154static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305155{
5156 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
5157 return wlan_logging_sock_deactivate_svc();
5158
5159 return 0;
5160}
5161#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005162static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305163{
5164 return 0;
5165}
5166
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005167static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305168{
5169 return 0;
5170}
5171#endif
5172
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005174 * hdd_register_notifiers - Register netdev notifiers.
5175 * @hdd_ctx: HDD context
5176 *
5177 * Register netdev notifiers like IPv4 and IPv6.
5178 *
5179 * Return: 0 on success and errno on failure
5180 */
5181static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
5182{
5183 int ret;
5184
5185 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5186 if (ret) {
5187 hdd_err("register_netdevice_notifier failed: %d", ret);
5188 goto out;
5189 }
5190
5191 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
5192 if (ret)
5193 goto unregister_notifier;
5194
5195 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5196 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5197 if (ret) {
5198 hdd_err("Failed to register IPv4 notifier: %d", ret);
5199 goto unregister_ip6_notifier;
5200 }
5201
5202 return 0;
5203
5204unregister_ip6_notifier:
5205 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5206unregister_notifier:
5207 unregister_netdevice_notifier(&hdd_netdev_notifier);
5208out:
5209 return ret;
5210
5211}
5212
5213/**
5214 * hdd_unregister_notifiers - Unregister netdev notifiers.
5215 * @hdd_ctx: HDD context
5216 *
5217 * Unregister netdev notifiers like IPv4 and IPv6.
5218 *
5219 * Return: None.
5220 */
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305221void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005222{
5223 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5224
5225 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5226
5227 unregister_netdevice_notifier(&hdd_netdev_notifier);
5228}
5229
5230/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005231 * hdd_exit_netlink_services - Exit netlink services
5232 * @hdd_ctx: HDD context
5233 *
5234 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
5235 * nl service.
5236 *
5237 * Return: None.
5238 */
5239static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
5240{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005241 hdd_close_cesium_nl_sock();
Naveen Rawat910726a2017-03-06 11:42:51 -08005242 hdd_deactivate_wifi_pos();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005243 ptt_sock_deactivate_svc();
5244
5245 nl_srv_exit();
5246}
5247
5248/**
5249 * hdd_init_netlink_services- Init netlink services
5250 * @hdd_ctx: HDD context
5251 *
5252 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
5253 * nl service.
5254 *
5255 * Return: 0 on success and errno on failure.
5256 */
5257static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
5258{
5259 int ret;
5260
Ryan Hsuceddceb2016-04-28 10:20:14 -07005261 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005262 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005263 hdd_err("nl_srv_init failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005264 goto out;
5265 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07005266 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005267
Naveen Rawat910726a2017-03-06 11:42:51 -08005268 ret = hdd_activate_wifi_pos(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005269 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005270 hdd_err("hdd_activate_wifi_pos failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005271 goto err_nl_srv;
5272 }
5273
5274 ret = ptt_sock_activate_svc();
5275 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005276 hdd_err("ptt_sock_activate_svc failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005277 goto err_nl_srv;
5278 }
5279
5280 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07005281 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005282 hdd_err("hdd_open_cesium_nl_sock failed ret: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005283
5284 ret = cnss_diag_activate_service();
5285 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005286 hdd_err("cnss_diag_activate_service failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005287 goto err_close_cesium;
5288 }
5289
5290 return 0;
5291
5292err_close_cesium:
5293 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005294 ptt_sock_deactivate_svc();
5295err_nl_srv:
5296 nl_srv_exit();
5297out:
5298 return ret;
5299}
5300
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005301/**
5302 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
5303 * @hdd_ctx: HDD context.
5304 *
5305 * Destroy RX wakelock.
5306 *
5307 * Return: None.
5308 */
5309static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
5310{
5311 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
5312}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005313
5314/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005315 * hdd_rx_wake_lock_create() - Create RX wakelock
5316 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005317 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005318 * Create RX wakelock.
5319 *
5320 * Return: None.
5321 */
5322static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
5323{
5324 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5325}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005326
5327/**
5328 * hdd_roc_context_init() - Init ROC context
5329 * @hdd_ctx: HDD context.
5330 *
5331 * Initialize ROC context.
5332 *
5333 * Return: 0 on success and errno on failure.
5334 */
5335static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
5336{
5337 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
5338 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
5339
5340 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5341
5342 return 0;
5343}
5344
5345/**
5346 * hdd_roc_context_destroy() - Destroy ROC context
5347 * @hdd_ctx: HDD context.
5348 *
5349 * Destroy roc list and flush the pending roc work.
5350 *
5351 * Return: None.
5352 */
5353static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
5354{
5355 flush_delayed_work(&hdd_ctx->roc_req_work);
5356 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08005357 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005358}
5359
5360/**
Houston Hoffman160db392016-10-10 17:37:51 -07005361 * hdd_context_deinit() - Deinitialize HDD context
5362 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005363 *
Houston Hoffman160db392016-10-10 17:37:51 -07005364 * Deinitialize HDD context along with all the feature specific contexts but
5365 * do not free hdd context itself. Caller of this API is supposed to free
5366 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005367 *
Houston Hoffman160db392016-10-10 17:37:51 -07005368 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005369 */
Houston Hoffman160db392016-10-10 17:37:51 -07005370static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005371{
Houston Hoffman160db392016-10-10 17:37:51 -07005372 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005373
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005374 hdd_roc_context_destroy(hdd_ctx);
5375
5376 hdd_sap_context_destroy(hdd_ctx);
5377
5378 hdd_rx_wake_lock_destroy(hdd_ctx);
5379
5380 hdd_tdls_context_destroy(hdd_ctx);
5381
5382 hdd_scan_context_destroy(hdd_ctx);
5383
5384 qdf_list_destroy(&hdd_ctx->hddAdapters);
5385
Houston Hoffman160db392016-10-10 17:37:51 -07005386 return 0;
5387}
5388
5389/**
5390 * hdd_context_destroy() - Destroy HDD context
5391 * @hdd_ctx: HDD context to be destroyed.
5392 *
5393 * Free config and HDD context as well as destroy all the resources.
5394 *
5395 * Return: None
5396 */
5397static void hdd_context_destroy(hdd_context_t *hdd_ctx)
5398{
5399 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
5400 hdd_logging_sock_deactivate_svc(hdd_ctx);
5401
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05305402 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5403
Houston Hoffman160db392016-10-10 17:37:51 -07005404 hdd_context_deinit(hdd_ctx);
5405
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305406 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005407 hdd_ctx->config = NULL;
5408
5409 wiphy_free(hdd_ctx->wiphy);
5410}
5411
5412/**
SaidiReddy Yenuga699d90e2017-04-14 16:09:24 +05305413 * wlan_destroy_bug_report_lock() - Destroy bug report lock
5414 *
5415 * This function is used to destroy bug report lock
5416 *
5417 * Return: None
5418 */
5419static void wlan_destroy_bug_report_lock(void)
5420{
5421 p_cds_contextType p_cds_context;
5422
5423 p_cds_context = cds_get_global_context();
5424 if (!p_cds_context) {
5425 hdd_err("cds context is NULL");
5426 return;
5427 }
5428
5429 qdf_spinlock_destroy(&p_cds_context->bug_report_lock);
5430}
5431
5432/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433 * hdd_wlan_exit() - HDD WLAN exit function
5434 * @hdd_ctx: Pointer to the HDD Context
5435 *
5436 * This is the driver exit point (invoked during rmmod)
5437 *
5438 * Return: None
5439 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005440static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441{
5442 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305443 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005444 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05305445 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446
5447 ENTER();
5448
Arun Khandavallifae92942016-08-01 13:31:08 +05305449 if (QDF_TIMER_STATE_RUNNING ==
5450 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005451 hdd_debug("Stop interface change timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05305452 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005453 }
5454
Arun Khandavallifae92942016-08-01 13:31:08 +05305455 if (!QDF_IS_STATUS_SUCCESS
5456 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
5457 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005458
Arun Khandavallifae92942016-08-01 13:31:08 +05305459
5460 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461
Nitesh Shah61c10d92016-10-19 19:29:15 +05305462 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
5463
Prashanth Bhattaab004382016-10-11 16:08:11 -07005464 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465
5466#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305467 if (QDF_TIMER_STATE_RUNNING ==
5468 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
5469 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470 }
5471
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305472 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05305473 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005474 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 }
Liangwei Dongaef84342016-10-21 05:28:00 -04005476 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5477 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5478 hdd_ctx->last_acs_channel_list = NULL;
5479 hdd_ctx->num_of_channels = 0;
5480 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005482
Arun Khandavallifae92942016-08-01 13:31:08 +05305483 mutex_lock(&hdd_ctx->iface_change_lock);
5484 driver_status = hdd_ctx->driver_status;
5485 mutex_unlock(&hdd_ctx->iface_change_lock);
5486
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 /*
5488 * Powersave Offload Case
5489 * Disable Idle Power Save Mode
5490 */
5491 hdd_set_idle_ps_config(hdd_ctx, false);
5492
Arun Khandavallifae92942016-08-01 13:31:08 +05305493 if (driver_status != DRIVER_MODULES_CLOSED) {
5494 hdd_unregister_wext_all_adapters(hdd_ctx);
5495 /*
5496 * Cancel any outstanding scan requests. We are about to close
5497 * all of our adapters, but an adapter structure is what SME
5498 * passes back to our callback function. Hence if there
5499 * are any outstanding scan requests then there is a
5500 * race condition between when the adapter is closed and
5501 * when the callback is invoked. We try to resolve that
5502 * race condition here by canceling any outstanding scans
5503 * before we close the adapters.
5504 * Note that the scans may be cancelled in an asynchronous
5505 * manner, so ideally there needs to be some kind of
5506 * synchronization. Rather than introduce a new
5507 * synchronization here, we will utilize the fact that we are
5508 * about to Request Full Power, and since that is synchronized,
5509 * the expectation is that by the time Request Full Power has
5510 * completed, all scans will be cancelled
5511 */
Sandeep Puligilla8de3c1c2017-04-13 17:56:18 -07005512 wlan_cfg80211_cleanup_scan_queue(hdd_ctx->hdd_pdev);
Arun Khandavallifae92942016-08-01 13:31:08 +05305513 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07005514 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305515 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516 }
5517
SaidiReddy Yenuga699d90e2017-04-14 16:09:24 +05305518 wlan_destroy_bug_report_lock();
5519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 /*
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305521 * Close the scheduler before calling cds_close to make sure
5522 * no thread is scheduled after the each module close is
5523 * is called i.e after all the data structures are freed.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305525 qdf_status = cds_sched_close(p_cds_context);
5526 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005527 hdd_err("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305528 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005529 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07005531 hdd_wlan_stop_modules(hdd_ctx, false);
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05305532
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305533 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
5534 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
5535 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
5536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537 /*
5538 * Close CDS
5539 * This frees pMac(HAL) context. There should not be any call
5540 * that requires pMac access after this.
5541 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005542
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07005543 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08005544 hdd_request_manager_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005545
Komal Seelam8634b772016-09-29 12:12:24 +05305546 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005547 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548
5549 hdd_ipa_cleanup(hdd_ctx);
5550
5551 /* Free up RoC request queue and flush workqueue */
5552 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05305554 wlansap_global_deinit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05305555 wlan_hdd_deinit_chan_info(hdd_ctx);
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305556 /*
5557 * If there is re_init failure wiphy would have already de-registered
5558 * check the wiphy status before un-registering again
5559 */
Ashish Kumar Dhanotiyae16feb72017-03-31 19:39:37 +05305560 if (wiphy && wiphy->registered) {
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305561 wiphy_unregister(wiphy);
5562 wlan_hdd_cfg80211_deinit(wiphy);
5563 hdd_lpass_notify_stop(hdd_ctx);
5564 }
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07005565
Arun Khandavallifae92942016-08-01 13:31:08 +05305566 hdd_exit_netlink_services(hdd_ctx);
5567 mutex_destroy(&hdd_ctx->iface_change_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05305568#ifdef FEATURE_WLAN_CH_AVOID
5569 mutex_destroy(&hdd_ctx->avoid_freq_lock);
5570#endif
Abhishek Singhe9068f12017-03-31 14:14:52 +05305571
5572 driver_status = hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
5573 if (driver_status)
5574 hdd_err("Pdev delete failed");
5575
5576 driver_status = hdd_objmgr_release_and_destroy_psoc(hdd_ctx);
5577 if (driver_status)
5578 hdd_err("Psoc delete failed");
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005579 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005580}
5581
5582void __hdd_wlan_exit(void)
5583{
5584 hdd_context_t *hdd_ctx;
5585
5586 ENTER();
5587
Anurag Chouhan6d760662016-02-20 16:05:43 +05305588 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 if (!hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005590 hdd_err("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005591 EXIT();
5592 return;
5593 }
5594
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005595 /* Check IPA HW Pipe shutdown */
5596 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
5597
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005598 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05305599 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005601 /* Do all the cleanup before deregistering the driver */
5602 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07005603
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604 EXIT();
5605}
5606
5607#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04005608/**
5609 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
5610 * @data: pointer to hdd_context_t
5611 *
5612 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
5613 * Then new ACS request will do a fresh scan without reusing the cached
5614 * scan information.
5615 *
5616 * Return: void
5617 */
Tang Yingying523322d2017-01-17 23:28:43 +08005618static void hdd_skip_acs_scan_timer_handler(void *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619{
5620 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
5621
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005622 hdd_debug("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005623 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04005624 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5625 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5626 hdd_ctx->last_acs_channel_list = NULL;
5627 hdd_ctx->num_of_channels = 0;
5628 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005629
5630 if (!hdd_ctx->hHal)
5631 return;
5632 sme_scan_flush_result(hdd_ctx->hHal);
5633}
5634#endif
5635
5636#ifdef QCA_HT_2040_COEX
5637/**
5638 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5639 * @adapter: pointer to adapter
5640 * @staId: station id
5641 * @macAddrSTA: station MAC address
5642 * @channel_type: channel type
5643 *
5644 * This function notifies FW with HT20/HT40 mode
5645 *
5646 * Return: 0 if successful, error number otherwise
5647 */
5648int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305649 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650{
5651 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305652 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653 hdd_context_t *hdd_ctx = NULL;
5654
5655 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5656
5657 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305658 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005659 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305660
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661 if (!hdd_ctx->hHal)
5662 return -EINVAL;
5663
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305664 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305666 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005667 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 return -EINVAL;
5669 }
5670
5671 return 0;
5672}
5673#endif
5674
5675/**
5676 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5677 * @state: state
5678 *
5679 * This function notifies FW with modem power status
5680 *
5681 * Return: 0 if successful, error number otherwise
5682 */
5683int hdd_wlan_notify_modem_power_state(int state)
5684{
5685 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305686 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005687 hdd_context_t *hdd_ctx;
5688
Anurag Chouhan6d760662016-02-20 16:05:43 +05305689 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005690 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305691 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305693
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005694 if (!hdd_ctx->hHal)
5695 return -EINVAL;
5696
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305697 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5698 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005699 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005700 state);
5701 return -EINVAL;
5702 }
5703 return 0;
5704}
5705
5706/**
5707 *
5708 * hdd_post_cds_enable_config() - HDD post cds start config helper
5709 * @adapter - Pointer to the HDD
5710 *
5711 * Return: None
5712 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305713QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005714{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305715 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005716
5717 /*
5718 * Send ready indication to the HDD. This will kick off the MAC
5719 * into a 'running' state and should kick off an initial scan.
5720 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305721 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5722 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005723 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5724 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305725 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005726 }
5727
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305728 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005729}
5730
5731/* wake lock APIs for HDD */
5732void hdd_prevent_suspend(uint32_t reason)
5733{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305734 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735}
5736
5737void hdd_allow_suspend(uint32_t reason)
5738{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305739 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005740}
5741
5742void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5743{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305744 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5745 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005746}
5747
5748/**
5749 * hdd_exchange_version_and_caps() - exchange version and capability with target
5750 * @hdd_ctx: Pointer to HDD context
5751 *
5752 * This is the HDD function to exchange version and capability information
5753 * between Host and Target
5754 *
5755 * This function gets reported version of FW.
5756 * It also finds the version of target headers used to compile the host;
5757 * It compares the above two and prints a warning if they are different;
5758 * It gets the SW and HW version string;
5759 * Finally, it exchanges capabilities between host and target i.e. host
5760 * and target exchange a msg indicating the features they support through a
5761 * bitmap
5762 *
5763 * Return: None
5764 */
5765void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5766{
5767
5768 tSirVersionType versionCompiled;
5769 tSirVersionType versionReported;
5770 tSirVersionString versionString;
5771 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305772 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005773
5774 memset(&versionCompiled, 0, sizeof(versionCompiled));
5775 memset(&versionReported, 0, sizeof(versionReported));
5776
5777 /* retrieve and display WCNSS version information */
5778 do {
5779
5780 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5781 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305782 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005783 hdd_err("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784 break;
5785 }
5786
5787 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5788 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305789 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005790 hdd_err("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 break;
5792 }
5793
5794 if ((versionCompiled.major != versionReported.major) ||
5795 (versionCompiled.minor != versionReported.minor) ||
5796 (versionCompiled.version != versionReported.version) ||
5797 (versionCompiled.revision != versionReported.revision)) {
5798 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5799 "Host expected %u.%u.%u.%u\n",
5800 WLAN_MODULE_NAME,
5801 (int)versionReported.major,
5802 (int)versionReported.minor,
5803 (int)versionReported.version,
5804 (int)versionReported.revision,
5805 (int)versionCompiled.major,
5806 (int)versionCompiled.minor,
5807 (int)versionCompiled.version,
5808 (int)versionCompiled.revision);
5809 } else {
5810 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5811 WLAN_MODULE_NAME,
5812 (int)versionReported.major,
5813 (int)versionReported.minor,
5814 (int)versionReported.version,
5815 (int)versionReported.revision);
5816 }
5817
5818 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5819 versionString,
5820 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305821 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005822 hdd_err("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005823 break;
5824 }
5825
5826 pr_info("%s: WCNSS software version %s\n",
5827 WLAN_MODULE_NAME, versionString);
5828
5829 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5830 versionString,
5831 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305832 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005833 hdd_err("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005834 break;
5835 }
5836
5837 pr_info("%s: WCNSS hardware version %s\n",
5838 WLAN_MODULE_NAME, versionString);
5839
5840 /*
5841 * 1.Check if FW version is greater than 0.1.1.0. Only then
5842 * send host-FW capability exchange message
5843 * 2.Host-FW capability exchange message is only present on
5844 * target 1.1 so send the message only if it the target is 1.1
5845 * minor numbers for different target branches:
5846 * 0 -> (1.0)Mainline Build
5847 * 1 -> (1.1)Mainline Build
5848 * 2->(1.04) Stability Build
5849 */
5850 if (((versionReported.major > 0) || (versionReported.minor > 1)
5851 || ((versionReported.minor >= 1)
5852 && (versionReported.version >= 1)))
5853 && ((versionReported.major == 1)
5854 && (versionReported.minor >= 1)))
5855 fwFeatCapsMsgSupported = 1;
5856
5857 if (fwFeatCapsMsgSupported) {
5858 /*
5859 * Indicate if IBSS heartbeat monitoring needs to be
5860 * offloaded
5861 */
5862 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5863 sme_disable_feature_capablity
5864 (IBSS_HEARTBEAT_OFFLOAD);
5865 }
5866
5867 sme_feature_caps_exchange(hdd_ctx->hHal);
5868 }
5869
5870 } while (0);
5871
5872}
5873
5874/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305875QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876{
Amar Singhal5cccafe2017-02-15 12:42:58 -08005877
Amar Singhal6f8592b2017-04-26 14:31:58 -07005878 return sme_init_chan_list(hdd_ctx->hHal,
5879 hdd_ctx->reg.alpha2,
5880 hdd_ctx->reg.cc_src);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005881}
5882
5883/**
5884 * hdd_is_5g_supported() - check if hardware supports 5GHz
5885 * @hdd_ctx: Pointer to the hdd context
5886 *
5887 * HDD function to know if hardware supports 5GHz
5888 *
5889 * Return: true if hardware supports 5GHz
5890 */
5891bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5892{
zdingf54169a2016-10-12 17:08:45 +08005893 if (!hdd_ctx || !hdd_ctx->config)
5894 return true;
5895
5896 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5897 return true;
5898 else
5899 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900}
5901
Amar Singhale4f28ee2015-10-21 14:36:56 -07005902static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005903{
5904 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005905 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005906
5907 wiphy = hdd_ctx->wiphy;
5908
5909 /*
5910 * The channel information in
5911 * wiphy needs to be initialized before wiphy registration
5912 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005913 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5914 if (ret_val) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005915 hdd_err("regulatory init failed");
Amar Singhale4f28ee2015-10-21 14:36:56 -07005916 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005917 }
5918
5919#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5920 wiphy->wowlan = &wowlan_support_reg_init;
5921#else
5922 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5923 WIPHY_WOWLAN_MAGIC_PKT |
5924 WIPHY_WOWLAN_DISCONNECT |
5925 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5926 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5927 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5928 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5929 WIPHY_WOWLAN_RFKILL_RELEASE;
5930
5931 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5932 WOW_MAX_FILTERS_PER_LIST);
5933 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5934 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5935#endif
5936
5937 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005938 ret_val = wlan_hdd_cfg80211_register(wiphy);
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305939 if (0 > ret_val) {
Amar Singhale4f28ee2015-10-21 14:36:56 -07005940 hdd_err("wiphy registration failed");
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305941 return ret_val;
5942 }
5943
Amar Singhal5cccafe2017-02-15 12:42:58 -08005944 if (!hdd_ctx->reg_offload)
5945 hdd_program_country_code(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005946
Amar Singhale4f28ee2015-10-21 14:36:56 -07005947 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005948}
5949
Ravi Joshie2331e82015-07-01 18:18:54 -07005950/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005951 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005952 * @hdd_ctx - handle to hdd context
5953 * @tx_packets - transmit packet count
5954 * @rx_packets - receive packet count
5955 *
5956 * The function controls the bus bandwidth and dynamic control of
5957 * tcp delayed ack configuration
5958 *
5959 * Returns: None
5960 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005961#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005962static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5963 const uint64_t tx_packets,
5964 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005965{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005966 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005967 uint64_t temp_rx = 0;
5968 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005969 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannac3da7062017-02-08 21:08:56 -08005970 static enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005971 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005972 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005973 uint16_t index = 0;
5974 bool vote_level_change = false;
5975 bool rx_level_change = false;
5976 bool tx_level_change = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005979 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005981 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005982 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005983 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005984 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005985 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005988 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5989 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005990 hdd_ctx->cur_vote_level = next_vote_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005991 vote_level_change = true;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005992 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305993 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305994 if (hdd_ctx->hbw_requested) {
5995 pld_remove_pm_qos(hdd_ctx->parent_dev);
5996 hdd_ctx->hbw_requested = false;
5997 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305998 if (cds_sched_handle_throughput_req(false))
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005999 hdd_warn("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05306000 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05306001 if (!hdd_ctx->hbw_requested) {
6002 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
6003 hdd_ctx->hbw_requested = true;
6004 }
6005
Nirav Shah3bbfa512016-05-12 16:43:49 +05306006 if (cds_sched_handle_throughput_req(true))
Srinivas Girigowdab841da72017-03-25 18:04:39 -07006007 hdd_warn("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05306008 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07006009 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010 }
Mohit Khannae71e2262015-11-10 09:37:24 -08006011
6012 /* fine-tuning parameters for RX Flows */
6013 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
6014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 hdd_ctx->prev_rx = rx_packets;
Mohit Khannab1dd1e82017-02-04 15:14:38 -08006016
Ravi Joshifed83572016-10-07 16:20:37 -07006017 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
6018 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
6019 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
6020 next_rx_level = WLAN_SVC_TP_HIGH;
6021 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07006022 } else {
Ravi Joshib89e7f72016-09-07 13:43:15 -07006023 hdd_ctx->rx_high_ind_cnt = 0;
Mohit Khannac3da7062017-02-08 21:08:56 -08006024 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07006025 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006027 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07006028 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006029 next_rx_level, temp_rx);
6030 hdd_ctx->cur_rx_level = next_rx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006031 rx_level_change = true;
Ravi Joshie2331e82015-07-01 18:18:54 -07006032 /* Send throughput indication only if it is enabled.
6033 * Disabling tcp_del_ack will revert the tcp stack behavior
6034 * to default delayed ack. Note that this will disable the
6035 * dynamic delayed ack mechanism across the system
6036 */
6037 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05306038 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
6039 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006040 &next_rx_level,
6041 sizeof(next_rx_level));
6042 }
6043
Mohit Khannae71e2262015-11-10 09:37:24 -08006044 /* fine-tuning parameters for TX Flows */
6045 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
6046 hdd_ctx->prev_tx = tx_packets;
6047 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
6048 next_tx_level = WLAN_SVC_TP_HIGH;
6049 else
6050 next_tx_level = WLAN_SVC_TP_LOW;
6051
Srinivas Girigowdab841da72017-03-25 18:04:39 -07006052 if (hdd_ctx->cur_tx_level != next_tx_level) {
Mohit Khannae71e2262015-11-10 09:37:24 -08006053 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
6054 next_tx_level, temp_tx);
6055 hdd_ctx->cur_tx_level = next_tx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006056 tx_level_change = true;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05306057 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
6058 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08006059 &next_tx_level,
6060 sizeof(next_tx_level));
6061 }
6062
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006063 index = hdd_ctx->hdd_txrx_hist_idx;
6064
6065 if (vote_level_change || tx_level_change || rx_level_change) {
6066 hdd_ctx->hdd_txrx_hist[index].next_tx_level = next_tx_level;
6067 hdd_ctx->hdd_txrx_hist[index].next_rx_level = next_rx_level;
6068 hdd_ctx->hdd_txrx_hist[index].next_vote_level = next_vote_level;
6069 hdd_ctx->hdd_txrx_hist[index].interval_rx = rx_packets;
6070 hdd_ctx->hdd_txrx_hist[index].interval_tx = tx_packets;
6071 hdd_ctx->hdd_txrx_hist[index].qtime = qdf_get_log_timestamp();
6072 hdd_ctx->hdd_txrx_hist_idx++;
6073 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
6074 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006075}
6076
6077#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306078static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006079{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306080 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
6081 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006082 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306083 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05306084 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
6085 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006086 uint64_t total_tx = 0, total_rx = 0;
6087 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306088 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306089 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006090 bool connected = false;
6091 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
6092
Prashanth Bhattaab004382016-10-11 16:08:11 -07006093 if (wlan_hdd_validate_context(hdd_ctx))
6094 return;
6095
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006096 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306097 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098 status =
6099 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
6100
6101 if (adapterNode->pAdapter == NULL)
6102 continue;
6103 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05306104 /*
6105 * Validate magic so we don't end up accessing
6106 * an invalid adapter.
6107 */
6108 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
6109 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006110
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006111 if ((adapter->device_mode == QDF_STA_MODE ||
6112 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006113 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
6114 != eConnectionState_Associated) {
6115
6116 continue;
6117 }
6118
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006119 if ((adapter->device_mode == QDF_SAP_MODE ||
6120 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006121 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
6122
6123 continue;
6124 }
6125
6126 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
6127 adapter->prev_tx_packets);
6128 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
6129 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306130
6131 if (adapter->device_mode == QDF_SAP_MODE ||
6132 adapter->device_mode == QDF_P2P_GO_MODE ||
6133 adapter->device_mode == QDF_IBSS_MODE) {
6134
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08006135 ret = cdp_get_intra_bss_fwd_pkts_count(
6136 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306137 adapter->sessionId,
6138 &fwd_tx_packets, &fwd_rx_packets);
6139 if (ret == A_OK) {
6140 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
6141 fwd_tx_packets,
6142 adapter->prev_fwd_tx_packets);
6143 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
6144 fwd_tx_packets,
6145 adapter->prev_fwd_rx_packets);
6146 }
6147 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006148
6149 total_rx += adapter->stats.rx_packets;
6150 total_tx += adapter->stats.tx_packets;
6151
6152 spin_lock_bh(&hdd_ctx->bus_bw_lock);
6153 adapter->prev_tx_packets = adapter->stats.tx_packets;
6154 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306155 adapter->prev_fwd_tx_packets = fwd_tx_packets;
6156 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006157 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
6158 connected = true;
6159 }
6160
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306161 /* add intra bss forwarded tx and rx packets */
6162 tx_packets += fwd_tx_packets_diff;
6163 rx_packets += fwd_rx_packets_diff;
6164
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006165 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
6166 tx_packets += (uint64_t)ipa_tx_packets;
6167 rx_packets += (uint64_t)ipa_rx_packets;
6168
6169 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006170 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006171 return;
6172 }
6173
Yuanyuan Liu13738502016-04-06 17:41:37 -07006174 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006175
6176 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
6177 hdd_ipa_uc_stat_request(adapter, 2);
6178
Dustin Brown2ed60362017-01-18 12:25:50 -08006179 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08006180 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08006181 if (hdd_ctx->bus_bw_timer_running)
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05306182 qdf_timer_mod(&hdd_ctx->bus_bw_timer,
Dustin Brownfce08d12017-01-17 16:29:38 -08006183 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08006184 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006185}
Prashanth Bhattaab004382016-10-11 16:08:11 -07006186
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306187/**
6188 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
6189 * @arg: Argument of timer function
6190 *
6191 * Schedule a workqueue in this function where all the processing is done.
6192 *
6193 * Return: None.
6194 */
6195static void __hdd_bus_bw_cbk(void *arg)
6196{
6197 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
6198
6199 if (wlan_hdd_validate_context(hdd_ctx))
6200 return;
6201
6202 schedule_work(&hdd_ctx->bus_bw_work);
6203}
6204
6205/**
6206 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
6207 * @arg: Argument of timer function
6208 *
6209 * Return: None.
6210 */
6211static void hdd_bus_bw_cbk(void *arg)
6212{
6213 cds_ssr_protect(__func__);
6214 __hdd_bus_bw_cbk(arg);
6215 cds_ssr_unprotect(__func__);
6216}
6217
Prashanth Bhattaab004382016-10-11 16:08:11 -07006218int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
6219{
6220 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306221 INIT_WORK(&hdd_ctx->bus_bw_work,
6222 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08006223 hdd_ctx->bus_bw_timer_running = false;
6224 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306225 qdf_timer_init(NULL,
6226 &hdd_ctx->bus_bw_timer,
6227 hdd_bus_bw_cbk, (void *)hdd_ctx,
6228 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006229
6230 return 0;
6231}
6232
6233void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
6234{
Dustin Brownfce08d12017-01-17 16:29:38 -08006235 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07006236 hdd_reset_tcp_delack(hdd_ctx);
6237
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006238 hdd_debug("wait for bus bw work to flush");
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306239 cancel_work_sync(&hdd_ctx->bus_bw_work);
6240 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08006241 hdd_ctx->bus_bw_timer_running = false;
6242 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006243}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006244#endif
6245
6246/**
Nirav Shahed34b212016-04-25 10:59:16 +05306247 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
6248 * @hdd_ctx: hdd context
6249 *
6250 * Return: 0 for success or error code
6251 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006252static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05306253{
6254 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
6255 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
6256 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006257 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05306258 return -ENOMEM;
6259 }
6260 return 0;
6261}
6262
6263/**
6264 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
6265 * @hdd_ctx: hdd context
6266 *
6267 * Return: none
6268 */
6269void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
6270{
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05306271 if (!hdd_ctx || hdd_ctx->hdd_txrx_hist == NULL)
6272 return;
6273
6274 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
6275 hdd_ctx->hdd_txrx_hist = NULL;
Nirav Shahed34b212016-04-25 10:59:16 +05306276}
6277
Nirav Shahda008342016-05-17 18:50:40 +05306278static uint8_t *convert_level_to_string(uint32_t level)
6279{
6280 switch (level) {
6281 /* initialize the wlan sub system */
6282 case WLAN_SVC_TP_NONE:
6283 return "NONE";
6284 case WLAN_SVC_TP_LOW:
6285 return "LOW";
6286 case WLAN_SVC_TP_MEDIUM:
6287 return "MED";
6288 case WLAN_SVC_TP_HIGH:
6289 return "HIGH";
6290 default:
6291 return "INVAL";
6292 }
6293}
6294
Nirav Shahed34b212016-04-25 10:59:16 +05306295
6296/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006297 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
6298 * @hdd_ctx: hdd context
6299 *
6300 * Return: none
6301 */
6302void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
6303{
6304 int i;
6305
6306#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006307 hdd_debug("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05306308 hdd_ctx->config->busBandwidthComputeInterval);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006309 hdd_debug("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006310 hdd_ctx->config->busBandwidthHighThreshold,
6311 hdd_ctx->config->busBandwidthMediumThreshold,
6312 hdd_ctx->config->busBandwidthLowThreshold);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006313 hdd_debug("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306314 hdd_ctx->config->enable_tcp_delack);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006315 hdd_debug("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006316 hdd_ctx->config->tcpDelackThresholdHigh,
6317 hdd_ctx->config->tcpDelackThresholdLow);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006318 hdd_debug("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05306319 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006320#endif
6321
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006322 hdd_debug("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306323 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
6324
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006325 hdd_debug("[index][timestamp]: interval_rx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006326
6327 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006328 /* using hdd_log to avoid printing function name */
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006329 if (hdd_ctx->hdd_txrx_hist[i].qtime > 0)
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006330 hdd_log(QDF_TRACE_LEVEL_ERROR,
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006331 "[%3d][%15llu]: %6llu, %6llu, %s, %s, %s",
6332 i, hdd_ctx->hdd_txrx_hist[i].qtime,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006333 hdd_ctx->hdd_txrx_hist[i].interval_rx,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006334 hdd_ctx->hdd_txrx_hist[i].interval_tx,
6335 convert_level_to_string(
6336 hdd_ctx->hdd_txrx_hist[i].
6337 next_vote_level),
6338 convert_level_to_string(
6339 hdd_ctx->hdd_txrx_hist[i].
6340 next_rx_level),
6341 convert_level_to_string(
6342 hdd_ctx->hdd_txrx_hist[i].
6343 next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006344 }
Mohit Khannac68622e2017-01-31 21:07:12 -08006345
6346 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347}
6348
6349/**
6350 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
6351 * @hdd_ctx: hdd context
6352 *
6353 * Return: none
6354 */
6355void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
6356{
6357 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05306358 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
6359 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006360}
6361
6362/**
Srinivas Girigowdab841da72017-03-25 18:04:39 -07006363 * wlan_hdd_display_netif_queue_history() - display netif queue history
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006364 * @pHddCtx: hdd context
6365 *
6366 * Return: none
6367 */
6368void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
6369{
6370
6371 hdd_adapter_t *adapter = NULL;
6372 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306373 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006374 int i;
Nirav Shahda008342016-05-17 18:50:40 +05306375 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006376
6377 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306378 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006379 adapter = adapter_node->pAdapter;
6380
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006381 hdd_debug("Netif queue operation statistics:");
6382 hdd_debug("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05306383 adapter->sessionId, adapter->device_mode);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006384 hdd_debug("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05306385 curr_time = qdf_system_ticks();
6386 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05306387 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05306388 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05306389 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306390 unpause = adapter->total_unpause_time;
6391 } else {
Nirav Shahda008342016-05-17 18:50:40 +05306392 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306393 pause = adapter->total_pause_time;
6394 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006395 hdd_debug("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05306396 qdf_system_ticks_to_msecs(total),
6397 qdf_system_ticks_to_msecs(pause),
6398 qdf_system_ticks_to_msecs(unpause));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006399 hdd_debug("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006400
Nirav Shahda008342016-05-17 18:50:40 +05306401 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
6402 qdf_time_t pause_delta = 0;
6403
6404 if (adapter->pause_map & (1 << i))
6405 pause_delta = delta;
6406
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006407 /* using hdd_log to avoid printing function name */
6408 hdd_log(QDF_TRACE_LEVEL_ERROR,
6409 "%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006410 hdd_reason_type_to_string(i),
6411 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05306412 adapter->queue_oper_stats[i].unpause_count,
6413 qdf_system_ticks_to_msecs(
6414 adapter->queue_oper_stats[i].total_pause_time +
6415 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006416 }
6417
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006418 hdd_debug("Netif queue operation history:");
6419 hdd_debug("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05306420 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
6421
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006422 hdd_debug("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006423
6424 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006425 /* using hdd_log to avoid printing function name */
6426 if (adapter->queue_oper_history[i].time == 0)
6427 continue;
6428 hdd_log(QDF_TRACE_LEVEL_ERROR,
6429 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05306430 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006431 adapter->queue_oper_history[i].time),
6432 hdd_action_type_to_string(
6433 adapter->queue_oper_history[i].netif_action),
6434 hdd_reason_type_to_string(
6435 adapter->queue_oper_history[i].netif_reason),
6436 adapter->queue_oper_history[i].pause_map);
6437 }
6438
6439 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6440 adapter_node = next;
6441 }
6442
6443
6444}
6445
6446/**
6447 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
6448 * @hdd_ctx: hdd context
6449 *
6450 * Return: none
6451 */
6452void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
6453{
6454 hdd_adapter_t *adapter = NULL;
6455 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306456 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006457
6458 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306459 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006460 adapter = adapter_node->pAdapter;
6461
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306462 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006463 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306464 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006465 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05306466 adapter->history_index = 0;
6467 adapter->start_time = adapter->last_time = qdf_system_ticks();
6468 adapter->total_pause_time = 0;
6469 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006470 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6471 adapter_node = next;
6472 }
6473}
6474
6475/**
6476 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
6477 * @halHandle: Hal handle
6478 * @pContext: Pointer to the context
6479 * @sessionId: Session ID
6480 * @scanId: Scan ID
6481 * @status: Status
6482 *
6483 * This is the callback to be executed when 11d scan is completed to flush out
6484 * the scan results
6485 *
6486 * 11d scan is done during driver load and is a passive scan on all
6487 * channels supported by the device, 11d scans may find some APs on
6488 * frequencies which are forbidden to be used in the regulatory domain
6489 * the device is operating in. If these APs are notified to the supplicant
6490 * it may try to connect to these APs, thus flush out all the scan results
6491 * which are present in SME after 11d scan is done.
6492 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306493 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006494 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306495static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006496 uint8_t sessionId, uint32_t scanId,
6497 eCsrScanStatus status)
6498{
6499 ENTER();
6500
6501 sme_scan_flush_result(halHandle);
6502
6503 EXIT();
6504
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306505 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006506}
6507
6508#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6509/**
6510 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
6511 * @hdd_ctx: hdd global context
6512 *
6513 * Return: none
6514 */
6515static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6516{
6517 uint8_t i;
6518
6519 mutex_init(&hdd_ctx->op_ctx.op_lock);
6520 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6521 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6522 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
6523 }
6524}
6525#else
6526static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6527{
6528}
6529#endif
6530
Yingying Tang95409972016-10-20 15:16:15 +08006531#ifdef WLAN_FEATURE_WOW_PULSE
6532/**
6533 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
6534 * @phddctx: hdd_context_t structure pointer
6535 * @enable: enable or disable this behaviour
6536 *
6537 * Return: int
6538 */
6539static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6540{
6541 struct hdd_config *pcfg_ini = phddctx->config;
6542 struct wow_pulse_mode wow_pulse_set_info;
6543 QDF_STATUS status;
6544
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006545 hdd_debug("wow pulse enable flag is %d", enable);
Yingying Tang95409972016-10-20 15:16:15 +08006546
6547 if (false == phddctx->config->wow_pulse_support)
6548 return 0;
6549
6550 /* prepare the request to send to SME */
6551 if (enable == true) {
6552 wow_pulse_set_info.wow_pulse_enable = true;
6553 wow_pulse_set_info.wow_pulse_pin =
6554 pcfg_ini->wow_pulse_pin;
6555 wow_pulse_set_info.wow_pulse_interval_low =
6556 pcfg_ini->wow_pulse_interval_low;
6557 wow_pulse_set_info.wow_pulse_interval_high =
6558 pcfg_ini->wow_pulse_interval_high;
6559 } else {
6560 wow_pulse_set_info.wow_pulse_enable = false;
6561 wow_pulse_set_info.wow_pulse_pin = 0;
6562 wow_pulse_set_info.wow_pulse_interval_low = 0;
6563 wow_pulse_set_info.wow_pulse_interval_high = 0;
6564 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006565 hdd_debug("enable %d pin %d low %d high %d",
Yingying Tang95409972016-10-20 15:16:15 +08006566 wow_pulse_set_info.wow_pulse_enable,
6567 wow_pulse_set_info.wow_pulse_pin,
6568 wow_pulse_set_info.wow_pulse_interval_low,
6569 wow_pulse_set_info.wow_pulse_interval_high);
6570
6571 status = sme_set_wow_pulse(&wow_pulse_set_info);
6572 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006573 hdd_debug("sme_set_wow_pulse failure!");
Yingying Tang95409972016-10-20 15:16:15 +08006574 return -EIO;
6575 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006576 hdd_debug("sme_set_wow_pulse success!");
Yingying Tang95409972016-10-20 15:16:15 +08006577 return 0;
6578}
6579#else
6580static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6581{
6582 return 0;
6583}
6584#endif
6585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006586#ifdef WLAN_FEATURE_FASTPATH
6587/**
6588 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
6589 * @hdd_cfg: hdd config
6590 * @context: lower layer context
6591 *
6592 * Return: none
6593 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306594void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006595 void *context)
6596{
6597 if (hdd_cfg->fastpath_enable)
6598 hif_enable_fastpath(context);
6599}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006600#endif
6601
Yuanyuan Liu13738502016-04-06 17:41:37 -07006602#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006603/**
6604 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006605 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006606 * @level: thermal level
6607 *
6608 * Change IPA data path to SW path when the thermal throttle level greater
6609 * than 0, and restore the original data path when throttle level is 0
6610 *
6611 * Return: none
6612 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006613static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006614{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006615 hdd_context_t *hdd_ctx = context;
6616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006617 /* Change IPA to SW path when throttle level greater than 0 */
6618 if (level > THROTTLE_LEVEL_0)
6619 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
6620 else
6621 /* restore original concurrency mode */
6622 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
6623}
6624
6625/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306626 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
6627 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05306628 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006629 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306630 * Get a safe channel to restart SAP. PCL already takes into account the
6631 * unsafe channels. So, the PCL is validated with the ACS range to provide
6632 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006633 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306634 * Return: Channel number to restart SAP in case of success. In case of any
6635 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006636 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306637static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
6638 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006639{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306640 struct sir_pcl_list pcl;
6641 QDF_STATUS status;
6642 uint32_t i, j;
6643 tHalHandle *hal_handle;
6644 hdd_context_t *hdd_ctx;
6645 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006646
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306647 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6648 if (!hdd_ctx) {
6649 hdd_err("invalid HDD context");
6650 return INVALID_CHANNEL_ID;
6651 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006652
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306653 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6654 if (!hal_handle) {
6655 hdd_err("invalid HAL handle");
6656 return INVALID_CHANNEL_ID;
6657 }
6658
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006659 status = policy_mgr_get_pcl_for_existing_conn(hdd_ctx->hdd_psoc,
6660 PM_SAP_MODE, pcl.pcl_list, &pcl.pcl_len,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306661 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6662 if (QDF_IS_STATUS_ERROR(status)) {
6663 hdd_err("Get PCL failed");
6664 return INVALID_CHANNEL_ID;
6665 }
6666
6667 if (!pcl.pcl_len) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006668 hdd_err("pcl length is zero. this is not expected");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306669 return INVALID_CHANNEL_ID;
6670 }
6671
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006672 hdd_debug("start:%d end:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306673 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6674 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6675
6676 /* PCL already takes unsafe channel into account */
6677 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006678 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306679 if ((pcl.pcl_list[i] >=
6680 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6681 (pcl.pcl_list[i] <=
6682 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006683 hdd_debug("found PCL safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306684 return pcl.pcl_list[i];
6685 }
6686 }
6687
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006688 hdd_debug("no safe channel from PCL found in ACS range");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306689
6690 /* Try for safe channel from all valid channel */
6691 pcl.pcl_len = MAX_NUM_CHAN;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006692 status = sme_get_cfg_valid_channels(pcl.pcl_list,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306693 &pcl.pcl_len);
6694 if (QDF_IS_STATUS_ERROR(status)) {
6695 hdd_err("error in getting valid channel list");
6696 return INVALID_CHANNEL_ID;
6697 }
6698
6699 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006700 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306701 found = false;
6702 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006703 if (pcl.pcl_list[i] ==
6704 hdd_ctx->unsafe_channel_list[j]) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006705 hdd_debug("unsafe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306706 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006707 break;
6708 }
6709 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306710
6711 if (found)
6712 continue;
6713
6714 if ((pcl.pcl_list[i] >=
6715 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6716 (pcl.pcl_list[i] <=
6717 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006718 hdd_debug("found safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306719 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006720 }
6721 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306722
6723 return INVALID_CHANNEL_ID;
6724}
6725
6726/**
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006727 * hdd_switch_sap_channel() - Move SAP to the given channel
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306728 * @adapter: AP adapter
6729 * @channel: Channel
6730 *
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006731 * Moves the SAP interface by invoking the function which
6732 * executes the callback to perform channel switch using (E)CSA.
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306733 *
6734 * Return: None
6735 */
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006736void hdd_switch_sap_channel(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306737{
6738 hdd_ap_ctx_t *hdd_ap_ctx;
6739 tHalHandle *hal_handle;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006740 hdd_context_t *hdd_ctx;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306741
6742 if (!adapter) {
6743 hdd_err("invalid adapter");
6744 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006745 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306746
6747 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6748
6749 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6750 if (!hal_handle) {
6751 hdd_err("invalid HAL handle");
6752 return;
6753 }
6754
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006755 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6756
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306757 hdd_ap_ctx->sapConfig.channel = channel;
6758 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6759 hdd_ap_ctx->sapConfig.ch_width_orig;
6760
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006761 hdd_debug("chan:%d width:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306762 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6763
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07006764 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
6765 hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306766 hdd_ap_ctx->sapConfig.sec_ch,
6767 &hdd_ap_ctx->sapConfig.ch_params);
6768
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006769 policy_mgr_change_sap_channel_with_csa(hdd_ctx->hdd_psoc,
6770 adapter->sessionId, channel,
6771 hdd_ap_ctx->sapConfig.ch_width_orig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006772}
Kapil Gupta8878ad92017-02-13 11:56:04 +05306773
6774int hdd_update_acs_timer_reason(hdd_adapter_t *adapter, uint8_t reason)
6775{
6776 struct hdd_external_acs_timer_context *timer_context;
6777
6778 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6779
6780 if (QDF_TIMER_STATE_RUNNING ==
6781 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
6782 ap.vendor_acs_timer)) {
6783 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
6784 }
6785 timer_context = (struct hdd_external_acs_timer_context *)
6786 adapter->sessionCtx.ap.vendor_acs_timer.user_data;
6787 timer_context->reason = reason;
6788 qdf_mc_timer_start(&adapter->sessionCtx.ap.vendor_acs_timer,
6789 WLAN_VENDOR_ACS_WAIT_TIME);
6790 /* Update config to application */
6791 hdd_cfg80211_update_acs_config(adapter, reason);
6792 hdd_notice("Updated ACS config to nl with reason %d", reason);
6793
6794 return 0;
6795}
6796
Agrawal Ashish467dde42016-09-08 18:44:22 +05306797/**
6798 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6799 * @hdd_ctx: hdd context pointer
6800 *
6801 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6802 * and if ACS is enabled, driver will ask userspace to restart the
6803 * sap. User space on LTE coex indication restart driver.
6804 *
6805 * Return - none
6806 */
6807void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6808{
6809 QDF_STATUS status;
6810 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6811 hdd_adapter_t *adapter_temp;
6812 uint32_t i;
6813 bool found = false;
6814 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006815
Agrawal Ashish467dde42016-09-08 18:44:22 +05306816 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6817 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6818 adapter_temp = adapter_node->pAdapter;
6819
6820 if (!adapter_temp) {
6821 hdd_err("adapter is NULL, moving to next one");
6822 goto next_adapater;
6823 }
6824
6825 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6826 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006827 hdd_debug("skip device mode:%d acs:%d",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306828 adapter_temp->device_mode,
6829 adapter_temp->sessionCtx.ap.sapConfig.
6830 acs_cfg.acs_mode);
6831 goto next_adapater;
6832 }
6833
6834 found = false;
6835 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006836 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306837 hdd_ctxt->unsafe_channel_list[i]) {
6838 found = true;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006839 hdd_debug("operating ch:%d is unsafe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306840 adapter_temp->sessionCtx.ap.operatingChannel);
6841 break;
6842 }
6843 }
6844
6845 if (!found) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006846 hdd_debug("ch:%d is safe. no need to change channel",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306847 adapter_temp->sessionCtx.ap.operatingChannel);
6848 goto next_adapater;
6849 }
6850
Kapil Gupta8878ad92017-02-13 11:56:04 +05306851 if (hdd_ctxt->config->vendor_acs_support &&
6852 hdd_ctxt->config->acs_support_for_dfs_ltecoex) {
6853 hdd_update_acs_timer_reason(adapter_temp,
6854 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
6855 goto next_adapater;
6856 } else
6857 restart_chan =
6858 hdd_get_safe_channel_from_pcl_and_acs_range(
Agrawal Ashish467dde42016-09-08 18:44:22 +05306859 adapter_temp);
6860 if (!restart_chan) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006861 hdd_err("fail to restart SAP");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306862 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006863 /*
6864 * SAP restart due to unsafe channel. While
6865 * restarting the SAP, make sure to clear
6866 * acs_channel, channel to reset to
6867 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306868 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006869 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306870 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6871 adapter_temp->sessionCtx.ap.sapConfig.channel =
6872 AUTO_CHANNEL_SELECT;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006873 hdd_debug("sending coex indication");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306874 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6875 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006876 hdd_switch_sap_channel(adapter_temp, restart_chan);
Agrawal Ashish467dde42016-09-08 18:44:22 +05306877 }
6878
6879next_adapater:
6880 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6881 adapter_node = next;
6882 }
6883}
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05306884
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006885/**
6886 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6887 * @adapter: HDD adapter pointer
6888 * @indParam: Channel avoid notification parameter
6889 *
6890 * Avoid channel notification from FW handler.
6891 * FW will send un-safe channel list to avoid over wrapping.
6892 * hostapd should not use notified channel
6893 *
6894 * Return: None
6895 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306896void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006897{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006898 hdd_context_t *hdd_ctxt;
6899 tSirChAvoidIndType *ch_avoid_indi;
6900 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006901 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6902 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006903 uint16_t start_channel;
6904 uint16_t end_channel;
6905 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006906 tHddAvoidFreqList hdd_avoid_freq_list;
6907 uint32_t i;
6908
6909 /* Basic sanity */
6910 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006911 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006912 return;
6913 }
6914
6915 hdd_ctxt = (hdd_context_t *) hdd_context;
6916 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6917 cds_context = hdd_ctxt->pcds_context;
6918
6919 /* Make unsafe channel list */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006920 hdd_debug("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006921 ch_avoid_indi->avoid_range_count);
6922
6923 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306924 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006925 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6926 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6927 ch_avoid_indi->avoid_freq_range[i].start_freq;
6928 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6929 ch_avoid_indi->avoid_freq_range[i].end_freq;
6930 }
6931 hdd_avoid_freq_list.avoidFreqRangeCount =
6932 ch_avoid_indi->avoid_range_count;
6933
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05306934 mutex_lock(&hdd_ctxt->avoid_freq_lock);
6935 hdd_ctxt->coex_avoid_freq_list = hdd_avoid_freq_list;
6936 mutex_unlock(&hdd_ctxt->avoid_freq_lock);
6937
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006938 /* clear existing unsafe channel cache */
6939 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306940 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006941 sizeof(hdd_ctxt->unsafe_channel_list));
6942
6943 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6944 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006945 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006946 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006947 break;
6948 }
6949
6950 start_channel = ieee80211_frequency_to_channel(
6951 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6952 end_channel = ieee80211_frequency_to_channel(
6953 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006954 hdd_debug("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006955 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6956 start_channel,
6957 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6958 end_channel);
6959
6960 /* do not process frequency bands that are not mapped to
6961 * predefined channels
6962 */
6963 if (start_channel == 0 || end_channel == 0)
6964 continue;
6965
Amar Singhalb8d4f152016-02-10 10:21:43 -08006966 for (channel_loop = CHAN_ENUM_1; channel_loop <=
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07006967 CHAN_ENUM_184; channel_loop++) {
6968 if (WLAN_REG_CH_TO_FREQ(channel_loop) >=
6969 ch_avoid_indi->avoid_freq_range[
6970 range_loop].start_freq) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006971 start_channel_idx = channel_loop;
6972 break;
6973 }
6974 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006975 for (channel_loop = CHAN_ENUM_1; channel_loop <=
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07006976 CHAN_ENUM_184; channel_loop++) {
6977 if (WLAN_REG_CH_TO_FREQ(channel_loop) >=
6978 ch_avoid_indi->avoid_freq_range[
6979 range_loop].end_freq) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006980 end_channel_idx = channel_loop;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07006981 if (WLAN_REG_CH_TO_FREQ(channel_loop) >
6982 ch_avoid_indi->avoid_freq_range[
6983 range_loop].end_freq)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006984 end_channel_idx--;
6985 break;
6986 }
6987 }
6988
Amar Singhalb8d4f152016-02-10 10:21:43 -08006989 if (start_channel_idx == INVALID_CHANNEL ||
6990 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006991 continue;
6992
6993 for (channel_loop = start_channel_idx; channel_loop <=
6994 end_channel_idx; channel_loop++) {
6995 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006996 hdd_ctxt->unsafe_channel_count++] =
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07006997 WLAN_REG_CH_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006998 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006999 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007000 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007001 break;
7002 }
7003 }
7004 }
7005
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007006 hdd_debug("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007007 hdd_ctxt->unsafe_channel_count);
7008
Yuanyuan Liu13738502016-04-06 17:41:37 -07007009 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
7010 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007011 hdd_ctxt->unsafe_channel_count)) {
7012 hdd_err("Failed to set unsafe channel");
7013
7014 /* clear existing unsafe channel cache */
7015 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307016 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007017 sizeof(hdd_ctxt->unsafe_channel_list));
7018
7019 return;
7020 }
7021
7022 for (channel_loop = 0;
7023 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007024 hdd_debug("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007025 hdd_ctxt->unsafe_channel_list[channel_loop]);
7026 }
7027
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05307028 mutex_lock(&hdd_ctxt->avoid_freq_lock);
7029 if (hdd_ctxt->dnbs_avoid_freq_list.avoidFreqRangeCount)
7030 if (wlan_hdd_merge_avoid_freqs(&hdd_avoid_freq_list,
7031 &hdd_ctxt->dnbs_avoid_freq_list)) {
7032 mutex_unlock(&hdd_ctxt->avoid_freq_lock);
7033 hdd_debug("unable to merge avoid freqs");
7034 return;
7035 }
7036 mutex_unlock(&hdd_ctxt->avoid_freq_lock);
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05307037 /*
7038 * first update the unsafe channel list to the platform driver and
7039 * send the avoid freq event to the application
7040 */
7041 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
7042
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05307043 if (!hdd_ctxt->unsafe_channel_count) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007044 hdd_debug("no unsafe channels - not restarting SAP");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05307045 return;
7046 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05307047 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007048}
7049
7050/**
7051 * hdd_init_channel_avoidance() - Initialize channel avoidance
7052 * @hdd_ctx: HDD global context
7053 *
7054 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07007055 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007056 * down to the lower layers. Then subscribe to subsequent channel
7057 * avoidance events.
7058 *
7059 * Return: None
7060 */
7061static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
7062{
7063 uint16_t unsafe_channel_count;
7064 int index;
7065
Yuanyuan Liu13738502016-04-06 17:41:37 -07007066 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
7067 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007068 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08007069 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007070
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007071 hdd_debug("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007072 hdd_ctx->unsafe_channel_count);
7073
Anurag Chouhan6d760662016-02-20 16:05:43 +05307074 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08007075 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007076
7077 for (index = 0; index < unsafe_channel_count; index++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007078 hdd_debug("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007079 hdd_ctx->unsafe_channel_list[index]);
7080
7081 }
7082
7083 /* Plug in avoid channel notification callback */
7084 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
7085}
7086#else
7087static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
7088{
7089}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007090static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007091{
7092}
Yuanyuan Liu13738502016-04-06 17:41:37 -07007093#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007094
7095/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08007096 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
7097 * user space
7098 * @frame_ind: Management frame data to be informed.
7099 *
7100 * This function is used to indicate management frame to
7101 * user space
7102 *
7103 * Return: None
7104 *
7105 */
7106void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
7107{
7108 hdd_context_t *hdd_ctx = NULL;
7109 hdd_adapter_t *adapter = NULL;
7110 void *cds_context = NULL;
7111 int i;
7112
7113 /* Get the global VOSS context.*/
7114 cds_context = cds_get_global_context();
7115 if (!cds_context) {
7116 hdd_err("Global CDS context is Null");
7117 return;
7118 }
7119 /* Get the HDD context.*/
7120 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
7121
7122 if (0 != wlan_hdd_validate_context(hdd_ctx))
7123 return;
7124
7125 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
7126 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
7127 adapter =
7128 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
7129 if (adapter)
7130 break;
7131 }
7132 } else {
7133 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
7134 frame_ind->sessionId);
7135 }
7136
7137 if ((NULL != adapter) &&
7138 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
7139 __hdd_indicate_mgmt_frame(adapter,
7140 frame_ind->frame_len,
7141 frame_ind->frameBuf,
7142 frame_ind->frameType,
7143 frame_ind->rxChan,
7144 frame_ind->rxRssi);
Rajeev Kumard004abc2016-02-17 12:09:56 -08007145}
7146
Kapil Gupta8878ad92017-02-13 11:56:04 +05307147static void hdd_lte_coex_restart_sap(hdd_adapter_t *adapter,
7148 hdd_context_t *hdd_ctx)
7149{
7150 uint8_t restart_chan = 0;
7151
7152 restart_chan =
7153 hdd_get_safe_channel_from_pcl_and_acs_range(adapter);
7154 if (!restart_chan) {
7155 hdd_alert("fail to restart SAP");
7156 } else {
7157 /* SAP restart due to unsafe channel. While restarting
7158 * the SAP, make sure to clear acs_channel, channel to
7159 * reset to 0. Otherwise these settings will override
7160 * the ACS while restart.
7161 */
7162 hdd_ctx->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
7163 adapter->sessionCtx.ap.sapConfig.channel =
7164 AUTO_CHANNEL_SELECT;
7165 hdd_info("sending coex indication");
7166 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
7167 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08007168 hdd_switch_sap_channel(adapter, restart_chan);
Kapil Gupta8878ad92017-02-13 11:56:04 +05307169 }
7170}
7171
7172void hdd_acs_response_timeout_handler(void *context)
7173{
7174 struct hdd_external_acs_timer_context *timer_context =
7175 (struct hdd_external_acs_timer_context *)context;
7176 hdd_adapter_t *adapter;
7177 hdd_context_t *hdd_ctx;
7178 uint8_t reason;
7179
7180 ENTER();
7181 if (!timer_context) {
7182 hdd_err("invlaid timer context");
7183 return;
7184 }
7185 adapter = timer_context->adapter;
7186 reason = timer_context->reason;
7187
7188
7189 if ((!adapter) ||
7190 (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
7191 hdd_err("invalid adapter or adapter has invalid magic");
7192 return;
7193 }
7194 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7195 if (wlan_hdd_validate_context(hdd_ctx))
7196 return;
7197
7198 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
7199 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
7200 else
7201 return;
7202
7203 hdd_err("ACS timeout happened for %s reason %d",
7204 adapter->dev->name, reason);
7205 switch (reason) {
7206 /* SAP init case */
7207 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
7208 wlan_sap_set_vendor_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7209 false);
7210 wlan_hdd_cfg80211_start_acs(adapter);
7211 break;
7212 /* DFS detected on current channel */
7213 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
7214 wlan_sap_update_next_channel(
7215 WLAN_HDD_GET_SAP_CTX_PTR(adapter), 0, 0);
7216 sme_update_new_channel_event(WLAN_HDD_GET_HAL_CTX(adapter),
7217 adapter->sessionId);
7218 break;
7219 /* LTE coex event on current channel */
7220 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
7221 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
7222 break;
7223 default:
7224 hdd_info("invalid reason for timer invoke");
7225
7226 }
7227}
7228
Rajeev Kumard004abc2016-02-17 12:09:56 -08007229/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007230 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
7231 * @hdd_ctx: HDD context
7232 *
7233 * Disables all the dual mac features like DBS, Agile DFS etc.
7234 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307235 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007236 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307237static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007238{
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007239 struct policy_mgr_dual_mac_config cfg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307240 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007241
7242 if (!hdd_ctx) {
7243 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307244 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007245 }
7246
7247 cfg.scan_config = 0;
7248 cfg.fw_mode_config = 0;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007249 cfg.set_dual_mac_cb = policy_mgr_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007250
7251 hdd_debug("Disabling all dual mac features...");
7252
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007253 status = sme_soc_set_dual_mac_config(cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307254 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007255 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
7256 return status;
7257 }
7258
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307259 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007260}
7261
7262/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007263 * hdd_override_ini_config - Override INI config
7264 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007265 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007266 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007267 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007268 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007269 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007270static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007271{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007272
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007273 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
7274 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007275 hdd_debug("Module enable_dfs_chan_scan set to %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007276 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007277 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007278 if (0 == enable_11d || 1 == enable_11d) {
7279 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007280 hdd_debug("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007281 }
Leo Chang11545d62016-10-17 14:53:50 -07007282
7283 if (!hdd_ipa_is_present(hdd_ctx))
7284 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007285}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007286
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007287/**
7288 * hdd_set_trace_level_for_each - Set trace level for each INI config
7289 * @hdd_ctx - HDD context
7290 *
7291 * Set trace level for each module based on INI config.
7292 *
7293 * Return: None
7294 */
7295static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
7296{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307297 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
7298 hdd_ctx->config->qdf_trace_enable_wdi);
7299 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
7300 hdd_ctx->config->qdf_trace_enable_hdd);
7301 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
7302 hdd_ctx->config->qdf_trace_enable_sme);
7303 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
7304 hdd_ctx->config->qdf_trace_enable_pe);
7305 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
7306 hdd_ctx->config->qdf_trace_enable_wma);
7307 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
7308 hdd_ctx->config->qdf_trace_enable_sys);
7309 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
7310 hdd_ctx->config->qdf_trace_enable_qdf);
7311 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
7312 hdd_ctx->config->qdf_trace_enable_sap);
7313 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
7314 hdd_ctx->config->qdf_trace_enable_hdd_sap);
7315 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
7316 hdd_ctx->config->qdf_trace_enable_bmi);
7317 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
7318 hdd_ctx->config->qdf_trace_enable_cfg);
7319 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
7320 hdd_ctx->config->qdf_trace_enable_epping);
7321 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
7322 hdd_ctx->config->qdf_trace_enable_qdf_devices);
7323 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05307324 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307325 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
7326 hdd_ctx->config->qdf_trace_enable_htc);
7327 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
7328 hdd_ctx->config->qdf_trace_enable_hif);
7329 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
7330 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
7331 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
7332 hdd_ctx->config->qdf_trace_enable_hdd_data);
Naveen Rawat7df31862017-03-01 17:09:30 -08007333 hdd_qdf_trace_enable(QDF_MODULE_ID_WIFIPOS,
7334 hdd_ctx->config->qdf_trace_enable_wifi_pos);
Naveen Rawatf2b0dbd2017-03-27 10:00:15 -07007335 hdd_qdf_trace_enable(QDF_MODULE_ID_NAN,
7336 hdd_ctx->config->qdf_trace_enable_nan);
Kiran Kumar Lokere798de7e2017-03-30 14:01:12 -07007337 hdd_qdf_trace_enable(QDF_MODULE_ID_REGULATORY,
7338 hdd_ctx->config->qdf_trace_enable_regulatory);
7339
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007340 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007341}
7342
7343/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007344 * hdd_context_init() - Initialize HDD context
7345 * @hdd_ctx: HDD context.
7346 *
7347 * Initialize HDD context along with all the feature specific contexts.
7348 *
7349 * return: 0 on success and errno on failure.
7350 */
7351static int hdd_context_init(hdd_context_t *hdd_ctx)
7352{
7353 int ret;
7354
7355 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
7356 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
7357
7358 hdd_init_ll_stats_ctx();
7359
7360 init_completion(&hdd_ctx->mc_sus_event_var);
7361 init_completion(&hdd_ctx->ready_to_suspend);
7362
7363 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307364 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007365 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307366
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007367 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
7368
7369 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
7370
7371 ret = hdd_scan_context_init(hdd_ctx);
7372 if (ret)
7373 goto list_destroy;
7374
Nitesh Shahd1266d72017-01-25 22:07:07 +05307375 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007376
7377 hdd_rx_wake_lock_create(hdd_ctx);
7378
7379 ret = hdd_sap_context_init(hdd_ctx);
7380 if (ret)
7381 goto scan_destroy;
7382
7383 ret = hdd_roc_context_init(hdd_ctx);
7384 if (ret)
7385 goto sap_destroy;
7386
7387 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
7388
7389 hdd_init_offloaded_packets_ctx(hdd_ctx);
7390
7391 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
7392 hdd_ctx->config);
7393 if (ret)
7394 goto roc_destroy;
7395
7396 return 0;
7397
7398roc_destroy:
7399 hdd_roc_context_destroy(hdd_ctx);
7400
7401sap_destroy:
7402 hdd_sap_context_destroy(hdd_ctx);
7403
7404scan_destroy:
7405 hdd_scan_context_destroy(hdd_ctx);
7406 hdd_rx_wake_lock_destroy(hdd_ctx);
7407 hdd_tdls_context_destroy(hdd_ctx);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007408list_destroy:
7409 qdf_list_destroy(&hdd_ctx->hddAdapters);
Sandeep Puligillad0004212017-02-26 18:34:56 -08007410
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007411 return ret;
7412}
7413
7414/**
7415 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05307416 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007417 *
7418 * Allocate and initialize HDD context. HDD context is allocated as part of
7419 * wiphy allocation and then context is initialized.
7420 *
7421 * Return: HDD context on success and ERR_PTR on failure
7422 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007423static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007424{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307425 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007426 int ret = 0;
7427 hdd_context_t *hdd_ctx;
7428 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307429 int qdf_print_idx = -1;
7430
7431 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
7432 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
7433 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
7434 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
7435 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
7436 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
7437 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
7438 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
7439 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
7440 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
7441 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
7442 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
7443 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7444 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7445 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
7446 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
7447 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
7448 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
7449 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
7450 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
7451 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiyaf928edf2017-02-06 14:43:24 +05307452 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
7453 [QDF_MODULE_ID_DP] = {QDF_TRACE_LEVEL_ALL},
7454 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
7455 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
7456 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
7457 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
Mukul Sharma4d7d6b02017-02-13 20:45:22 +05307458 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
Abhishek Singh9679dbf2017-02-15 11:35:41 +05307459 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
Tushnim Bhattacharyya6796d8d2017-03-17 11:06:03 -07007460 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL},
7461 [QDF_MODULE_ID_POLICY_MGR] = {QDF_TRACE_LEVEL_ALL},
Wu Gao9a704f42017-03-10 18:42:11 +08007462 [QDF_MODULE_ID_P2P] = {QDF_TRACE_LEVEL_ALL},
Frank Liud4b2fa02017-03-29 11:46:48 +08007463 [QDF_MODULE_ID_TDLS] = {QDF_TRACE_LEVEL_ALL},
Kiran Kumar Lokere798de7e2017-03-30 14:01:12 -07007464 [QDF_MODULE_ID_REGULATORY] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307465 };
7466
7467 status = qdf_print_setup();
7468 if (status != QDF_STATUS_SUCCESS) {
7469 pr_err("QDF print control object setup failed\n");
7470 ret = -EINVAL;
7471 goto err_out;
7472 }
7473 /* Register the module here with QDF */
7474 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
7475 "MCL_WLAN");
7476
7477 /* if qdf_print_idx is negative */
7478 if (qdf_print_idx < 0) {
7479 pr_err("QDF print control can not be registered %d\n",
7480 qdf_print_idx);
7481 ret = -EINVAL;
7482 goto err_out;
7483 }
7484
7485 /* Store the qdf_pidx information into qdf module */
7486 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007487
7488 ENTER();
7489
7490 p_cds_context = cds_get_global_context();
7491 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007492 hdd_err("Failed to get CDS global context");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007493 ret = -EINVAL;
7494 goto err_out;
7495 }
7496
7497 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
7498
7499 if (hdd_ctx == NULL) {
7500 ret = -ENOMEM;
7501 goto err_out;
7502 }
7503
7504 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007505 hdd_ctx->parent_dev = dev;
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05307506 hdd_ctx->last_scan_reject_session_id = 0xFF;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007507
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307508 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007509 if (hdd_ctx->config == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007510 hdd_err("Failed to alloc memory for HDD config!");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007511 ret = -ENOMEM;
7512 goto err_free_hdd_context;
7513 }
7514
7515 /* Read and parse the qcom_cfg.ini file */
7516 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307517 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307518 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007519 WLAN_INI_FILE);
7520 ret = -EINVAL;
7521 goto err_free_config;
7522 }
7523
Dustin Brown7f939932017-05-18 15:02:17 -07007524 hdd_debug("setting timer multiplier: %u",
7525 hdd_ctx->config->timer_multiplier);
7526 qdf_timer_set_multiplier(hdd_ctx->config->timer_multiplier);
7527
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007528 hdd_debug("Setting configuredMcastBcastFilter: %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007529 hdd_ctx->config->mcastBcastFilterSetting);
7530
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307531 if (hdd_ctx->config->fhostNSOffload)
7532 hdd_ctx->ns_offload_enable = true;
7533
Abhishek Singh5ea86532016-04-27 14:10:53 +05307534 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
7535
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007536 hdd_override_ini_config(hdd_ctx);
7537
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007538 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007539
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007540 ret = hdd_context_init(hdd_ctx);
7541
7542 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007543 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007544
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007545
Nachiket Kukade8003d252017-03-30 15:55:58 +05307546 ret = pld_set_fw_log_mode(hdd_ctx->parent_dev,
7547 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007548
Nachiket Kukade8003d252017-03-30 15:55:58 +05307549 if (ret && cds_is_fw_down())
7550 goto err_deinit_hdd_context;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007551
7552 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05307553 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007554
Anurag Chouhan6d760662016-02-20 16:05:43 +05307555 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007556 goto skip_multicast_logging;
7557
7558 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
7559
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007560 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
7561 if (ret)
7562 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05307563
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007564 ret = hdd_logging_sock_activate_svc(hdd_ctx);
7565 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05307566 goto err_free_histogram;
7567
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007568skip_multicast_logging:
7569 hdd_set_trace_level_for_each(hdd_ctx);
7570
7571 return hdd_ctx;
7572
Nirav Shahed34b212016-04-25 10:59:16 +05307573err_free_histogram:
7574 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
7575
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007576err_deinit_hdd_context:
7577 hdd_context_deinit(hdd_ctx);
7578
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007579err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307580 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007581
7582err_free_hdd_context:
7583 wiphy_free(hdd_ctx->wiphy);
7584
7585err_out:
7586 return ERR_PTR(ret);
7587}
7588
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007589#ifdef WLAN_OPEN_P2P_INTERFACE
7590/**
7591 * hdd_open_p2p_interface - Open P2P interface
7592 * @hdd_ctx: HDD context
7593 * @rtnl_held: True if RTNL lock held
7594 *
7595 * Open P2P interface during probe. This function called to open the P2P
7596 * interface at probe along with STA interface.
7597 *
7598 * Return: 0 on success and errno on failure
7599 */
7600static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7601{
7602 hdd_adapter_t *adapter;
7603 uint8_t *p2p_dev_addr;
7604
7605 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
7606 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307607 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007608 hdd_ctx->config->intfMacAddr[0].bytes,
7609 sizeof(tSirMacAddr));
7610
7611 /*
7612 * Generate the P2P Device Address. This consists of
7613 * the device's primary MAC address with the locally
7614 * administered bit set.
7615 */
7616 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
7617 } else {
7618 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7619 if (p2p_dev_addr == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007620 hdd_err("Failed to allocate mac_address for p2p_device");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007621 return -ENOSPC;
7622 }
7623
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307624 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307625 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007626 }
7627
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007628 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007629 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08007630 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007631
7632 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007633 hdd_err("Failed to do hdd_open_adapter for P2P Device Interface");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007634 return -ENOSPC;
7635 }
7636
7637 return 0;
7638}
7639#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05307640static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007641 bool rtnl_held)
7642{
7643 return 0;
7644}
7645#endif
7646
Jeff Johnson957bc272017-02-02 08:54:48 -08007647static int hdd_open_ocb_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7648{
7649 hdd_adapter_t *adapter;
7650 int ret = 0;
7651
7652 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
7653 wlan_hdd_get_intf_addr(hdd_ctx),
7654 NET_NAME_UNKNOWN, rtnl_held);
7655 if (adapter == NULL) {
7656 hdd_err("Failed to open 802.11p interface");
7657 ret = -ENOSPC;
7658 }
7659
7660 return ret;
7661}
7662
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007663/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307664 * hdd_start_station_adapter()- Start the Station Adapter
7665 * @adapter: HDD adapter
7666 *
7667 * This function initializes the adapter for the station mode.
7668 *
7669 * Return: 0 on success or errno on failure.
7670 */
7671int hdd_start_station_adapter(hdd_adapter_t *adapter)
7672{
7673 QDF_STATUS status;
7674
7675 ENTER_DEV(adapter->dev);
7676
7677 status = hdd_init_station_mode(adapter);
7678
7679 if (QDF_STATUS_SUCCESS != status) {
7680 hdd_err("Error Initializing station mode: %d", status);
7681 return qdf_status_to_os_return(status);
7682 }
7683
Arun Khandavallifae92942016-08-01 13:31:08 +05307684 hdd_register_tx_flow_control(adapter,
7685 hdd_tx_resume_timer_expired_handler,
7686 hdd_tx_resume_cb);
7687
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307688 EXIT();
7689 return 0;
7690}
7691
7692/**
7693 * hdd_start_ap_adapter()- Start AP Adapter
7694 * @adapter: HDD adapter
7695 *
7696 * This function initializes the adapter for the AP mode.
7697 *
7698 * Return: 0 on success errno on failure.
7699 */
7700int hdd_start_ap_adapter(hdd_adapter_t *adapter)
7701{
7702 QDF_STATUS status;
7703
7704 ENTER();
7705
Arun Khandavallicc544b32017-01-30 19:52:16 +05307706 status = hdd_init_ap_mode(adapter, false);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307707
7708 if (QDF_STATUS_SUCCESS != status) {
7709 hdd_err("Error Initializing the AP mode: %d", status);
7710 return qdf_status_to_os_return(status);
7711 }
7712
Arun Khandavallifae92942016-08-01 13:31:08 +05307713 hdd_register_tx_flow_control(adapter,
7714 hdd_softap_tx_resume_timer_expired_handler,
7715 hdd_softap_tx_resume_cb);
7716
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307717 EXIT();
7718 return 0;
7719}
7720
7721/**
7722 * hdd_start_ftm_adapter()- Start FTM adapter
7723 * @adapter: HDD adapter
7724 *
7725 * This function initializes the adapter for the FTM mode.
7726 *
7727 * Return: 0 on success or errno on failure.
7728 */
7729int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
7730{
7731 QDF_STATUS qdf_status;
7732
7733 ENTER_DEV(adapter->dev);
7734
7735 qdf_status = hdd_init_tx_rx(adapter);
7736
7737 if (QDF_STATUS_SUCCESS != qdf_status) {
7738 hdd_err("Failed to start FTM adapter: %d", qdf_status);
7739 return qdf_status_to_os_return(qdf_status);
7740 }
7741
7742 return 0;
7743 EXIT();
7744}
7745
7746/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007747 * hdd_open_interfaces - Open all required interfaces
7748 * hdd_ctx: HDD context
7749 * rtnl_held: True if RTNL lock is held
7750 *
7751 * Open all the interfaces like STA, P2P and OCB based on the configuration.
7752 *
Jeff Johnson957bc272017-02-02 08:54:48 -08007753 * Return: 0 if all interfaces were created, otherwise negative errno
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007754 */
Jeff Johnson957bc272017-02-02 08:54:48 -08007755static int hdd_open_interfaces(hdd_context_t *hdd_ctx, bool rtnl_held)
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007756{
Jeff Johnson957bc272017-02-02 08:54:48 -08007757 hdd_adapter_t *adapter;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007758 int ret;
7759
Jeff Johnson957bc272017-02-02 08:54:48 -08007760 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
Arun Khandavallifae92942016-08-01 13:31:08 +05307761 /* Create only 802.11p interface */
Jeff Johnson957bc272017-02-02 08:54:48 -08007762 return hdd_open_ocb_interface(hdd_ctx, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007763
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007764 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007765 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08007766 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007767
7768 if (adapter == NULL)
Jeff Johnson957bc272017-02-02 08:54:48 -08007769 return -ENOSPC;
7770
Deepak Dhamdherea2785822016-11-17 01:17:45 -08007771 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
7772 adapter->fast_roaming_allowed = true;
7773
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007774 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
7775 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08007776 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007777
7778 /* Open 802.11p Interface */
7779 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Jeff Johnson957bc272017-02-02 08:54:48 -08007780 ret = hdd_open_ocb_interface(hdd_ctx, rtnl_held);
7781 if (ret)
7782 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007783 }
7784
Jeff Johnson957bc272017-02-02 08:54:48 -08007785 return 0;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007786
Jeff Johnson957bc272017-02-02 08:54:48 -08007787err_close_adapters:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007788 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Jeff Johnson957bc272017-02-02 08:54:48 -08007789 return ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007790}
7791
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007792/**
7793 * hdd_update_country_code - Update country code
7794 * @hdd_ctx: HDD context
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007795 *
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07007796 * Update country code based on module parameter country_code
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007797 *
7798 * Return: 0 on success and errno on failure
7799 */
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07007800static int hdd_update_country_code(hdd_context_t *hdd_ctx)
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007801{
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07007802 if (!country_code)
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007803 return 0;
7804
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07007805 return hdd_reg_set_country(hdd_ctx, country_code);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007806}
7807
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307808#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7809/**
7810 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7811 * @cds_cfg: CDS Configuration
7812 * @hdd_ctx: Pointer to hdd context
7813 *
7814 * Return: none
7815 */
7816static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7817 *cds_cfg,
7818 hdd_context_t *hdd_ctx)
7819{
7820 cds_cfg->tx_flow_stop_queue_th =
7821 hdd_ctx->config->TxFlowStopQueueThreshold;
7822 cds_cfg->tx_flow_start_queue_offset =
7823 hdd_ctx->config->TxFlowStartQueueOffset;
7824}
7825#else
7826static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7827 *cds_cfg,
7828 hdd_context_t *hdd_ctx)
7829{
7830}
7831#endif
7832
7833#ifdef FEATURE_WLAN_RA_FILTERING
7834/**
7835 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7836 * @cds_cfg: CDS Configuration
7837 * @hdd_ctx: Pointer to hdd context
7838 *
7839 * Return: none
7840 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307841static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307842 hdd_context_t *hdd_ctx)
7843{
7844 cds_cfg->ra_ratelimit_interval =
7845 hdd_ctx->config->RArateLimitInterval;
7846 cds_cfg->is_ra_ratelimit_enabled =
7847 hdd_ctx->config->IsRArateLimitEnabled;
7848}
7849#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307850static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307851 hdd_context_t *hdd_ctx)
7852{
7853}
7854#endif
7855
7856/**
7857 * hdd_update_cds_config() - API to update cds configuration parameters
7858 * @hdd_ctx: HDD Context
7859 *
7860 * Return: 0 for Success, errno on failure
7861 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007862static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307863{
7864 struct cds_config_info *cds_cfg;
7865
7866 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7867 if (!cds_cfg) {
7868 hdd_err("failed to allocate cds config");
7869 return -ENOMEM;
7870 }
7871
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307872 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08007873 if (!hdd_ctx->config->nMaxPsPoll ||
7874 !hdd_ctx->config->enablePowersaveOffload) {
7875 cds_cfg->powersave_offload_enabled =
7876 hdd_ctx->config->enablePowersaveOffload;
7877 } else {
7878 if ((hdd_ctx->config->enablePowersaveOffload ==
7879 PS_QPOWER_NODEEPSLEEP) ||
7880 (hdd_ctx->config->enablePowersaveOffload ==
7881 PS_LEGACY_NODEEPSLEEP))
7882 cds_cfg->powersave_offload_enabled =
7883 PS_LEGACY_NODEEPSLEEP;
7884 else
7885 cds_cfg->powersave_offload_enabled =
7886 PS_LEGACY_DEEPSLEEP;
7887 hdd_info("Qpower disabled in cds config, %d",
7888 cds_cfg->powersave_offload_enabled);
7889 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307890 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7891 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7892 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7893 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7894 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7895
7896 /* Here ol_ini_info is used to store ini status of arp offload
7897 * ns offload and others. Currently 1st bit is used for arp
7898 * off load and 2nd bit for ns offload currently, rest bits are unused
7899 */
7900 if (hdd_ctx->config->fhostArpOffload)
7901 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7902 if (hdd_ctx->config->fhostNSOffload)
7903 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7904
7905 /*
7906 * Copy the DFS Phyerr Filtering Offload status.
7907 * This parameter reflects the value of the
7908 * dfs_phyerr_filter_offload flag as set in the ini.
7909 */
7910 cds_cfg->dfs_phyerr_filter_offload =
7911 hdd_ctx->config->fDfsPhyerrFilterOffload;
7912 if (hdd_ctx->config->ssdp)
7913 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7914
7915 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7916 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7917
7918 cds_cfg->ap_maxoffload_reorderbuffs =
7919 hdd_ctx->config->apMaxOffloadReorderBuffs;
7920
7921 cds_cfg->ap_disable_intrabss_fwd =
7922 hdd_ctx->config->apDisableIntraBssFwd;
7923
7924 cds_cfg->dfs_pri_multiplier =
7925 hdd_ctx->config->dfsRadarPriMultiplier;
7926 cds_cfg->reorder_offload =
7927 hdd_ctx->config->reorderOffloadSupport;
7928
7929 /* IPA micro controller data path offload resource config item */
7930 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007931 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7932 /* IpaUcTxBufCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007933 hdd_debug("Round down IpaUcTxBufCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007934 hdd_ctx->config->IpaUcTxBufCount);
7935 hdd_ctx->config->IpaUcTxBufCount =
7936 rounddown_pow_of_two(
7937 hdd_ctx->config->IpaUcTxBufCount);
7938 if (!hdd_ctx->config->IpaUcTxBufCount) {
7939 hdd_err("Failed to round down IpaUcTxBufCount");
7940 return -EINVAL;
7941 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007942 hdd_debug("IpaUcTxBufCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007943 hdd_ctx->config->IpaUcTxBufCount);
7944 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307945 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7946 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007947 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7948 /* IpaUcRxIndRingCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007949 hdd_debug("Round down IpaUcRxIndRingCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007950 hdd_ctx->config->IpaUcRxIndRingCount);
7951 hdd_ctx->config->IpaUcRxIndRingCount =
7952 rounddown_pow_of_two(
7953 hdd_ctx->config->IpaUcRxIndRingCount);
7954 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7955 hdd_err("Failed to round down IpaUcRxIndRingCount");
7956 return -EINVAL;
7957 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007958 hdd_debug("IpaUcRxIndRingCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007959 hdd_ctx->config->IpaUcRxIndRingCount);
7960 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307961 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007962 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307963 cds_cfg->uc_tx_partition_base =
7964 hdd_ctx->config->IpaUcTxPartitionBase;
7965 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7966
7967 cds_cfg->ip_tcp_udp_checksum_offload =
7968 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307969 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307970 cds_cfg->ce_classify_enabled =
7971 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007972 cds_cfg->bpf_packet_filter_enable =
7973 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307974 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7975 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7976 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007977 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007978 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007979 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007980 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Hanumanth Reddy Pothulae87621b2017-04-12 20:53:35 +05307981 cds_cfg->active_uc_bpf_mode = hdd_ctx->config->active_uc_bpf_mode;
7982 cds_cfg->active_mc_bc_bpf_mode = hdd_ctx->config->active_mc_bc_bpf_mode;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307983
7984 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7985 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7986 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007987 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307988 cds_init_ini_config(cds_cfg);
7989 return 0;
7990}
7991
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007992/**
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007993 * hdd_update_user_config() - API to update user configuration
7994 * parameters to obj mgr which are used by multiple components
7995 * @hdd_ctx: HDD Context
7996 *
7997 * Return: 0 for Success, errno on failure
7998 */
7999static int hdd_update_user_config(hdd_context_t *hdd_ctx)
8000{
8001 struct wlan_objmgr_psoc_user_config *user_config;
8002
8003 user_config = qdf_mem_malloc(sizeof(*user_config));
8004 if (user_config == NULL) {
8005 hdd_alert("Failed to alloc memory for user_config!");
8006 return -ENOMEM;
8007 }
8008
8009 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
8010 user_config->dual_mac_feature_disable =
8011 hdd_ctx->config->dual_mac_feature_disable;
8012 user_config->indoor_channel_support =
8013 hdd_ctx->config->indoor_channel_support;
8014 user_config->is_11d_support_enabled =
8015 hdd_ctx->config->Is11dSupportEnabled;
8016 user_config->is_11h_support_enabled =
8017 hdd_ctx->config->Is11hSupportEnabled;
8018 user_config->optimize_chan_avoid_event =
8019 hdd_ctx->config->goptimize_chan_avoid_event;
8020 user_config->skip_dfs_chnl_in_p2p_search =
8021 hdd_ctx->config->skipDfsChnlInP2pSearch;
Naveen Rawat222b2e92017-03-16 09:52:21 -07008022 user_config->band_capability = hdd_ctx->config->nBandCapability;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08008023 wlan_objmgr_psoc_set_user_config(hdd_ctx->hdd_psoc, user_config);
8024
8025 qdf_mem_free(user_config);
8026 return 0;
8027}
8028
8029/**
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08008030 * hdd_init_thermal_info - Initialize thermal level
8031 * @hdd_ctx: HDD context
8032 *
8033 * Initialize thermal level at SME layer and set the thermal level callback
8034 * which would be called when a configured thermal threshold is hit.
8035 *
8036 * Return: 0 on success and errno on failure
8037 */
8038static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
8039{
8040 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308041 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08008042
8043 thermal_param.smeThermalMgmtEnabled =
8044 hdd_ctx->config->thermalMitigationEnable;
8045 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
8046
Poddar, Siddarth83905022016-04-16 17:56:08 -07008047 thermal_param.sme_throttle_duty_cycle_tbl[0] =
8048 hdd_ctx->config->throttle_dutycycle_level0;
8049 thermal_param.sme_throttle_duty_cycle_tbl[1] =
8050 hdd_ctx->config->throttle_dutycycle_level1;
8051 thermal_param.sme_throttle_duty_cycle_tbl[2] =
8052 hdd_ctx->config->throttle_dutycycle_level2;
8053 thermal_param.sme_throttle_duty_cycle_tbl[3] =
8054 hdd_ctx->config->throttle_dutycycle_level3;
8055
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08008056 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
8057 hdd_ctx->config->thermalTempMinLevel0;
8058 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
8059 hdd_ctx->config->thermalTempMaxLevel0;
8060 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
8061 hdd_ctx->config->thermalTempMinLevel1;
8062 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
8063 hdd_ctx->config->thermalTempMaxLevel1;
8064 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
8065 hdd_ctx->config->thermalTempMinLevel2;
8066 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
8067 hdd_ctx->config->thermalTempMaxLevel2;
8068 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
8069 hdd_ctx->config->thermalTempMinLevel3;
8070 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
8071 hdd_ctx->config->thermalTempMaxLevel3;
8072
8073 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
8074
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308075 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05308076 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08008077
8078 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
8079 hdd_set_thermal_level_cb);
8080
8081 return 0;
8082
8083}
8084
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008085#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
8086/**
8087 * hdd_hold_rtnl_lock - Hold RTNL lock
8088 *
8089 * Hold RTNL lock
8090 *
8091 * Return: True if held and false otherwise
8092 */
8093static inline bool hdd_hold_rtnl_lock(void)
8094{
8095 rtnl_lock();
8096 return true;
8097}
8098
8099/**
8100 * hdd_release_rtnl_lock - Release RTNL lock
8101 *
8102 * Release RTNL lock
8103 *
8104 * Return: None
8105 */
8106static inline void hdd_release_rtnl_lock(void)
8107{
8108 rtnl_unlock();
8109}
8110#else
8111static inline bool hdd_hold_rtnl_lock(void) { return false; }
8112static inline void hdd_release_rtnl_lock(void) { }
8113#endif
8114
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008115#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008116
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308117/* MAX iwpriv command support */
8118#define PKTLOG_SET_BUFF_SIZE 3
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308119#define PKTLOG_CLEAR_BUFF 4
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308120#define MAX_PKTLOG_SIZE 16
8121
8122/**
8123 * hdd_pktlog_set_buff_size() - set pktlog buffer size
8124 * @hdd_ctx: hdd context
8125 * @set_value2: pktlog buffer size value
8126 *
8127 *
8128 * Return: 0 for success or error.
8129 */
8130static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
8131{
8132 struct sir_wifi_start_log start_log = { 0 };
8133 QDF_STATUS status;
8134
8135 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8136 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
8137 start_log.ini_triggered = cds_is_packet_log_enabled();
8138 start_log.user_triggered = 1;
8139 start_log.size = set_value2;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308140 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308141
8142 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8143 if (!QDF_IS_STATUS_SUCCESS(status)) {
8144 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8145 EXIT();
8146 return -EINVAL;
8147 }
8148
8149 return 0;
8150}
8151
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008152/**
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308153 * hdd_pktlog_clear_buff() - clear pktlog buffer
8154 * @hdd_ctx: hdd context
8155 *
8156 * Return: 0 for success or error.
8157 */
8158static int hdd_pktlog_clear_buff(hdd_context_t *hdd_ctx)
8159{
8160 struct sir_wifi_start_log start_log;
8161 QDF_STATUS status;
8162
8163 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8164 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
8165 start_log.ini_triggered = cds_is_packet_log_enabled();
8166 start_log.user_triggered = 1;
8167 start_log.size = 0;
8168 start_log.is_pktlog_buff_clear = true;
8169
8170 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8171 if (!QDF_IS_STATUS_SUCCESS(status)) {
8172 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8173 EXIT();
8174 return -EINVAL;
8175 }
8176
8177 return 0;
8178}
8179
8180
8181/**
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008182 * hdd_process_pktlog_command() - process pktlog command
8183 * @hdd_ctx: hdd context
8184 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308185 * @set_value2: pktlog buffer size value
8186 *
8187 * This function process pktlog command.
8188 * set_value2 only matters when set_value is 3 (set buff size)
8189 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008190 *
8191 * Return: 0 for success or error.
8192 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308193int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
8194 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008195{
8196 int ret;
8197 bool enable;
8198 uint8_t user_triggered = 0;
8199
8200 ret = wlan_hdd_validate_context(hdd_ctx);
8201 if (0 != ret)
8202 return ret;
8203
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008204 hdd_debug("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008205
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308206 if (set_value > PKTLOG_CLEAR_BUFF) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008207 hdd_err("invalid pktlog value %d", set_value);
8208 return -EINVAL;
8209 }
8210
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308211 if (set_value == PKTLOG_SET_BUFF_SIZE) {
8212 if (set_value2 <= 0) {
8213 hdd_err("invalid pktlog size %d", set_value2);
8214 return -EINVAL;
8215 } else if (set_value2 > MAX_PKTLOG_SIZE) {
8216 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
8217 return -EINVAL;
8218 }
8219 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308220 } else if (set_value == PKTLOG_CLEAR_BUFF) {
8221 return hdd_pktlog_clear_buff(hdd_ctx);
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308222 }
8223
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008224 /*
8225 * set_value = 0 then disable packetlog
8226 * set_value = 1 enable packetlog forcefully
8227 * set_vlaue = 2 then disable packetlog if disabled through ini or
8228 * enable packetlog with AUTO type.
8229 */
8230 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
8231 true : false;
8232
8233 if (1 == set_value) {
8234 enable = true;
8235 user_triggered = 1;
8236 }
8237
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308238 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008239}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008240/**
8241 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
8242 * @hdd_ctx: HDD context
8243 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308244 * @user_triggered: triggered through iwpriv
8245 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008246 *
8247 * Return: 0 on success; error number otherwise
8248 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008249int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308250 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008251{
8252 struct sir_wifi_start_log start_log;
8253 QDF_STATUS status;
8254
8255 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8256 start_log.verbose_level =
8257 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008258 start_log.ini_triggered = cds_is_packet_log_enabled();
8259 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308260 start_log.size = size;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308261 start_log.is_pktlog_buff_clear = false;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05308262 /*
8263 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
8264 * commands. Host uses this flag to decide whether to send pktlog
8265 * disable command to fw without sending pktlog enable command
8266 * previously. For eg, If vendor sends pktlog disable command without
8267 * sending pktlog enable command, then host discards the packet
8268 * but for iwpriv command, host will send it to fw.
8269 */
8270 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008271 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8272 if (!QDF_IS_STATUS_SUCCESS(status)) {
8273 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8274 EXIT();
8275 return -EINVAL;
8276 }
8277
8278 return 0;
8279}
8280#endif /* REMOVE_PKT_LOG */
8281
Komal Seelam92fff912016-03-24 11:51:41 +05308282/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008283 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
8284 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05308285 * @dev: Device Pointer
8286 * @num: Number of Valid Mac address
8287 *
8288 * Return: Pointer to MAC address buffer
8289 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008290static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
8291 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05308292{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008293 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05308294}
Komal Seelam92fff912016-03-24 11:51:41 +05308295
8296/**
8297 * hdd_populate_random_mac_addr() - API to populate random mac addresses
8298 * @hdd_ctx: HDD Context
8299 * @num: Number of random mac addresses needed
8300 *
8301 * Generate random addresses using bit manipulation on the base mac address
8302 *
8303 * Return: None
8304 */
8305static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
8306{
8307 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
8308 uint32_t iter;
8309 struct hdd_config *ini = hdd_ctx->config;
8310 uint8_t *buf = NULL;
8311 uint8_t macaddr_b3, tmp_br3;
8312 uint8_t *src = ini->intfMacAddr[0].bytes;
8313
8314 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
8315 buf = ini->intfMacAddr[iter].bytes;
8316 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
8317 macaddr_b3 = buf[3];
8318 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
8319 INTF_MACADDR_MASK;
8320 macaddr_b3 += tmp_br3;
8321 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
8322 buf[0] |= 0x02;
8323 buf[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008324 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308325 }
8326}
8327
8328/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008329 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05308330 * @hdd_ctx: HDD Context
8331 *
8332 * API to get mac addresses from platform driver and update the driver
8333 * structures and configure FW with the base mac address.
8334 * Return: int
8335 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008336static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05308337{
8338 uint32_t no_of_mac_addr, iter;
8339 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
8340 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
8341 uint8_t *addr, *buf;
8342 struct device *dev = hdd_ctx->parent_dev;
8343 struct hdd_config *ini = hdd_ctx->config;
8344 tSirMacAddr mac_addr;
8345 QDF_STATUS status;
8346
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008347 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05308348
8349 if (no_of_mac_addr == 0 || !addr) {
8350 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
8351 return -EINVAL;
8352 }
8353
8354 if (no_of_mac_addr > max_mac_addr)
8355 no_of_mac_addr = max_mac_addr;
8356
8357 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
8358
8359 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
8360 buf = ini->intfMacAddr[iter].bytes;
8361 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008362 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308363 }
8364
8365 status = sme_set_custom_mac_addr(mac_addr);
8366
8367 if (!QDF_IS_STATUS_SUCCESS(status))
8368 return -EAGAIN;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07008369
Komal Seelam92fff912016-03-24 11:51:41 +05308370 if (no_of_mac_addr < max_mac_addr)
8371 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
8372 no_of_mac_addr);
8373 return 0;
8374}
8375
8376/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008377 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
8378 * @hdd_ctx: HDD Context
8379 *
8380 * Update MAC address to FW. If MAC address passed by FW is invalid, host
8381 * will generate its own MAC and update it to FW.
8382 *
8383 * Return: 0 for success
8384 * Non-zero error code for failure
8385 */
8386static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
8387{
8388 tSirMacAddr customMacAddr;
8389 QDF_STATUS status;
8390
8391 qdf_mem_copy(&customMacAddr,
8392 &hdd_ctx->config->intfMacAddr[0].bytes[0],
8393 sizeof(tSirMacAddr));
8394 status = sme_set_custom_mac_addr(customMacAddr);
8395 if (!QDF_IS_STATUS_SUCCESS(status))
8396 return -EAGAIN;
8397 return 0;
8398}
8399
8400/**
Komal Seelam92fff912016-03-24 11:51:41 +05308401 * hdd_initialize_mac_address() - API to get wlan mac addresses
8402 * @hdd_ctx: HDD Context
8403 *
8404 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
8405 * is provisioned with mac addresses, driver uses it, else it will use
8406 * wlan_mac.bin to update HW MAC addresses.
8407 *
8408 * Return: None
8409 */
8410static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
8411{
8412 QDF_STATUS status;
8413 int ret;
8414
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008415 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05308416 if (ret == 0)
8417 return;
8418
Yuanyuan Liu3d62f6a2017-06-08 11:08:46 -07008419 hdd_info("MAC is not programmed in platform driver ret: %d, use wlan_mac.bin",
8420 ret);
Komal Seelam92fff912016-03-24 11:51:41 +05308421
8422 status = hdd_update_mac_config(hdd_ctx);
8423
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008424 if (QDF_IS_STATUS_SUCCESS(status))
8425 return;
8426
Yuanyuan Liu3d62f6a2017-06-08 11:08:46 -07008427 hdd_info("MAC is not programmed in wlan_mac.bin ret %d, use default MAC",
8428 status);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008429
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008430 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008431 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008432 if (ret != 0) {
8433 hdd_err("MAC address out-of-sync, ret:%d", ret);
8434 QDF_ASSERT(ret);
8435 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008436 }
Komal Seelam92fff912016-03-24 11:51:41 +05308437}
8438
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008439/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008440 * hdd_tsf_init() - Initialize the TSF synchronization interface
8441 * @hdd_ctx: HDD global context
8442 *
8443 * When TSF synchronization via GPIO is supported by the driver and
8444 * has been enabled in the configuration file, this function plumbs
8445 * the GPIO value down to firmware via SME.
8446 *
8447 * Return: None
8448 */
8449#ifdef WLAN_FEATURE_TSF
8450static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8451{
8452 QDF_STATUS status;
8453
8454 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
8455 return;
8456
8457 status = sme_set_tsf_gpio(hdd_ctx->hHal,
8458 hdd_ctx->config->tsf_gpio_pin);
8459 if (!QDF_IS_STATUS_SUCCESS(status))
8460 hdd_err("Set tsf GPIO failed, status: %d", status);
8461}
8462#else
8463static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8464{
8465}
8466#endif
8467
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008468static int hdd_set_smart_chainmask_enabled(hdd_context_t *hdd_ctx)
8469{
8470 int vdev_id = 0;
8471 int param_id = WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME;
8472 int value = hdd_ctx->config->smart_chainmask_enabled;
8473 int vpdev = PDEV_CMD;
8474 int ret;
8475
8476 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8477 if (ret)
8478 hdd_err("WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME failed %d", ret);
8479
8480 return ret;
8481}
8482
8483static int hdd_set_alternative_chainmask_enabled(hdd_context_t *hdd_ctx)
8484{
8485 int vdev_id = 0;
8486 int param_id = WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME;
8487 int value = hdd_ctx->config->alternative_chainmask_enabled;
8488 int vpdev = PDEV_CMD;
8489 int ret;
8490
8491 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8492 if (ret)
8493 hdd_err("WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME failed %d",
8494 ret);
8495
8496 return ret;
8497}
8498
Jeff Johnson12a744b2017-04-04 08:19:37 -07008499static int hdd_set_ani_enabled(hdd_context_t *hdd_ctx)
8500{
8501 int vdev_id = 0;
8502 int param_id = WMI_PDEV_PARAM_ANI_ENABLE;
8503 int value = hdd_ctx->config->ani_enabled;
8504 int vpdev = PDEV_CMD;
8505 int ret;
8506
8507 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8508 if (ret)
8509 hdd_err("WMI_PDEV_PARAM_ANI_ENABLE failed %d", ret);
8510
8511 return ret;
8512}
8513
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008514/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07008515 * hdd_pre_enable_configure() - Configurations prior to cds_enable
8516 * @hdd_ctx: HDD context
8517 *
8518 * Pre configurations to be done at lower layer before calling cds enable.
8519 *
8520 * Return: 0 on success and errno on failure.
8521 */
8522static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
8523{
8524 int ret;
8525 QDF_STATUS status;
8526 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07008527 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008528
Leo Changfdb45c32016-10-28 11:09:23 -07008529 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008530 /*
8531 * Set 802.11p config
8532 * TODO-OCB: This has been temporarily added here to ensure this
8533 * parameter is set in CSR when we init the channel list. This should
8534 * be removed once the 5.9 GHz channels are added to the regulatory
8535 * domain.
8536 */
8537 hdd_set_dot11p_config(hdd_ctx);
8538
8539 /*
8540 * Note that the cds_pre_enable() sequence triggers the cfg download.
8541 * The cfg download must occur before we update the SME config
8542 * since the SME config operation must access the cfg database
8543 */
8544 status = hdd_set_sme_config(hdd_ctx);
8545
8546 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008547 hdd_err("Failed hdd_set_sme_config: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008548 ret = qdf_status_to_os_return(status);
8549 goto out;
8550 }
8551
Tushnim Bhattacharyyaba8ee932017-03-23 09:27:40 -07008552 status = hdd_set_policy_mgr_user_cfg(hdd_ctx);
8553 if (QDF_STATUS_SUCCESS != status) {
8554 hdd_alert("Failed hdd_set_policy_mgr_user_cfg: %d", status);
8555 ret = qdf_status_to_os_return(status);
8556 goto out;
8557 }
8558
Prashanth Bhatta07998752016-04-28 12:35:33 -07008559 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
8560 hdd_ctx->config->tx_chain_mask_1ss,
8561 PDEV_CMD);
8562 if (0 != ret) {
8563 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
8564 goto out;
8565 }
8566
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008567 ret = hdd_set_smart_chainmask_enabled(hdd_ctx);
8568 if (ret)
8569 goto out;
8570
8571 ret = hdd_set_alternative_chainmask_enabled(hdd_ctx);
8572 if (ret)
8573 goto out;
8574
Jeff Johnson12a744b2017-04-04 08:19:37 -07008575 ret = hdd_set_ani_enabled(hdd_ctx);
8576 if (ret)
8577 goto out;
8578
Srinivas Girigowda70e169a2017-03-07 23:55:57 -08008579 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
8580 hdd_ctx->config->arp_ac_category,
8581 PDEV_CMD);
8582 if (0 != ret) {
8583 hdd_err("WMI_PDEV_PARAM_ARP_AC_OVERRIDE ac: %d ret: %d",
8584 hdd_ctx->config->arp_ac_category, ret);
8585 goto out;
8586 }
8587
8588
Prashanth Bhatta07998752016-04-28 12:35:33 -07008589 status = hdd_set_sme_chan_list(hdd_ctx);
8590 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008591 hdd_err("Failed to init channel list: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008592 ret = qdf_status_to_os_return(status);
8593 goto out;
8594 }
8595
8596 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07008597 if (!hdd_update_config_cfg(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008598 hdd_err("config update failed");
Prashanth Bhatta07998752016-04-28 12:35:33 -07008599 ret = -EINVAL;
8600 goto out;
8601 }
8602
Prashanth Bhatta07998752016-04-28 12:35:33 -07008603 /*
8604 * Set the MAC Address Currently this is used by HAL to add self sta.
8605 * Remove this once self sta is added as part of session open.
8606 */
8607 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
8608 hdd_ctx->config->intfMacAddr[0].bytes,
8609 sizeof(hdd_ctx->config->intfMacAddr[0]));
8610
8611 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
8612 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
8613 hal_status, hal_status);
8614 ret = -EINVAL;
8615 goto out;
8616 }
8617
8618 hdd_init_channel_avoidance(hdd_ctx);
8619
8620out:
8621 return ret;
8622}
8623
8624/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008625 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
8626 * @context_ptr - hdd context pointer
8627 * @event_ptr - event structure pointer
8628 *
8629 * This is the p2p listen offload stop event handler, it sends vendor
8630 * event back to supplicant to notify the stop reason.
8631 *
8632 * Return: None
8633 */
8634static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
8635 void *event_ptr)
8636{
8637 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
8638 struct sir_p2p_lo_event *evt = event_ptr;
8639 struct sk_buff *vendor_event;
8640
8641 ENTER();
8642
8643 if (hdd_ctx == NULL) {
8644 hdd_err("Invalid HDD context pointer");
8645 return;
8646 }
8647
8648 vendor_event =
8649 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8650 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
8651 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
8652 GFP_KERNEL);
8653
8654 if (!vendor_event) {
8655 hdd_err("cfg80211_vendor_event_alloc failed");
8656 return;
8657 }
8658
8659 if (nla_put_u32(vendor_event,
8660 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
8661 evt->reason_code)) {
8662 hdd_err("nla put failed");
8663 kfree_skb(vendor_event);
8664 return;
8665 }
8666
8667 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8668}
8669
8670/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308671 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
8672 * @hdd_ctx: HDD context
8673 *
8674 * This function sends the adaptive dwell time config configuration to the
8675 * firmware via WMA
8676 *
8677 * Return: 0 - success, < 0 - failure
8678 */
8679static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
8680{
8681 QDF_STATUS status;
8682 struct adaptive_dwelltime_params dwelltime_params;
8683
8684 dwelltime_params.is_enabled =
8685 hdd_ctx->config->adaptive_dwell_mode_enabled;
8686 dwelltime_params.dwelltime_mode =
8687 hdd_ctx->config->global_adapt_dwelltime_mode;
8688 dwelltime_params.lpf_weight =
8689 hdd_ctx->config->adapt_dwell_lpf_weight;
8690 dwelltime_params.passive_mon_intval =
8691 hdd_ctx->config->adapt_dwell_passive_mon_intval;
8692 dwelltime_params.wifi_act_threshold =
8693 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
8694
8695 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
8696 &dwelltime_params);
8697
8698 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
8699 if (!QDF_IS_STATUS_SUCCESS(status)) {
8700 hdd_err("Failed to send Adaptive Dwelltime configuration!");
8701 return -EAGAIN;
8702 }
8703 return 0;
8704}
8705
Nitesh Shahf9a09ff2017-05-22 15:46:25 +05308706int hdd_dbs_scan_selection_init(hdd_context_t *hdd_ctx)
8707{
8708 QDF_STATUS status;
8709 struct wmi_dbs_scan_sel_params dbs_scan_params;
8710 uint32_t i = 0;
8711 uint8_t count = 0, numentries = 0;
8712 uint8_t dbs_scan_config[CDS_DBS_SCAN_PARAM_PER_CLIENT
8713 * CDS_DBS_SCAN_CLIENTS_MAX];
8714
8715 /* check if DBS is enabled or supported */
8716 if ((hdd_ctx->config->dual_mac_feature_disable)
8717 || (!policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc)))
8718 return -EINVAL;
8719
8720 hdd_string_to_u8_array(hdd_ctx->config->dbs_scan_selection,
8721 dbs_scan_config, &numentries,
8722 (CDS_DBS_SCAN_PARAM_PER_CLIENT
8723 * CDS_DBS_SCAN_CLIENTS_MAX));
8724
8725 hdd_info("numentries %hu", numentries);
8726 if (!numentries) {
8727 hdd_info("Donot send scan_selection_config");
8728 return 0;
8729 }
8730
8731 /* hdd_set_fw_log_params */
8732 dbs_scan_params.num_clients = 0;
8733 while (count < (numentries - 2)) {
8734 dbs_scan_params.module_id[i] = dbs_scan_config[count];
8735 dbs_scan_params.num_dbs_scans[i] = dbs_scan_config[count + 1];
8736 dbs_scan_params.num_non_dbs_scans[i] =
8737 dbs_scan_config[count + 2];
8738 dbs_scan_params.num_clients++;
8739 hdd_debug("module:%d NDS:%d NNDS:%d",
8740 dbs_scan_params.module_id[i],
8741 dbs_scan_params.num_dbs_scans[i],
8742 dbs_scan_params.num_non_dbs_scans[i]);
8743 count += CDS_DBS_SCAN_PARAM_PER_CLIENT;
8744 i++;
8745 }
8746
8747 dbs_scan_params.pdev_id = 0;
8748
8749 hdd_debug("clients:%d pdev:%d",
8750 dbs_scan_params.num_clients, dbs_scan_params.pdev_id);
8751
8752 status = sme_set_dbs_scan_selection_config(hdd_ctx->hHal,
8753 &dbs_scan_params);
8754 hdd_debug("Sending DBS Scan Selection Configuration to fw");
8755 if (!QDF_IS_STATUS_SUCCESS(status)) {
8756 hdd_err("Failed to send DBS Scan selection configuration!");
8757 return -EAGAIN;
8758 }
8759 return 0;
8760}
8761
Arun Khandavallid4349a92016-07-25 11:10:43 +05308762#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8763/**
8764 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
8765 * @hdd_ctx: HDD context
8766 *
8767 * Set auto shutdown callback to get indications from firmware to indicate
8768 * userspace to shutdown WLAN after a configured amount of inactivity.
8769 *
8770 * Return: 0 on success and errno on failure.
8771 */
8772static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8773{
8774 QDF_STATUS status;
8775
8776 if (!hdd_ctx->config->WlanAutoShutdown)
8777 return 0;
8778
8779 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
8780 wlan_hdd_auto_shutdown_cb);
8781 if (status != QDF_STATUS_SUCCESS)
8782 hdd_err("Auto shutdown feature could not be enabled: %d",
8783 status);
8784
8785 return qdf_status_to_os_return(status);
8786}
8787#else
8788static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8789{
8790 return 0;
8791}
8792#endif
8793
8794/**
8795 * hdd_features_init() - Init features
8796 * @hdd_ctx: HDD context
8797 * @adapter: Primary adapter context
8798 *
8799 * Initialize features and their feature context after WLAN firmware is up.
8800 *
8801 * Return: 0 on success and errno on failure.
8802 */
8803static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8804{
8805 tSirTxPowerLimit hddtxlimit;
8806 QDF_STATUS status;
8807 int ret;
8808
8809 ENTER();
8810
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008811 ret = hdd_update_country_code(hdd_ctx);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308812 if (ret) {
8813 hdd_err("Failed to update country code: %d", ret);
8814 goto out;
8815 }
8816
8817 /* FW capabilities received, Set the Dot11 mode */
8818 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07008819 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
8820 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308821
Arun Khandavallid4349a92016-07-25 11:10:43 +05308822
8823 if (hdd_ctx->config->fIsImpsEnabled)
8824 hdd_set_idle_ps_config(hdd_ctx, true);
8825 else
8826 hdd_set_idle_ps_config(hdd_ctx, false);
8827
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308828 if (hdd_ctx->config->enable_go_cts2self_for_sta)
Srinivas Girigowdab841da72017-03-25 18:04:39 -07008829 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308830
Arun Khandavallid4349a92016-07-25 11:10:43 +05308831 if (hdd_lro_init(hdd_ctx))
8832 hdd_err("Unable to initialize LRO in fw");
8833
8834 if (hdd_adaptive_dwelltime_init(hdd_ctx))
8835 hdd_err("Unable to send adaptive dwelltime setting to FW");
8836
Nitesh Shahf9a09ff2017-05-22 15:46:25 +05308837 if (hdd_dbs_scan_selection_init(hdd_ctx))
8838 hdd_err("Unable to send DBS scan selection setting to FW");
8839
Arun Khandavallid4349a92016-07-25 11:10:43 +05308840 ret = hdd_init_thermal_info(hdd_ctx);
8841 if (ret) {
8842 hdd_err("Error while initializing thermal information");
8843 goto deregister_frames;
8844 }
8845
Poddar, Siddarth66a46592017-02-22 11:44:44 +05308846 if (cds_is_packet_log_enabled())
8847 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
8848
Arun Khandavallid4349a92016-07-25 11:10:43 +05308849 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
8850 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
8851 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
8852 if (!QDF_IS_STATUS_SUCCESS(status))
8853 hdd_err("Error setting txlimit in sme: %d", status);
8854
8855 hdd_tsf_init(hdd_ctx);
8856
Arun Khandavallid4349a92016-07-25 11:10:43 +05308857 ret = hdd_register_cb(hdd_ctx);
8858 if (ret) {
8859 hdd_err("Failed to register HDD callbacks!");
8860 goto deregister_frames;
8861 }
8862
8863 if (hdd_ctx->config->dual_mac_feature_disable) {
8864 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
8865 if (status != QDF_STATUS_SUCCESS) {
8866 hdd_err("Failed to disable dual mac features");
8867 goto deregister_cb;
8868 }
8869 }
Selvaraj, Sridhar371f55e2017-02-21 10:36:15 +05308870 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8871 status = sme_enable_disable_chanavoidind_event(
8872 hdd_ctx->hHal, 0);
8873 if (!QDF_IS_STATUS_SUCCESS(status)) {
8874 hdd_err("Failed to disable Chan Avoidance Indication");
8875 goto deregister_cb;
8876 }
8877 }
Arun Khandavallid4349a92016-07-25 11:10:43 +05308878
8879 /* register P2P Listen Offload event callback */
8880 if (wma_is_p2p_lo_capable())
8881 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
8882 wlan_hdd_p2p_lo_event_callback);
8883
8884 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
8885
8886 if (ret)
8887 goto deregister_cb;
8888
8889 EXIT();
8890 return 0;
8891
8892deregister_cb:
8893 hdd_deregister_cb(hdd_ctx);
8894deregister_frames:
8895 wlan_hdd_cfg80211_deregister_frames(adapter);
8896out:
8897 return -EINVAL;
8898
8899}
8900
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308901#ifdef NAPIER_SCAN
8902/**
8903 *
8904 * hdd_post_cds_enable_config() - HDD post cds start config helper
8905 * @adapter - Pointer to the HDD
8906 *
8907 * Return: None
8908 */
8909static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8910{
8911 QDF_STATUS status;
8912
8913 status = ucfg_scan_register_bcn_cb(hdd_ctx->hdd_psoc,
8914 wlan_cfg80211_inform_bss_frame,
8915 SCAN_CB_TYPE_INFORM_BCN);
8916 if (!QDF_IS_STATUS_SUCCESS(status)) {
8917 hdd_err("failed with status code %08d [x%08x]",
8918 status, status);
8919 return status;
8920 }
8921
8922 return QDF_STATUS_SUCCESS;
8923}
8924#else
8925static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8926{
8927 return QDF_STATUS_SUCCESS;
8928}
8929
8930#endif
Arun Khandavallid4349a92016-07-25 11:10:43 +05308931
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308932/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308933 * hdd_configure_cds() - Configure cds modules
8934 * @hdd_ctx: HDD context
8935 * @adapter: Primary adapter context
8936 *
8937 * Enable Cds modules after WLAN firmware is up.
8938 *
8939 * Return: 0 on success and errno on failure.
8940 */
8941int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8942{
8943 int ret;
8944 QDF_STATUS status;
Arun Khandavallifae92942016-08-01 13:31:08 +05308945
8946 ret = hdd_pre_enable_configure(hdd_ctx);
8947 if (ret) {
8948 hdd_err("Failed to pre-configure cds");
8949 goto out;
8950 }
8951
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008952 /* Always get latest IPA resources allocated from cds_open and configure
8953 * IPA module before configuring them to FW. Sequence required as crash
8954 * observed otherwise.
8955 */
Manikandan Mohan2e803a02017-02-14 14:57:53 -08008956 if (hdd_ipa_uc_ol_init(hdd_ctx)) {
8957 hdd_err("Failed to setup pipes");
8958 goto out;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008959 }
8960
Arun Khandavallifae92942016-08-01 13:31:08 +05308961 /*
8962 * Start CDS which starts up the SME/MAC/HAL modules and everything
8963 * else
8964 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308965 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308966
8967 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008968 hdd_err("cds_enable failed");
Arun Khandavallifae92942016-08-01 13:31:08 +05308969 goto out;
8970 }
8971
8972 status = hdd_post_cds_enable_config(hdd_ctx);
8973 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008974 hdd_err("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008975 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308976 }
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308977 status = hdd_register_bcn_cb(hdd_ctx);
8978 if (!QDF_IS_STATUS_SUCCESS(status)) {
8979 hdd_alert("hdd_post_cds_enable_config failed");
8980 goto cds_disable;
8981 }
Arun Khandavallifae92942016-08-01 13:31:08 +05308982
8983 ret = hdd_features_init(hdd_ctx, adapter);
8984 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008985 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308986
Arun Khandavallifae92942016-08-01 13:31:08 +05308987
8988 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008989
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008990cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308991 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008992
Arun Khandavallifae92942016-08-01 13:31:08 +05308993out:
8994 return -EINVAL;
8995}
8996
8997/**
8998 * hdd_deconfigure_cds() -De-Configure cds
8999 * @hdd_ctx: HDD context
9000 *
9001 * Deconfigure Cds modules before WLAN firmware is down.
9002 *
9003 * Return: 0 on success and errno on failure.
9004 */
Jeff Johnson590e2012016-10-05 16:16:24 -07009005static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05309006{
9007 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07009008 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05309009
9010 ENTER();
9011 /* De-register the SME callbacks */
9012 hdd_deregister_cb(hdd_ctx);
9013
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05309014 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05309015 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
9016 hdd_err("Failed to Disable the CDS Modules! :%d",
9017 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07009018 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05309019 }
9020
9021 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07009022 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309023}
9024
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07009025#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
9026static void hdd_deregister_policy_manager_callback(
9027 struct wlan_objmgr_psoc *psoc)
9028{
9029 if (QDF_STATUS_SUCCESS !=
9030 policy_mgr_deregister_hdd_cb(psoc)) {
9031 hdd_err("HDD callback deregister with policy manager failed");
9032 }
9033}
9034#else
9035static void hdd_deregister_policy_manager_callback(
9036 struct wlan_objmgr_psoc *psoc)
9037{
9038}
9039#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05309040
9041/**
9042 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
9043 * @hdd_ctx: HDD context
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009044 * @ftm_mode: ftm mode
Arun Khandavallifae92942016-08-01 13:31:08 +05309045 *
9046 * This function maintains the driver state machine it will be invoked from
9047 * exit, shutdown and con_mode change handler. Depending on the driver state
9048 * shall perform the stopping/closing of the modules.
9049 *
9050 * Return: 0 for success; non-zero for failure
9051 */
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009052int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
Arun Khandavallifae92942016-08-01 13:31:08 +05309053{
9054 void *hif_ctx;
9055 qdf_device_t qdf_ctx;
9056 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309057 int ret = 0;
Dustin Brown70111822017-03-30 15:31:40 -07009058 bool is_idle_stop = !cds_is_driver_unloading() &&
9059 !cds_is_driver_recovering();
9060 int active_threads;
Arun Khandavallifae92942016-08-01 13:31:08 +05309061
9062 ENTER();
9063
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07009064 hdd_deregister_policy_manager_callback(hdd_ctx->hdd_psoc);
9065
Arun Khandavallifae92942016-08-01 13:31:08 +05309066 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
9067 if (!qdf_ctx) {
9068 hdd_err("QDF device context NULL");
9069 return -EINVAL;
9070 }
9071
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309072 mutex_lock(&hdd_ctx->iface_change_lock);
9073 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05309074
Dustin Brown70111822017-03-30 15:31:40 -07009075 active_threads = cds_return_external_threads_count();
9076 if (active_threads > 0 || hdd_ctx->isWiphySuspended) {
Rajeev Kumar86177c22017-03-16 19:44:39 -07009077 hdd_warn("External threads %d wiphy suspend %d",
Dustin Brown70111822017-03-30 15:31:40 -07009078 active_threads, hdd_ctx->isWiphySuspended);
9079
9080 cds_print_external_threads();
9081
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009082 if (is_idle_stop && !ftm_mode) {
Dustin Brown70111822017-03-30 15:31:40 -07009083 mutex_unlock(&hdd_ctx->iface_change_lock);
9084 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009085 hdd_ctx->config->iface_change_wait_time);
9086 hdd_ctx->stop_modules_in_progress = false;
Dustin Brown70111822017-03-30 15:31:40 -07009087 return 0;
9088 }
Rajeev Kumar86177c22017-03-16 19:44:39 -07009089 }
9090
Arun Khandavallifae92942016-08-01 13:31:08 +05309091 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
9092
9093 switch (hdd_ctx->driver_status) {
9094 case DRIVER_MODULES_UNINITIALIZED:
9095 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309096 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05309097 case DRIVER_MODULES_CLOSED:
9098 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309099 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05309100 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05309101 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05309102 if (hdd_deconfigure_cds(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009103 hdd_err("Failed to de-configure CDS");
Arun Khandavallifae92942016-08-01 13:31:08 +05309104 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309105 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05309106 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009107 hdd_debug("successfully Disabled the CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05309108 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
9109 break;
9110 case DRIVER_MODULES_OPENED:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009111 hdd_debug("Closing CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05309112 break;
9113 default:
9114 hdd_err("Trying to stop wlan in a wrong state: %d",
9115 hdd_ctx->driver_status);
9116 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309117 ret = -EINVAL;
9118 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05309119 }
9120
Rajeev Kumarbe021242017-02-16 16:12:23 -08009121 qdf_status = cds_post_disable();
Govind Singhb048e872016-09-27 22:07:43 +05309122 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
9123 hdd_err("Failed to process post CDS disable Modules! :%d",
9124 qdf_status);
9125 ret = -EINVAL;
9126 QDF_ASSERT(0);
9127 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05309128 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05309129 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009130 hdd_warn("Failed to stop CDS: %d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05309131 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05309132 QDF_ASSERT(0);
9133 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07009134
Arun Khandavallifae92942016-08-01 13:31:08 +05309135 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
9136 if (!hif_ctx) {
9137 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309138 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05309139 }
9140
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05309141 hdd_hif_close(hdd_ctx, hif_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309142
9143 ol_cds_free();
9144
Dustin Brown70111822017-03-30 15:31:40 -07009145 if (is_idle_stop) {
Arun Khandavallifae92942016-08-01 13:31:08 +05309146 ret = pld_power_off(qdf_ctx->dev);
9147 if (ret)
9148 hdd_err("CNSS power down failed put device into Low power mode:%d",
9149 ret);
9150 }
9151 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07009152 /*
9153 * Reset total mac phy during module stop such that during
9154 * next module start same psoc is used to populate new service
9155 * ready data
9156 */
9157 hdd_ctx->hdd_psoc->total_mac_phy = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05309158
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309159done:
9160 hdd_ctx->stop_modules_in_progress = false;
9161 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05309162 EXIT();
9163
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309164 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309165
9166}
9167
9168/**
9169 * hdd_iface_change_callback() - Function invoked when stop modules expires
9170 * @priv: pointer to hdd context
9171 *
9172 * This function is invoked when the timer waiting for the interface change
9173 * expires, it shall cut-down the power to wlan and stop all the modules.
9174 *
9175 * Return: void
9176 */
9177static void hdd_iface_change_callback(void *priv)
9178{
9179 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
9180 int ret;
9181 int status = wlan_hdd_validate_context(hdd_ctx);
9182
9183 if (status)
9184 return;
9185
9186 ENTER();
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009187 hdd_debug("Interface change timer expired close the modules!");
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009188 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309189 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009190 hdd_err("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05309191 EXIT();
9192}
9193
9194/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309195 * hdd_state_info_dump() - prints state information of hdd layer
9196 * @buf: buffer pointer
9197 * @size: size of buffer to be filled
9198 *
9199 * This function is used to dump state information of hdd layer
9200 *
9201 * Return: None
9202 */
9203static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
9204{
9205 hdd_context_t *hdd_ctx;
9206 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
9207 QDF_STATUS status;
9208 hdd_station_ctx_t *hdd_sta_ctx;
9209 hdd_adapter_t *adapter;
9210 uint16_t len = 0;
9211 char *buf = *buf_ptr;
9212
9213 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9214 if (!hdd_ctx) {
9215 hdd_err("Failed to get hdd context ");
9216 return;
9217 }
9218
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009219 hdd_debug("size of buffer: %d", *size);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309220
9221 len += scnprintf(buf + len, *size - len,
9222 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
9223 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08009224 "\n is_scheduler_suspended %d",
9225 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309226
9227 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
9228
9229 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
9230 adapter = adapter_node->pAdapter;
9231 if (adapter->dev)
9232 len += scnprintf(buf + len, *size - len,
9233 "\n device name: %s", adapter->dev->name);
9234 len += scnprintf(buf + len, *size - len,
9235 "\n device_mode: %d", adapter->device_mode);
9236 switch (adapter->device_mode) {
9237 case QDF_STA_MODE:
9238 case QDF_P2P_CLIENT_MODE:
9239 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9240 len += scnprintf(buf + len, *size - len,
9241 "\n connState: %d",
9242 hdd_sta_ctx->conn_info.connState);
9243 break;
9244
9245 default:
9246 break;
9247 }
9248 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
9249 adapter_node = next;
9250 }
9251
9252 *size -= len;
9253 *buf_ptr += len;
9254}
9255
9256/**
9257 * hdd_register_debug_callback() - registration function for hdd layer
9258 * to print hdd state information
9259 *
9260 * Return: None
9261 */
9262static void hdd_register_debug_callback(void)
9263{
9264 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
9265}
9266
SaidiReddy Yenuga699d90e2017-04-14 16:09:24 +05309267/*
9268 * wlan_init_bug_report_lock() - Initialize bug report lock
9269 *
9270 * This function is used to create bug report lock
9271 *
9272 * Return: None
9273 */
9274static void wlan_init_bug_report_lock(void)
9275{
9276 p_cds_contextType p_cds_context;
9277
9278 p_cds_context = cds_get_global_context();
9279 if (!p_cds_context) {
9280 hdd_err("cds context is NULL");
9281 return;
9282 }
9283
9284 qdf_spinlock_create(&p_cds_context->bug_report_lock);
9285}
9286
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309287/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009288 * hdd_wlan_startup() - HDD init function
9289 * @dev: Pointer to the underlying device
9290 *
9291 * This is the driver startup code executed once a WLAN device has been detected
9292 *
9293 * Return: 0 for success, < 0 for failure
9294 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309295int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009296{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309297 QDF_STATUS status;
Jeff Johnson957bc272017-02-02 08:54:48 -08009298 hdd_context_t *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009299 int ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009300 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309301 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009302
9303 ENTER();
9304
Arun Khandavallifae92942016-08-01 13:31:08 +05309305 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009306
9307 if (IS_ERR(hdd_ctx))
9308 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009309
Abhishek Singhe9068f12017-03-31 14:14:52 +05309310 ret = hdd_objmgr_create_and_store_psoc(hdd_ctx,
9311 DEFAULT_PSOC_ID);
9312 if (ret) {
9313 hdd_err("Psoc creation fails!");
9314 QDF_BUG(0);
9315 goto err_hdd_free_context;
9316 }
9317
Arun Khandavallifae92942016-08-01 13:31:08 +05309318 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
9319 hdd_iface_change_callback, (void *)hdd_ctx);
9320
9321 mutex_init(&hdd_ctx->iface_change_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05309322#ifdef FEATURE_WLAN_CH_AVOID
9323 mutex_init(&hdd_ctx->avoid_freq_lock);
9324#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05309325
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009326 ret = hdd_init_netlink_services(hdd_ctx);
9327 if (ret)
9328 goto err_hdd_free_context;
9329
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009330 hdd_request_manager_init();
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07009331 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309332
Jeff Johnson957bc272017-02-02 08:54:48 -08009333 ret = hdd_wlan_start_modules(hdd_ctx, NULL, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309334 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009335 hdd_err("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009336 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009337 }
9338
SaidiReddy Yenuga699d90e2017-04-14 16:09:24 +05309339 wlan_init_bug_report_lock();
9340
Yingying Tang80e15f32016-09-27 18:23:01 +08009341 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342
Yingying Tang95409972016-10-20 15:16:15 +08009343 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009344 hdd_debug("Failed to set wow pulse");
Yingying Tang95409972016-10-20 15:16:15 +08009345
Anurag Chouhan6d760662016-02-20 16:05:43 +05309346 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347
9348 if (NULL == hdd_ctx->hHal) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009349 hdd_err("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05309350 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009351 }
9352
Prashanth Bhatta07998752016-04-28 12:35:33 -07009353 ret = hdd_wiphy_init(hdd_ctx);
9354 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009355 hdd_err("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05309356 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009357 }
9358
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05309359 if (hdd_ctx->config->enable_dp_trace)
9360 qdf_dp_trace_init();
9361
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309362 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009363 goto err_wiphy_unregister;
9364
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05309365 wlan_hdd_init_chan_info(hdd_ctx);
9366
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07009367 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08009368
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009369 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009370
Jeff Johnson957bc272017-02-02 08:54:48 -08009371 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
9372 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009373 hdd_err("Failed to open interfaces: %d", ret);
Jeff Johnson46bde382017-02-01 15:31:16 -08009374 goto err_release_rtnl_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009375 }
9376
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009377 hdd_release_rtnl_lock();
9378 rtnl_held = false;
9379
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009380 wlan_hdd_update_11n_mode(hdd_ctx->config);
9381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009382#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05309383 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309384 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009385 hdd_skip_acs_scan_timer_handler,
9386 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309387 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07009388 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04009389 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009390#endif
9391
Nitesh Shah61c10d92016-10-19 19:29:15 +05309392 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
9393 QDF_TIMER_TYPE_SW,
9394 wlan_hdd_change_tdls_mode,
9395 hdd_ctx);
9396
Prashanth Bhattaab004382016-10-11 16:08:11 -07009397 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398
Jeff Johnson9afc5012016-09-23 13:56:27 -07009399 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009400
Nirav Shahbd36b062016-07-18 11:12:59 +05309401 if (hdd_ctx->rps)
9402 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07009403
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009404 ret = hdd_register_notifiers(hdd_ctx);
9405 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08009406 goto err_close_adapters;
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05309407
9408 status = wlansap_global_init();
9409 if (QDF_IS_STATUS_ERROR(status))
Jeff Johnson957bc272017-02-02 08:54:48 -08009410 goto err_close_adapters;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009411
Komal Seelam8634b772016-09-29 12:12:24 +05309412 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009413 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309414 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009415
bings612b9c42016-11-07 10:52:03 +08009416 if (hdd_enable_egap(hdd_ctx))
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009417 hdd_debug("enhance green ap is not enabled");
bings612b9c42016-11-07 10:52:03 +08009418
Arun Khandavallifae92942016-08-01 13:31:08 +05309419 if (hdd_ctx->config->fIsImpsEnabled)
9420 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309421
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309422 if (hdd_ctx->config->sifs_burst_duration) {
9423 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
9424 hdd_ctx->config->sifs_burst_duration;
9425
9426 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
9427 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
9428 set_value, PDEV_CMD);
9429 }
9430
Paul Zhang42dade02017-05-12 19:20:37 +08009431 if (hdd_ctx->config->is_force_1x1)
9432 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_SET_IOT_PATTERN,
9433 1, PDEV_CMD);
9434
lifeng959a04c2017-05-10 14:21:28 +08009435 if (hdd_ctx->config->max_mpdus_inampdu) {
9436 set_value = hdd_ctx->config->max_mpdus_inampdu;
9437 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_MAX_MPDUS_IN_AMPDU,
9438 set_value, PDEV_CMD);
9439 }
9440
9441 if (hdd_ctx->config->enable_rts_sifsbursting) {
9442 set_value = hdd_ctx->config->enable_rts_sifsbursting;
9443 wma_cli_set_command(0,
9444 (int)WMI_PDEV_PARAM_ENABLE_RTS_SIFS_BURSTING,
9445 set_value, PDEV_CMD);
9446 }
9447
Arun Khandavallifae92942016-08-01 13:31:08 +05309448 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
Hanumanth Reddy Pothula42e714a2016-12-21 19:33:57 +05309449 hdd_ctx->config->iface_change_wait_time);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309450
Sachin Ahujadddd2632017-03-07 19:07:24 +05309451 hdd_start_complete(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009452 goto success;
9453
Jeff Johnson957bc272017-02-02 08:54:48 -08009454err_close_adapters:
Jeff Johnson46bde382017-02-01 15:31:16 -08009455 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009456
Jeff Johnson46bde382017-02-01 15:31:16 -08009457err_release_rtnl_lock:
Arun Khandavallid4349a92016-07-25 11:10:43 +05309458 if (rtnl_held)
9459 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009460
Anurag Chouhance6a4052016-09-14 18:20:42 +05309461 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08009462
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009463err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009464 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009465
Arun Khandavallifae92942016-08-01 13:31:08 +05309466err_stop_modules:
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009467 hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309468
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05309469err_exit_nl_srv:
Arunk Khandavallifbc1ef02017-03-14 21:25:05 +05309470 if (DRIVER_MODULES_CLOSED == hdd_ctx->driver_status) {
9471 status = cds_sched_close(hdd_ctx->pcds_context);
9472 if (!QDF_IS_STATUS_SUCCESS(status)) {
9473 hdd_err("Failed to close CDS Scheduler");
9474 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
9475 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009476 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009477
Houston Hoffman47a4a052016-11-14 23:22:44 -08009478 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009479 hdd_request_manager_deinit();
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009480 hdd_exit_netlink_services(hdd_ctx);
9481
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309482 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009483err_hdd_free_context:
Nachiket Kukade8003d252017-03-30 15:55:58 +05309484 if (cds_is_fw_down())
9485 hdd_err("Not setting the complete event as fw is down");
9486 else
9487 hdd_start_complete(ret);
9488
Arun Khandavallifae92942016-08-01 13:31:08 +05309489 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
9490 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07009491 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009492 return -EIO;
9493
9494success:
9495 EXIT();
9496 return 0;
9497}
9498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009499/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309500 * hdd_wlan_update_target_info() - update target type info
9501 * @hdd_ctx: HDD context
9502 * @context: hif context
9503 *
9504 * Update target info received from firmware in hdd context
9505 * Return:None
9506 */
9507
9508void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
9509{
9510 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
9511
9512 if (!tgt_info) {
9513 hdd_err("Target info is Null");
9514 return;
9515 }
9516
9517 hdd_ctx->target_type = tgt_info->target_type;
9518}
9519
9520/**
9521 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309522 * @hdd_ctx: HDD context
9523 *
9524 * Register the HDD callbacks to CDS/SME.
9525 *
9526 * Return: 0 for success or Error code for failure
9527 */
9528int hdd_register_cb(hdd_context_t *hdd_ctx)
9529{
9530 QDF_STATUS status;
9531 int ret = 0;
9532
9533 ENTER();
9534
9535 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
9536
9537 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
9538 hdd_send_oem_data_rsp_msg);
9539
9540 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
9541 wlan_hdd_cfg80211_fw_mem_dump_cb);
9542 if (!QDF_IS_STATUS_SUCCESS(status)) {
9543 hdd_err("Failed to register memdump callback");
9544 ret = -EINVAL;
9545 return ret;
9546 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05309547 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
9548 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309549 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
9550 sme_nan_register_callback(hdd_ctx->hHal,
9551 wlan_hdd_cfg80211_nan_callback);
9552 sme_stats_ext_register_callback(hdd_ctx->hHal,
9553 wlan_hdd_cfg80211_stats_ext_callback);
9554
9555 sme_ext_scan_register_callback(hdd_ctx->hHal,
9556 wlan_hdd_cfg80211_extscan_callback);
9557
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309558 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
9559 hdd_rssi_threshold_breached);
9560
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309561 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
9562 wlan_hdd_cfg80211_link_layer_stats_callback);
9563
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309564 sme_rso_cmd_status_cb(hdd_ctx->hHal, wlan_hdd_rso_cmd_status_cb);
9565
Zhang Qianca38fb12016-12-23 11:10:48 +08009566 sme_set_link_layer_ext_cb(hdd_ctx->hHal,
9567 wlan_hdd_cfg80211_link_layer_stats_ext_callback);
9568
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05309569 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
9570 hdd_lost_link_info_cb);
9571 /* print error and not block the startup process */
9572 if (!QDF_IS_STATUS_SUCCESS(status))
9573 hdd_err("set lost link info callback failed");
9574
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309575 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
9576
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009577 sme_register_set_connection_info_cb(hdd_ctx->hHal,
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009578 hdd_set_connection_in_progress,
9579 hdd_is_connection_in_progress);
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309580
9581 status = sme_congestion_register_callback(hdd_ctx->hHal,
9582 hdd_update_cca_info_cb);
9583 if (!QDF_IS_STATUS_SUCCESS(status))
9584 hdd_err("set congestion callback failed");
9585
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309586 EXIT();
9587
9588 return ret;
9589}
9590
9591/**
9592 * hdd_deregister_cb() - De-Register HDD callbacks.
9593 * @hdd_ctx: HDD context
9594 *
9595 * De-Register the HDD callbacks to CDS/SME.
9596 *
9597 * Return: void
9598 */
9599void hdd_deregister_cb(hdd_context_t *hdd_ctx)
9600{
9601 QDF_STATUS status;
9602
9603 ENTER();
9604
9605 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
9606 if (!QDF_IS_STATUS_SUCCESS(status))
9607 hdd_err("De-register of dcc stats callback failed: %d",
9608 status);
9609
9610 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309611 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
9612
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309613 sme_stats_ext_register_callback(hdd_ctx->hHal,
9614 wlan_hdd_cfg80211_stats_ext_callback);
9615
9616 sme_nan_deregister_callback(hdd_ctx->hHal);
9617 status = sme_reset_tsfcb(hdd_ctx->hHal);
9618 if (!QDF_IS_STATUS_SUCCESS(status))
9619 hdd_err("Failed to de-register tsfcb the callback:%d",
9620 status);
9621 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
9622 if (!QDF_IS_STATUS_SUCCESS(status))
9623 hdd_err("Failed to de-register the fw mem dump callback: %d",
9624 status);
9625
9626 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
9627 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
9628
9629 EXIT();
9630}
9631
9632/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009633 * hdd_softap_sta_deauth() - handle deauth req from HDD
9634 * @adapter: Pointer to the HDD
9635 * @enable: bool value
9636 *
9637 * This to take counter measure to handle deauth req from HDD
9638 *
9639 * Return: None
9640 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309641QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 struct tagCsrDelStaParams *pDelStaParams)
9643{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309644 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009645
9646 ENTER();
9647
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009648 hdd_debug("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009649 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9650
9651 /* Ignore request to deauth bcmc station */
9652 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309653 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009654
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309655 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009656 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9657 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009658
9659 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309660 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009661}
9662
9663/**
9664 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
9665 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309666 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667 *
9668 * This to take counter measure to handle deauth req from HDD
9669 *
9670 * Return: None
9671 */
9672void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309673 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009674{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009675 ENTER();
9676
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009677 hdd_debug("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009678 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9679
9680 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309681 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009682 return;
9683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309685 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686}
9687
9688void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
9689 bool enable)
9690{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009691 ENTER();
9692
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009693 hdd_debug("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009694 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9695
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009696 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9697 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009698}
9699
9700/**
9701 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
9702 * @hdd_ctx: HDD Context
9703 *
9704 * API to find if there is any STA or P2P-Client is connected
9705 *
9706 * Return: true if connected; false otherwise
9707 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309708QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009709{
9710 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
9711}
9712
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009713/**
9714 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
9715 * @adapter: HDD adapter pointer
9716 *
9717 * This function loop through each adapter and disable roaming on each STA
9718 * device mode except the input adapter.
9719 *
9720 * Note: On the input adapter roaming is not enabled yet hence no need to
9721 * disable.
9722 *
9723 * Return: None
9724 */
9725void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
9726{
9727 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9728 hdd_adapter_t *adapterIdx = NULL;
9729 hdd_adapter_list_node_t *adapterNode = NULL;
9730 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309731 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732
9733 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009734 hdd_ctx->config->isRoamOffloadScanEnabled &&
9735 QDF_STA_MODE == adapter->device_mode &&
9736 policy_mgr_is_sta_active_connection_exists(
9737 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009738 hdd_debug("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009739 adapter->sessionId);
9740 /*
9741 * Loop through adapter and disable roaming for each STA device
9742 * mode except the input adapter.
9743 */
9744 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309746 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009747 adapterIdx = adapterNode->pAdapter;
9748
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009749 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009750 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009751 hdd_debug("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009752 adapterIdx->sessionId);
9753 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
9754 (adapterIdx),
9755 adapterIdx->sessionId, 0);
9756 }
9757
9758 status = hdd_get_next_adapter(hdd_ctx,
9759 adapterNode,
9760 &pNext);
9761 adapterNode = pNext;
9762 }
9763 }
9764}
9765
9766/**
9767 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
9768 * @adapter: HDD adapter pointer
9769 *
9770 * This function loop through each adapter and enable roaming on each STA
9771 * device mode except the input adapter.
9772 * Note: On the input adapter no need to enable roaming because link got
9773 * disconnected on this.
9774 *
9775 * Return: None
9776 */
9777void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
9778{
9779 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9780 hdd_adapter_t *adapterIdx = NULL;
9781 hdd_adapter_list_node_t *adapterNode = NULL;
9782 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309783 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009784
9785 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009786 hdd_ctx->config->isRoamOffloadScanEnabled &&
9787 QDF_STA_MODE == adapter->device_mode &&
9788 policy_mgr_is_sta_active_connection_exists(
9789 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009790 hdd_debug("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791 adapter->sessionId);
9792 /*
9793 * Loop through adapter and enable roaming for each STA device
9794 * mode except the input adapter.
9795 */
9796 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9797
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309798 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009799 adapterIdx = adapterNode->pAdapter;
9800
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009801 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009802 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009803 hdd_debug("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009804 adapterIdx->sessionId);
9805 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
9806 (adapterIdx),
9807 adapterIdx->sessionId,
9808 REASON_CONNECT);
9809 }
9810
9811 status = hdd_get_next_adapter(hdd_ctx,
9812 adapterNode,
9813 &pNext);
9814 adapterNode = pNext;
9815 }
9816 }
9817}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309819/**
9820 * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
9821 * @skb: sk buffer pointer
9822 *
9823 * Sends the bcast message to SVC multicast group with generic nl socket
9824 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
9825 *
9826 * Return: None
9827 */
9828static void nl_srv_bcast_svc(struct sk_buff *skb)
9829{
9830#ifdef CNSS_GENL
9831 nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
9832#else
9833 nl_srv_bcast(skb);
9834#endif
9835}
9836
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309837void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009838{
9839 struct sk_buff *skb;
9840 struct nlmsghdr *nlh;
9841 tAniMsgHdr *ani_hdr;
9842 void *nl_data = NULL;
9843 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309844 struct radio_index_tlv *radio_info;
9845 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009846
9847 if (in_interrupt() || irqs_disabled() || in_atomic())
9848 flags = GFP_ATOMIC;
9849
9850 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
9851
Srinivas Girigowdab841da72017-03-25 18:04:39 -07009852 if (skb == NULL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009853 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854
9855 nlh = (struct nlmsghdr *)skb->data;
9856 nlh->nlmsg_pid = 0; /* from kernel */
9857 nlh->nlmsg_flags = 0;
9858 nlh->nlmsg_seq = 0;
9859 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
9860
9861 ani_hdr = NLMSG_DATA(nlh);
9862 ani_hdr->type = type;
9863
9864 switch (type) {
9865 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05309866 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009867 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009868 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009869 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009870 ani_hdr->length = 0;
9871 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009872 break;
9873 case WLAN_SVC_WLAN_STATUS_IND:
9874 case WLAN_SVC_WLAN_VERSION_IND:
9875 case WLAN_SVC_DFS_CAC_START_IND:
9876 case WLAN_SVC_DFS_CAC_END_IND:
9877 case WLAN_SVC_DFS_RADAR_DETECT_IND:
9878 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
9879 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08009880 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05309881 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882 ani_hdr->length = len;
9883 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
9884 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
9885 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009886 break;
9887
9888 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07009889 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009890 type);
9891 kfree_skb(skb);
9892 return;
9893 }
9894
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309895 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08009896 * Add radio index at the end of the svc event in TLV format
9897 * to maintain the backward compatibility with userspace
9898 * applications.
9899 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309900
9901 tlv_len = 0;
9902
9903 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
9904 < WLAN_NL_MAX_PAYLOAD) {
9905 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
9906 sizeof(*ani_hdr) + len);
9907 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
9908 radio_info->length = (unsigned short) sizeof(radio_info->radio);
9909 radio_info->radio = radio;
9910 tlv_len = sizeof(*radio_info);
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009911 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309912 "Added radio index tlv - radio index %d",
9913 radio_info->radio);
9914 }
9915
9916 nlh->nlmsg_len += tlv_len;
9917 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
9918
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309919 nl_srv_bcast_svc(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009920}
9921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009922#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
9923void wlan_hdd_auto_shutdown_cb(void)
9924{
hque52fdd62017-06-05 11:27:44 +08009925 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309926
9927 if (!hdd_ctx)
9928 return;
9929
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009930 hdd_debug("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309931 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
9932 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009933}
9934
9935void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
9936{
9937 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309938 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009939 hdd_adapter_t *adapter;
9940 bool ap_connected = false, sta_connected = false;
9941 tHalHandle hal_handle;
9942
9943 hal_handle = hdd_ctx->hHal;
9944 if (hal_handle == NULL)
9945 return;
9946
9947 if (hdd_ctx->config->WlanAutoShutdown == 0)
9948 return;
9949
9950 if (enable == false) {
9951 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309952 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009953 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009954 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309955 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009956 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957 return;
9958 }
9959
9960 /* To enable shutdown timer check conncurrency */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009961 if (policy_mgr_concurrent_open_sessions_running(
9962 hdd_ctx->hdd_psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009963 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9964
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309965 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009966 adapter = adapterNode->pAdapter;
9967 if (adapter
9968 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009969 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009970 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9971 conn_info.connState ==
9972 eConnectionState_Associated) {
9973 sta_connected = true;
9974 break;
9975 }
9976 }
9977 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009978 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009979 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
9980 bApActive == true) {
9981 ap_connected = true;
9982 break;
9983 }
9984 }
9985 status = hdd_get_next_adapter(hdd_ctx,
9986 adapterNode,
9987 &pNext);
9988 adapterNode = pNext;
9989 }
9990 }
9991
9992 if (ap_connected == true || sta_connected == true) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009993 hdd_debug("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009995 }
Jeff Johnson68755312017-02-10 11:46:55 -08009996
9997 if (sme_set_auto_shutdown_timer(hal_handle,
9998 hdd_ctx->config->WlanAutoShutdown)
9999 != QDF_STATUS_SUCCESS)
10000 hdd_err("Failed to start wlan auto shutdown timer");
10001 else
10002 hdd_notice("Auto Shutdown timer for %d seconds enabled",
10003 hdd_ctx->config->WlanAutoShutdown);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010004}
10005#endif
10006
10007hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
10008 bool check_start_bss)
10009{
10010 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
10011 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010012 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010013 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
10014
10015 con_sap_adapter = NULL;
10016
10017 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010018 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010019 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010020 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
10021 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010022 adapter != this_sap_adapter) {
10023 if (check_start_bss) {
10024 if (test_bit(SOFTAP_BSS_STARTED,
10025 &adapter->event_flags)) {
10026 con_sap_adapter = adapter;
10027 break;
10028 }
10029 } else {
10030 con_sap_adapter = adapter;
10031 break;
10032 }
10033 }
10034 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
10035 adapterNode = pNext;
10036 }
10037
10038 return con_sap_adapter;
10039}
10040
10041#ifdef MSM_PLATFORM
Dustin Brown5ec6b552017-03-31 12:11:40 -070010042static inline bool hdd_adapter_is_sta(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010043{
Dustin Brown5ec6b552017-03-31 12:11:40 -070010044 return adapter->device_mode == QDF_STA_MODE ||
10045 adapter->device_mode == QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010046}
10047
Dustin Brown5ec6b552017-03-31 12:11:40 -070010048static inline bool hdd_adapter_is_ap(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010049{
Dustin Brown5ec6b552017-03-31 12:11:40 -070010050 return adapter->device_mode == QDF_SAP_MODE ||
10051 adapter->device_mode == QDF_P2P_GO_MODE;
10052}
10053
10054static bool hdd_any_adapter_is_assoc(hdd_context_t *hdd_ctx)
10055{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010056 QDF_STATUS status;
Dustin Brown5ec6b552017-03-31 12:11:40 -070010057 hdd_adapter_list_node_t *node;
10058
10059 status = hdd_get_front_adapter(hdd_ctx, &node);
10060 while (QDF_IS_STATUS_SUCCESS(status) && node) {
10061 hdd_adapter_t *adapter = node->pAdapter;
10062
10063 if (adapter &&
10064 hdd_adapter_is_sta(adapter) &&
10065 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
10066 conn_info.connState == eConnectionState_Associated) {
10067 return true;
10068 }
10069
10070 if (adapter &&
10071 hdd_adapter_is_ap(adapter) &&
10072 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive) {
10073 return true;
10074 }
10075
10076 status = hdd_get_next_adapter(hdd_ctx, node, &node);
10077 }
10078
10079 return false;
10080}
10081
10082static bool hdd_bus_bw_compute_timer_is_running(hdd_context_t *hdd_ctx)
10083{
10084 bool is_running;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010085
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +053010086 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown5ec6b552017-03-31 12:11:40 -070010087 is_running = hdd_ctx->bus_bw_timer_running;
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +053010088 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010089
Dustin Brown5ec6b552017-03-31 12:11:40 -070010090 return is_running;
10091}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010092
Dustin Brown5ec6b552017-03-31 12:11:40 -070010093static void __hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
10094{
10095 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
10096 hdd_ctx->bus_bw_timer_running = true;
10097 qdf_timer_start(&hdd_ctx->bus_bw_timer,
10098 hdd_ctx->config->busBandwidthComputeInterval);
10099 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
10100}
10101
10102void hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
10103{
10104 ENTER();
10105
10106 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
10107 hdd_debug("Bandwidth compute timer already started");
10108 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 }
10110
Dustin Brown5ec6b552017-03-31 12:11:40 -070010111 __hdd_bus_bw_compute_timer_start(hdd_ctx);
10112
10113 EXIT();
10114}
10115
10116void hdd_bus_bw_compute_timer_try_start(hdd_context_t *hdd_ctx)
10117{
10118 ENTER();
10119
10120 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
10121 hdd_debug("Bandwidth compute timer already started");
10122 return;
Ravi Joshib89e7f72016-09-07 13:43:15 -070010123 }
Dustin Brown5ec6b552017-03-31 12:11:40 -070010124
10125 if (hdd_any_adapter_is_assoc(hdd_ctx))
10126 __hdd_bus_bw_compute_timer_start(hdd_ctx);
10127
10128 EXIT();
10129}
10130
10131static void __hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
10132{
10133 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
10134
10135 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
10136 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
10137 hdd_ctx->bus_bw_timer_running = false;
10138 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
10139
10140 hdd_reset_tcp_delack(hdd_ctx);
10141}
10142
10143void hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
10144{
10145 ENTER();
10146
10147 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
10148 hdd_debug("Bandwidth compute timer already stopped");
10149 return;
10150 }
10151
10152 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
10153
10154 EXIT();
10155}
10156
10157void hdd_bus_bw_compute_timer_try_stop(hdd_context_t *hdd_ctx)
10158{
10159 ENTER();
10160
10161 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
10162 hdd_debug("Bandwidth compute timer already stopped");
10163 return;
10164 }
10165
10166 if (!hdd_any_adapter_is_assoc(hdd_ctx))
10167 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
10168
10169 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170}
10171#endif
10172
10173/**
10174 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
10175 * and sta's operating channel.
10176 * @sta_adapter: Describe the first argument to foobar.
10177 * @ap_adapter: Describe the second argument to foobar.
10178 * @roam_profile: Roam profile of AP to which STA wants to connect.
10179 * @concurrent_chnl_same: If both SAP and STA channels are same then
10180 * set this flag to true else false.
10181 *
10182 * This function checks the sap's operating channel and sta's operating channel.
10183 * if both are same then it will return false else it will restart the sap in
10184 * sta's channel and return true.
10185 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010186 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010188QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010189 hdd_adapter_t *ap_adapter,
10190 tCsrRoamProfile *roam_profile,
10191 tScanResultHandle *scan_cache,
10192 bool *concurrent_chnl_same)
10193{
10194 hdd_ap_ctx_t *hdd_ap_ctx;
10195 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010196 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010197 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198 *concurrent_chnl_same = true;
10199
10200 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10201 status =
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070010202 sme_get_ap_channel_from_scan_cache(roam_profile,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203 scan_cache,
10204 &channel_id);
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010205 if (QDF_STATUS_SUCCESS == status) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010206 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010207 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
10208 if (hdd_ap_ctx->operatingChannel != channel_id) {
10209 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010210 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010211 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010212 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010213 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
10214 if (hdd_ap_ctx->operatingChannel != channel_id) {
10215 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010216 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010217 }
10218 }
10219 } else {
10220 /*
10221 * Lets handle worst case scenario here, Scan cache lookup is
10222 * failed so we have to stop the SAP to avoid any channel
10223 * discrepancy between SAP's channel and STA's channel.
10224 * Return the status as failure so caller function could know
10225 * that scan look up is failed.
10226 */
Jeff Johnson28f8a772016-08-15 15:30:36 -070010227 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010228 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010229 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010230 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010231}
10232
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010233/**
10234 * wlan_hdd_stop_sap() - This function stops bss of SAP.
10235 * @ap_adapter: SAP adapter
10236 *
10237 * This function will process the stopping of sap adapter.
10238 *
10239 * Return: None
10240 */
10241void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
10242{
10243 hdd_ap_ctx_t *hdd_ap_ctx;
10244 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010245 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010246 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010247
10248 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010249 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250 return;
10251 }
10252
10253 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10254 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053010255 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010256 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +053010257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010258 mutex_lock(&hdd_ctx->sap_lock);
10259 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010260 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
10262 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010263 hdd_debug("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010264 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010265 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010266 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +053010267 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -080010268 qdf_stop_bss_event,
10269 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010270 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010271 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -070010272 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010273 return;
10274 }
10275 }
10276 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080010277 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
10278 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010279 ap_adapter->sessionId);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010280 hdd_debug("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010281 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010282 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010283 }
10284 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285}
10286
10287/**
10288 * wlan_hdd_start_sap() - this function starts bss of SAP.
10289 * @ap_adapter: SAP adapter
10290 *
10291 * This function will process the starting of sap adapter.
10292 *
10293 * Return: None
10294 */
Arun Khandavallicc544b32017-01-30 19:52:16 +053010295void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010296{
10297 hdd_ap_ctx_t *hdd_ap_ctx;
10298 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010299 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010300 hdd_context_t *hdd_ctx;
10301 tsap_Config_t *sap_config;
10302
10303 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010304 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010305 return;
10306 }
10307
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010308 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -070010309 hdd_err("SoftAp role has not been enabled");
10310 return;
10311 }
10312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010313 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
10314 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10315 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10316 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
10317
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 mutex_lock(&hdd_ctx->sap_lock);
10319 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
10320 goto end;
10321
10322 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010323 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
10325 goto end;
10326 }
10327
Wei Song2f76f642016-11-18 16:32:53 +080010328 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010329 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
10330 &hdd_ap_ctx->sapConfig,
10331 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010332 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010333 goto end;
10334
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010335 hdd_debug("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010336 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -080010337 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010338 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010339 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340 goto end;
10341 }
Jeff Johnson28f8a772016-08-15 15:30:36 -070010342 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010343 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -080010344 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080010345 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
10346 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010347 ap_adapter->sessionId);
10348 hostapd_state->bCommit = true;
10349
10350end:
10351 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010352}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010353
10354/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010355 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
10356 * mac scan config
10357 * @status: Status of set antenna mode
10358 *
10359 * Callback on setting the dual mac configuration
10360 *
10361 * Return: None
10362 */
10363void wlan_hdd_soc_set_antenna_mode_cb(
10364 enum set_antenna_mode_status status)
10365{
10366 hdd_context_t *hdd_ctx;
10367
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010368 hdd_debug("Status: %d", status);
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010369
10370 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10371 if (0 != wlan_hdd_validate_context(hdd_ctx))
10372 return;
10373
10374 /* Signal the completion of set dual mac config */
10375 complete(&hdd_ctx->set_antenna_mode_cmpl);
10376}
10377
10378/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010379 * hdd_get_fw_version() - Get FW version
10380 * @hdd_ctx: pointer to HDD context.
10381 * @major_spid: FW version - major spid.
10382 * @minor_spid: FW version - minor spid
10383 * @ssid: FW version - ssid
10384 * @crmid: FW version - crmid
10385 *
10386 * This function is called to get the firmware build version stored
10387 * as part of the HDD context
10388 *
10389 * Return: None
10390 */
10391void hdd_get_fw_version(hdd_context_t *hdd_ctx,
10392 uint32_t *major_spid, uint32_t *minor_spid,
10393 uint32_t *siid, uint32_t *crmid)
10394{
10395 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
10396 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
10397 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
10398 *crmid = hdd_ctx->target_fw_version & 0x7fff;
10399}
10400
10401#ifdef QCA_CONFIG_SMP
10402/**
10403 * wlan_hdd_get_cpu() - get cpu_index
10404 *
10405 * Return: cpu_index
10406 */
10407int wlan_hdd_get_cpu(void)
10408{
10409 int cpu_index = get_cpu();
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411 put_cpu();
10412 return cpu_index;
10413}
10414#endif
10415
10416/**
10417 * hdd_get_fwpath() - get framework path
10418 *
10419 * This function is used to get the string written by
10420 * userspace to start the wlan driver
10421 *
10422 * Return: string
10423 */
10424const char *hdd_get_fwpath(void)
10425{
10426 return fwpath.string;
10427}
10428
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010429/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010430 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010431 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010432 * This function initilizes CDS global context with the help of cds_init. This
10433 * has to be the first function called after probe to get a valid global
10434 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010435 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010436 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010437 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010438int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010439{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010440 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010441 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010442
Houston Hoffman9e06e542016-12-12 12:06:26 -080010443 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010444#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10445 wlan_logging_sock_init_svc();
10446#endif
10447
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010448 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010449 hdd_err("Failed to allocate CDS context");
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010450 ret = -ENOMEM;
10451 goto err_out;
10452 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010453
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010454 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +053010455 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010456
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010457err_out:
10458 return ret;
10459}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010460
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010461/**
10462 * hdd_deinit() - Deinitialize Driver
10463 *
10464 * This function frees CDS global context with the help of cds_deinit. This
10465 * has to be the last function call in remove callback to free the global
10466 * context.
10467 */
10468void hdd_deinit(void)
10469{
Dustin Brownedce4a52017-05-10 11:59:15 -070010470 hdd_deinit_wowl();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010471 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010472
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010473#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10474 wlan_logging_sock_deinit_svc();
10475#endif
10476}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010477
Yue Ma6e7b1a02017-04-03 14:17:46 -070010478#ifdef QCA_WIFI_NAPIER_EMULATION
10479#define HDD_WLAN_START_WAIT_TIME ((CDS_WMA_TIMEOUT + 5000) * 100)
10480#else
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010481#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
Yue Ma6e7b1a02017-04-03 14:17:46 -070010482#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010483
Sachin Ahujadddd2632017-03-07 19:07:24 +053010484static int wlan_hdd_state_ctrl_param_open(struct inode *inode,
10485 struct file *file)
10486{
10487 return 0;
10488}
10489
10490static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
10491 const char __user *user_buf,
10492 size_t count,
10493 loff_t *f_pos)
10494{
10495 char buf;
10496 static const char wlan_off_str[] = "OFF";
10497 static const char wlan_on_str[] = "ON";
10498 int ret;
10499 unsigned long rc;
10500
10501 if (copy_from_user(&buf, user_buf, 3)) {
10502 pr_err("Failed to read buffer\n");
10503 return -EINVAL;
10504 }
10505
10506 if (strncmp(&buf, wlan_off_str, strlen(wlan_off_str)) == 0) {
10507 pr_debug("Wifi turning off from UI\n");
10508 goto exit;
10509 }
10510
10511 if (strncmp(&buf, wlan_on_str, strlen(wlan_on_str)) != 0) {
10512 pr_err("Invalid value received from framework");
10513 goto exit;
10514 }
10515
10516 if (!cds_is_driver_loaded()) {
Sachin Ahujaee62b542017-04-21 14:14:16 +053010517 init_completion(&wlan_start_comp);
Sachin Ahujadddd2632017-03-07 19:07:24 +053010518 rc = wait_for_completion_timeout(&wlan_start_comp,
10519 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
10520 if (!rc) {
10521 hdd_alert("Timed-out waiting in wlan_hdd_state_ctrl_param_write");
10522 ret = -EINVAL;
10523 hdd_start_complete(ret);
10524 return ret;
10525 }
10526
10527 hdd_start_complete(0);
10528 }
10529
10530exit:
10531 return count;
10532}
10533
10534
10535const struct file_operations wlan_hdd_state_fops = {
10536 .owner = THIS_MODULE,
10537 .open = wlan_hdd_state_ctrl_param_open,
10538 .write = wlan_hdd_state_ctrl_param_write,
10539};
10540
10541static int wlan_hdd_state_ctrl_param_create(void)
10542{
10543 unsigned int wlan_hdd_state_major = 0;
10544 int ret;
10545 struct device *dev;
10546
10547 device = MKDEV(wlan_hdd_state_major, 0);
10548
10549 ret = alloc_chrdev_region(&device, 0, dev_num, "qcwlanstate");
10550 if (ret) {
10551 pr_err("Failed to register qcwlanstate");
10552 goto dev_alloc_err;
10553 }
10554 wlan_hdd_state_major = MAJOR(device);
10555
10556 class = class_create(THIS_MODULE, WLAN_MODULE_NAME);
10557 if (IS_ERR(class)) {
10558 pr_err("wlan_hdd_state class_create error");
10559 goto class_err;
10560 }
10561
10562 dev = device_create(class, NULL, device, NULL, WLAN_MODULE_NAME);
10563 if (IS_ERR(dev)) {
10564 pr_err("wlan_hdd_statedevice_create error");
10565 goto err_class_destroy;
10566 }
10567
10568 cdev_init(&wlan_hdd_state_cdev, &wlan_hdd_state_fops);
10569 ret = cdev_add(&wlan_hdd_state_cdev, device, dev_num);
10570 if (ret) {
10571 pr_err("Failed to add cdev error");
10572 goto cdev_add_err;
10573 }
10574
10575 pr_info("wlan_hdd_state %s major(%d) initialized",
10576 WLAN_MODULE_NAME, wlan_hdd_state_major);
10577
10578 return 0;
10579
10580cdev_add_err:
10581 device_destroy(class, device);
10582err_class_destroy:
10583 class_destroy(class);
10584class_err:
10585 unregister_chrdev_region(device, dev_num);
10586dev_alloc_err:
10587 return -ENODEV;
10588}
10589
10590static void wlan_hdd_state_ctrl_param_destroy(void)
10591{
10592 cdev_del(&wlan_hdd_state_cdev);
10593 device_destroy(class, device);
10594 class_destroy(class);
10595 unregister_chrdev_region(device, dev_num);
10596
10597 pr_info("Device node unregistered");
10598}
10599
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010600/**
10601 * __hdd_module_init - Module init helper
10602 *
10603 * Module init helper function used by both module and static driver.
10604 *
10605 * Return: 0 for success, errno on failure
10606 */
10607static int __hdd_module_init(void)
10608{
10609 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010610
Dustin Brownab482ac2017-06-09 17:00:44 -070010611 pr_err("%s: Loading driver v%s (%s)%s\n",
10612 WLAN_MODULE_NAME,
10613 QWLAN_VERSIONSTR,
10614 BUILD_TIMESTAMP,
10615 TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010616
Sachin Ahujadddd2632017-03-07 19:07:24 +053010617 ret = wlan_hdd_state_ctrl_param_create();
10618 if (ret) {
10619 pr_err("wlan_hdd_state_create:%x\n", ret);
10620 goto err_dev_state;
10621 }
10622
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010623 pld_init();
10624
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010625 ret = hdd_init();
10626 if (ret) {
10627 pr_err("hdd_init failed %x\n", ret);
10628 goto err_hdd_init;
10629 }
10630
Rajeev Kumar97767a02016-11-30 11:20:40 -080010631 dispatcher_init();
10632
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010633 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010634
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010635 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010636
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010637 ret = wlan_hdd_register_driver();
10638 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -070010639 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
10640 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010641 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010642 }
10643
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010644 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010645
10646 return 0;
10647out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010648 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -080010649 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010650 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010651
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010652err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010653 pld_deinit();
Sachin Ahujadddd2632017-03-07 19:07:24 +053010654 wlan_hdd_state_ctrl_param_destroy();
10655err_dev_state:
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010656 return ret;
10657}
10658
10659/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010660 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
10661 *
10662 * Block the unloading of the driver until the cds recovery is completed
10663 *
10664 * Return: None
10665 */
10666static void hdd_wait_for_recovery_completion(void)
10667{
10668 int retry = 0;
10669
10670 /* Wait for recovery to complete */
10671 while (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010672 hdd_err("Recovery in progress; wait here!!!");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010673 msleep(1000);
10674 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010675 hdd_err("SSR never completed, error");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010676 QDF_BUG(0);
10677 }
10678 }
10679}
10680
10681/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010682 * __hdd_module_exit - Module exit helper
10683 *
10684 * Module exit helper function used by both module and static driver.
10685 */
10686static void __hdd_module_exit(void)
10687{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010688 int qdf_print_idx = -1;
10689
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010690 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
10691 QWLAN_VERSIONSTR);
10692
bings6028ee82017-03-29 07:51:40 +080010693 cds_set_unload_in_progress(true);
10694
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010695 hdd_wait_for_recovery_completion();
10696
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010697 wlan_hdd_unregister_driver();
10698
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010699 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010700
Rajeev Kumar97767a02016-11-30 11:20:40 -080010701 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010702 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010703 pld_deinit();
10704
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010705 qdf_print_idx = qdf_get_pidx();
10706 qdf_print_ctrl_cleanup(qdf_print_idx);
Sachin Ahujadddd2632017-03-07 19:07:24 +053010707 wlan_hdd_state_ctrl_param_destroy();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010708}
10709
Arun Khandavallifae92942016-08-01 13:31:08 +053010710#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010711/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010712 * wlan_boot_cb() - Wlan boot callback
10713 * @kobj: object whose directory we're creating the link in.
10714 * @attr: attribute the user is interacting with
10715 * @buff: the buffer containing the user data
10716 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010717 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010718 * This callback is invoked when the fs is ready to start the
10719 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010720 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010721 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010722 */
Arun Khandavallifae92942016-08-01 13:31:08 +053010723static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010724 struct kobj_attribute *attr,
10725 const char *buf,
10726 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010727{
Arun Khandavallifae92942016-08-01 13:31:08 +053010728
Arun Khandavallifae92942016-08-01 13:31:08 +053010729 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010730 pr_err("%s: wlan driver already initialized\n", __func__);
10731 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +053010732 }
10733
Arun Khandavallifae92942016-08-01 13:31:08 +053010734 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010735 pr_err("%s: wlan driver initialization failed\n", __func__);
10736 return -EIO;
10737 }
10738
10739 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +053010740
10741 return count;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010742}
Arun Khandavallifae92942016-08-01 13:31:08 +053010743
10744/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010745 * hdd_sysfs_cleanup() - cleanup sysfs
10746 *
10747 * Return: None
10748 *
10749 */
10750static void hdd_sysfs_cleanup(void)
10751{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010752 /* remove from group */
10753 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
10754 sysfs_remove_group(wlan_loader->boot_wlan_obj,
10755 wlan_loader->attr_group);
10756
10757 /* unlink the object from parent */
10758 kobject_del(wlan_loader->boot_wlan_obj);
10759
10760 /* free the object */
10761 kobject_put(wlan_loader->boot_wlan_obj);
10762
10763 kfree(wlan_loader->attr_group);
10764 kfree(wlan_loader);
10765
10766 wlan_loader = NULL;
10767}
10768
10769/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010770 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
10771 * ready
10772 *
10773 * This is creates the syfs entry boot_wlan. Which shall be invoked
10774 * when the filesystem is ready.
10775 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010776 * QDF API cannot be used here since this function is called even before
10777 * initializing WLAN driver.
10778 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010779 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +053010780 */
10781static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010782{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010783 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010784
10785 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010786 if (!wlan_loader)
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010787 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010788
10789 wlan_loader->boot_wlan_obj = NULL;
10790 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
10791 GFP_KERNEL);
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010792 if (!wlan_loader->attr_group)
Arun Khandavallifae92942016-08-01 13:31:08 +053010793 goto error_return;
Arun Khandavallifae92942016-08-01 13:31:08 +053010794
10795 wlan_loader->loaded_state = 0;
10796 wlan_loader->attr_group->attrs = attrs;
10797
10798 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
10799 kernel_kobj);
10800 if (!wlan_loader->boot_wlan_obj) {
10801 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010802 goto error_return;
10803 }
10804
10805 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
10806 wlan_loader->attr_group);
10807 if (ret) {
10808 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
10809 goto error_return;
10810 }
10811
10812 return 0;
10813
10814error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010815 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +053010816
10817 return ret;
10818}
10819
10820/**
10821 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
10822 *
10823 * Return: 0 on success or errno on failure
10824 */
10825static int wlan_deinit_sysfs(void)
10826{
Arun Khandavallifae92942016-08-01 13:31:08 +053010827 if (!wlan_loader) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010828 hdd_err("wlan loader context is Null!");
Arun Khandavallifae92942016-08-01 13:31:08 +053010829 return -EINVAL;
10830 }
10831
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010832 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010833 return 0;
10834}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010835
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010836#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +053010837
10838#ifdef MODULE
10839/**
10840 * __hdd_module_init - Module init helper
10841 *
10842 * Module init helper function used by both module and static driver.
10843 *
10844 * Return: 0 for success, errno on failure
10845 */
10846static int hdd_module_init(void)
10847{
Arun Khandavallifae92942016-08-01 13:31:08 +053010848 if (__hdd_module_init()) {
10849 pr_err("%s: Failed to register handler\n", __func__);
Dustin Brownab482ac2017-06-09 17:00:44 -070010850 return -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +053010851 }
10852
Dustin Brownab482ac2017-06-09 17:00:44 -070010853 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +053010854}
10855#else
10856static int __init hdd_module_init(void)
10857{
10858 int ret = -EINVAL;
10859
10860 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010861 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +053010862 pr_err("Failed to create sysfs entry for loading wlan");
10863
10864 return ret;
10865}
10866#endif
10867
10868
10869#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010870/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010871 * hdd_module_exit() - Exit function
10872 *
10873 * This is the driver exit point (invoked when module is unloaded using rmmod)
10874 *
10875 * Return: None
10876 */
10877static void __exit hdd_module_exit(void)
10878{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010879 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010880}
Arun Khandavallifae92942016-08-01 13:31:08 +053010881#else
10882static void __exit hdd_module_exit(void)
10883{
10884 __hdd_module_exit();
10885 wlan_deinit_sysfs();
10886}
10887#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010888
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010889static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
10890{
10891 return param_set_copystring(kmessage, kp);
10892}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010893
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010894/**
10895 * is_con_mode_valid() check con mode is valid or not
10896 * @mode: global con mode
10897 *
10898 * Return: TRUE on success FALSE on failure
10899 */
10900static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
10901{
10902 switch (mode) {
10903 case QDF_GLOBAL_MONITOR_MODE:
10904 case QDF_GLOBAL_FTM_MODE:
10905 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010906 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010907 return true;
10908 default:
10909 return false;
10910 }
10911}
10912
10913/**
10914 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
10915 * @mode: global con mode
10916 *
10917 * Return: adapter mode
10918 */
10919static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
10920 enum tQDF_GLOBAL_CON_MODE mode)
10921{
10922
10923 switch (mode) {
10924 case QDF_GLOBAL_MISSION_MODE:
10925 return QDF_STA_MODE;
10926 case QDF_GLOBAL_MONITOR_MODE:
10927 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010928 case QDF_GLOBAL_EPPING_MODE:
10929 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010930 case QDF_GLOBAL_FTM_MODE:
10931 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010932 case QDF_GLOBAL_QVIT_MODE:
10933 return QDF_QVIT_MODE;
10934 default:
10935 return QDF_MAX_NO_OF_MODE;
10936 }
10937}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010938
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010939static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
10940 enum tQDF_GLOBAL_CON_MODE curr_mode)
10941{
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010942 int driver_status;
10943
10944 driver_status = hdd_ctx->driver_status;
10945
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010946 switch (curr_mode) {
10947 case QDF_GLOBAL_MISSION_MODE:
10948 case QDF_GLOBAL_MONITOR_MODE:
10949 case QDF_GLOBAL_FTM_MODE:
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010950 if (driver_status != DRIVER_MODULES_CLOSED) {
10951 hdd_abort_mac_scan_all_adapters(hdd_ctx);
10952 hdd_stop_all_adapters(hdd_ctx);
10953 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010954 hdd_deinit_all_adapters(hdd_ctx, false);
10955 hdd_close_all_adapters(hdd_ctx, false);
10956 break;
10957 case QDF_GLOBAL_EPPING_MODE:
10958 epping_disable();
10959 epping_close();
10960 break;
10961 default:
10962 return;
10963 }
10964}
10965
10966static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
10967 enum tQDF_GLOBAL_CON_MODE mode)
10968{
10969 hdd_adapter_t *adapter;
10970 int ret = 0;
10971 bool rtnl_held;
10972 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
10973 QDF_STATUS status;
10974
10975 if (!qdf_dev) {
10976 hdd_err("qdf device context is Null return!");
10977 return -EINVAL;
10978 }
10979
10980 rtnl_held = hdd_hold_rtnl_lock();
10981 switch (mode) {
10982 case QDF_GLOBAL_MISSION_MODE:
Jeff Johnson957bc272017-02-02 08:54:48 -080010983 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
10984 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010985 hdd_err("Failed to open interfaces: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010986 break;
10987 case QDF_GLOBAL_FTM_MODE:
10988 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
10989 wlan_hdd_get_intf_addr(hdd_ctx),
10990 NET_NAME_UNKNOWN, rtnl_held);
10991 if (adapter == NULL)
10992 ret = -EINVAL;
10993 break;
10994 case QDF_GLOBAL_MONITOR_MODE:
10995 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
10996 wlan_hdd_get_intf_addr(hdd_ctx),
10997 NET_NAME_UNKNOWN, rtnl_held);
10998 if (adapter == NULL)
10999 ret = -EINVAL;
11000 break;
11001 case QDF_GLOBAL_EPPING_MODE:
11002 status = epping_open();
Srinivas Girigowdab841da72017-03-25 18:04:39 -070011003 if (status != QDF_STATUS_SUCCESS) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011004 hdd_err("Failed to open in eeping mode: %d", status);
11005 ret = -EINVAL;
11006 break;
11007 }
11008 ret = epping_enable(qdf_dev->dev);
11009 if (ret) {
11010 hdd_err("Failed to enable in epping mode : %d", ret);
11011 epping_close();
11012 }
11013 break;
11014 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011015 hdd_err("Mode not supported");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011016 ret = -ENOTSUPP;
11017 break;
11018 }
11019 hdd_release_rtnl_lock();
11020 rtnl_held = false;
11021 return ret;
11022}
11023
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011024/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053011025 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011026 * @kmessage: con mode name on which driver to be bring up
11027 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053011028 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011029 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011030 * This function is invoked when user updates con mode using sys entry,
11031 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011032 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011033 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011034 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011035static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
11036 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011037{
11038 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +053011039 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011040 enum tQDF_GLOBAL_CON_MODE curr_mode;
11041 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011042
Dustin Brownab6029b2017-05-24 13:04:19 -070011043 hdd_info("con_mode handler: %s", kmessage);
11044
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053011045 ret = wlan_hdd_validate_context(hdd_ctx);
11046 if (ret)
11047 return ret;
11048
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011049 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011050
11051 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +053011052
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011053 if (!(is_con_mode_valid(con_mode))) {
11054 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011055 ret = -EINVAL;
11056 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011057 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011058
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011059 curr_mode = hdd_get_conparam();
11060 if (curr_mode == con_mode) {
11061 hdd_err("curr mode: %d is same as user triggered mode %d",
11062 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011063 ret = 0;
11064 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011065 }
11066
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011067 /* Cleanup present mode before switching to new mode */
11068 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +053011069
Rajeev Kumar3fef4e82017-03-31 20:25:23 -070011070 ret = hdd_wlan_stop_modules(hdd_ctx, true);
Arun Khandavallifae92942016-08-01 13:31:08 +053011071 if (ret) {
11072 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011073 goto reset_flags;
11074 }
11075
11076 hdd_set_conparam(con_mode);
11077
11078 /* Register for new con_mode & then kick_start modules again */
11079 ret = hdd_register_req_mode(hdd_ctx, con_mode);
11080 if (ret) {
11081 hdd_err("Failed to register for new mode");
11082 goto reset_flags;
11083 }
11084
11085 adapter_mode = hdd_get_adpter_mode(con_mode);
11086 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
11087 hdd_err("invalid adapter");
11088 ret = -EINVAL;
11089 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053011090 }
11091
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053011092 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +053011093 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011094 hdd_err("Failed to get adapter:%d", adapter_mode);
11095 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053011096 }
11097
11098 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
11099 if (ret) {
11100 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011101 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053011102 }
11103
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011104 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
11105 con_mode == QDF_GLOBAL_FTM_MODE) {
11106 if (hdd_start_adapter(adapter)) {
11107 hdd_err("Failed to start %s adapter", kmessage);
11108 ret = -EINVAL;
11109 goto reset_flags;
11110 }
Arun Khandavallifae92942016-08-01 13:31:08 +053011111 }
11112
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053011113 hdd_info("Mode successfully changed to %s", kmessage);
11114 ret = 0;
11115
11116reset_flags:
11117 cds_set_load_in_progress(false);
11118 return ret;
11119}
11120
11121
11122static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
11123{
11124 int ret;
11125 hdd_context_t *hdd_ctx;
11126
11127 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11128 ret = wlan_hdd_validate_context(hdd_ctx);
11129 if (ret)
11130 return ret;
11131
11132 cds_ssr_protect(__func__);
11133 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
11134 cds_ssr_unprotect(__func__);
11135
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011136 return ret;
11137}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011138
11139/**
11140 * hdd_get_conparam() - driver exit point
11141 *
11142 * This is the driver exit point (invoked when module is unloaded using rmmod)
11143 *
Anurag Chouhan6d760662016-02-20 16:05:43 +053011144 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011145 */
Anurag Chouhan6d760662016-02-20 16:05:43 +053011146enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011147{
Anurag Chouhan6d760662016-02-20 16:05:43 +053011148 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011149}
11150
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080011151void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011152{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080011153 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080011154}
11155
Komal Seelamc11bb222016-01-27 18:57:10 +053011156/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053011157 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
11158 * @hdd_ctx: HDD context
11159 *
11160 * Cleans up the pre cac interface, if it exists
11161 *
11162 * Return: None
11163 */
11164void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
11165{
11166 uint8_t session_id;
11167 QDF_STATUS status;
11168 struct hdd_adapter_s *precac_adapter;
11169
11170 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
11171 if (QDF_IS_STATUS_ERROR(status)) {
11172 hdd_err("failed to get pre cac vdev id");
11173 return;
11174 }
11175
11176 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
11177 if (!precac_adapter) {
11178 hdd_err("invalid pre cac adapater");
11179 return;
11180 }
11181
11182 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
11183 wlan_hdd_sap_pre_cac_failure,
11184 (void *)precac_adapter);
11185 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
11186
11187}
11188
11189/**
Komal Seelamec702b02016-02-24 18:42:16 +053011190 * hdd_update_ol_config - API to update ol configuration parameters
11191 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +053011192 *
Komal Seelamc11bb222016-01-27 18:57:10 +053011193 * Return: void
11194 */
Komal Seelamec702b02016-02-24 18:42:16 +053011195static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +053011196{
Komal Seelamec702b02016-02-24 18:42:16 +053011197 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +053011198 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +053011199
Komal Seelamec702b02016-02-24 18:42:16 +053011200 if (!ol_ctx)
11201 return;
11202
11203 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
11204 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
11205 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
11206 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -070011207 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +053011208
11209 ol_init_ini_config(ol_ctx, &cfg);
11210}
11211
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070011212#ifdef FEATURE_RUNTIME_PM
11213/**
11214 * hdd_populate_runtime_cfg() - populate runtime configuration
11215 * @hdd_ctx: hdd context
11216 * @cfg: pointer to the configuration memory being populated
11217 *
11218 * Return: void
11219 */
11220static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
11221 struct hif_config_info *cfg)
11222{
11223 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
11224 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
11225}
11226#else
11227static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
11228 struct hif_config_info *cfg)
11229{
11230}
11231#endif
11232
Komal Seelamec702b02016-02-24 18:42:16 +053011233/**
11234 * hdd_update_hif_config - API to update HIF configuration parameters
11235 * @hdd_ctx: HDD Context
11236 *
11237 * Return: void
11238 */
11239static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
11240{
Anurag Chouhandf2b2682016-02-29 14:15:27 +053011241 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +053011242 struct hif_config_info cfg;
11243
11244 if (!scn)
11245 return;
11246
11247 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070011248 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053011249 hif_init_ini_config(scn, &cfg);
11250}
11251
11252/**
11253 * hdd_update_config() - Initialize driver per module ini parameters
11254 * @hdd_ctx: HDD Context
11255 *
11256 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011257 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053011258 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011259int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053011260{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011261 int ret;
11262
Komal Seelamec702b02016-02-24 18:42:16 +053011263 hdd_update_ol_config(hdd_ctx);
11264 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011265 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
11266 ret = hdd_update_cds_config_ftm(hdd_ctx);
11267 else
11268 ret = hdd_update_cds_config(hdd_ctx);
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -080011269 ret = hdd_update_user_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011270
11271 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053011272}
11273
Mukul Sharma9d797a02017-01-05 20:26:03 +053011274#ifdef FEATURE_WLAN_RA_FILTERING
11275/**
11276 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
11277 * @psoc_cfg: pmo psoc Configuration
11278 * @hdd_ctx: Pointer to hdd context
11279 *
11280 * Return: none
11281 */
11282static inline void hdd_ra_populate_pmo_config(
11283 struct pmo_psoc_cfg *psoc_cfg,
11284 hdd_context_t *hdd_ctx)
11285{
11286 psoc_cfg->ra_ratelimit_interval =
11287 hdd_ctx->config->RArateLimitInterval;
11288 psoc_cfg->ra_ratelimit_enable =
11289 hdd_ctx->config->IsRArateLimitEnabled;
11290}
11291#else
11292static inline void hdd_ra_populate_pmo_config(
11293 struct cds_config_info *cds_cfg,
11294 hdd_context_t *hdd_ctx)
11295{
11296}
11297#endif
11298/**
11299 * hdd_update_pmo_config - API to update pmo configuration parameters
11300 * @hdd_ctx: HDD context
11301 *
11302 * Return: void
11303 */
11304static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
11305{
11306 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
11307 struct pmo_psoc_cfg psoc_cfg;
11308 QDF_STATUS status;
11309
11310 /*
11311 * Value of hdd_ctx->wowEnable can be,
11312 * 0 - Disable both magic pattern match and pattern byte match.
11313 * 1 - Enable magic pattern match on all interfaces.
11314 * 2 - Enable pattern byte match on all interfaces.
11315 * 3 - Enable both magic patter and pattern byte match on
11316 * all interfaces.
11317 */
11318 psoc_cfg.magic_ptrn_enable =
11319 (hdd_ctx->config->wowEnable & 0x01) ? true : false;
11320 psoc_cfg.ptrn_match_enable_all_vdev =
11321 (hdd_ctx->config->wowEnable & 0x02) ? true : false;
11322 psoc_cfg.bpf_enable =
11323 hdd_ctx->config->bpf_packet_filter_enable;
11324 psoc_cfg.arp_offload_enable = hdd_ctx->config->fhostArpOffload;
Dustin Brown1224e212017-05-12 14:02:12 -070011325 psoc_cfg.hw_filter_mode = hdd_ctx->config->hw_filter_mode;
Mukul Sharma9d797a02017-01-05 20:26:03 +053011326 psoc_cfg.ns_offload_enable_static = hdd_ctx->config->fhostNSOffload;
11327 if (hdd_ctx->config->fhostNSOffload)
11328 psoc_cfg.ns_offload_enable_dynamic = true;
11329 psoc_cfg.ssdp = hdd_ctx->config->ssdp;
11330 psoc_cfg.enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
11331 psoc_cfg.active_mode_offload =
11332 hdd_ctx->config->active_mode_offload;
11333 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
11334 psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters;
Mukul Sharma9223f232017-03-08 18:42:27 +053011335 psoc_cfg.sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
11336 psoc_cfg.sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
11337 psoc_cfg.sta_max_li_mod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
11338 psoc_cfg.power_save_mode =
11339 hdd_ctx->config->enablePowersaveOffload;
Mukul Sharma9d797a02017-01-05 20:26:03 +053011340
11341 hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9223f232017-03-08 18:42:27 +053011342 hdd_nan_populate_pmo_config(&psoc_cfg, hdd_ctx);
11343 hdd_lpass_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053011344 status = pmo_ucfg_update_psoc_config(psoc, &psoc_cfg);
11345 if (status != QDF_STATUS_SUCCESS) {
11346 hdd_err("failed pmo psoc configuration");
11347 return -EINVAL;
11348 }
11349
11350 return 0;
11351}
11352
Abhishek Singh257a9482017-03-06 16:52:39 +053011353#ifdef NAPIER_SCAN
Abhishek Singhb20db962017-03-03 21:28:46 +053011354
11355#ifdef FEATURE_WLAN_SCAN_PNO
11356static inline void hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
11357 struct hdd_config *cfg)
11358{
11359 pno_cfg->channel_prediction = cfg->pno_channel_prediction;
11360 pno_cfg->top_k_num_of_channels = cfg->top_k_num_of_channels;
11361 pno_cfg->stationary_thresh = cfg->stationary_thresh;
11362 pno_cfg->adaptive_dwell_mode = cfg->adaptive_dwell_mode_enabled;
11363 pno_cfg->channel_prediction_full_scan =
11364 cfg->channel_prediction_full_scan;
11365}
11366#else
11367static inline void
11368hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
11369 struct hdd_config *cfg)
11370{
11371 return;
11372}
11373#endif
11374
Abhishek Singh257a9482017-03-06 16:52:39 +053011375/**
11376 * hdd_update_scan_config - API to update scan configuration parameters
11377 * @hdd_ctx: HDD context
11378 *
11379 * Return: 0 if success else err
11380 */
11381static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
11382{
11383 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
11384 struct scan_user_cfg scan_cfg;
11385 struct hdd_config *cfg = hdd_ctx->config;
11386 QDF_STATUS status;
11387
11388 scan_cfg.active_dwell = cfg->nActiveMaxChnTime;
11389 scan_cfg.passive_dwell = cfg->nPassiveMaxChnTime;
11390 scan_cfg.conc_active_dwell = cfg->nActiveMaxChnTimeConc;
11391 scan_cfg.conc_passive_dwell = cfg->nPassiveMaxChnTimeConc;
11392 scan_cfg.conc_max_rest_time = cfg->nRestTimeConc;
11393 scan_cfg.conc_min_rest_time = cfg->min_rest_time_conc;
11394 scan_cfg.conc_idle_time = cfg->idle_time_conc;
Abhishek Singh158fe252017-03-23 11:09:34 +053011395 /* convert to ms */
11396 scan_cfg.scan_cache_aging_time =
11397 cfg->scanAgingTimeout * 1000;
11398 scan_cfg.prefer_5ghz = cfg->nRoamPrefer5GHz;
11399 scan_cfg.select_5ghz_margin = cfg->nSelect5GHzMargin;
11400 scan_cfg.scan_bucket_threshold = cfg->first_scan_bucket_threshold;
11401 scan_cfg.rssi_cat_gap = cfg->nRssiCatGap;
Abhishek Singh257a9482017-03-06 16:52:39 +053011402 scan_cfg.scan_dwell_time_mode = cfg->scan_adaptive_dwell_mode;
Kapil Guptafa9a8c62017-04-10 15:25:40 +053011403 scan_cfg.is_snr_monitoring_enabled = cfg->fEnableSNRMonitoring;
Abhishek Singh257a9482017-03-06 16:52:39 +053011404
Abhishek Singhb20db962017-03-03 21:28:46 +053011405 hdd_update_pno_config(&scan_cfg.pno_cfg, cfg);
11406
Abhishek Singh257a9482017-03-06 16:52:39 +053011407 status = ucfg_scan_update_user_config(psoc, &scan_cfg);
11408 if (status != QDF_STATUS_SUCCESS) {
11409 hdd_err("failed pmo psoc configuration");
11410 return -EINVAL;
11411 }
11412
11413 return 0;
11414}
11415#else
11416static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
11417{
11418 return 0;
11419}
11420#endif
11421
Frank Liud4b2fa02017-03-29 11:46:48 +080011422#ifdef CONVERGED_TDLS_ENABLE
11423static int hdd_update_tdls_config(hdd_context_t *hdd_ctx)
11424{
11425 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
11426 struct tdls_start_params tdls_cfg;
11427 struct tdls_user_config *config = &tdls_cfg.config;
11428 struct hdd_config *cfg = hdd_ctx->config;
11429 QDF_STATUS status;
11430
11431 config->tdls_tx_states_period = cfg->fTDLSTxStatsPeriod;
11432 config->tdls_tx_pkt_threshold = cfg->fTDLSTxPacketThreshold;
11433 config->tdls_rx_pkt_threshold = cfg->fTDLSRxFrameThreshold;
11434 config->tdls_max_discovery_attempt = cfg->fTDLSMaxDiscoveryAttempt;
11435 config->tdls_idle_timeout = cfg->tdls_idle_timeout;
11436 config->tdls_idle_pkt_threshold = cfg->fTDLSIdlePacketThreshold;
11437 config->tdls_rssi_trigger_threshold = cfg->fTDLSRSSITriggerThreshold;
11438 config->tdls_rssi_teardown_threshold = cfg->fTDLSRSSITeardownThreshold;
11439 config->tdls_rssi_delta = cfg->fTDLSRSSIDelta;
11440 config->tdls_uapsd_mask = cfg->fTDLSUapsdMask;
11441 config->tdls_uapsd_inactivity_time = cfg->fTDLSPuapsdInactivityTimer;
11442 config->tdls_uapsd_pti_window = cfg->fTDLSPuapsdPTIWindow;
11443 config->tdls_uapsd_ptr_timeout = cfg->fTDLSPuapsdPTRTimeout;
11444 config->tdls_pre_off_chan_num = cfg->fTDLSPrefOffChanNum;
11445 config->tdls_pre_off_chan_bw = cfg->fTDLSPrefOffChanBandwidth;
11446 config->tdls_peer_kickout_threshold = cfg->tdls_peer_kickout_threshold;
11447 config->delayed_trig_framint = cfg->DelayedTriggerFrmInt;
11448 config->tdls_feature_flags = ((cfg->fEnableTDLSOffChannel ?
11449 1 << TDLS_FEATURE_OFF_CHANNEL : 0) |
11450 (cfg->fEnableTDLSWmmMode ? 1 << TDLS_FEATURE_WMM : 0) |
11451 (cfg->fEnableTDLSBufferSta ? 1 << TDLS_FEATURE_BUFFER_STA : 0) |
11452 (cfg->fEnableTDLSSleepSta ? 1 << TDLS_FEATURE_SLEEP_STA : 0) |
11453 (cfg->enable_tdls_scan ? 1 << TDLS_FEATURE_SCAN : 0) |
11454 (cfg->fEnableTDLSSupport ? 1 << TDLS_FEATURE_ENABLE : 0) |
11455 (cfg->fEnableTDLSImplicitTrigger ?
11456 1 << TDLS_FEAUTRE_IMPLICIT_TRIGGER : 0) |
11457 (cfg->fTDLSExternalControl ?
11458 1 << TDLS_FEATURE_EXTERNAL_CONTROL : 0));
11459
11460 tdls_cfg.tdls_send_mgmt_req = eWNI_SME_TDLS_SEND_MGMT_REQ;
11461 tdls_cfg.tdls_add_sta_req = eWNI_SME_TDLS_ADD_STA_REQ;
11462 tdls_cfg.tdls_del_sta_req = eWNI_SME_TDLS_DEL_STA_REQ;
11463 tdls_cfg.tdls_update_peer_state = WMA_UPDATE_TDLS_PEER_STATE;
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011464 tdls_cfg.tdls_del_all_peers = eWNI_SME_DEL_ALL_TDLS_PEERS;
Kabilan Kannan256e3182017-05-02 16:02:37 -070011465 tdls_cfg.tdls_update_dp_vdev_flags = CDP_UPDATE_TDLS_FLAGS;
Frank Liud4b2fa02017-03-29 11:46:48 +080011466 tdls_cfg.tdls_event_cb = wlan_cfg80211_tdls_event_callback;
11467 tdls_cfg.tdls_evt_cb_data = psoc;
11468 tdls_cfg.tdls_tl_peer_data = hdd_ctx;
11469 tdls_cfg.tdls_reg_tl_peer = hdd_tdls_register_tdls_peer;
11470 tdls_cfg.tdls_dereg_tl_peer = hdd_tdls_deregister_tdl_peer;
Kabilan Kannanf56f9d52017-04-05 03:31:34 -070011471 tdls_cfg.tdls_wmm_cb = hdd_wmm_is_acm_allowed;
11472 tdls_cfg.tdls_wmm_cb_data = psoc;
11473 tdls_cfg.tdls_rx_cb = wlan_cfg80211_tdls_rx_callback;
11474 tdls_cfg.tdls_rx_cb_data = psoc;
Kabilan Kannan256e3182017-05-02 16:02:37 -070011475 tdls_cfg.tdls_dp_vdev_update = hdd_update_dp_vdev_flags;
Frank Liud4b2fa02017-03-29 11:46:48 +080011476
11477 status = ucfg_tdls_update_config(psoc, &tdls_cfg);
11478 if (status != QDF_STATUS_SUCCESS) {
11479 hdd_err("failed pmo psoc configuration");
11480 return -EINVAL;
11481 }
11482
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011483 hdd_ctx->tdls_umac_comp_active = true;
Kabilan Kannan256e3182017-05-02 16:02:37 -070011484 /* disable napier specific tdls data path */
11485 hdd_ctx->tdls_nap_active = false;
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011486
Frank Liud4b2fa02017-03-29 11:46:48 +080011487 return 0;
11488}
11489#else
11490static int hdd_update_tdls_config(hdd_context_t *hdd_ctx)
11491{
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011492 hdd_ctx->tdls_umac_comp_active = false;
Kabilan Kannan256e3182017-05-02 16:02:37 -070011493 /* disable napier specific tdls data path */
11494 hdd_ctx->tdls_nap_active = false;
Frank Liud4b2fa02017-03-29 11:46:48 +080011495 return 0;
11496}
11497#endif
11498
Mukul Sharma9d797a02017-01-05 20:26:03 +053011499int hdd_update_components_config(hdd_context_t *hdd_ctx)
11500{
11501 int ret;
11502
11503 ret = hdd_update_pmo_config(hdd_ctx);
Abhishek Singh257a9482017-03-06 16:52:39 +053011504 if (ret)
11505 return ret;
11506 ret = hdd_update_scan_config(hdd_ctx);
Frank Liud4b2fa02017-03-29 11:46:48 +080011507 if (ret)
11508 return ret;
11509 ret = hdd_update_tdls_config(hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053011510
11511 return ret;
11512}
11513
Agrawal Ashish65634612016-08-18 13:24:32 +053011514/**
11515 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
11516 * @mode : cfg80211 DFS mode
11517 *
11518 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
11519 */
11520enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
11521{
11522 switch (mode) {
11523 case DFS_MODE_ENABLE:
11524 return ACS_DFS_MODE_ENABLE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011525 case DFS_MODE_DISABLE:
11526 return ACS_DFS_MODE_DISABLE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011527 case DFS_MODE_DEPRIORITIZE:
11528 return ACS_DFS_MODE_DEPRIORITIZE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011529 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011530 hdd_debug("ACS dfs mode is NONE");
11531 return ACS_DFS_MODE_NONE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011532 }
11533}
11534
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011535/**
11536 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
11537 * @hddctx: pointer to hdd context
11538 * @set_value: enable/disable
11539 *
11540 * When Host sends vendor command enable, FW will send *ONE* CA ind to
11541 * Host(even though it is duplicate). When Host send vendor command
11542 * disable,FW doesn't perform any action. Whenever any change in
11543 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
11544 *
11545 * return - 0 on success, appropriate error values on failure.
11546 */
11547int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
11548{
11549 QDF_STATUS status;
11550
Srinivas Girigowdab841da72017-03-25 18:04:39 -070011551 if (0 != wlan_hdd_validate_context(hddctx))
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011552 return -EAGAIN;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011553
11554 if (!hddctx->config->goptimize_chan_avoid_event) {
11555 hdd_warn("goptimize_chan_avoid_event ini param disabled");
11556 return -EINVAL;
11557 }
11558
11559 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
11560 if (!QDF_IS_STATUS_SUCCESS(status)) {
11561 hdd_err("Failed to send chan avoid command to SME");
11562 return -EINVAL;
11563 }
11564 return 0;
11565}
Agrawal Ashish65634612016-08-18 13:24:32 +053011566
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011567/**
11568 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
11569 * @value: value to set
11570 *
11571 * This function will set the passed value to roaming in progress flag.
11572 *
11573 * Return: None
11574 */
11575void hdd_set_roaming_in_progress(bool value)
11576{
11577 hdd_context_t *hdd_ctx;
11578
11579 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11580 if (!hdd_ctx) {
11581 hdd_err("HDD context is NULL");
11582 return;
11583 }
11584
11585 hdd_ctx->roaming_in_progress = value;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011586 hdd_debug("Roaming in Progress set to %d", value);
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011587}
11588
11589/**
11590 * hdd_is_roaming_in_progress() - check if roaming is in progress
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011591 * @adapter - HDD adapter
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011592 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011593 * Return: true if roaming is in progress for STA type, else false
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011594 */
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011595bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter)
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011596{
11597 hdd_context_t *hdd_ctx;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011598 bool ret_status = false;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011599
11600 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11601 if (!hdd_ctx) {
11602 hdd_err("HDD context is NULL");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011603 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011604 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011605 hdd_debug("dev mode = %d, roaming_in_progress = %d",
11606 adapter->device_mode, hdd_ctx->roaming_in_progress);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011607 ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
11608 hdd_ctx->roaming_in_progress);
11609
11610 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011611}
11612
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011613/**
11614 * hdd_is_connection_in_progress() - check if connection is in
11615 * progress
11616 * @session_id: session id
11617 * @reason: scan reject reason
11618 *
11619 * Go through each adapter and check if Connection is in progress
11620 *
11621 * Return: true if connection is in progress else false
11622 */
11623bool hdd_is_connection_in_progress(uint8_t *session_id,
11624 enum scan_reject_states *reason)
11625{
11626 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
11627 hdd_station_ctx_t *hdd_sta_ctx = NULL;
11628 hdd_adapter_t *adapter = NULL;
11629 QDF_STATUS status = 0;
11630 uint8_t sta_id = 0;
11631 uint8_t *sta_mac = NULL;
11632 hdd_context_t *hdd_ctx;
11633
11634 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11635 if (!hdd_ctx) {
11636 hdd_err("HDD context is NULL");
11637 return false;
11638 }
11639
11640 if (true == hdd_ctx->btCoexModeSet) {
11641 hdd_info("BTCoex Mode operation in progress");
11642 return true;
11643 }
11644 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
11645 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
11646 adapter = adapter_node->pAdapter;
11647 if (!adapter)
11648 goto end;
11649
11650 hdd_info("Adapter with device mode %s(%d) exists",
11651 hdd_device_mode_to_string(adapter->device_mode),
11652 adapter->device_mode);
11653 if (((QDF_STA_MODE == adapter->device_mode)
11654 || (QDF_P2P_CLIENT_MODE == adapter->device_mode)
11655 || (QDF_P2P_DEVICE_MODE == adapter->device_mode))
11656 && (eConnectionState_Connecting ==
11657 (WLAN_HDD_GET_STATION_CTX_PTR(adapter))->
11658 conn_info.connState)) {
11659 hdd_err("%p(%d) Connection is in progress",
11660 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11661 adapter->sessionId);
11662 if (session_id && reason) {
11663 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011664 *reason = CONNECTION_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011665 }
11666 return true;
11667 }
Archana Ramachandran62886ce2017-03-24 14:46:32 -070011668 /*
11669 * sme_neighbor_middle_of_roaming is for LFR2
11670 * hdd_is_roaming_in_progress is for LFR3
11671 */
11672 if (((QDF_STA_MODE == adapter->device_mode) &&
11673 sme_neighbor_middle_of_roaming(
11674 WLAN_HDD_GET_HAL_CTX(adapter),
11675 adapter->sessionId)) ||
11676 hdd_is_roaming_in_progress(adapter)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011677 hdd_err("%p(%d) Reassociation in progress",
11678 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11679 adapter->sessionId);
11680 if (session_id && reason) {
11681 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011682 *reason = REASSOC_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011683 }
11684 return true;
11685 }
11686 if ((QDF_STA_MODE == adapter->device_mode) ||
11687 (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
11688 (QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
11689 hdd_sta_ctx =
11690 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
11691 if ((eConnectionState_Associated ==
11692 hdd_sta_ctx->conn_info.connState)
11693 && (false ==
11694 hdd_sta_ctx->conn_info.uIsAuthenticated)) {
11695 sta_mac = (uint8_t *)
11696 &(adapter->macAddressCurrent.bytes[0]);
11697 hdd_err("client " MAC_ADDRESS_STR
11698 " is in middle of WPS/EAPOL exchange.",
11699 MAC_ADDR_ARRAY(sta_mac));
11700 if (session_id && reason) {
11701 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011702 *reason = EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011703 }
11704 return true;
11705 }
11706 } else if ((QDF_SAP_MODE == adapter->device_mode) ||
11707 (QDF_P2P_GO_MODE == adapter->device_mode)) {
11708 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
11709 sta_id++) {
11710 if (!((adapter->aStaInfo[sta_id].isUsed)
11711 && (OL_TXRX_PEER_STATE_CONN ==
11712 adapter->aStaInfo[sta_id].tlSTAState)))
11713 continue;
11714
11715 sta_mac = (uint8_t *)
11716 &(adapter->aStaInfo[sta_id].
11717 macAddrSTA.bytes[0]);
11718 hdd_err("client " MAC_ADDRESS_STR
11719 " of SAP/GO is in middle of WPS/EAPOL exchange",
11720 MAC_ADDR_ARRAY(sta_mac));
11721 if (session_id && reason) {
11722 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011723 *reason = SAP_EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011724 }
11725 return true;
11726 }
11727 if (hdd_ctx->connection_in_progress) {
11728 hdd_err("AP/GO: connection is in progress");
11729 return true;
11730 }
11731 }
11732end:
11733 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
11734 adapter_node = next;
11735 }
11736 return false;
11737}
11738
11739/**
11740 * hdd_restart_sap() - to restart SAP in driver internally
11741 * @ap_adapter: Pointer to SAP hdd_adapter_t structure
11742 *
11743 * Return: None
11744 */
11745void hdd_restart_sap(hdd_adapter_t *ap_adapter)
11746{
11747 hdd_ap_ctx_t *hdd_ap_ctx;
11748 hdd_hostapd_state_t *hostapd_state;
11749 QDF_STATUS qdf_status;
11750 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
11751 tsap_Config_t *sap_config;
11752 void *sap_ctx;
11753
11754 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11755 sap_config = &hdd_ap_ctx->sapConfig;
11756 sap_ctx = hdd_ap_ctx->sapContext;
11757
11758 mutex_lock(&hdd_ctx->sap_lock);
11759 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
11760 wlan_hdd_del_station(ap_adapter);
11761 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
11762 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11763 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
11764 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {
11765 qdf_status =
11766 qdf_wait_single_event(&hostapd_state->
11767 qdf_stop_bss_event,
11768 SME_CMD_TIMEOUT_VALUE);
11769
11770 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11771 cds_err("SAP Stop Failed");
11772 goto end;
11773 }
11774 }
11775 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011776 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011777 ap_adapter->device_mode, ap_adapter->sessionId);
11778 cds_err("SAP Stop Success");
11779
11780 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
11781 cds_err("SAP Not able to set AP IEs");
11782 wlansap_reset_sap_config_add_ie(sap_config,
11783 eUPDATE_IE_ALL);
11784 goto end;
11785 }
11786
11787 qdf_event_reset(&hostapd_state->qdf_event);
11788 if (wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb,
11789 sap_config,
11790 ap_adapter->dev) != QDF_STATUS_SUCCESS) {
11791 cds_err("SAP Start Bss fail");
11792 wlansap_reset_sap_config_add_ie(sap_config,
11793 eUPDATE_IE_ALL);
11794 goto end;
11795 }
11796
11797 cds_info("Waiting for SAP to start");
11798 qdf_status =
11799 qdf_wait_single_event(&hostapd_state->qdf_event,
11800 SME_CMD_TIMEOUT_VALUE);
11801 wlansap_reset_sap_config_add_ie(sap_config,
11802 eUPDATE_IE_ALL);
11803 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11804 cds_err("SAP Start failed");
11805 goto end;
11806 }
11807 cds_err("SAP Start Success");
11808 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
11809 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011810 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
11811 ap_adapter->device_mode,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011812 ap_adapter->sessionId);
11813 hostapd_state->bCommit = true;
11814 }
11815end:
11816 mutex_unlock(&hdd_ctx->sap_lock);
11817 return;
11818}
11819
11820/**
11821 * hdd_check_and_restart_sap_with_non_dfs_acs() - Restart SAP
11822 * with non dfs acs
11823 *
11824 * Restarts SAP in non-DFS ACS mode when STA-AP mode DFS is not supported
11825 *
11826 * Return: None
11827 */
11828void hdd_check_and_restart_sap_with_non_dfs_acs(void)
11829{
11830 hdd_adapter_t *ap_adapter;
11831 hdd_context_t *hdd_ctx;
11832 cds_context_type *cds_ctx;
11833
11834 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11835 if (!hdd_ctx) {
11836 cds_err("HDD context is NULL");
11837 return;
11838 }
11839
11840 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
11841 if (!cds_ctx) {
11842 cds_err("Invalid CDS Context");
11843 return;
11844 }
11845
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011846 if (policy_mgr_get_concurrency_mode(hdd_ctx->hdd_psoc)
11847 != (QDF_STA_MASK | QDF_SAP_MASK)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011848 cds_info("Concurrency mode is not SAP");
11849 return;
11850 }
11851
11852 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011853 if (ap_adapter != NULL && test_bit(SOFTAP_BSS_STARTED,
11854 &ap_adapter->event_flags) &&
11855 wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
11856 ap_adapter->sessionCtx.ap.operatingChannel)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011857
11858 cds_warn("STA-AP Mode DFS not supported. Restart SAP with Non DFS ACS");
11859 ap_adapter->sessionCtx.ap.sapConfig.channel =
11860 AUTO_CHANNEL_SELECT;
11861 ap_adapter->sessionCtx.ap.sapConfig.
11862 acs_cfg.acs_mode = true;
11863
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011864 hdd_restart_sap(ap_adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011865 }
11866}
11867
11868/**
11869 * hdd_set_connection_in_progress() - to set the connection in
11870 * progress flag
11871 * @value: value to set
11872 *
11873 * This function will set the passed value to connection in progress flag.
11874 * If value is previously being set to true then no need to set it again.
11875 *
11876 * Return: true if value is being set correctly and false otherwise.
11877 */
11878bool hdd_set_connection_in_progress(bool value)
11879{
11880 bool status = true;
11881 hdd_context_t *hdd_ctx;
11882
11883 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11884 if (!hdd_ctx) {
11885 cds_err("HDD context is NULL");
11886 return false;
11887 }
11888
11889 qdf_spin_lock(&hdd_ctx->connection_status_lock);
11890 /*
11891 * if the value is set to true previously and if someone is
11892 * trying to make it true again then it could be some race
11893 * condition being triggered. Avoid this situation by returning
11894 * false
11895 */
11896 if (hdd_ctx->connection_in_progress && value)
11897 status = false;
11898 else
11899 hdd_ctx->connection_in_progress = value;
11900 qdf_spin_unlock(&hdd_ctx->connection_status_lock);
11901 return status;
11902}
11903
Archana Ramachandranb8c04f92017-03-17 20:05:47 -070011904int wlan_hdd_send_p2p_quota(hdd_adapter_t *adapter, int set_value)
11905{
11906 if (!adapter) {
11907 hdd_err("Invalid adapter");
11908 return -EINVAL;
11909 }
11910 hdd_info("Send MCC P2P QUOTA to WMA: %d", set_value);
11911 wma_cli_set_command(adapter->sessionId,
11912 WMA_VDEV_MCC_SET_TIME_QUOTA,
11913 set_value, VDEV_CMD);
11914 return 0;
11915
11916}
11917
11918int wlan_hdd_send_mcc_latency(hdd_adapter_t *adapter, int set_value)
11919{
11920 if (!adapter) {
11921 hdd_err("Invalid adapter");
11922 return -EINVAL;
11923 }
11924
11925 hdd_info("Send MCC latency WMA: %d", set_value);
11926 wma_cli_set_command(adapter->sessionId,
11927 WMA_VDEV_MCC_SET_TIME_LATENCY,
11928 set_value, VDEV_CMD);
11929 return 0;
11930}
11931
Archana Ramachandranea34c4f2017-03-19 18:56:18 -070011932hdd_adapter_t *wlan_hdd_get_adapter_from_vdev(struct wlan_objmgr_psoc
11933 *psoc, uint8_t vdev_id)
11934{
11935 hdd_adapter_t *adapter = NULL;
11936 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11937
11938 /*
11939 * Currently PSOC is not being used. But this logic will
11940 * change once we have the converged implementation of
11941 * HDD context per PSOC in place. This would break if
11942 * multiple vdev objects reuse the vdev id.
11943 */
11944 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
11945 if (!adapter)
11946 hdd_err("Get adapter by vdev id failed");
11947
11948 return adapter;
11949}
11950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011951/* Register the module init/exit functions */
11952module_init(hdd_module_init);
11953module_exit(hdd_module_exit);
11954
11955MODULE_LICENSE("Dual BSD/GPL");
11956MODULE_AUTHOR("Qualcomm Atheros, Inc.");
11957MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
11958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011959module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
11960 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011961
11962module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
11963 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
11964
11965module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
11966
11967module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
11968
11969module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);