blob: a1e99bf292c51d5a39d64c123f06e8b647f9a884 [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"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800122
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +0530123#ifdef CNSS_GENL
124#include <net/cnss_nl.h>
125#endif
Amar Singhal5cccafe2017-02-15 12:42:58 -0800126#include "wlan_reg_ucfg_api.h"
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +0530127
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128#ifdef MODULE
129#define WLAN_MODULE_NAME module_name(THIS_MODULE)
130#else
131#define WLAN_MODULE_NAME "wlan"
132#endif
133
134#ifdef TIMER_MANAGER
135#define TIMER_MANAGER_STR " +TIMER_MANAGER"
136#else
137#define TIMER_MANAGER_STR ""
138#endif
139
140#ifdef MEMORY_DEBUG
141#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
142#else
143#define MEMORY_DEBUG_STR ""
144#endif
145
Sachin Ahujadddd2632017-03-07 19:07:24 +0530146int wlan_start_ret_val;
147static DECLARE_COMPLETION(wlan_start_comp);
148static unsigned int dev_num = 1;
149static struct cdev wlan_hdd_state_cdev;
150static struct class *class;
151static dev_t device;
Arun Khandavallifae92942016-08-01 13:31:08 +0530152#ifndef MODULE
153static struct gwlan_loader *wlan_loader;
154static ssize_t wlan_boot_cb(struct kobject *kobj,
155 struct kobj_attribute *attr,
156 const char *buf, size_t count);
157struct gwlan_loader {
158 bool loaded_state;
159 struct kobject *boot_wlan_obj;
160 struct attribute_group *attr_group;
161};
162
163static struct kobj_attribute wlan_boot_attribute =
164 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
165
166static struct attribute *attrs[] = {
167 &wlan_boot_attribute.attr,
168 NULL,
169};
170
171#define MODULE_INITIALIZED 1
172#endif
173
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174/* the Android framework expects this param even though we don't use it */
175#define BUF_LEN 20
176static char fwpath_buffer[BUF_LEN];
177static struct kparam_string fwpath = {
178 .string = fwpath_buffer,
179 .maxlen = BUF_LEN,
180};
181
182static char *country_code;
183static int enable_11d = -1;
184static int enable_dfs_chan_scan = -1;
185
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186/*
187 * spinlock for synchronizing asynchronous request/response
188 * (full description of use in wlan_hdd_main.h)
189 */
190DEFINE_SPINLOCK(hdd_context_lock);
191
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800192#define WLAN_NLINK_CESIUM 30
193
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530194static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195
196#define WOW_MAX_FILTER_LISTS 1
197#define WOW_MAX_FILTERS_PER_LIST 4
198#define WOW_MIN_PATTERN_SIZE 6
199#define WOW_MAX_PATTERN_SIZE 64
200
201#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
202static const struct wiphy_wowlan_support wowlan_support_reg_init = {
203 .flags = WIPHY_WOWLAN_ANY |
204 WIPHY_WOWLAN_MAGIC_PKT |
205 WIPHY_WOWLAN_DISCONNECT |
206 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
207 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
208 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
209 WIPHY_WOWLAN_4WAY_HANDSHAKE |
210 WIPHY_WOWLAN_RFKILL_RELEASE,
211 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
212 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
213 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
214};
215#endif
216
217/* internal function declaration */
218
219struct sock *cesium_nl_srv_sock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800220#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700221static void wlan_hdd_auto_shutdown_cb(void);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222#endif
223
Sachin Ahujadddd2632017-03-07 19:07:24 +0530224void hdd_start_complete(int ret)
225{
226 wlan_start_ret_val = ret;
227
228 complete(&wlan_start_comp);
229}
230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530232 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
233 * @hdd_ctx: pointer to hdd_context_t
234 *
235 * Return: none
236 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700237static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530238{
239 hdd_adapter_t *adapter;
240 hdd_adapter_list_node_t *adapter_node, *next;
241 QDF_STATUS status = QDF_STATUS_SUCCESS;
242
243 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
244 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
245 adapter = adapter_node->pAdapter;
246 if (NULL != adapter)
247 hdd_send_rps_ind(adapter);
248 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
249 adapter_node = next;
250 }
251}
252
253/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800254 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
255 * @vdev_id: vdev_id
256 * @action: action type
257 * @reason: reason type
258 *
259 * Return: none
260 */
261void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
262 enum netif_action_type action, enum netif_reason_type reason)
263{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530264 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800265 hdd_adapter_t *adapter;
266
267 if (!hdd_ctx) {
268 hdd_err("hdd ctx is NULL");
269 return;
270 }
271 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
272
273 wlan_hdd_netif_queue_control(adapter, action, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800274}
275
276/*
277 * Store WLAN driver version info in a global variable such that crash debugger
278 * can extract it from driver debug symbol and crashdump for post processing
279 */
280uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
281
282/**
283 * hdd_device_mode_to_string() - return string conversion of device mode
284 * @device_mode: device mode
285 *
286 * This utility function helps log string conversion of device mode.
287 *
288 * Return: string conversion of device mode, if match found;
289 * "Unknown" otherwise.
290 */
291const char *hdd_device_mode_to_string(uint8_t device_mode)
292{
293 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800294 CASE_RETURN_STRING(QDF_STA_MODE);
295 CASE_RETURN_STRING(QDF_SAP_MODE);
296 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
297 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
298 CASE_RETURN_STRING(QDF_FTM_MODE);
299 CASE_RETURN_STRING(QDF_IBSS_MODE);
300 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
301 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700302 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800303 default:
304 return "Unknown";
305 }
306}
307
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530308/**
309 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
310 * @adapter: HDD adapter
311 * @chan_number: Channel number
312 * @chan_bw: Bandwidth
313 *
314 * Checks if the given bandwidth is valid for the given channel number.
315 *
316 * Return: 0 for success, non-zero for failure
317 */
318int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
319 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800320 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530321{
322 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
323 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
324 bool found = false;
325 tHalHandle hal;
326
327 hal = WLAN_HDD_GET_HAL_CTX(adapter);
328 if (!hal) {
329 hdd_err("Invalid HAL context");
330 return -EINVAL;
331 }
332
333 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
334 hdd_err("No valid channel list");
335 return -EOPNOTSUPP;
336 }
337
338 for (i = 0; i < len; i++) {
339 if (chan[i] == chan_number) {
340 found = true;
341 break;
342 }
343 }
344
345 if (found == false) {
346 hdd_err("Channel not in driver's valid channel list");
347 return -EOPNOTSUPP;
348 }
349
350 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
351 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
352 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
353 return -EINVAL;
354 }
355
356 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
357 if (chan_bw == CH_WIDTH_80MHZ) {
358 hdd_err("BW80 not possible in 2.4GHz band");
359 return -EINVAL;
360 }
361 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
362 (chan_bw != CH_WIDTH_MAX)) {
363 hdd_err("Only BW20 possible on channel 14");
364 return -EINVAL;
365 }
366 }
367
368 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
369 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
370 (chan_bw != CH_WIDTH_MAX)) {
371 hdd_err("Only BW20 possible on channel 165");
372 return -EINVAL;
373 }
374 }
375
376 return 0;
377}
378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379static int __hdd_netdev_notifier_call(struct notifier_block *nb,
380 unsigned long state, void *data)
381{
382#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
383 struct netdev_notifier_info *dev_notif_info = data;
384 struct net_device *dev = dev_notif_info->dev;
385#else
386 struct net_device *dev = data;
387#endif
388 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
389 hdd_context_t *hdd_ctx;
390
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800391 ENTER_DEV(dev);
392
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 /* Make sure that this callback corresponds to our device. */
394 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
395 return NOTIFY_DONE;
396
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530397 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700399 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400 return NOTIFY_DONE;
401 }
402
403 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700404 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405 return NOTIFY_DONE;
406 }
407
408 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
409 if (NULL == hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800410 hdd_err("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530411 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 return NOTIFY_DONE;
413 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800414 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 return NOTIFY_DONE;
416
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800417 hdd_debug("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 dev->name, state);
419
420 switch (state) {
421 case NETDEV_REGISTER:
422 break;
423
424 case NETDEV_UNREGISTER:
425 break;
426
427 case NETDEV_UP:
428 sme_ch_avoid_update_req(hdd_ctx->hHal);
429 break;
430
431 case NETDEV_DOWN:
432 break;
433
434 case NETDEV_CHANGE:
435 if (true == adapter->isLinkUpSvcNeeded)
436 complete(&adapter->linkup_event_var);
437 break;
438
439 case NETDEV_GOING_DOWN:
440 if (adapter->scan_info.mScanPending != false) {
441 unsigned long rc;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700442
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 INIT_COMPLETION(adapter->scan_info.
444 abortscan_event_var);
445 hdd_abort_mac_scan(adapter->pHddCtx,
446 adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530447 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800448 eCSR_SCAN_ABORT_DEFAULT);
449 rc = wait_for_completion_timeout(
450 &adapter->scan_info.abortscan_event_var,
451 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700452 if (!rc)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700453 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 } else {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800455 hdd_debug("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456 }
457 break;
458
459 default:
460 break;
461 }
462
463 return NOTIFY_DONE;
464}
465
466/**
467 * hdd_netdev_notifier_call() - netdev notifier callback function
468 * @nb: pointer to notifier block
469 * @state: state
470 * @ndev: ndev pointer
471 *
472 * Return: 0 on success, error number otherwise.
473 */
474static int hdd_netdev_notifier_call(struct notifier_block *nb,
475 unsigned long state,
476 void *ndev)
477{
478 int ret;
479
480 cds_ssr_protect(__func__);
481 ret = __hdd_netdev_notifier_call(nb, state, ndev);
482 cds_ssr_unprotect(__func__);
483
484 return ret;
485}
486
487struct notifier_block hdd_netdev_notifier = {
488 .notifier_call = hdd_netdev_notifier_call,
489};
490
491/* variable to hold the insmod parameters */
492static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800493
494/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800496
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530497/**
498 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
499 * @ch_width: NL channel width
500 *
501 * Converts the NL channel width to the driver's internal representation
502 *
503 * Return: Converted channel width. In case of non matching NL channel width,
504 * CH_WIDTH_MAX will be returned.
505 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800506enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530507{
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800508 uint8_t fw_ch_bw;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700509
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800510 fw_ch_bw = wma_get_vht_ch_width();
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530511 switch (ch_width) {
512 case NL80211_CHAN_WIDTH_20_NOHT:
513 case NL80211_CHAN_WIDTH_20:
514 return CH_WIDTH_20MHZ;
515 case NL80211_CHAN_WIDTH_40:
516 return CH_WIDTH_40MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530517 case NL80211_CHAN_WIDTH_80:
518 return CH_WIDTH_80MHZ;
519 case NL80211_CHAN_WIDTH_80P80:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800520 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
521 return CH_WIDTH_80P80MHZ;
522 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
523 return CH_WIDTH_160MHZ;
524 else
525 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530526 case NL80211_CHAN_WIDTH_160:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800527 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
528 return CH_WIDTH_160MHZ;
529 else
530 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530531 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800532 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530533 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800534 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530535 default:
536 hdd_err("Invalid channel width %d, setting to default",
537 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800538 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530539 }
540}
541
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530542/* wlan_hdd_find_opclass() - Find operating class for a channel
543 * @hal: handler to HAL
544 * @channel: channel id
545 * @bw_offset: bandwidth offset
546 *
547 * Function invokes sme api to find the operating class
548 *
549 * Return: operating class
550 */
551uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
552 uint8_t bw_offset)
553{
554 uint8_t opclass = 0;
555
556 sme_get_opclass(hal, channel, bw_offset, &opclass);
557 return opclass;
558}
559
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800560/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530561 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530562 * @module_id: Module whose trace level is being configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 * @bitmask: Bitmask of log levels to be enabled
564 *
565 * Called immediately after the cfg.ini is read in order to configure
566 * the desired trace levels.
567 *
568 * Return: None
569 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530570int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530572 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530573 int qdf_print_idx = -1;
574 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575 /*
576 * if the bitmask is the default value, then a bitmask was not
577 * specified in cfg.ini, so leave the logging level alone (it
578 * will remain at the "compiled in" default value)
579 */
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700580 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530581 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530583 qdf_print_idx = qdf_get_pidx();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530585 /* a mask was specified. start by disabling all logging */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530586 status = qdf_print_set_category_verbose(qdf_print_idx, module_id,
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530587 QDF_TRACE_LEVEL_NONE, 0);
588
589 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530590 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530592 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593 while (0 != bitmask) {
594 if (bitmask & 1) {
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530595 status = qdf_print_set_category_verbose(qdf_print_idx,
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530596 module_id, level, 1);
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530597 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530598 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 level++;
602 bitmask >>= 1;
603 }
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530604 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800605}
606
607/**
608 * wlan_hdd_validate_context() - check the HDD context
609 * @hdd_ctx: HDD context pointer
610 *
611 * Return: 0 if the context is valid. Error code otherwise
612 */
613int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
614{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530616 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 return -ENODEV;
618 }
619
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800620 if (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800621 hdd_debug("%pS Recovery in Progress. State: 0x%x Ignore!!!",
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530622 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623 return -EAGAIN;
624 }
625
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800626 if (cds_is_load_or_unload_in_progress()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800627 hdd_debug("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530628 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629 return -EAGAIN;
630 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530631
632 if (hdd_ctx->start_modules_in_progress ||
633 hdd_ctx->stop_modules_in_progress) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800634 hdd_debug("%pS Start/Stop Modules in progress. Ignore!!!",
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530635 (void *)_RET_IP_);
636 return -EAGAIN;
637 }
638
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 return 0;
640}
641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642/**
643 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
644 * @hdd_adapter_t Hdd adapter.
645 *
646 * This function sets the IBSS power save config parameters to WMA
647 * which will send it to firmware if FW supports IBSS power save
648 * before vdev start.
649 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530650 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 * on failure.
652 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530653QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654{
655 int ret;
656 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
657
658 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700659 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530660 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 }
662
663 ret = wma_cli_set_command(adapter->sessionId,
664 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
665 hdd_ctx->config->ibssATIMWinSize,
666 VDEV_CMD);
667 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700668 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530669 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800670 }
671
672 ret = wma_cli_set_command(adapter->sessionId,
673 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
674 hdd_ctx->config->isIbssPowerSaveAllowed,
675 VDEV_CMD);
676 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700677 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
678 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530679 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 }
681
682 ret = wma_cli_set_command(adapter->sessionId,
683 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
684 hdd_ctx->config->
685 isIbssPowerCollapseAllowed, VDEV_CMD);
686 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700687 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
688 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530689 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 }
691
692 ret = wma_cli_set_command(adapter->sessionId,
693 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
694 hdd_ctx->config->isIbssAwakeOnTxRx,
695 VDEV_CMD);
696 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700697 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530698 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 }
700
701 ret = wma_cli_set_command(adapter->sessionId,
702 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
703 hdd_ctx->config->ibssInactivityCount,
704 VDEV_CMD);
705 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700706 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530707 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 }
709
710 ret = wma_cli_set_command(adapter->sessionId,
711 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
712 hdd_ctx->config->ibssTxSpEndInactivityTime,
713 VDEV_CMD);
714 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700715 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
716 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530717 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800718 }
719
720 ret = wma_cli_set_command(adapter->sessionId,
721 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
722 hdd_ctx->config->ibssPsWarmupTime,
723 VDEV_CMD);
724 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700725 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
726 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530727 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800728 }
729
730 ret = wma_cli_set_command(adapter->sessionId,
731 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
732 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
733 VDEV_CMD);
734 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700735 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
736 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530737 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738 }
739
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530740 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800741}
742
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743#define INTF_MACADDR_MASK 0x7
744
745/**
746 * hdd_update_macaddr() - update mac address
747 * @config: hdd configuration
748 * @hw_macaddr: mac address
749 *
750 * Mac address for multiple virtual interface is found as following
751 * i) The mac address of the first interface is just the actual hw mac address.
752 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
753 * define the mac address for the remaining interfaces and locally
754 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
755 * supported virtual interfaces, right now this is 0x07 (meaning 8
756 * interface).
757 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
758 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
759 *
760 * Return: None
761 */
762void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530763 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764{
765 int8_t i;
766 uint8_t macaddr_b3, tmp_br3;
767
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530768 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530769 QDF_MAC_ADDR_SIZE);
770 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530771 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530772 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 macaddr_b3 = config->intfMacAddr[i].bytes[3];
774 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
775 INTF_MACADDR_MASK;
776 macaddr_b3 += tmp_br3;
777
778 /* XOR-ing bit-24 of the mac address. This will give enough
779 * mac address range before collision
780 */
781 macaddr_b3 ^= (1 << 7);
782
783 /* Set locally administered bit */
784 config->intfMacAddr[i].bytes[0] |= 0x02;
785 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800786 hdd_debug("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787 MAC_ADDRESS_STR, i,
788 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
789 }
790}
791
792static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
793 struct wma_tgt_services *cfg)
794{
795 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796
797 /* Set up UAPSD */
798 config->apUapsdEnabled &= cfg->uapsd;
799
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800800 /* 11AX mode support */
801 if ((config->dot11Mode == eHDD_DOT11_MODE_11ax ||
802 config->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY) && !cfg->en_11ax)
803 config->dot11Mode = eHDD_DOT11_MODE_11ac;
804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805 /* 11AC mode support */
806 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
807 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
808 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800809
810 /* ARP offload: override user setting if invalid */
811 config->fhostArpOffload &= cfg->arp_offload;
812
813#ifdef FEATURE_WLAN_SCAN_PNO
814 /* PNO offload */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800815 hdd_debug("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816 if (cfg->pno_offload)
817 config->PnoOffload = true;
818#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819#ifdef FEATURE_WLAN_TDLS
820 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530821 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
822 cfg->en_tdls_offchan;
823 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
824 cfg->en_tdls_uapsd_buf_sta;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700825 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 config->fEnableTDLSSleepSta = true;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700827 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828 config->fEnableTDLSSleepSta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800829#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830#ifdef WLAN_FEATURE_ROAM_OFFLOAD
831 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
832#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700833 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834
835}
836
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700837/**
838 * hdd_update_vdev_nss() - sets the vdev nss
839 * @hdd_ctx: HDD context
840 *
841 * Sets the Nss per vdev type based on INI
842 *
843 * Return: None
844 */
845static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
846{
847 struct hdd_config *cfg_ini = hdd_ctx->config;
848 uint8_t max_supp_nss = 1;
849
Naveen Rawat10b1c152017-01-18 11:16:06 -0800850 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700851 max_supp_nss = 2;
852
853 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
854 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
855
856 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
857 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
858}
859
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530860/**
861 * hdd_update_hw_dbs_capable() - sets the dbs capability of the device
862 * @hdd_ctx: HDD context
863 *
864 * Sets the DBS capability as per INI and firmware capability
865 *
866 * Return: None
867 */
868static void hdd_update_hw_dbs_capable(hdd_context_t *hdd_ctx)
869{
870 struct hdd_config *cfg_ini = hdd_ctx->config;
871 uint8_t hw_dbs_capable = 0;
872
873 if ((!cfg_ini->dual_mac_feature_disable)
Archana Ramachandran62886ce2017-03-24 14:46:32 -0700874 && policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc))
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530875 hw_dbs_capable = 1;
876
877 sme_update_hw_dbs_capable(hdd_ctx->hHal, hw_dbs_capable);
878}
879
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800880static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
881 struct wma_tgt_ht_cap *cfg)
882{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530883 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 uint32_t value, val32;
885 uint16_t val16;
886 struct hdd_config *pconfig = hdd_ctx->config;
887 tSirMacHTCapabilityInfo *phtCapInfo;
888 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
889 uint8_t enable_tx_stbc;
890
891 /* check and update RX STBC */
892 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
893 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
894
895 /* get the MPDU density */
896 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
897
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530898 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700899 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800900 value = 0;
901 }
902
903 /*
904 * MPDU density:
905 * override user's setting if value is larger
906 * than the one supported by target
907 */
908 if (value > cfg->mpdu_density) {
909 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
910 cfg->mpdu_density);
911
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530912 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800913 hdd_err("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 }
915
916 /* get the HT capability info */
917 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530918 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700919 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920 return;
921 }
922 val16 = (uint16_t) val32;
923 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
924
925 /* Set the LDPC capability */
926 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
927
928 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
929 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
930
931 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
932 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
933
934 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
935 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
936
937 enable_tx_stbc = pconfig->enableTxSTBC;
938
939 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
940 pconfig->enable2x2 = 1;
941 } else {
942 pconfig->enable2x2 = 0;
943 enable_tx_stbc = 0;
944
945 /* 1x1 */
946 /* Update Rx Highest Long GI data Rate */
947 if (sme_cfg_set_int(hdd_ctx->hHal,
948 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700949 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530950 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700951 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 }
953
954 /* Update Tx Highest Long GI data Rate */
955 if (sme_cfg_set_int
956 (hdd_ctx->hHal,
957 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700958 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530959 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700960 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961 }
962 }
963 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
964 enable_tx_stbc = 0;
965 phtCapInfo->txSTBC = enable_tx_stbc;
966
967 val32 = val16;
968 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530969 if (status != QDF_STATUS_SUCCESS)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800970 hdd_err("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
972 value = SIZE_OF_SUPPORTED_MCS_SET;
973 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530974 &value) == QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800975 hdd_debug("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976
977 if (pconfig->enable2x2) {
978 for (value = 0; value < cfg->num_rf_chains; value++)
979 mcs_set[value] =
980 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
981
982 status =
983 sme_cfg_set_str(hdd_ctx->hHal,
984 WNI_CFG_SUPPORTED_MCS_SET,
985 mcs_set,
986 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530987 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800988 hdd_err("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989 }
990 }
991#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
992}
993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800994static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
995 struct wma_tgt_vht_cap *cfg)
996{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530997 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998 uint32_t value = 0;
999 struct hdd_config *pconfig = hdd_ctx->config;
1000 struct wiphy *wiphy = hdd_ctx->wiphy;
1001 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -07001002 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001003 uint32_t temp = 0;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001004 uint32_t ch_width = eHT_CHANNEL_WIDTH_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001005
Dustin Brown5e06bd32016-10-04 12:49:10 -07001006 if (!band_5g) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001007 hdd_debug("5GHz band disabled, skipping capability population");
Dustin Brown5e06bd32016-10-04 12:49:10 -07001008 return;
1009 }
1010
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001011 /* Get the current MPDU length */
1012 status =
1013 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1014 &value);
1015
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301016 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001017 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001018 value = 0;
1019 }
1020
1021 /*
1022 * VHT max MPDU length:
1023 * override if user configured value is too high
1024 * that the target cannot support
1025 */
1026 if (value > cfg->vht_max_mpdu) {
1027 status = sme_cfg_set_int(hdd_ctx->hHal,
1028 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1029 cfg->vht_max_mpdu);
1030
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001031 if (status == QDF_STATUS_E_FAILURE)
1032 hdd_err("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001033 }
1034
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001035 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1036 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1037
1038 if (pconfig->enable2x2)
1039 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1040
1041 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1042 QDF_STATUS_E_FAILURE) {
1043 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1044 }
1045
1046 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1047 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1048 if (pconfig->enable2x2)
1049 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1050
1051 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1052 QDF_STATUS_E_FAILURE) {
1053 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1054 }
1055
1056 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1057 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1058 if (pconfig->enable2x2)
1059 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1060
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001061 hdd_debug("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001062 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1063
1064 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1065 QDF_STATUS_E_FAILURE) {
1066 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1067 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001069 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001070 &value);
1071
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301072 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001073 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 value = 0;
1075 }
1076
1077 /* Set the LDPC capability */
1078 if (value && !cfg->vht_rx_ldpc) {
1079 status = sme_cfg_set_int(hdd_ctx->hHal,
1080 WNI_CFG_VHT_LDPC_CODING_CAP,
1081 cfg->vht_rx_ldpc);
1082
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001083 if (status == QDF_STATUS_E_FAILURE)
1084 hdd_err("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001085 }
1086
1087 /* Get current GI 80 value */
1088 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1089 &value);
1090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301091 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001092 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001093 value = 0;
1094 }
1095
1096 /* set the Guard interval 80MHz */
1097 if (value && !cfg->vht_short_gi_80) {
1098 status = sme_cfg_set_int(hdd_ctx->hHal,
1099 WNI_CFG_VHT_SHORT_GI_80MHZ,
1100 cfg->vht_short_gi_80);
1101
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001102 if (status == QDF_STATUS_E_FAILURE)
1103 hdd_err("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001104 }
1105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106 /* Get VHT TX STBC cap */
1107 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1108
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301109 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001110 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 value = 0;
1112 }
1113
1114 /* VHT TX STBC cap */
1115 if (value && !cfg->vht_tx_stbc) {
1116 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1117 cfg->vht_tx_stbc);
1118
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001119 if (status == QDF_STATUS_E_FAILURE)
1120 hdd_err("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 }
1122
1123 /* Get VHT RX STBC cap */
1124 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1125
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301126 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001127 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001128 value = 0;
1129 }
1130
1131 /* VHT RX STBC cap */
1132 if (value && !cfg->vht_rx_stbc) {
1133 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1134 cfg->vht_rx_stbc);
1135
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001136 if (status == QDF_STATUS_E_FAILURE)
1137 hdd_err("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138 }
1139
1140 /* Get VHT SU Beamformer cap */
1141 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1142 &value);
1143
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301144 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001145 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 value = 0;
1147 }
1148
1149 /* set VHT SU Beamformer cap */
1150 if (value && !cfg->vht_su_bformer) {
1151 status = sme_cfg_set_int(hdd_ctx->hHal,
1152 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1153 cfg->vht_su_bformer);
1154
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001155 if (status == QDF_STATUS_E_FAILURE)
1156 hdd_err("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157 }
1158
1159 /* check and update SU BEAMFORMEE capabality */
1160 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1161 pconfig->enableTxBF = cfg->vht_su_bformee;
1162
1163 status = sme_cfg_set_int(hdd_ctx->hHal,
1164 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1165 pconfig->enableTxBF);
1166
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001167 if (status == QDF_STATUS_E_FAILURE)
1168 hdd_err("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001169
1170 /* Get VHT MU Beamformer cap */
1171 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1172 &value);
1173
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301174 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001175 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001176 value = 0;
1177 }
1178
1179 /* set VHT MU Beamformer cap */
1180 if (value && !cfg->vht_mu_bformer) {
1181 status = sme_cfg_set_int(hdd_ctx->hHal,
1182 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1183 cfg->vht_mu_bformer);
1184
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001185 if (status == QDF_STATUS_E_FAILURE)
1186 hdd_err("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001187 }
1188
1189 /* Get VHT MU Beamformee cap */
1190 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_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 MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 value = 0;
1196 }
1197
1198 /* set VHT MU Beamformee cap */
1199 if (value && !cfg->vht_mu_bformee) {
1200 status = sme_cfg_set_int(hdd_ctx->hHal,
1201 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1202 cfg->vht_mu_bformee);
1203
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001204 if (status == QDF_STATUS_E_FAILURE)
1205 hdd_err("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 }
1207
1208 /* Get VHT MAX AMPDU Len exp */
1209 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1210 &value);
1211
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301212 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001213 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001214 value = 0;
1215 }
1216
1217 /*
1218 * VHT max AMPDU len exp:
1219 * override if user configured value is too high
1220 * that the target cannot support.
1221 * Even though Rome publish ampdu_len=7, it can
1222 * only support 4 because of some h/w bug.
1223 */
1224
1225 if (value > cfg->vht_max_ampdu_len_exp) {
1226 status = sme_cfg_set_int(hdd_ctx->hHal,
1227 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1228 cfg->vht_max_ampdu_len_exp);
1229
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001230 if (status == QDF_STATUS_E_FAILURE)
1231 hdd_err("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 }
1233
1234 /* Get VHT TXOP PS CAP */
1235 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301237 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001238 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 value = 0;
1240 }
1241
1242 /* set VHT TXOP PS cap */
1243 if (value && !cfg->vht_txop_ps) {
1244 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1245 cfg->vht_txop_ps);
1246
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001247 if (status == QDF_STATUS_E_FAILURE)
1248 hdd_err("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 }
1250
1251 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1252 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1253 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1254 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1255 else
1256 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1257
1258
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001259 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1260 status = sme_cfg_set_int(hdd_ctx->hHal,
1261 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1262 VHT_CAP_160_AND_80P80_SUPP);
1263 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001264 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 band_5g->vht_cap.cap |=
1266 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001267 ch_width = eHT_CHANNEL_WIDTH_80P80MHZ;
1268 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1269 status = sme_cfg_set_int(hdd_ctx->hHal,
1270 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1271 VHT_CAP_160_SUPP);
1272 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001273 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274 band_5g->vht_cap.cap |=
1275 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001276 ch_width = eHT_CHANNEL_WIDTH_160MHZ;
1277 }
1278 pconfig->vhtChannelWidth = QDF_MIN(pconfig->vhtChannelWidth,
1279 ch_width);
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301280 /* Get the current GI 160 value */
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001281 status = sme_cfg_get_int(hdd_ctx->hHal,
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301282 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001283 &value);
1284 if (status != QDF_STATUS_SUCCESS) {
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301285 hdd_err("could not get GI 80 & 160");
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001286 value = 0;
1287 }
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301288 /* set the Guard interval 160MHz */
1289 if (value && !cfg->vht_short_gi_160) {
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001290 status = sme_cfg_set_int(hdd_ctx->hHal,
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301291 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1292 cfg->vht_short_gi_160);
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001293
1294 if (status == QDF_STATUS_E_FAILURE)
Ashish Kumar Dhanotiya7ebf5692017-04-12 20:04:47 +05301295 hdd_err("failed to set SHORT GI 160MHZ");
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001296 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297
1298 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1299 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1300
1301 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1302 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1303 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1304 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1305
1306 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1307 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1308
1309 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1310 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1311 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1312 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1313 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1314 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1315
1316 band_5g->vht_cap.cap |=
1317 (cfg->vht_max_ampdu_len_exp <<
1318 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1319
1320 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1321 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1322 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1323 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1324 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1325 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1326 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1327 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1328
1329 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1330 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1331
1332}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001334/**
1335 * hdd_generate_macaddr_auto() - Auto-generate mac address
1336 * @hdd_ctx: Pointer to the HDD context
1337 *
1338 * Auto-generate mac address using device serial number.
1339 * Keep the first 3 bytes of OUI as before and replace
1340 * the last 3 bytes with the lower 3 bytes of serial number.
1341 *
1342 * Return: 0 for success
1343 * Non zero failure code for errors
1344 */
1345static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1346{
1347 unsigned int serialno = 0;
1348 struct qdf_mac_addr mac_addr = {
1349 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1350 };
1351
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001352 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001353 if (serialno == 0)
1354 return -EINVAL;
1355
1356 serialno &= 0x00ffffff;
1357
1358 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1359 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1360 mac_addr.bytes[5] = serialno & 0xff;
1361
1362 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1363 return 0;
1364}
1365
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301366/**
1367 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1368 * configuration to cfg_ini in HDD
1369 * @hdd_ctx: Pointer to hdd_ctx
1370 * @cfg: target configuration
1371 *
1372 * Return: None
1373 */
1374#ifdef FEATURE_WLAN_RA_FILTERING
1375static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1376 struct wma_tgt_cfg *cfg)
1377{
1378 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1379}
1380#else
1381static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1382 struct wma_tgt_cfg *cfg)
1383{
1384}
1385#endif
1386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387void hdd_update_tgt_cfg(void *context, void *param)
1388{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001389 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1391 struct wma_tgt_cfg *cfg = param;
1392 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001393 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301394
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07001395 /* Reuse same pdev for module stop and start */
1396 if ((hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) ||
1397 (!cds_is_driver_loading())) {
1398 hdd_err("Reuse pdev for module start/stop");
1399 } else {
1400 ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
1401 if (ret) {
1402 hdd_err("pdev creation fails!");
1403 QDF_BUG(0);
1404 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301405 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001406 if (cds_cfg) {
1407 if (hdd_ctx->config->enable_sub_20_channel_width !=
1408 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1409 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1410 cds_cfg->sub_20_channel_width =
1411 WLAN_SUB_20_CH_WIDTH_NONE;
1412 } else {
1413 cds_cfg->sub_20_channel_width =
1414 hdd_ctx->config->enable_sub_20_channel_width;
1415 }
1416 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417
1418 /* first store the INI band capability */
1419 temp_band_cap = hdd_ctx->config->nBandCapability;
1420
1421 hdd_ctx->config->nBandCapability = cfg->band_cap;
1422
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001423 /*
1424 * now overwrite the target band capability with INI
1425 * setting if INI setting is a subset
1426 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427
1428 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1429 (temp_band_cap != eCSR_BAND_ALL))
1430 hdd_ctx->config->nBandCapability = temp_band_cap;
1431 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1432 (temp_band_cap != eCSR_BAND_ALL) &&
1433 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001434 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 }
1436
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001437 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1439 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1440 }
1441
1442 /* This can be extended to other configurations like ht, vht cap... */
1443
Anurag Chouhanc5548422016-02-24 18:33:27 +05301444 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001445 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001446 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001448 static struct qdf_mac_addr default_mac_addr = {
1449 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1450 };
1451 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1452 &default_mac_addr)) {
1453 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1454 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1455 MAC_ADDRESS_STR,
1456 MAC_ADDR_ARRAY(hdd_ctx->config->
1457 intfMacAddr[0].bytes));
1458 } else {
1459 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1460 MAC_ADDRESS_STR,
1461 MAC_ADDR_ARRAY(hdd_ctx->config->
1462 intfMacAddr[0].bytes));
1463 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001464 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 }
1466
1467 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001468 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469
1470 hdd_ctx->max_intf_count = cfg->max_intf_count;
1471
Jeff Johnsonc875e242016-09-23 18:12:34 -07001472 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001473 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001475 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1476 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1477
1478 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001480 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajaned1efd92016-09-24 18:05:47 -07001481 if (cfg->services.en_11ax) {
1482 hdd_info("11AX: 11ax is enabled - update HDD config");
1483 hdd_update_tgt_he_cap(hdd_ctx, cfg);
1484 }
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001485
1486 hdd_update_vdev_nss(hdd_ctx);
1487
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +05301488 hdd_update_hw_dbs_capable(hdd_ctx);
1489
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001490 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001491 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001492 hdd_debug("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001493 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001494
1495 hdd_ctx->current_antenna_mode =
1496 (hdd_ctx->config->enable2x2 == 0x01) ?
1497 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001498 hdd_debug("Init current antenna mode: %d",
Archana Ramachandran393f3792015-11-13 17:13:21 -08001499 hdd_ctx->current_antenna_mode);
1500
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001501 hdd_debug("Target BPF %d Host BPF %d",
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001502 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1503 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1504 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301505 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301506
Arun Khandavallid454d422016-08-17 12:47:05 +05301507 /*
1508 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1509 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1510 * configure the STA mode wow pattern.
1511 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301512 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301513 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301514
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301515 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1516
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001517 /* Configure NAN datapath features */
1518 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Arif Hussain759a0232017-03-20 13:17:18 -07001519 hdd_ctx->dfs_cac_offload = cfg->dfs_cac_offload;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520}
1521
1522/**
1523 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1524 * @context: HDD context pointer
1525 * @param: HDD radar indication pointer
1526 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001527 * This function is invoked in atomic context when a radar
1528 * is found on the SAP current operating channel and Data Tx
1529 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001530 * Actions: Stop the netif Tx queues,Indicate Radar present
1531 * in HDD context for future usage.
1532 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301533 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001534 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301535bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536{
1537 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1538 struct wma_dfs_radar_ind *hdd_radar_event =
1539 (struct wma_dfs_radar_ind *)param;
1540 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1541 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301542 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301543 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301545 if (!hdd_ctx || !hdd_radar_event ||
1546 hdd_ctx->config->disableDFSChSwitch)
1547 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548
1549 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001550 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301551 /*
1552 * Application already triggered channel switch
1553 * on current channel, so return here.
1554 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301555 return false;
1556 }
1557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301559 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001560 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301561 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1562 if ((QDF_SAP_MODE == adapter->device_mode ||
1563 QDF_P2P_GO_MODE == adapter->device_mode) &&
1564 (CHANNEL_STATE_DFS ==
1565 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001566 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1567 dfs_cac_block_tx = true;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001568 hdd_debug("tx blocked for session:%d",
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301569 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001570 }
1571
1572 status = hdd_get_next_adapter(hdd_ctx,
1573 adapterNode,
1574 &pNext);
1575 adapterNode = pNext;
1576 }
1577 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301578
1579 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581
1582/**
1583 * hdd_is_valid_mac_address() - validate MAC address
1584 * @pMacAddr: Pointer to the input MAC address
1585 *
1586 * This function validates whether the given MAC address is valid or not
1587 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1588 * where X is the hexa decimal digit character and separated by ':'
1589 * This algorithm works even if MAC address is not separated by ':'
1590 *
1591 * This code checks given input string mac contains exactly 12 hexadecimal
1592 * digits and a separator colon : appears in the input string only after
1593 * an even number of hex digits.
1594 *
1595 * Return: 1 for valid and 0 for invalid
1596 */
1597bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1598{
1599 int xdigit = 0;
1600 int separator = 0;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07001601
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001602 while (*pMacAddr) {
1603 if (isxdigit(*pMacAddr)) {
1604 xdigit++;
1605 } else if (':' == *pMacAddr) {
1606 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1607 break;
1608
1609 ++separator;
1610 } else {
1611 /* Invalid MAC found */
1612 return 0;
1613 }
1614 ++pMacAddr;
1615 }
1616 return xdigit == 12 && (separator == 5 || separator == 0);
1617}
1618
1619/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301620 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1621 * @dev: Handle to struct net_device to be updated.
1622 *
1623 * Return: None
1624 */
1625static void hdd_mon_mode_ether_setup(struct net_device *dev)
1626{
1627 dev->header_ops = NULL;
1628 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1629 dev->hard_header_len = ETH_HLEN;
1630 dev->mtu = ETH_DATA_LEN;
1631 dev->addr_len = ETH_ALEN;
1632 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1633 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1634 dev->priv_flags |= IFF_TX_SKB_SHARING;
1635
1636 memset(dev->broadcast, 0xFF, ETH_ALEN);
1637}
1638
1639/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001640 * __hdd__mon_open() - HDD Open function
1641 * @dev: Pointer to net_device structure
1642 *
1643 * This is called in response to ifconfig up
1644 *
1645 * Return: 0 for success; non-zero for failure
1646 */
1647static int __hdd_mon_open(struct net_device *dev)
1648{
1649 int ret;
1650
1651 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301652 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001653 ret = hdd_set_mon_rx_cb(dev);
1654 return ret;
1655}
1656
1657/**
1658 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1659 * @dev: Pointer to net_device structure
1660 *
1661 * This is called in response to ifconfig up
1662 *
1663 * Return: 0 for success; non-zero for failure
1664 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001665static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001666{
1667 int ret;
1668
1669 cds_ssr_protect(__func__);
1670 ret = __hdd_mon_open(dev);
1671 cds_ssr_unprotect(__func__);
1672
1673 return ret;
1674}
1675
1676/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301677 * hdd_start_adapter() - Wrapper function for device specific adapter
1678 * @adapter: pointer to HDD adapter
1679 *
1680 * This function is called to start the device specific adapter for
1681 * the mode passed in the adapter's device_mode.
1682 *
1683 * Return: 0 for success; non-zero for failure
1684 */
1685int hdd_start_adapter(hdd_adapter_t *adapter)
1686{
1687
1688 int ret;
1689 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1690
1691 ENTER_DEV(adapter->dev);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001692 hdd_debug("Start_adapter for mode : %d", adapter->device_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05301693
1694 switch (device_mode) {
1695 case QDF_P2P_CLIENT_MODE:
1696 case QDF_P2P_DEVICE_MODE:
1697 case QDF_OCB_MODE:
1698 case QDF_STA_MODE:
1699 case QDF_MONITOR_MODE:
1700 ret = hdd_start_station_adapter(adapter);
1701 if (ret)
1702 goto err_start_adapter;
1703 break;
1704 case QDF_P2P_GO_MODE:
1705 case QDF_SAP_MODE:
1706 ret = hdd_start_ap_adapter(adapter);
1707 if (ret)
1708 goto err_start_adapter;
1709 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301710 case QDF_IBSS_MODE:
1711 /*
1712 * For IBSS interface is initialized as part of
1713 * hdd_init_station_mode()
1714 */
1715 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301716 case QDF_FTM_MODE:
1717 ret = hdd_start_ftm_adapter(adapter);
1718 if (ret)
1719 goto err_start_adapter;
1720 break;
1721 default:
1722 hdd_err("Invalid session type %d", device_mode);
1723 QDF_ASSERT(0);
1724 goto err_start_adapter;
1725 }
1726 if (hdd_set_fw_params(adapter))
1727 hdd_err("Failed to set the FW params for the adapter!");
1728
1729 /*
1730 * Action frame registered in one adapter which will
1731 * applicable to all interfaces
1732 */
1733 wlan_hdd_cfg80211_register_frames(adapter);
1734 EXIT();
1735 return 0;
1736err_start_adapter:
1737 return -EINVAL;
1738}
1739
1740/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301741 * hdd_enable_power_management() - API to Enable Power Management
1742 *
1743 * API invokes Bus Interface Layer power management functionality
1744 *
1745 * Return: None
1746 */
1747static void hdd_enable_power_management(void)
1748{
1749 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1750
1751 if (!hif_ctx) {
1752 hdd_err("Bus Interface Context is Invalid");
1753 return;
1754 }
1755
1756 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1757}
1758
1759/**
1760 * hdd_disable_power_management() - API to disable Power Management
1761 *
1762 * API disable Bus Interface Layer Power management functionality
1763 *
1764 * Return: None
1765 */
1766static void hdd_disable_power_management(void)
1767{
1768 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1769
1770 if (!hif_ctx) {
1771 hdd_err("Bus Interface Context is Invalid");
1772 return;
1773 }
1774
1775 hif_disable_power_management(hif_ctx);
1776}
1777
1778/**
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301779 * hdd_update_hw_sw_info() - API to update the HW/SW information
1780 *
1781 * API to update the HW and SW information in the driver
1782 *
1783 * Return: None
1784 */
1785static void hdd_update_hw_sw_info(hdd_context_t *hdd_ctx)
1786{
1787 void *hif_sc;
1788
1789 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
1790 if (!hif_sc) {
1791 hdd_err("HIF context is NULL");
1792 return;
1793 }
1794
1795 /*
1796 * target hw version/revision would only be retrieved after firmware
1797 * download
1798 */
1799 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
1800 &hdd_ctx->target_hw_revision,
1801 &hdd_ctx->target_hw_name);
1802
1803 /* Get the wlan hw/fw version */
1804 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
1805
1806 return;
1807}
1808
1809/**
gbian62edd7e2017-03-07 13:12:13 +08001810 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
1811 * @hdd_ctx: Pointer to hdd context
1812 *
1813 * Return: none
1814 */
1815static void
1816hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
1817{
1818 uint8_t num_entries = 0;
1819 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
1820 uint8_t *tx_sched_wrr_ac;
1821 int i;
1822 cds_context_type *cds_ctx;
1823
1824 if (NULL == hdd_ctx)
1825 return;
1826
1827 if (NULL == hdd_ctx->config) {
1828 /* Do nothing if hdd_ctx is invalid */
1829 hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
1830 return;
1831 }
1832
1833 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1834
1835 if (!cds_ctx) {
1836 hdd_err("Invalid CDS Context");
1837 return;
1838 }
1839
1840 for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
1841 switch (i) {
1842 case OL_TX_WMM_AC_BE:
1843 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
1844 break;
1845 case OL_TX_WMM_AC_BK:
1846 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
1847 break;
1848 case OL_TX_WMM_AC_VI:
1849 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
1850 break;
1851 case OL_TX_WMM_AC_VO:
1852 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
1853 break;
1854 default:
1855 tx_sched_wrr_ac = NULL;
1856 break;
1857 }
1858
1859 hdd_string_to_u8_array(tx_sched_wrr_ac,
1860 tx_sched_wrr_param,
1861 &num_entries,
1862 sizeof(tx_sched_wrr_param));
1863
1864 if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
1865 cds_ctx->ac_specs[i].wrr_skip_weight =
1866 tx_sched_wrr_param[0];
1867 cds_ctx->ac_specs[i].credit_threshold =
1868 tx_sched_wrr_param[1];
1869 cds_ctx->ac_specs[i].send_limit =
1870 tx_sched_wrr_param[2];
1871 cds_ctx->ac_specs[i].credit_reserve =
1872 tx_sched_wrr_param[3];
1873 cds_ctx->ac_specs[i].discard_weight =
1874 tx_sched_wrr_param[4];
1875 }
1876
1877 num_entries = 0;
1878 }
1879}
1880
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001881#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001882static enum policy_mgr_con_mode wlan_hdd_get_mode_for_non_connected_vdev(
1883 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
1884{
1885 hdd_adapter_t *adapter = NULL;
1886 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1887
1888 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
1889 if (!adapter) {
1890 hdd_err("Adapter is NULL");
1891 return PM_MAX_NUM_OF_MODE;
1892 }
1893
1894 return policy_mgr_convert_device_mode_to_qdf_type(
1895 adapter->device_mode);
1896}
1897
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001898static void hdd_register_policy_manager_callback(
1899 struct wlan_objmgr_psoc *psoc)
1900{
1901 struct policy_mgr_hdd_cbacks hdd_cbacks;
1902 hdd_cbacks.sap_restart_chan_switch_cb =
1903 sap_restart_chan_switch_cb;
1904 hdd_cbacks.wlan_hdd_get_channel_for_sap_restart =
1905 wlan_hdd_get_channel_for_sap_restart;
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001906 hdd_cbacks.get_mode_for_non_connected_vdev =
1907 wlan_hdd_get_mode_for_non_connected_vdev;
1908
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001909 if (QDF_STATUS_SUCCESS !=
1910 policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {
1911 hdd_err("HDD callback registration with policy manager failed");
1912 }
1913}
1914#else
1915static void hdd_register_policy_manager_callback(
1916 struct wlan_objmgr_psoc *psoc)
1917{
1918}
1919#endif
1920
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001921#ifdef WLAN_FEATURE_NAN_CONVERGENCE
1922static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1923{
1924 struct nan_callbacks cb_obj = {0};
1925
1926 cb_obj.ndi_open = hdd_ndi_open;
1927 cb_obj.ndi_close = hdd_ndi_close;
1928 cb_obj.ndi_start = hdd_ndi_start;
1929 cb_obj.ndi_delete = hdd_ndi_delete;
1930 cb_obj.drv_ndi_create_rsp_handler = hdd_ndi_drv_ndi_create_rsp_handler;
1931 cb_obj.drv_ndi_delete_rsp_handler = hdd_ndi_drv_ndi_delete_rsp_handler;
1932
Naveen Rawat37f62c82017-03-26 22:24:43 -07001933 cb_obj.new_peer_ind = hdd_ndp_new_peer_handler;
1934 cb_obj.get_peer_idx = hdd_ndp_get_peer_idx;
Naveen Rawatb3143ea2017-03-26 22:25:46 -07001935 cb_obj.peer_departed_ind = hdd_ndp_peer_departed_handler;
Naveen Rawat37f62c82017-03-26 22:24:43 -07001936
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001937 os_if_nan_register_hdd_callbacks(hdd_ctx->hdd_psoc, &cb_obj);
1938}
1939#else
1940static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1941{
1942}
1943#endif
1944
gbian62edd7e2017-03-07 13:12:13 +08001945/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301946 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1947 * @hdd_ctx: HDD context
1948 * @adapter: HDD adapter
1949 * @reinit: flag to indicate from SSR or normal path
1950 *
1951 * This function maintains the driver state machine it will be invoked from
1952 * startup, reinit and change interface. Depending on the driver state shall
1953 * perform the opening of the modules.
1954 *
1955 * Return: 0 for success; non-zero for failure
1956 */
1957int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1958 bool reinit)
1959{
1960 int ret;
1961 qdf_device_t qdf_dev;
1962 QDF_STATUS status;
1963 p_cds_contextType p_cds_context;
1964 bool unint = false;
1965 void *hif_ctx;
1966
1967 ENTER();
1968
1969 p_cds_context = cds_get_global_context();
1970 if (!p_cds_context) {
1971 hdd_err("Global Context is NULL");
1972 QDF_ASSERT(0);
1973 return -EINVAL;
1974 }
1975
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001976 hdd_debug("start modules called in state! :%d reinit: %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05301977 hdd_ctx->driver_status, reinit);
1978
1979 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1980 if (!qdf_dev) {
1981 hdd_err("QDF Device Context is Invalid return");
1982 return -EINVAL;
1983 }
1984
1985 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301986 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301987
1988 if (QDF_TIMER_STATE_RUNNING ==
1989 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1990
1991 hdd_set_idle_ps_config(hdd_ctx, false);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001992 hdd_debug("Interface change Timer running Stop timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05301993 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1994 }
1995
1996 switch (hdd_ctx->driver_status) {
1997 case DRIVER_MODULES_UNINITIALIZED:
1998 unint = true;
1999 /* Fall through dont add break here */
2000 case DRIVER_MODULES_CLOSED:
2001 if (!reinit && !unint) {
2002 ret = pld_power_on(qdf_dev->dev);
2003 if (ret) {
2004 hdd_err("Failed to Powerup the device: %d", ret);
2005 goto release_lock;
2006 }
2007 }
2008 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
2009 qdf_dev->bus_type,
2010 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
2011 HIF_ENABLE_TYPE_PROBE);
2012 if (ret) {
2013 hdd_err("Failed to open hif: %d", ret);
2014 goto power_down;
2015 }
2016
2017 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05302018 if (!hif_ctx) {
2019 hdd_err("hif context is null!!");
2020 goto power_down;
2021 }
2022
Arun Khandavallifae92942016-08-01 13:31:08 +05302023 status = ol_cds_init(qdf_dev, hif_ctx);
2024 if (status != QDF_STATUS_SUCCESS) {
2025 hdd_err("No Memory to Create BMI Context :%d", status);
2026 goto hif_close;
2027 }
2028
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002029 ret = hdd_update_config(hdd_ctx);
2030 if (ret) {
2031 hdd_err("Failed to update configuration :%d", ret);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302032 goto ol_cds_free;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002033 }
2034
gbian62edd7e2017-03-07 13:12:13 +08002035 hdd_update_cds_ac_specs_params(hdd_ctx);
2036
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302037 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05302038 if (!QDF_IS_STATUS_SUCCESS(status)) {
2039 hdd_err("Failed to Open CDS: %d", status);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302040 goto ol_cds_free;
Arun Khandavallifae92942016-08-01 13:31:08 +05302041 }
2042
Mukul Sharma9d797a02017-01-05 20:26:03 +05302043 /* initalize components configurations after psoc open */
2044 ret = hdd_update_components_config(hdd_ctx);
2045 if (ret) {
2046 hdd_err("Failed to update components configs :%d",
2047 ret);
2048 goto close;
2049 }
2050
Naveen Rawatcb5c5402017-03-22 10:12:19 -07002051 /*
2052 * NAN compoenet requires certian operations like, open adapter,
2053 * close adapter, etc. to be initiated by HDD, for those
2054 * register HDD callbacks with UMAC's NAN componenet.
2055 */
2056 hdd_nan_register_callbacks(hdd_ctx);
2057
Arun Khandavallifae92942016-08-01 13:31:08 +05302058 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
2059
2060 status = cds_pre_enable(hdd_ctx->pcds_context);
2061 if (!QDF_IS_STATUS_SUCCESS(status)) {
2062 hdd_err("Failed to pre-enable CDS: %d", status);
2063 goto close;
2064 }
2065
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07002066 hdd_register_policy_manager_callback(
2067 hdd_ctx->hdd_psoc);
2068
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302069 hdd_update_hw_sw_info(hdd_ctx);
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05302070 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302071
Arun Khandavallifae92942016-08-01 13:31:08 +05302072 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2073 sme_register_ftm_msg_processor(hdd_ctx->hHal,
2074 hdd_ftm_mc_process_msg);
2075 break;
2076 }
2077 if (unint) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002078 hdd_debug("In phase-1 initialization don't enable modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05302079 break;
2080 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302081
2082 if (reinit) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08002083 if (hdd_ipa_uc_ssr_reinit(hdd_ctx)) {
2084 hdd_err("HDD IPA UC reinit failed");
2085 goto close;
2086 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302087 }
2088
Arun Khandavallifae92942016-08-01 13:31:08 +05302089 /* Fall through dont add break here */
2090 case DRIVER_MODULES_OPENED:
2091 if (!adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002092 hdd_err("adapter is Null");
Arun Khandavallifae92942016-08-01 13:31:08 +05302093 goto close;
2094 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05302095 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2096 hdd_err("in ftm mode, no need to configure cds modules");
2097 break;
2098 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302099 if (hdd_configure_cds(hdd_ctx, adapter)) {
2100 hdd_err("Failed to Enable cds modules");
2101 goto close;
2102 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05302103 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05302104 hdd_info("Driver Modules Successfully Enabled");
2105 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
2106 break;
2107 case DRIVER_MODULES_ENABLED:
2108 hdd_info("Driver modules already Enabled");
2109 break;
2110 default:
2111 hdd_err("WLAN start invoked in wrong state! :%d\n",
2112 hdd_ctx->driver_status);
2113 goto release_lock;
2114 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302115 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302116 mutex_unlock(&hdd_ctx->iface_change_lock);
2117 EXIT();
2118 return 0;
2119
2120close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302121 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05302122
2123ol_cds_free:
2124 ol_cds_free();
2125
2126hif_close:
2127 hdd_hif_close(p_cds_context->pHIFContext);
2128power_down:
2129 if (!reinit && !unint)
2130 pld_power_off(qdf_dev->dev);
2131release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302132 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302133 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302134 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05302135 return -EINVAL;
2136}
2137
Naveen Rawat910726a2017-03-06 11:42:51 -08002138#ifdef WIFI_POS_CONVERGED
2139static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2140{
2141 int ret = os_if_wifi_pos_register_nl();
2142
2143 if (ret)
2144 hdd_err("os_if_wifi_pos_register_nl failed");
2145
2146 return ret;
2147}
2148
2149static int hdd_deactivate_wifi_pos(void)
2150{
2151 int ret = os_if_wifi_pos_deregister_nl();
2152
2153 if (ret)
2154 hdd_err("os_if_wifi_pos_deregister_nl failed");
2155
2156 return ret;
2157}
2158
2159/**
2160 * hdd_populate_wifi_pos_cfg - populates wifi_pos parameters
2161 * @hdd_ctx: hdd context
2162 *
2163 * Return: status of operation
2164 */
2165static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2166{
2167 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2168 struct hdd_config *cfg = hdd_ctx->config;
2169
2170 wifi_pos_set_oem_target_type(psoc, hdd_ctx->target_type);
2171 wifi_pos_set_oem_fw_version(psoc, hdd_ctx->target_fw_version);
2172 wifi_pos_set_drv_ver_major(psoc, QWLAN_VERSION_MAJOR);
2173 wifi_pos_set_drv_ver_minor(psoc, QWLAN_VERSION_MINOR);
2174 wifi_pos_set_drv_ver_patch(psoc, QWLAN_VERSION_PATCH);
2175 wifi_pos_set_drv_ver_build(psoc, QWLAN_VERSION_BUILD);
2176 wifi_pos_set_dwell_time_min(psoc, cfg->nNeighborScanMinChanTime);
2177 wifi_pos_set_dwell_time_max(psoc, cfg->nNeighborScanMaxChanTime);
2178}
2179#else
2180static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2181{
2182 return oem_activate_service(hdd_ctx);
2183}
2184
2185static int hdd_deactivate_wifi_pos(void)
2186{
2187 return 0;
2188}
2189
2190static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2191{
2192}
2193#endif
2194
Arun Khandavallifae92942016-08-01 13:31:08 +05302195/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002196 * __hdd_open() - HDD Open function
2197 * @dev: Pointer to net_device structure
2198 *
2199 * This is called in response to ifconfig up
2200 *
2201 * Return: 0 for success; non-zero for failure
2202 */
2203static int __hdd_open(struct net_device *dev)
2204{
2205 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2206 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2207 int ret;
2208
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002209 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302210 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05302211 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212
2213 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302214 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217
Arun Khandavallifae92942016-08-01 13:31:08 +05302218 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
2219 if (ret) {
2220 hdd_err("Failed to start WLAN modules return");
2221 return -ret;
2222 }
2223
2224
2225 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2226 ret = hdd_start_adapter(adapter);
2227 if (ret) {
2228 hdd_err("Failed to start adapter :%d",
2229 adapter->device_mode);
2230 return ret;
2231 }
2232 }
2233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2235 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302236 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237 /* Enable TX queues only when we are connected */
2238 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05302239 WLAN_START_ALL_NETIF_QUEUE,
2240 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 }
2242
Naveen Rawat286def52016-09-23 15:38:02 -07002243 /* Enable carrier and transmit queues for NDI */
2244 if (WLAN_HDD_IS_NDI(adapter)) {
2245 hdd_notice("Enabling Tx Queues");
2246 wlan_hdd_netif_queue_control(adapter,
2247 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
2248 WLAN_CONTROL_PATH);
2249 }
2250
Naveen Rawat910726a2017-03-06 11:42:51 -08002251 hdd_populate_wifi_pos_cfg(hdd_ctx);
2252
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253 return ret;
2254}
2255
Arun Khandavallifae92942016-08-01 13:31:08 +05302256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257/**
2258 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
2259 * @dev: Pointer to net_device structure
2260 *
2261 * This is called in response to ifconfig up
2262 *
2263 * Return: 0 for success; non-zero for failure
2264 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002265static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002266{
2267 int ret;
2268
2269 cds_ssr_protect(__func__);
2270 ret = __hdd_open(dev);
2271 cds_ssr_unprotect(__func__);
2272
2273 return ret;
2274}
2275
2276/**
2277 * __hdd_stop() - HDD stop function
2278 * @dev: Pointer to net_device structure
2279 *
2280 * This is called in response to ifconfig down
2281 *
2282 * Return: 0 for success; non-zero for failure
2283 */
2284static int __hdd_stop(struct net_device *dev)
2285{
2286 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2287 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2288 int ret;
2289
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002290 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302292 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 adapter->sessionId, adapter->device_mode));
2294
2295 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302296 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002298
2299 /* Nothing to be done if the interface is not opened */
2300 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002301 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 return -ENODEV;
2303 }
2304
2305 /* Make sure the interface is marked as closed */
2306 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002307 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308
2309 /*
2310 * Disable TX on the interface, after this hard_start_xmit() will not
2311 * be called on that interface
2312 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002313 hdd_notice("Disabling queues");
Himanshu Agarwal865201d2017-04-12 15:45:31 +05302314 wlan_hdd_netif_queue_control(adapter,
2315 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
2316 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317
2318 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002319 * NAN data interface is different in some sense. The traffic on NDI is
2320 * bursty in nature and depends on the need to transfer. The service
2321 * layer may down the interface after the usage and up again when
2322 * required. In some sense, the NDI is expected to be available
2323 * (like SAP) iface until NDI delete request is issued by the service
2324 * layer. Skip BSS termination and adapter deletion for NAN Data
2325 * interface (NDI).
2326 */
2327 if (WLAN_HDD_IS_NDI(adapter))
2328 return 0;
2329
2330 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 * The interface is marked as down for outside world (aka kernel)
2332 * But the driver is pretty much alive inside. The driver needs to
2333 * tear down the existing connection on the netdev (session)
2334 * cleanup the data pipes and wait until the control plane is stabilized
2335 * for this interface. The call also needs to wait until the above
2336 * mentioned actions are completed before returning to the caller.
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002337 * Notice that hdd_stop_adapter is requested not to close the session
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 * That is intentional to be able to scan if it is a STA/P2P interface
2339 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302340 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341
2342 /* DeInit the adapter. This ensures datapath cleanup as well */
2343 hdd_deinit_adapter(hdd_ctx, adapter, true);
2344
Arun Khandavallifae92942016-08-01 13:31:08 +05302345
2346 /*
2347 * Find if any iface is up. If any iface is up then can't put device to
2348 * sleep/power save mode
2349 */
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05302350 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002351 hdd_debug("Closing all modules from the hdd_stop");
Arun Khandavallifae92942016-08-01 13:31:08 +05302352 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2353 hdd_ctx->config->iface_change_wait_time
2354 * 50000);
2355 }
2356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 EXIT();
2358 return 0;
2359}
2360
2361/**
2362 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2363 * @dev: pointer to net_device structure
2364 *
2365 * This is called in response to ifconfig down
2366 *
2367 * Return: 0 for success and error number for failure
2368 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002369static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370{
2371 int ret;
2372
2373 cds_ssr_protect(__func__);
2374 ret = __hdd_stop(dev);
2375 cds_ssr_unprotect(__func__);
2376
2377 return ret;
2378}
2379
2380/**
2381 * __hdd_uninit() - HDD uninit function
2382 * @dev: Pointer to net_device structure
2383 *
2384 * This is called during the netdev unregister to uninitialize all data
2385 * associated with the device
2386 *
2387 * Return: None
2388 */
2389static void __hdd_uninit(struct net_device *dev)
2390{
2391 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2392
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002393 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002394
2395 do {
2396 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002397 hdd_err("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398 break;
2399 }
2400
2401 if (NULL == adapter->pHddCtx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002402 hdd_err("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002403 break;
2404 }
2405
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002406 if (dev != adapter->dev)
2407 hdd_err("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408
2409 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2410
2411 /* after uninit our adapter structure will no longer be valid */
2412 adapter->dev = NULL;
2413 adapter->magic = 0;
2414 } while (0);
2415
2416 EXIT();
2417}
2418
2419/**
2420 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2421 * @dev: pointer to net_device structure
2422 *
2423 * This is called during the netdev unregister to uninitialize all data
2424 * associated with the device
2425 *
2426 * Return: none
2427 */
2428static void hdd_uninit(struct net_device *dev)
2429{
2430 cds_ssr_protect(__func__);
2431 __hdd_uninit(dev);
2432 cds_ssr_unprotect(__func__);
2433}
2434
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002435static int hdd_open_cesium_nl_sock(void)
2436{
2437#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2438 struct netlink_kernel_cfg cfg = {
2439 .groups = WLAN_NLINK_MCAST_GRP_ID,
2440 .input = NULL
2441 };
2442#endif
2443 int ret = 0;
2444
2445#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2446 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2447#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2448 THIS_MODULE,
2449#endif
2450 &cfg);
2451#else
2452 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2453 WLAN_NLINK_MCAST_GRP_ID,
2454 NULL, NULL, THIS_MODULE);
2455#endif
2456
2457 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002458 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002459 ret = -ECONNREFUSED;
2460 }
2461
2462 return ret;
2463}
2464
2465static void hdd_close_cesium_nl_sock(void)
2466{
2467 if (NULL != cesium_nl_srv_sock) {
2468 netlink_kernel_release(cesium_nl_srv_sock);
2469 cesium_nl_srv_sock = NULL;
2470 }
2471}
2472
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473/**
2474 * __hdd_set_mac_address() - set the user specified mac address
2475 * @dev: Pointer to the net device.
2476 * @addr: Pointer to the sockaddr.
2477 *
2478 * This function sets the user specified mac address using
2479 * the command ifconfig wlanX hw ether <mac adress>.
2480 *
2481 * Return: 0 for success, non zero for failure
2482 */
2483static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2484{
2485 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2486 hdd_context_t *hdd_ctx;
2487 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302488 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 int ret;
2490
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002491 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002492
2493 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2494 ret = wlan_hdd_validate_context(hdd_ctx);
2495 if (0 != ret)
2496 return ret;
2497
2498 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2499 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2500
2501 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302502 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503}
2504
2505/**
2506 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2507 * function from SSR
2508 * @dev: pointer to net_device structure
2509 * @addr: Pointer to the sockaddr
2510 *
2511 * This function sets the user specified mac address using
2512 * the command ifconfig wlanX hw ether <mac adress>.
2513 *
2514 * Return: 0 for success.
2515 */
2516static int hdd_set_mac_address(struct net_device *dev, void *addr)
2517{
2518 int ret;
2519
2520 cds_ssr_protect(__func__);
2521 ret = __hdd_set_mac_address(dev, addr);
2522 cds_ssr_unprotect(__func__);
2523
2524 return ret;
2525}
2526
2527uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2528{
2529 int i;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002530
Anurag Chouhan6d760662016-02-20 16:05:43 +05302531 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2533 break;
2534 }
2535
Anurag Chouhan6d760662016-02-20 16:05:43 +05302536 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 return NULL;
2538
2539 hdd_ctx->config->intfAddrMask |= (1 << i);
2540 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2541}
2542
2543void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2544{
2545 int i;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002546
Anurag Chouhan6d760662016-02-20 16:05:43 +05302547 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 if (!memcmp(releaseAddr,
2549 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2550 6)) {
2551 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2552 break;
2553 }
2554 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555}
2556
2557#ifdef WLAN_FEATURE_PACKET_FILTERING
2558/**
2559 * __hdd_set_multicast_list() - set the multicast address list
2560 * @dev: Pointer to the WLAN device.
2561 * @skb: Pointer to OS packet (sk_buff).
2562 *
2563 * This funciton sets the multicast address list.
2564 *
2565 * Return: None
2566 */
2567static void __hdd_set_multicast_list(struct net_device *dev)
2568{
2569 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 int i = 0, status;
2571 struct netdev_hw_addr *ha;
2572 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302573 struct pmo_mc_addr_list_params *mc_list_request = NULL;
2574 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2575 int mc_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002576
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002577 ENTER_DEV(dev);
Anurag Chouhan6d760662016-02-20 16:05:43 +05302578 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302579 goto out;
Mukul Sharma51c44942015-10-30 19:30:19 +05302580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302582 if (0 != status)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302583 goto out;
2584
2585 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
2586 if (!mc_list_request) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002587 hdd_err("Cannot allocate mc_list_request");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302588 goto out;
2589 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590
2591 if (dev->flags & IFF_ALLMULTI) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002592 hdd_debug("allow all multicast frames");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302593 hdd_disable_and_flush_mc_addr_list(adapter,
2594 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 } else {
2596 mc_count = netdev_mc_count(dev);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302597 if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002598 hdd_debug("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302599 pmo_ucfg_max_mc_addr_supported(psoc));
2600 hdd_disable_and_flush_mc_addr_list(adapter,
2601 pmo_mc_list_change_notify);
2602 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 netdev_for_each_mc_addr(ha, dev) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002605 hdd_debug("ha_addr[%d] "MAC_ADDRESS_STR,
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302606 i, MAC_ADDR_ARRAY(ha->addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 if (i == mc_count)
2608 break;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302609 memset(&(mc_list_request->mc_addr[i].bytes),
2610 0, ETH_ALEN);
2611 memcpy(&(mc_list_request->mc_addr[i].bytes),
2612 ha->addr, ETH_ALEN);
2613 hdd_info("mlist[%d] = %pM", i,
2614 mc_list_request->mc_addr[i].bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615 i++;
2616 }
2617 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302618
2619 mc_list_request->psoc = psoc;
2620 mc_list_request->vdev_id = adapter->sessionId;
2621 mc_list_request->count = mc_count;
2622 status = hdd_cache_mc_addr_list(mc_list_request);
2623 if (status == 0) {
2624 hdd_enable_mc_addr_filtering(adapter,
2625 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 } else {
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302627 hdd_err("error while caching mc list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302629out:
2630 if (mc_list_request)
2631 qdf_mem_free(mc_list_request);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302632 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633}
2634
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302635
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636/**
2637 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2638 * @dev: pointer to net_device
2639 *
2640 * Return: none
2641 */
2642static void hdd_set_multicast_list(struct net_device *dev)
2643{
2644 cds_ssr_protect(__func__);
2645 __hdd_set_multicast_list(dev);
2646 cds_ssr_unprotect(__func__);
2647}
2648#endif
2649
2650/**
2651 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2652 * @dev: Pointer to the WLAN device.
2653 * @skb: Pointer to OS packet (sk_buff).
2654 *
2655 * This function is registered with the Linux OS for network
2656 * core to decide which queue to use first.
2657 *
2658 * Return: ac, Queue Index/access category corresponding to UP in IP header
2659 */
2660static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2661#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2662 , void *accel_priv
2663#endif
2664#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2665 , select_queue_fallback_t fallback
2666#endif
2667)
2668{
2669 return hdd_wmm_select_queue(dev, skb);
2670}
2671
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002672static const struct net_device_ops wlan_drv_ops = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 .ndo_open = hdd_open,
2674 .ndo_stop = hdd_stop,
2675 .ndo_uninit = hdd_uninit,
2676 .ndo_start_xmit = hdd_hard_start_xmit,
2677 .ndo_tx_timeout = hdd_tx_timeout,
2678 .ndo_get_stats = hdd_get_stats,
2679 .ndo_do_ioctl = hdd_ioctl,
2680 .ndo_set_mac_address = hdd_set_mac_address,
2681 .ndo_select_queue = hdd_select_queue,
2682#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684#endif
2685};
2686
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002687/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002688static const struct net_device_ops wlan_mon_drv_ops = {
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002689 .ndo_open = hdd_mon_open,
2690 .ndo_stop = hdd_stop,
2691 .ndo_get_stats = hdd_get_stats,
2692};
2693
2694/**
2695 * hdd_set_station_ops() - update net_device ops for monitor mode
2696 * @pWlanDev: Handle to struct net_device to be updated.
2697 * Return: None
2698 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699void hdd_set_station_ops(struct net_device *pWlanDev)
2700{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002701 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2702 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2703 else
2704 pWlanDev->netdev_ops = &wlan_drv_ops;
2705}
2706
Komal Seelama89be8d2016-09-29 11:09:26 +05302707#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302708/**
2709 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2710 * @hdd_ctx: HDD context
2711 *
2712 * Return: None
2713 */
2714static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2715{
2716 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2717
2718 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302719 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302720 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302721}
2722
2723/**
2724 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2725 * @hdd_ctx: HDD Context
2726 *
2727 * Return: None
2728 */
2729static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2730{
2731 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2732
2733 qdf_runtime_lock_deinit(ctx->scan);
2734 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302735 qdf_runtime_lock_deinit(ctx->roc);
2736 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302737 qdf_runtime_lock_deinit(ctx->dfs);
2738 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302739}
2740
Komal Seelama89be8d2016-09-29 11:09:26 +05302741static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2742{
2743 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2744
2745 ctx->connect = qdf_runtime_lock_init("connect");
2746}
2747
2748static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2749{
2750 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2751
2752 qdf_runtime_lock_deinit(ctx->connect);
2753 ctx->connect = NULL;
2754}
2755#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302756static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2757static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302758static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2759static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2760#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002761/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002762 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2763 * @hdd_ctx: global hdd context
2764 * @macAddr: mac address to assign to the interface
2765 * @name: User-visible name of the interface
2766 *
2767 * hdd adapter pointer would point to the netdev->priv space, this function
2768 * would retrive the pointer, and setup the hdd adapter configuration.
2769 *
2770 * Return: the pointer to hdd adapter, otherwise NULL
2771 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2773 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002774 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002775 const char *name)
2776{
2777 struct net_device *pWlanDev = NULL;
2778 hdd_adapter_t *adapter = NULL;
2779 /*
2780 * cfg80211 initialization and registration....
2781 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002782 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2783#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2784 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002786 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2787 hdd_mon_mode_ether_setup : ether_setup),
2788 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002789
2790 if (pWlanDev != NULL) {
2791
2792 /* Save the pointer to the net_device in the HDD adapter */
2793 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2794
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302795 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796
2797 adapter->dev = pWlanDev;
2798 adapter->pHddCtx = hdd_ctx;
2799 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302800 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801
2802 init_completion(&adapter->session_open_comp_var);
2803 init_completion(&adapter->session_close_comp_var);
2804 init_completion(&adapter->disconnect_comp_var);
2805 init_completion(&adapter->linkup_event_var);
2806 init_completion(&adapter->cancel_rem_on_chan_var);
2807 init_completion(&adapter->rem_on_chan_ready_event);
2808 init_completion(&adapter->sta_authorized_event);
2809 init_completion(&adapter->offchannel_tx_event);
2810 init_completion(&adapter->tx_action_cnf_event);
2811#ifdef FEATURE_WLAN_TDLS
2812 init_completion(&adapter->tdls_add_station_comp);
2813 init_completion(&adapter->tdls_del_station_comp);
2814 init_completion(&adapter->tdls_mgmt_comp);
2815 init_completion(&adapter->tdls_link_establish_req_comp);
2816#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002817 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818 init_completion(&adapter->change_country_code);
2819
2820
2821 init_completion(&adapter->scan_info.abortscan_event_var);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302822 init_completion(&adapter->lfr_fw_status.disable_lfr_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823
2824 adapter->offloads_configured = false;
2825 adapter->isLinkUpSvcNeeded = false;
2826 adapter->higherDtimTransition = true;
2827 /* Init the net_device structure */
2828 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2829
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302830 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302832 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833 sizeof(tSirMacAddr));
2834 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835
2836 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2837 pWlanDev->features |=
2838 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2839 pWlanDev->features |= NETIF_F_RXCSUM;
2840
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002841 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2842
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 hdd_set_station_ops(adapter->dev);
2844
2845 pWlanDev->destructor = free_netdev;
2846 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002847 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 adapter->wdev.wiphy = hdd_ctx->wiphy;
2849 adapter->wdev.netdev = pWlanDev;
2850 /* set pWlanDev's parent to underlying device */
2851 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2852 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302853 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002854 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302855 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856 }
2857
2858 return adapter;
2859}
2860
Jeff Johnson590e2012016-10-05 16:16:24 -07002861static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2862 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863{
2864 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002866 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2868 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002869 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302870 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871 }
2872 }
2873 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002874 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302875 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876 }
2877 } else {
2878 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002879 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302880 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881 }
2882 }
2883 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2884
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302885 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886}
2887
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002888QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889{
2890 hdd_adapter_t *adapter = pContext;
2891
2892 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002893 hdd_err("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302894 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 }
2896
2897 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002898 hdd_err("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302899 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 }
2901
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002902 /*
2903 * For NAN Data interface, the close session results in the final
2904 * indication to the userspace
2905 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002906 if (adapter->device_mode == QDF_NDI_MODE)
2907 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002908
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2910
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 /*
2912 * We can be blocked while waiting for scheduled work to be
2913 * flushed, and the adapter structure can potentially be freed, in
2914 * which case the magic will have been reset. So make sure the
2915 * magic is still good, and hence the adapter structure is still
2916 * valid, before signaling completion
2917 */
2918 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2919 complete(&adapter->session_close_comp_var);
2920
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302921 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922}
2923
Krunal Soni8c37e322016-02-03 16:08:37 -08002924/**
2925 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2926 * @adapter: pointer to device adapter
Krunal Soni8c37e322016-02-03 16:08:37 -08002927 *
2928 * This routine will check the mode of adapter and if it is required then it
2929 * will initialize the TDLS operations
2930 *
2931 * Return: QDF_STATUS
2932 */
2933#ifdef FEATURE_WLAN_TDLS
Dustin Brownd28772b2017-03-17 14:16:07 -07002934static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002935{
Dustin Brownd28772b2017-03-17 14:16:07 -07002936 if (adapter->device_mode == QDF_IBSS_MODE)
2937 return QDF_STATUS_SUCCESS;
2938
2939 if (wlan_hdd_tdls_init(adapter)) {
2940 hdd_err("wlan_hdd_tdls_init failed");
2941 return QDF_STATUS_E_FAILURE;
Krunal Soni8c37e322016-02-03 16:08:37 -08002942 }
Dustin Brownd28772b2017-03-17 14:16:07 -07002943 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2944
Krunal Soni8c37e322016-02-03 16:08:37 -08002945 return QDF_STATUS_SUCCESS;
2946}
2947#else
Dustin Brownd28772b2017-03-17 14:16:07 -07002948static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002949{
2950 return QDF_STATUS_SUCCESS;
2951}
2952#endif
2953
Dustin Brownd28772b2017-03-17 14:16:07 -07002954int hdd_vdev_ready(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955{
Dustin Brownd28772b2017-03-17 14:16:07 -07002956 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957
Dustin Brownd28772b2017-03-17 14:16:07 -07002958 status = pmo_vdev_ready(adapter->hdd_vdev);
2959
2960 return qdf_status_to_os_return(status);
2961}
2962
2963int hdd_vdev_destroy(hdd_adapter_t *adapter)
2964{
2965 QDF_STATUS status;
2966 int errno;
2967 hdd_context_t *hdd_ctx;
2968 unsigned long rc;
2969
2970 hdd_info("destroying vdev %d", adapter->sessionId);
2971
2972 /* vdev created sanity check */
2973 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2974 hdd_err("vdev for Id %d does not exist", adapter->sessionId);
2975 return -EINVAL;
2976 }
2977
Dustin Brown0d2eeae2017-03-24 15:21:32 -07002978 /* do vdev logical destroy via objmgr */
2979 errno = hdd_objmgr_destroy_vdev(adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07002980 if (errno) {
2981 hdd_err("failed to destroy objmgr vdev: %d", errno);
2982 return errno;
2983 }
2984
2985 /* close sme session (destroy vdev in firmware via legacy API) */
2986 INIT_COMPLETION(adapter->session_close_comp_var);
2987 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2988 status = sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2989 hdd_sme_close_session_callback, adapter);
2990 if (QDF_IS_STATUS_ERROR(status)) {
2991 hdd_err("failed to close sme session: %d", status);
2992 return qdf_status_to_os_return(status);
2993 }
2994
2995 /* block on a completion variable until sme session is closed */
2996 rc = wait_for_completion_timeout(
2997 &adapter->session_close_comp_var,
2998 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2999 if (!rc) {
3000 hdd_err("timed out waiting for close sme session: %ld", rc);
3001 if (adapter->device_mode == QDF_NDI_MODE)
3002 hdd_ndp_session_end_handler(adapter);
3003 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
3004 return -ETIMEDOUT;
3005 }
3006
Dustin Brown0d2eeae2017-03-24 15:21:32 -07003007 /* now that sme session is closed, allow physical vdev destroy */
3008 errno = hdd_objmgr_release_vdev(adapter);
3009 if (errno) {
3010 hdd_err("failed to release objmgr vdev: %d", errno);
3011 return errno;
3012 }
3013
Dustin Brownd28772b2017-03-17 14:16:07 -07003014 hdd_info("vdev destroyed successfully");
3015
3016 return 0;
3017}
3018
3019int hdd_vdev_create(hdd_adapter_t *adapter)
3020{
3021 QDF_STATUS status;
3022 int errno;
3023 hdd_context_t *hdd_ctx;
3024 uint32_t type;
3025 uint32_t sub_type;
3026 unsigned long rc;
3027
3028 hdd_info("creating new vdev");
3029
3030 /* determine vdev (sub)type */
3031 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303032 if (QDF_STATUS_SUCCESS != status) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003033 hdd_err("failed to get vdev type: %d", status);
3034 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003036
3037 /* do vdev create via objmgr */
3038 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown7d043f62017-03-27 12:07:36 -07003039 errno = hdd_objmgr_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07003040 if (errno) {
3041 hdd_err("failed to create objmgr vdev: %d", errno);
3042 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003044
3045 /* Open a SME session (prepare vdev in firmware via legacy API) */
3046 INIT_COMPLETION(adapter->session_open_comp_var);
3047 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
3048 (uint8_t *)&adapter->macAddressCurrent,
3049 adapter->sessionId, type, sub_type);
3050 if (QDF_IS_STATUS_ERROR(status)) {
3051 hdd_err("failed to open sme session: %d", status);
3052 errno = qdf_status_to_os_return(status);
3053 goto objmgr_vdev_destroy;
3054 }
3055
3056 /* block on a completion variable until sme session is opened */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 rc = wait_for_completion_timeout(
3058 &adapter->session_open_comp_var,
3059 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3060 if (!rc) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003061 hdd_err("timed out waiting for open sme session: %ld", rc);
3062 errno = -ETIMEDOUT;
3063 goto objmgr_vdev_destroy;
3064 }
3065
3066 /* firmware ready for component communication, raise vdev_ready event */
3067 errno = hdd_vdev_ready(adapter);
3068 if (errno) {
3069 hdd_err("failed to dispatch vdev ready event: %d", errno);
3070 goto hdd_vdev_destroy;
3071 }
3072
3073 hdd_info("vdev %d created successfully", adapter->sessionId);
3074
3075 return 0;
3076
3077 /*
3078 * Due to legacy constraints, we need to destroy in the same order as
3079 * create. So, split error handling into 2 cases to accommodate.
3080 */
3081
3082objmgr_vdev_destroy:
Dustin Brown7d043f62017-03-27 12:07:36 -07003083 QDF_BUG(!hdd_objmgr_release_and_destroy_vdev(adapter));
Dustin Brownd28772b2017-03-17 14:16:07 -07003084
3085 return errno;
3086
3087hdd_vdev_destroy:
3088 QDF_BUG(!hdd_vdev_destroy(adapter));
3089
3090 return errno;
3091}
3092
3093QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
3094{
3095 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
3096 hdd_context_t *hdd_ctx;
3097 QDF_STATUS status;
3098 int ret_val;
3099
3100 ret_val = hdd_vdev_create(adapter);
3101 if (ret_val) {
3102 hdd_err("failed to create vdev: %d", ret_val);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303103 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 }
3105
Dustin Brownd28772b2017-03-17 14:16:07 -07003106 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3107 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
3108 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Naveen Rawata410c5a2016-09-19 14:22:33 -07003109 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Dustin Brownd28772b2017-03-17 14:16:07 -07003110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111 /* Register wireless extensions */
Dustin Brownd28772b2017-03-17 14:16:07 -07003112 status = hdd_register_wext(adapter->dev);
3113 if (QDF_IS_STATUS_ERROR(status)) {
3114 hdd_err("failed to register wireless extensions: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 goto error_register_wext;
3116 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118 /* Set the Connection State to Not Connected */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003119 hdd_debug("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3121
Deepak Dhamdherea2785822016-11-17 01:17:45 -08003122 /* set fast roaming capability in sme session */
3123 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
3124 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003125 /* Set the default operation channel */
3126 pHddStaCtx->conn_info.operationChannel =
3127 hdd_ctx->config->OperatingChannel;
3128
3129 /* Make the default Auth Type as OPEN */
3130 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3131
3132 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303133 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003134 hdd_err("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135 status, status);
3136 goto error_init_txrx;
3137 }
3138
3139 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3140
3141 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303142 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003143 hdd_err("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144 status, status);
3145 goto error_wmm_init;
3146 }
3147
3148 set_bit(WMM_INIT_DONE, &adapter->event_flags);
3149
3150 ret_val = wma_cli_set_command(adapter->sessionId,
3151 WMI_PDEV_PARAM_BURST_ENABLE,
3152 hdd_ctx->config->enableSifsBurst,
3153 PDEV_CMD);
Dustin Brownd28772b2017-03-17 14:16:07 -07003154 if (ret_val)
3155 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156
Dustin Brownd28772b2017-03-17 14:16:07 -07003157 status = hdd_check_and_init_tdls(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08003158 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303161 status = hdd_lro_enable(hdd_ctx, adapter);
3162 if (status != QDF_STATUS_SUCCESS)
3163 goto error_lro_enable;
3164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303167error_lro_enable:
3168 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169error_tdls_init:
3170 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3171 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172error_wmm_init:
3173 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3174 hdd_deinit_tx_rx(adapter);
3175error_init_txrx:
Dustin Brownd28772b2017-03-17 14:16:07 -07003176 hdd_unregister_wext(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177error_register_wext:
Dustin Brownd28772b2017-03-17 14:16:07 -07003178 QDF_BUG(!hdd_vdev_destroy(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 return status;
3181}
3182
3183void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
3184{
3185 hdd_cfg80211_state_t *cfgState;
3186
3187 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3188
3189 if (NULL != cfgState->buf) {
3190 unsigned long rc;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003191
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 rc = wait_for_completion_timeout(
3193 &adapter->tx_action_cnf_event,
3194 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3195 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003196 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05303197 /*
3198 * Inform tx status as FAILURE to upper layer and free
3199 * cfgState->buf
3200 */
3201 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 }
3203 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204}
3205
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303206/**
3207 * hdd_station_adapter_deinit() - De-initialize the station adapter
3208 * @hdd_ctx: global hdd context
3209 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07003210 * @rtnl_held: Used to indicate whether or not the caller is holding
3211 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303212 *
3213 * This function De-initializes the STA/P2P/OCB adapter.
3214 *
3215 * Return: None.
3216 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003217static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
3218 hdd_adapter_t *adapter,
3219 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303220{
3221 ENTER_DEV(adapter->dev);
3222
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303223 if (adapter->dev) {
3224 if (rtnl_held)
3225 adapter->dev->wireless_handlers = NULL;
3226 else {
3227 rtnl_lock();
3228 adapter->dev->wireless_handlers = NULL;
3229 rtnl_unlock();
3230 }
3231 }
3232
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303233 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
3234 hdd_deinit_tx_rx(adapter);
3235 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3236 }
3237
3238 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3239 hdd_wmm_adapter_close(adapter);
3240 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3241 }
3242
3243 hdd_cleanup_actionframe(hdd_ctx, adapter);
3244 wlan_hdd_tdls_exit(adapter);
3245
3246 EXIT();
3247}
3248
3249/**
3250 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
3251 * @hdd_ctx: global hdd context
3252 * @adapter: HDD adapter
3253 * @rtnl_held: the rtnl lock hold flag
3254 * This function De-initializes the AP/P2PGo adapter.
3255 *
3256 * Return: None.
3257 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003258static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
3259 hdd_adapter_t *adapter,
3260 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303261{
3262 ENTER_DEV(adapter->dev);
3263
3264 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3265 hdd_wmm_adapter_close(adapter);
3266 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3267 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003268 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303269
3270 hdd_cleanup_actionframe(hdd_ctx, adapter);
3271
3272 hdd_unregister_hostapd(adapter, rtnl_held);
3273
3274 EXIT();
3275}
3276
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3278 bool rtnl_held)
3279{
3280 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003283 case QDF_STA_MODE:
3284 case QDF_P2P_CLIENT_MODE:
3285 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303287 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288 break;
3289 }
3290
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003291 case QDF_SAP_MODE:
3292 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003293 {
3294
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303295 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003296 break;
3297 }
3298
3299 default:
3300 break;
3301 }
3302
3303 EXIT();
3304}
3305
Jeff Johnson590e2012016-10-05 16:16:24 -07003306static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3307 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308{
3309 struct net_device *pWlanDev = NULL;
3310
3311 if (adapter)
3312 pWlanDev = adapter->dev;
3313 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003314 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003315 return;
3316 }
3317
Rajeev Kumardca5f812016-02-04 17:28:06 -08003318 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303319
3320 if (adapter->scan_info.default_scan_ies) {
3321 qdf_mem_free(adapter->scan_info.default_scan_ies);
3322 adapter->scan_info.default_scan_ies = NULL;
3323 }
3324
Komal Seelama89be8d2016-09-29 11:09:26 +05303325 hdd_adapter_runtime_suspend_denit(adapter);
3326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327 /*
3328 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
3329 * the driver is almost closed and cannot handle either control
3330 * messages or data. However, unregister_netdevice() call above will
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003331 * eventually invoke hdd_stop(ndo_close) driver callback, which attempts
3332 * to close the active connections(basically excites control path) which
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333 * is not right. Setting this flag helps hdd_stop() to recognize that
3334 * the interface is closed and restricts any operations on that
3335 */
3336 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3337
3338 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003339 if (rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340 unregister_netdevice(pWlanDev);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003341 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342 unregister_netdev(pWlanDev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 /*
3344 * Note that the adapter is no longer valid at this point
3345 * since the memory has been reclaimed
3346 */
3347 }
3348}
3349
Jeff Johnson590e2012016-10-05 16:16:24 -07003350static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
3351 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352{
3353 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3354 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303355 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303358 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359 adapter = adapterNode->pAdapter;
3360 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303361 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303363 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 }
3365 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3366 adapterNode = pNext;
3367 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303368 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369}
Ryan Hsu07495ea2016-01-21 15:25:39 -08003370
Arun Khandavalli2358d522016-05-16 18:05:37 +05303371#ifdef CONFIG_FW_LOGS_BASED_ON_INI
3372/**
3373 * hdd_set_fw_log_params() - Set log parameters to FW
3374 * @hdd_ctx: HDD Context
3375 * @adapter: HDD Adapter
3376 *
3377 * This function set the FW Debug log level based on the INI.
3378 *
3379 * Return: None
3380 */
3381static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3382 hdd_adapter_t *adapter)
3383{
3384 uint8_t count = 0, numentries = 0,
3385 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3386 uint32_t value = 0;
3387 int ret;
3388
Arun Khandavallifae92942016-08-01 13:31:08 +05303389 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3390 (!hdd_ctx->config->enable_fw_log)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003391 hdd_debug("enable_fw_log not enabled in INI or in FTM mode return");
Arun Khandavalli2358d522016-05-16 18:05:37 +05303392 return;
3393 }
3394
Arun Khandavallifae92942016-08-01 13:31:08 +05303395 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303396 hdd_ctx->fw_log_settings.dl_type =
3397 hdd_ctx->config->enableFwLogType;
3398 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303399 WMI_DBGLOG_TYPE,
3400 hdd_ctx->config->enableFwLogType,
3401 DBG_CMD);
3402 if (ret != 0)
3403 hdd_err("Failed to enable FW log type ret %d",
3404 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303405
3406 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303407 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303408 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303409 WMI_DBGLOG_LOG_LEVEL,
3410 hdd_ctx->config->enableFwLogLevel,
3411 DBG_CMD);
3412 if (ret != 0)
3413 hdd_err("Failed to enable FW log level ret %d",
3414 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303415
3416 hdd_string_to_u8_array(
3417 hdd_ctx->config->enableFwModuleLogLevel,
3418 moduleloglevel,
3419 &numentries,
3420 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3421
3422 while (count < numentries) {
3423 /*
3424 * FW module log level input string looks like
3425 * below:
3426 * gFwDebugModuleLoglevel=<FW Module ID>,
3427 * <Log Level>,...
3428 * For example:
3429 * gFwDebugModuleLoglevel=
3430 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3431 * Above input string means :
3432 * For FW module ID 1 enable log level 0
3433 * For FW module ID 2 enable log level 1
3434 * For FW module ID 3 enable log level 2
3435 * For FW module ID 4 enable log level 3
3436 * For FW module ID 5 enable log level 4
3437 * For FW module ID 6 enable log level 5
3438 * For FW module ID 7 enable log level 6
3439 */
3440
Nishank Aggarwale239d962017-03-03 12:26:02 +05303441 if ((moduleloglevel[count] > WLAN_MODULE_ID_MAX)
3442 || (moduleloglevel[count + 1] > DBGLOG_LVL_MAX)) {
3443 hdd_err("Module id %d and dbglog level %d input length is more than max",
3444 moduleloglevel[count],
3445 moduleloglevel[count + 1]);
3446 return;
3447 }
3448
3449 value = moduleloglevel[count] << 16;
3450 value |= moduleloglevel[count + 1];
Arun Khandavalli2358d522016-05-16 18:05:37 +05303451 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303452 WMI_DBGLOG_MOD_LOG_LEVEL,
3453 value, DBG_CMD);
3454 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303455 hdd_err("Failed to enable FW module log level %d ret %d",
3456 value, ret);
3457
3458 count += 2;
3459 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303460
Arun Khandavalli2358d522016-05-16 18:05:37 +05303461}
3462#else
3463static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3464 hdd_adapter_t *adapter)
3465{
3466}
3467
3468#endif
3469
3470/**
3471 * hdd_set_fw_params() - Set parameters to firmware
3472 * @adapter: HDD adapter
3473 *
3474 * This function Sets various parameters to fw once the
3475 * adapter is started.
3476 *
3477 * Return: 0 on success or errno on failure
3478 */
3479int hdd_set_fw_params(hdd_adapter_t *adapter)
3480{
3481 int ret;
3482 hdd_context_t *hdd_ctx;
3483
3484 ENTER_DEV(adapter->dev);
3485
3486 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3487 if (!hdd_ctx)
3488 return -EINVAL;
3489
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003490 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303491 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303492#define HDD_DTIM_1CHAIN_RX_ID 0x5
3493#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003494 /*
3495 * Disable DTIM 1 chain Rx when in 1x1,
3496 * we are passing two value
3497 * as param_id << 29 | param_value.
3498 * Below param_value = 0(disable)
3499 */
3500 ret = wma_cli_set_command(adapter->sessionId,
3501 WMI_STA_SMPS_PARAM_CMDID,
3502 HDD_DTIM_1CHAIN_RX_ID <<
3503 HDD_SMPS_PARAM_VALUE_S,
3504 VDEV_CMD);
3505 if (ret) {
3506 hdd_err("DTIM 1 chain set failed %d", ret);
3507 goto error;
3508 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303509
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003510 ret = wma_cli_set_command(adapter->sessionId,
3511 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3512 hdd_ctx->config->txchainmask1x1,
3513 PDEV_CMD);
3514 if (ret) {
3515 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3516 ret);
3517 goto error;
3518 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303519
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003520 ret = wma_cli_set_command(adapter->sessionId,
3521 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3522 hdd_ctx->config->rxchainmask1x1,
3523 PDEV_CMD);
3524 if (ret) {
3525 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3526 ret);
3527 goto error;
3528 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303529#undef HDD_DTIM_1CHAIN_RX_ID
3530#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003531 } else {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003532 hdd_debug("FTM Mode or 2x2 mode - Do not set 1x1 params");
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003533 }
3534
Arun Khandavallifae92942016-08-01 13:31:08 +05303535 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3536 ret = wma_cli_set_command(adapter->sessionId,
3537 WMI_PDEV_PARAM_HYST_EN,
3538 hdd_ctx->config->enableMemDeepSleep,
3539 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303540
Arun Khandavallifae92942016-08-01 13:31:08 +05303541 if (ret) {
3542 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3543 ret);
3544 goto error;
3545 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303546
3547 ret = wma_cli_set_command(adapter->sessionId,
3548 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3549 hdd_ctx->config->rts_profile,
3550 VDEV_CMD);
3551 if (ret) {
3552 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3553 goto error;
3554 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303555 }
3556
3557 hdd_set_fw_log_params(hdd_ctx, adapter);
3558
3559 EXIT();
3560 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303561
Arun Khandavalli2358d522016-05-16 18:05:37 +05303562error:
3563 return -EINVAL;
3564}
3565
Ryan Hsu07495ea2016-01-21 15:25:39 -08003566/**
3567 * hdd_open_adapter() - open and setup the hdd adatper
3568 * @hdd_ctx: global hdd context
3569 * @session_type: type of the interface to be created
3570 * @iface_name: User-visible name of the interface
3571 * @macAddr: MAC address to assign to the interface
3572 * @name_assign_type: the name of assign type of the netdev
3573 * @rtnl_held: the rtnl lock hold flag
3574 *
3575 * This function open and setup the hdd adpater according to the device
3576 * type request, assign the name, the mac address assigned, and then prepared
3577 * the hdd related parameters, queue, lock and ready to start.
3578 *
3579 * Return: the pointer of hdd adapter, otherwise NULL.
3580 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3582 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003583 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003584 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585{
3586 hdd_adapter_t *adapter = NULL;
3587 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303588 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08003591 hdd_info("%s interface created. iftype: %d", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592
3593 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3594 /*
3595 * Max limit reached on the number of vdevs configured by the
3596 * host. Return error
3597 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303598 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3599 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003600 return NULL;
3601 }
3602
3603 if (macAddr == NULL) {
3604 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303605 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003606 return NULL;
3607 }
3608 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303609 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303610 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3611 " already exists",
3612 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613 return NULL;
3614 }
3615
3616 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003617 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618 /* Reset locally administered bit if the device mode is STA */
3619 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3620 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003621 case QDF_P2P_CLIENT_MODE:
3622 case QDF_P2P_DEVICE_MODE:
3623 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003624 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303625 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003626 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3627 name_assign_type,
3628 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629
3630 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303631 hdd_err("failed to allocate adapter for session %d",
3632 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633 return NULL;
3634 }
3635
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003636 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003638 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003639 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303640 else if (QDF_MONITOR_MODE == session_type)
3641 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 else
3643 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3644
3645 adapter->device_mode = session_type;
3646
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303647 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003648 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303649 if (QDF_STATUS_SUCCESS != status)
3650 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303651 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003652
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003653 /*
3654 * Workqueue which gets scheduled in IPv4 notification
3655 * callback
3656 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003657 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3658 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659
3660#ifdef WLAN_NS_OFFLOAD
3661 /*
3662 * Workqueue which gets scheduled in IPv6
3663 * notification callback.
3664 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3666 hdd_ipv6_notifier_work_queue);
3667#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003668 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303669 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303671 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 }
3673
3674 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303675 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003676 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303677 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3678 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003682 case QDF_P2P_GO_MODE:
3683 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003684 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3685 name_assign_type,
3686 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003688 hdd_err("failed to allocate adapter for session %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05303689 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 return NULL;
3691 }
3692
3693 adapter->wdev.iftype =
3694 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003695 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696 NL80211_IFTYPE_P2P_GO;
3697 adapter->device_mode = session_type;
3698
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003699 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303700 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3702 goto err_free_netdev;
3703 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303704 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303706 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3707 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003708 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303709 case QDF_FTM_MODE:
3710 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3711 name_assign_type,
3712 "wlan0");
3713 if (NULL == adapter) {
3714 hdd_err("Failed to allocate adapter for FTM mode");
3715 return NULL;
3716 }
3717 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3718 adapter->device_mode = session_type;
3719 status = hdd_register_interface(adapter, rtnl_held);
3720 if (QDF_STATUS_SUCCESS != status) {
3721 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3722 goto err_free_netdev;
3723 }
3724 /* Stop the Interface TX queue. */
3725 hdd_info("Disabling queues");
3726 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303727 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3728 WLAN_CONTROL_PATH);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303729 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003731 hdd_err("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303732 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 return NULL;
3734 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735
3736 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3737 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3738
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303739 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003740 /* Add it to the hdd's session list. */
3741 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303742 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303744 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003745 } else {
3746 pHddAdapterNode->pAdapter = adapter;
3747 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3748 }
3749 }
3750
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303751 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752 if (NULL != adapter) {
3753 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3754 adapter = NULL;
3755 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003756 if (NULL != pHddAdapterNode)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303757 qdf_mem_free(pHddAdapterNode);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003759 return NULL;
3760 }
3761
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303762 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003763 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
3764 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765
3766 /* Initialize the WoWL service */
3767 if (!hdd_init_wowl(adapter)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003768 hdd_err("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303769 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770 }
3771
3772 /* Adapter successfully added. Increment the vdev count */
3773 hdd_ctx->current_intf_count++;
3774
Jeff Johnson5880d792016-08-15 13:32:30 -07003775 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 hdd_ctx->current_intf_count);
3777
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003778 hdd_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003779 }
3780
Rajeev Kumardca5f812016-02-04 17:28:06 -08003781 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3782 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783
3784 return adapter;
3785
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303786err_close_adapter:
3787 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003789 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303790 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003791
3792 return NULL;
3793}
3794
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303795QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003796 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797{
3798 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303799 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800
3801 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303802 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003803 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804 status);
3805 return status;
3806 }
3807
3808 while (pCurrent->pAdapter != adapter) {
3809 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303810 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 break;
3812
3813 pCurrent = pNext;
3814 }
3815 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303816 if (QDF_STATUS_SUCCESS == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003817 hdd_debug("wait for bus bw work to flush");
Dustin Brown5ec6b552017-03-31 12:11:40 -07003818 hdd_bus_bw_compute_timer_stop(hdd_ctx);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303819 cancel_work_sync(&hdd_ctx->bus_bw_work);
Dustin Brown5ec6b552017-03-31 12:11:40 -07003820
3821 /* cleanup adapter */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003822 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
3823 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003824 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303826 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827 adapterNode = NULL;
3828
Dustin Brown5ec6b552017-03-31 12:11:40 -07003829 /* conditionally restart the bw timer */
3830 hdd_bus_bw_compute_timer_try_start(hdd_ctx);
3831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003832 /* Adapter removed. Decrement vdev count */
3833 if (hdd_ctx->current_intf_count != 0)
3834 hdd_ctx->current_intf_count--;
3835
3836 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303837 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303839
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303840 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003841}
3842
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003843/**
3844 * hdd_close_all_adapters - Close all open adapters
3845 * @hdd_ctx: Hdd context
3846 * rtnl_held: True if RTNL lock held
3847 *
3848 * Close all open adapters.
3849 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303850 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003851 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303852QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853{
3854 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303855 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856
3857 ENTER();
3858
3859 do {
3860 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303861 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303862 wlan_hdd_release_intf_addr(hdd_ctx,
3863 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003865 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303866 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303867 /* Adapter removed. Decrement vdev count */
3868 if (hdd_ctx->current_intf_count != 0)
3869 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003870 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303871 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872
3873 EXIT();
3874
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303875 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003876}
3877
3878void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3879{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303880 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881 tSirUpdateIE updateIE;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003882
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003884 case QDF_STA_MODE:
3885 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003886 {
3887 hdd_station_ctx_t *pHddStaCtx =
3888 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003889 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003890 break;
3891 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003892 case QDF_SAP_MODE:
3893 case QDF_P2P_GO_MODE:
3894 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003896 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897 break;
3898 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003899 case QDF_FTM_MODE:
3900 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003901 default:
3902 /*
3903 * wlan_hdd_reset_prob_rspies should not have been called
3904 * for these kind of devices
3905 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003906 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 pHostapdAdapter->device_mode);
3908 return;
3909 }
3910
Anurag Chouhanc5548422016-02-24 18:33:27 +05303911 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3913 updateIE.ieBufferlength = 0;
3914 updateIE.pAdditionIEBuffer = NULL;
3915 updateIE.append = true;
3916 updateIE.notify = false;
3917 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3918 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303919 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003920 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921 }
3922}
3923
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303924QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925 const bool bCloseSession)
3926{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303927 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003928 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3929 union iwreq_data wrqu;
3930 tSirUpdateIE updateIE;
3931 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303932 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933
3934 ENTER();
3935
Sachin Ahuja988fd102016-09-15 17:16:25 +05303936 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003937 hdd_notice("Disabling queues");
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303938 wlan_hdd_netif_queue_control(adapter,
3939 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3940 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003941 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003942 case QDF_STA_MODE:
3943 case QDF_P2P_CLIENT_MODE:
3944 case QDF_IBSS_MODE:
3945 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003946 case QDF_NDI_MODE:
3947 if ((QDF_NDI_MODE == adapter->device_mode) ||
3948 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3950 hdd_is_connecting(
3951 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003952 INIT_COMPLETION(adapter->disconnect_comp_var);
3953 /*
3954 * For NDI do not use pWextState from sta_ctx, if needed
3955 * extract from ndi_ctx.
3956 */
3957 if (QDF_NDI_MODE == adapter->device_mode)
3958 qdf_ret_status = sme_roam_disconnect(
3959 hdd_ctx->hHal,
3960 adapter->sessionId,
3961 eCSR_DISCONNECT_REASON_NDI_DELETE);
3962 else if (pWextState->roamProfile.BSSType ==
3963 eCSR_BSS_TYPE_START_IBSS)
3964 qdf_ret_status = sme_roam_disconnect(
3965 hdd_ctx->hHal,
3966 adapter->sessionId,
3967 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003968 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003969 qdf_ret_status = sme_roam_disconnect(
3970 hdd_ctx->hHal,
3971 adapter->sessionId,
3972 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003973 /* success implies disconnect command got
3974 * queued up successfully
3975 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303976 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003977 rc = wait_for_completion_timeout(
3978 &adapter->disconnect_comp_var,
3979 msecs_to_jiffies
3980 (WLAN_WAIT_TIME_DISCONNECT));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003981 if (!rc)
3982 hdd_warn("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003983 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003984 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003985 }
3986 memset(&wrqu, '\0', sizeof(wrqu));
3987 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3988 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3989 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3990 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303991 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003992 if (scan_info != NULL && scan_info->mScanPending)
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303993 wlan_hdd_scan_abort(adapter);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003994
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303995 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303996 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003997
3998#ifdef WLAN_OPEN_SOURCE
3999 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
4000#endif
4001
4002 hdd_deregister_tx_flow_control(adapter);
4003
4004#ifdef WLAN_NS_OFFLOAD
4005#ifdef WLAN_OPEN_SOURCE
4006 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
4007#endif
4008#endif
4009
4010 /*
4011 * It is possible that the caller of this function does not
4012 * wish to close the session
4013 */
Krunal Soni985b8132017-02-10 18:49:08 -08004014 if (true == bCloseSession) {
4015 if (0 != wlan_hdd_try_disconnect(adapter)) {
4016 hdd_err("Error: Can't disconnect adapter");
4017 return QDF_STATUS_E_FAILURE;
4018 }
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004019 hdd_vdev_destroy(adapter);
Krunal Soni985b8132017-02-10 18:49:08 -08004020 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 break;
4022
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004023 case QDF_SAP_MODE:
4024 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004026 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
4028
4029 hdd_deregister_tx_flow_control(adapter);
4030
4031 mutex_lock(&hdd_ctx->sap_lock);
4032 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304033 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05304034 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035
4036 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 status = wlansap_stop_bss(
4038 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304040 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041 hdd_hostapd_state_t *hostapd_state =
4042 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304043 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304044 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304045 qdf_status =
4046 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08004047 qdf_stop_bss_event,
4048 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049
Anurag Chouhance0dc992016-02-16 18:18:03 +05304050 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004051 hdd_err("failure waiting for wlansap_stop_bss %d",
4052 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053 }
4054 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07004055 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 }
4057 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004058 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4059 adapter->device_mode,
4060 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061
Anurag Chouhanc5548422016-02-24 18:33:27 +05304062 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08004063 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064 updateIE.smeSessionId = adapter->sessionId;
4065 updateIE.ieBufferlength = 0;
4066 updateIE.pAdditionIEBuffer = NULL;
4067 updateIE.append = false;
4068 updateIE.notify = false;
4069 /* Probe bcn reset */
4070 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4071 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304072 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004073 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004074 }
4075 /* Assoc resp reset */
4076 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4077 &updateIE,
4078 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304079 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004080 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 }
4082 /* Reset WNI_CFG_PROBE_RSP Flags */
4083 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304084 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004085 adapter->sessionCtx.ap.beacon = NULL;
4086 }
Peng Xu66162de2016-02-11 17:01:20 -08004087 if (true == bCloseSession)
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004088 hdd_vdev_destroy(adapter);
Manikandan Mohan5df78272017-03-22 16:28:50 -07004089 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004090 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004091 case QDF_OCB_MODE:
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -08004092 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004093 (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
Leo Changfdb45c32016-10-28 11:09:23 -07004094 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004095 break;
4096 default:
4097 break;
4098 }
4099
4100 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304101 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102}
4103
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05304104/**
4105 * hdd_deinit_all_adapters - deinit all adapters
4106 * @hdd_ctx: HDD context
4107 * @rtnl_held: True if RTNL lock held
4108 *
4109 */
4110void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
4111{
4112 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4113 QDF_STATUS status;
4114 hdd_adapter_t *adapter;
4115
4116 ENTER();
4117
4118 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4119
4120 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4121 adapter = adapter_node->pAdapter;
4122 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
4123 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4124 adapter_node = next;
4125 }
4126
4127 EXIT();
4128}
4129
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304130QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004131{
4132 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304133 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 hdd_adapter_t *adapter;
4135
4136 ENTER();
4137
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304138 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4141
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304142 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004143 adapter = adapterNode->pAdapter;
4144 hdd_stop_adapter(hdd_ctx, adapter, true);
4145 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4146 adapterNode = pNext;
4147 }
4148
4149 EXIT();
4150
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304151 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152}
4153
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304154QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004155{
4156 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304157 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 hdd_adapter_t *adapter;
4159
4160 ENTER();
4161
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304162 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4165
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304166 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004167 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07004168 hdd_notice("Disabling queues");
Arun Khandavallicc544b32017-01-30 19:52:16 +05304169 if (hdd_ctx->config->sap_internal_restart &&
4170 adapter->device_mode == QDF_SAP_MODE) {
4171 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05304172 WLAN_STOP_ALL_NETIF_QUEUE,
Arun Khandavallicc544b32017-01-30 19:52:16 +05304173 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004174 if (test_bit(SOFTAP_BSS_STARTED,
4175 &adapter->event_flags)) {
4176 hdd_sap_indicate_disconnect_for_sta(adapter);
4177 hdd_cleanup_actionframe(hdd_ctx, adapter);
4178 hdd_sap_destroy_events(adapter);
4179 }
4180 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
4181 } else {
Arun Khandavallicc544b32017-01-30 19:52:16 +05304182 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05304183 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004185 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004186
4187 adapter->sessionCtx.station.hdd_ReassocScenario = false;
4188
4189 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004190 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4191 adapter->device_mode, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
4193 hdd_wmm_adapter_close(adapter);
4194 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
4195 }
4196
Wu Gao36717432016-11-21 15:09:48 +08004197 /*
4198 * If adapter is SAP, set session ID to invalid since SAP
4199 * session will be cleanup during SSR.
4200 */
4201 if (adapter->device_mode == QDF_SAP_MODE)
4202 wlansap_set_invalid_session(
4203 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
4204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004205 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4206 adapterNode = pNext;
4207 }
4208
4209 EXIT();
4210
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304211 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212}
4213
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304214bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
4215{
4216 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4217 QDF_STATUS status;
4218 bool close_modules = true;
4219
4220 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4221 while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
4222 if (test_bit(DEVICE_IFACE_OPENED,
4223 &adapter_node->pAdapter->event_flags)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004224 hdd_debug("Still other ifaces are up cannot close modules");
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304225 close_modules = false;
4226 break;
4227 }
4228 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4229 adapter_node = next;
4230 }
4231
4232 return close_modules;
4233}
4234
Arun Khandavallifae92942016-08-01 13:31:08 +05304235/**
4236 * hdd_is_interface_up()- Checkfor interface up before ssr
4237 * @hdd_ctx: HDD context
4238 *
4239 * check if there are any wlan interfaces before SSR accordingly start
4240 * the interface.
4241 *
4242 * Return: 0 if interface was opened else false
4243 */
4244static bool hdd_is_interface_up(hdd_adapter_t *adapter)
4245{
4246 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
4247 return true;
4248 else
4249 return false;
4250}
4251
Anurag Chouhanc4092922016-09-08 15:56:11 +05304252#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05304253 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304254struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4255 struct ieee80211_channel *channel,
4256 const u8 *bssid, const u8 *ssid,
4257 size_t ssid_len)
4258{
4259 return cfg80211_get_bss(wiphy, channel, bssid,
4260 ssid, ssid_len,
4261 WLAN_CAPABILITY_ESS,
4262 WLAN_CAPABILITY_ESS);
4263}
4264#else
4265struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4266 struct ieee80211_channel *channel,
4267 const u8 *bssid, const u8 *ssid,
4268 size_t ssid_len)
4269{
4270 return cfg80211_get_bss(wiphy, channel, bssid,
4271 ssid, ssid_len,
4272 IEEE80211_BSS_TYPE_ESS,
4273 IEEE80211_PRIVACY_ANY);
4274}
4275#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304276
Abhishek Singha84d3952016-09-13 13:45:05 +05304277#if defined CFG80211_CONNECT_BSS
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304278#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
4279 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
4280/**
4281 * hdd_convert_timeout_reason() - Convert to kernel specific enum
4282 * @timeout_reason: reason for connect timeout
4283 *
4284 * This function is used to convert host timeout
4285 * reason enum to kernel specific enum.
4286 *
4287 * Return: nl timeout enum
4288 */
4289static enum nl80211_timeout_reason hdd_convert_timeout_reason(
4290 tSirResultCodes timeout_reason)
4291{
4292 switch (timeout_reason) {
4293 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
4294 return NL80211_TIMEOUT_SCAN;
4295 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
4296 return NL80211_TIMEOUT_AUTH;
4297 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
4298 return NL80211_TIMEOUT_ASSOC;
4299 default:
4300 return NL80211_TIMEOUT_UNSPECIFIED;
4301 }
4302}
4303
4304/**
4305 * hdd_cfg80211_connect_timeout() - API to send connection timeout reason
4306 * @dev: network device
4307 * @bssid: bssid to which we want to associate
4308 * @timeout_reason: reason for connect timeout
4309 *
4310 * This API is used to send connection timeout reason to supplicant
4311 *
4312 * Return: void
4313 */
4314static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4315 const u8 *bssid,
4316 tSirResultCodes timeout_reason)
4317{
4318 enum nl80211_timeout_reason nl_timeout_reason;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004319
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304320 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4321
4322 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
4323 nl_timeout_reason);
4324}
4325
4326/**
4327 * __hdd_connect_bss() - API to send connection status to supplicant
4328 * @dev: network device
4329 * @bssid: bssid to which we want to associate
4330 * @req_ie: Request Information Element
4331 * @req_ie_len: len of the req IE
4332 * @resp_ie: Response IE
4333 * @resp_ie_len: len of ht response IE
4334 * @status: status
4335 * @gfp: Kernel Flag
4336 * @timeout_reason: reason for connect timeout
4337 *
4338 * Return: void
4339 */
4340static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4341 struct cfg80211_bss *bss, const u8 *req_ie,
4342 size_t req_ie_len, const u8 *resp_ie,
4343 size_t resp_ie_len, int status, gfp_t gfp,
4344 tSirResultCodes timeout_reason)
4345{
4346 enum nl80211_timeout_reason nl_timeout_reason;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004347
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304348 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4349
4350 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4351 resp_ie, resp_ie_len, status, gfp,
4352 nl_timeout_reason);
4353}
4354#else
4355#if defined CFG80211_CONNECT_TIMEOUT
4356static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4357 const u8 *bssid,
4358 tSirResultCodes timeout_reason)
4359{
4360 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
4361}
4362#endif
4363
4364static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4365 struct cfg80211_bss *bss, const u8 *req_ie,
4366 size_t req_ie_len, const u8 *resp_ie,
4367 size_t resp_ie_len, int status, gfp_t gfp,
4368 tSirResultCodes timeout_reason)
4369{
4370 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4371 resp_ie, resp_ie_len, status, gfp);
4372}
4373#endif
4374
Abhishek Singha84d3952016-09-13 13:45:05 +05304375/**
4376 * hdd_connect_bss() - API to send connection status to supplicant
4377 * @dev: network device
4378 * @bssid: bssid to which we want to associate
4379 * @req_ie: Request Information Element
4380 * @req_ie_len: len of the req IE
4381 * @resp_ie: Response IE
4382 * @resp_ie_len: len of ht response IE
4383 * @status: status
4384 * @gfp: Kernel Flag
4385 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304386 * @timeout_reason: reason for connect timeout
Abhishek Singha84d3952016-09-13 13:45:05 +05304387 *
4388 * The API is a wrapper to send connection status to supplicant
4389 *
4390 * Return: Void
4391 */
4392#if defined CFG80211_CONNECT_TIMEOUT
4393static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4394 struct cfg80211_bss *bss, const u8 *req_ie,
4395 size_t req_ie_len, const u8 *resp_ie,
4396 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304397 bool connect_timeout,
4398 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304399{
4400 if (connect_timeout)
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304401 hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304402 else
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304403 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4404 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304405}
4406#else
4407static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4408 struct cfg80211_bss *bss, const u8 *req_ie,
4409 size_t req_ie_len, const u8 *resp_ie,
4410 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304411 bool connect_timeout,
4412 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304413{
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304414 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4415 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304416}
4417#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304418
4419/**
4420 * hdd_connect_result() - API to send connection status to supplicant
4421 * @dev: network device
4422 * @bssid: bssid to which we want to associate
4423 * @roam_info: information about connected bss
4424 * @req_ie: Request Information Element
4425 * @req_ie_len: len of the req IE
4426 * @resp_ie: Response IE
4427 * @resp_ie_len: len of ht response IE
4428 * @status: status
4429 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05304430 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304431 * @timeout_reason: reason for connect timeout
Anurag Chouhanc4092922016-09-08 15:56:11 +05304432 *
4433 * The API is a wrapper to send connection status to supplicant
4434 * and allow runtime suspend
4435 *
4436 * Return: Void
4437 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304438void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4439 tCsrRoamInfo *roam_info, const u8 *req_ie,
4440 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304441 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304442 bool connect_timeout,
4443 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304444{
4445 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4446 struct cfg80211_bss *bss = NULL;
4447
4448 if (WLAN_STATUS_SUCCESS == status) {
4449 struct ieee80211_channel *chan;
4450 int freq;
4451 int chan_no = roam_info->pBssDesc->channelId;
4452
4453 if (chan_no <= 14)
4454 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004455 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304456 else
4457 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004458 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304459
4460 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
4461 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
4462 roam_info->u.pConnectedProfile->SSID.ssId,
4463 roam_info->u.pConnectedProfile->SSID.length);
4464 }
Komal Seelama89be8d2016-09-29 11:09:26 +05304465
Abhishek Singha84d3952016-09-13 13:45:05 +05304466 hdd_connect_bss(dev, bssid, bss, req_ie,
4467 req_ie_len, resp_ie, resp_ie_len,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304468 status, gfp, connect_timeout, timeout_reason);
Komal Seelama89be8d2016-09-29 11:09:26 +05304469
4470 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304471}
4472#else
4473void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4474 tCsrRoamInfo *roam_info, const u8 *req_ie,
4475 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304476 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304477 bool connect_timeout,
4478 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304479{
Komal Seelama89be8d2016-09-29 11:09:26 +05304480 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4481
Anurag Chouhanc4092922016-09-08 15:56:11 +05304482 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4483 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304484 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304485}
4486#endif
4487
4488
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304489QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490{
4491 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304492 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 hdd_adapter_t *adapter;
4494#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304495 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496#endif
4497 eConnectionState connState;
4498
4499 ENTER();
4500
4501 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304502 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 adapter = adapterNode->pAdapter;
4504
Arun Khandavallifae92942016-08-01 13:31:08 +05304505 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304506 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508 hdd_wmm_init(adapter);
4509
4510 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004511 case QDF_STA_MODE:
4512 case QDF_P2P_CLIENT_MODE:
4513 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514
4515 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4516 ->conn_info.connState;
4517
4518 hdd_init_station_mode(adapter);
4519 /* Open the gates for HDD to receive Wext commands */
4520 adapter->isLinkUpSvcNeeded = false;
4521 adapter->scan_info.mScanPending = false;
4522
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004523 /* Indicate disconnect event to supplicant
4524 * if associated previously
4525 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004527 eConnectionState_IbssConnected == connState ||
4528 eConnectionState_NotConnected == connState ||
4529 eConnectionState_IbssDisconnected == connState ||
4530 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 union iwreq_data wrqu;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 memset(&wrqu, '\0', sizeof(wrqu));
4534 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4535 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4536 wireless_send_event(adapter->dev, SIOCGIWAP,
4537 &wrqu, NULL);
4538 adapter->sessionCtx.station.
4539 hdd_ReassocScenario = false;
4540
4541 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304542 wlan_hdd_cfg80211_indicate_disconnect(
4543 adapter->dev, false,
4544 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004545 } else if (eConnectionState_Connecting == connState) {
4546 /*
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004547 * Indicate connect failure to supplicant if we
4548 * were in the process of connecting
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004549 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304550 hdd_connect_result(adapter->dev, NULL, NULL,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304551 NULL, 0, NULL, 0,
4552 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004553 GFP_KERNEL, false, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 }
4555
4556 hdd_register_tx_flow_control(adapter,
4557 hdd_tx_resume_timer_expired_handler,
4558 hdd_tx_resume_cb);
4559
4560 break;
4561
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004562 case QDF_SAP_MODE:
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004563 if (hdd_ctx->config->sap_internal_restart)
Arun Khandavallicc544b32017-01-30 19:52:16 +05304564 hdd_init_ap_mode(adapter, true);
4565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004566 break;
4567
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004568 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004569#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004570 hdd_debug("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4572#else
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004573 hdd_debug("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574 /* event supplicant to restart */
4575 cfg80211_del_sta(adapter->dev,
4576 (const u8 *)&bcastMac.bytes[0],
4577 GFP_KERNEL);
4578#endif
4579 break;
4580
4581 default:
4582 break;
4583 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304584get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4586 adapterNode = pNext;
4587 }
4588
4589 EXIT();
4590
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304591 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592}
4593
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304594QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004595 hdd_adapter_list_node_t **padapterNode)
4596{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304597 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004598
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004599 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304600 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4601 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004602 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004603 return status;
4604}
4605
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304606QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 hdd_adapter_list_node_t *adapterNode,
4608 hdd_adapter_list_node_t **pNextAdapterNode)
4609{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304610 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004611
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004612 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304613 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4614 (qdf_list_node_t *) adapterNode,
4615 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004617 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004618 return status;
4619}
4620
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304621QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 hdd_adapter_list_node_t *adapterNode)
4623{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304624 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004625
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004626 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304627 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004628 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004629 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 return status;
4631}
4632
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304633QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004634 hdd_adapter_list_node_t **padapterNode)
4635{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304636 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004637
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004638 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304639 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4640 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004641 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004642 return status;
4643}
4644
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304645QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004646 hdd_adapter_list_node_t *adapterNode)
4647{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304648 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004649
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004650 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304651 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4652 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004653 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654 return status;
4655}
4656
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304657QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 hdd_adapter_list_node_t *adapterNode)
4659{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304660 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004661
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004662 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304663 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4664 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004665 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666 return status;
4667}
4668
4669hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4670 tSirMacAddr macAddr)
4671{
4672 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4673 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304674 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675
4676 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4677
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304678 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679 adapter = adapterNode->pAdapter;
4680
4681 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304682 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004683 macAddr, sizeof(tSirMacAddr)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 return adapter;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004685
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4687 adapterNode = pNext;
4688 }
4689
4690 return NULL;
4691
4692}
4693
4694hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4695 uint32_t vdev_id)
4696{
4697 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4698 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304699 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304701 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004702
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304703 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704 adapter = adapterNode->pAdapter;
4705
4706 if (adapter->sessionId == vdev_id)
4707 return adapter;
4708
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304709 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4711 adapterNode = pNext;
4712 }
4713
Jeff Johnson5880d792016-08-15 13:32:30 -07004714 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715
4716 return NULL;
4717}
4718
Abhishek Singh7996eb72015-12-30 17:24:02 +05304719/**
4720 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4721 * the sessionid
4722 * @hdd_ctx: hdd context.
4723 * @sme_session_id: sme session is for the adapter to get.
4724 *
4725 * This function is used to get the adapter with provided session id
4726 *
4727 * Return: adapter pointer if found
4728 *
4729 */
4730hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4731 uint32_t sme_session_id)
4732{
4733 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4734 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304735 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304736
4737
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304738 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304739
4740 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304741 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304742 adapter = adapter_node->pAdapter;
4743
4744 if (adapter &&
4745 adapter->sessionId == sme_session_id)
4746 return adapter;
4747
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304748 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304749 hdd_get_next_adapter(hdd_ctx,
4750 adapter_node, &next);
4751 adapter_node = next;
4752 }
4753 return NULL;
4754}
4755
Naveen Rawat4edb6822017-04-12 10:09:17 -07004756hdd_adapter_t *hdd_get_adapter_by_iface_name(hdd_context_t *hdd_ctx,
4757 const char *iface_name)
4758{
4759 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4760 hdd_adapter_t *adapter;
4761 QDF_STATUS qdf_status;
4762
4763 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4764
4765 while ((NULL != adapter_node) &&
4766 (QDF_STATUS_SUCCESS == qdf_status)) {
4767 adapter = adapter_node->pAdapter;
4768
4769 if (adapter &&
4770 !qdf_str_cmp(adapter->dev->name, iface_name))
4771 return adapter;
4772
4773 qdf_status =
4774 hdd_get_next_adapter(hdd_ctx,
4775 adapter_node, &next);
4776 adapter_node = next;
4777 }
4778 return NULL;
4779}
4780
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004781/**
4782 * hdd_get_adapter() - to get adapter matching the mode
4783 * @hdd_ctx: hdd context
4784 * @mode: adapter mode
4785 *
4786 * This routine will return the pointer to adapter matching
4787 * with the passed mode.
4788 *
4789 * Return: pointer to adapter or null
4790 */
4791hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4792 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793{
4794 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4795 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304796 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797
4798 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4799
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304800 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004801 adapter = adapterNode->pAdapter;
4802
4803 if (adapter && (mode == adapter->device_mode))
4804 return adapter;
4805
4806 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4807 adapterNode = pNext;
4808 }
4809
4810 return NULL;
4811
4812}
4813
4814/**
4815 * hdd_get_operating_channel() - return operating channel of the device mode
4816 * @hdd_ctx: Pointer to the HDD context.
4817 * @mode: Device mode for which operating channel is required.
4818 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004819 * QDF_STA_MODE,
4820 * QDF_P2P_CLIENT_MODE,
4821 * QDF_SAP_MODE,
4822 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 *
4824 * This API returns the operating channel of the requested device mode
4825 *
4826 * Return: channel number. "0" id the requested device is not found OR it is
4827 * not connected.
4828 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004829uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4830 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831{
4832 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304833 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004834 hdd_adapter_t *adapter;
4835 uint8_t operatingChannel = 0;
4836
4837 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4838
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304839 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004840 adapter = adapterNode->pAdapter;
4841
4842 if (mode == adapter->device_mode) {
4843 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004844 case QDF_STA_MODE:
4845 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004846 if (hdd_conn_is_connected
4847 (WLAN_HDD_GET_STATION_CTX_PTR
4848 (adapter))) {
4849 operatingChannel =
4850 (WLAN_HDD_GET_STATION_CTX_PTR
4851 (adapter))->conn_info.
4852 operationChannel;
4853 }
4854 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004855 case QDF_SAP_MODE:
4856 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004857 /* softap connection info */
4858 if (test_bit
4859 (SOFTAP_BSS_STARTED,
4860 &adapter->event_flags))
4861 operatingChannel =
4862 (WLAN_HDD_GET_AP_CTX_PTR
4863 (adapter))->operatingChannel;
4864 break;
4865 default:
4866 break;
4867 }
4868
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004869 /* Found the device of interest. break the loop */
4870 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871 }
4872
4873 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4874 adapterNode = pNext;
4875 }
4876 return operatingChannel;
4877}
4878
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304879static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 hdd_ctx)
4881{
4882 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304883 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004884 hdd_adapter_t *adapter;
4885
4886 ENTER();
4887
4888 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4889
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304890 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004892 if ((adapter->device_mode == QDF_STA_MODE) ||
4893 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4894 (adapter->device_mode == QDF_IBSS_MODE) ||
4895 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4896 (adapter->device_mode == QDF_SAP_MODE) ||
4897 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004898 wlan_hdd_cfg80211_deregister_frames(adapter);
4899 hdd_unregister_wext(adapter->dev);
4900 }
4901 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4902 adapterNode = pNext;
4903 }
4904
4905 EXIT();
4906
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304907 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908}
4909
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304910QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911{
4912 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304913 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 hdd_adapter_t *adapter;
4915
4916 ENTER();
4917
4918 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4919
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304920 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004922 if ((adapter->device_mode == QDF_STA_MODE) ||
4923 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4924 (adapter->device_mode == QDF_IBSS_MODE) ||
4925 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4926 (adapter->device_mode == QDF_SAP_MODE) ||
4927 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05304929 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930 eCSR_SCAN_ABORT_DEFAULT);
4931 }
4932 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4933 adapterNode = pNext;
4934 }
4935
4936 EXIT();
4937
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304938 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939}
4940
Dustin Brownf27bce82016-11-03 12:52:27 -07004941/**
4942 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4943 * adapters
4944 * @hdd_ctx: The HDD context containing the adapters to operate on
4945 *
4946 * return: QDF_STATUS_SUCCESS
4947 */
4948static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4949{
4950 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4951 QDF_STATUS status;
4952 hdd_adapter_t *adapter;
4953 int err;
4954
4955 ENTER();
4956
4957 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4958
4959 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4960 adapter = adapter_node->pAdapter;
4961 if ((adapter->device_mode == QDF_STA_MODE) ||
4962 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4963 (adapter->device_mode == QDF_IBSS_MODE) ||
4964 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4965 (adapter->device_mode == QDF_SAP_MODE) ||
4966 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4967 err = wlan_hdd_sched_scan_stop(adapter->dev);
4968 if (err)
4969 hdd_err("Unable to stop scheduled scan");
4970 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004971 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
4972 &next_node);
Dustin Brownf27bce82016-11-03 12:52:27 -07004973 adapter_node = next_node;
4974 }
4975
4976 EXIT();
4977
4978 return QDF_STATUS_SUCCESS;
4979}
4980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981#ifdef WLAN_NS_OFFLOAD
4982/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004983 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984 * @hdd_ctx: Pointer to hdd context
4985 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004986 * Unregister for IPv6 address change notifications.
4987 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004988 * Return: None
4989 */
4990static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4991{
4992 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993}
4994
4995/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004996 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997 * @hdd_ctx: Pointer to hdd context
4998 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004999 * Register for IPv6 address change notifications.
5000 *
5001 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005003static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005004{
5005 int ret;
5006
5007 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
5008 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005009 if (ret) {
5010 hdd_err("Failed to register IPv6 notifier: %d", ret);
5011 goto out;
5012 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005014 hdd_debug("Registered IPv6 notifier");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005015out:
5016 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017}
5018#else
5019/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005020 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 * @hdd_ctx: Pointer to hdd context
5022 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005023 * Unregister for IPv6 address change notifications.
5024 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 * Return: None
5026 */
5027static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
5028{
5029}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005030
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005032 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033 * @hdd_ctx: Pointer to hdd context
5034 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005035 * Register for IPv6 address change notifications.
5036 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005037 * Return: None
5038 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005039static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005040{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005041 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042}
5043#endif
5044
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305045#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
5046/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005047 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305048 * @hdd_ctx: HDD context
5049 *
5050 * Activates the logging service
5051 *
5052 * Return: Zero in case of success, negative value otherwise
5053 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005054static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305055{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005056 int ret;
5057 struct hdd_config *config = hdd_ctx->config;
5058
5059 if (!config->wlanLoggingEnable)
5060 return 0;
5061
Srinivas Girigowda8187e792017-03-03 11:50:59 -08005062 ret = wlan_logging_sock_activate_svc(config->wlanLoggingToConsole,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005063 config->wlanLoggingNumBuf);
5064 if (ret)
5065 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
5066 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305067}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005068
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305069/**
5070 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
5071 * @hdd_ctx: HDD context
5072 *
5073 * Deactivates the logging service
5074 *
5075 * Return: 0 on deactivating the logging service
5076 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005077static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305078{
5079 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
5080 return wlan_logging_sock_deactivate_svc();
5081
5082 return 0;
5083}
5084#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005085static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305086{
5087 return 0;
5088}
5089
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005090static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305091{
5092 return 0;
5093}
5094#endif
5095
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005096/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005097 * hdd_register_notifiers - Register netdev notifiers.
5098 * @hdd_ctx: HDD context
5099 *
5100 * Register netdev notifiers like IPv4 and IPv6.
5101 *
5102 * Return: 0 on success and errno on failure
5103 */
5104static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
5105{
5106 int ret;
5107
5108 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5109 if (ret) {
5110 hdd_err("register_netdevice_notifier failed: %d", ret);
5111 goto out;
5112 }
5113
5114 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
5115 if (ret)
5116 goto unregister_notifier;
5117
5118 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5119 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5120 if (ret) {
5121 hdd_err("Failed to register IPv4 notifier: %d", ret);
5122 goto unregister_ip6_notifier;
5123 }
5124
5125 return 0;
5126
5127unregister_ip6_notifier:
5128 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5129unregister_notifier:
5130 unregister_netdevice_notifier(&hdd_netdev_notifier);
5131out:
5132 return ret;
5133
5134}
5135
5136/**
5137 * hdd_unregister_notifiers - Unregister netdev notifiers.
5138 * @hdd_ctx: HDD context
5139 *
5140 * Unregister netdev notifiers like IPv4 and IPv6.
5141 *
5142 * Return: None.
5143 */
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305144void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005145{
5146 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5147
5148 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5149
5150 unregister_netdevice_notifier(&hdd_netdev_notifier);
5151}
5152
5153/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005154 * hdd_exit_netlink_services - Exit netlink services
5155 * @hdd_ctx: HDD context
5156 *
5157 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
5158 * nl service.
5159 *
5160 * Return: None.
5161 */
5162static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
5163{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005164 hdd_close_cesium_nl_sock();
Naveen Rawat910726a2017-03-06 11:42:51 -08005165 hdd_deactivate_wifi_pos();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005166 ptt_sock_deactivate_svc();
5167
5168 nl_srv_exit();
5169}
5170
5171/**
5172 * hdd_init_netlink_services- Init netlink services
5173 * @hdd_ctx: HDD context
5174 *
5175 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
5176 * nl service.
5177 *
5178 * Return: 0 on success and errno on failure.
5179 */
5180static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
5181{
5182 int ret;
5183
Ryan Hsuceddceb2016-04-28 10:20:14 -07005184 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005185 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005186 hdd_err("nl_srv_init failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005187 goto out;
5188 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07005189 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005190
Naveen Rawat910726a2017-03-06 11:42:51 -08005191 ret = hdd_activate_wifi_pos(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005192 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005193 hdd_err("hdd_activate_wifi_pos failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005194 goto err_nl_srv;
5195 }
5196
5197 ret = ptt_sock_activate_svc();
5198 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005199 hdd_err("ptt_sock_activate_svc failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005200 goto err_nl_srv;
5201 }
5202
5203 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07005204 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005205 hdd_err("hdd_open_cesium_nl_sock failed ret: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005206
5207 ret = cnss_diag_activate_service();
5208 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005209 hdd_err("cnss_diag_activate_service failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005210 goto err_close_cesium;
5211 }
5212
5213 return 0;
5214
5215err_close_cesium:
5216 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005217 ptt_sock_deactivate_svc();
5218err_nl_srv:
5219 nl_srv_exit();
5220out:
5221 return ret;
5222}
5223
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005224/**
5225 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
5226 * @hdd_ctx: HDD context.
5227 *
5228 * Destroy RX wakelock.
5229 *
5230 * Return: None.
5231 */
5232static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
5233{
5234 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
5235}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005236
5237/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005238 * hdd_rx_wake_lock_create() - Create RX wakelock
5239 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005240 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005241 * Create RX wakelock.
5242 *
5243 * Return: None.
5244 */
5245static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
5246{
5247 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5248}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005249
5250/**
5251 * hdd_roc_context_init() - Init ROC context
5252 * @hdd_ctx: HDD context.
5253 *
5254 * Initialize ROC context.
5255 *
5256 * Return: 0 on success and errno on failure.
5257 */
5258static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
5259{
5260 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
5261 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
5262
5263 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5264
5265 return 0;
5266}
5267
5268/**
5269 * hdd_roc_context_destroy() - Destroy ROC context
5270 * @hdd_ctx: HDD context.
5271 *
5272 * Destroy roc list and flush the pending roc work.
5273 *
5274 * Return: None.
5275 */
5276static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
5277{
5278 flush_delayed_work(&hdd_ctx->roc_req_work);
5279 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08005280 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005281}
5282
5283/**
Houston Hoffman160db392016-10-10 17:37:51 -07005284 * hdd_context_deinit() - Deinitialize HDD context
5285 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005286 *
Houston Hoffman160db392016-10-10 17:37:51 -07005287 * Deinitialize HDD context along with all the feature specific contexts but
5288 * do not free hdd context itself. Caller of this API is supposed to free
5289 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005290 *
Houston Hoffman160db392016-10-10 17:37:51 -07005291 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005292 */
Houston Hoffman160db392016-10-10 17:37:51 -07005293static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005294{
Houston Hoffman160db392016-10-10 17:37:51 -07005295 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005296
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005297 hdd_roc_context_destroy(hdd_ctx);
5298
5299 hdd_sap_context_destroy(hdd_ctx);
5300
5301 hdd_rx_wake_lock_destroy(hdd_ctx);
5302
5303 hdd_tdls_context_destroy(hdd_ctx);
5304
5305 hdd_scan_context_destroy(hdd_ctx);
5306
5307 qdf_list_destroy(&hdd_ctx->hddAdapters);
5308
Houston Hoffman160db392016-10-10 17:37:51 -07005309 return 0;
5310}
5311
5312/**
5313 * hdd_context_destroy() - Destroy HDD context
5314 * @hdd_ctx: HDD context to be destroyed.
5315 *
5316 * Free config and HDD context as well as destroy all the resources.
5317 *
5318 * Return: None
5319 */
5320static void hdd_context_destroy(hdd_context_t *hdd_ctx)
5321{
5322 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
5323 hdd_logging_sock_deactivate_svc(hdd_ctx);
5324
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05305325 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5326
Houston Hoffman160db392016-10-10 17:37:51 -07005327 hdd_context_deinit(hdd_ctx);
5328
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305329 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005330 hdd_ctx->config = NULL;
5331
5332 wiphy_free(hdd_ctx->wiphy);
5333}
5334
5335/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 * hdd_wlan_exit() - HDD WLAN exit function
5337 * @hdd_ctx: Pointer to the HDD Context
5338 *
5339 * This is the driver exit point (invoked during rmmod)
5340 *
5341 * Return: None
5342 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005343static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344{
5345 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305346 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005347 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05305348 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349
5350 ENTER();
5351
Arun Khandavallifae92942016-08-01 13:31:08 +05305352 if (QDF_TIMER_STATE_RUNNING ==
5353 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005354 hdd_debug("Stop interface change timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05305355 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 }
5357
Arun Khandavallifae92942016-08-01 13:31:08 +05305358 if (!QDF_IS_STATUS_SUCCESS
5359 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
5360 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005361
Arun Khandavallifae92942016-08-01 13:31:08 +05305362
5363 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364
Nitesh Shah61c10d92016-10-19 19:29:15 +05305365 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
5366
Prashanth Bhattaab004382016-10-11 16:08:11 -07005367 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368
5369#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305370 if (QDF_TIMER_STATE_RUNNING ==
5371 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
5372 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 }
5374
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305375 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05305376 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005377 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378 }
Liangwei Dongaef84342016-10-21 05:28:00 -04005379 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5380 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5381 hdd_ctx->last_acs_channel_list = NULL;
5382 hdd_ctx->num_of_channels = 0;
5383 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005384#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385
Arun Khandavallifae92942016-08-01 13:31:08 +05305386 mutex_lock(&hdd_ctx->iface_change_lock);
5387 driver_status = hdd_ctx->driver_status;
5388 mutex_unlock(&hdd_ctx->iface_change_lock);
5389
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390 /*
5391 * Powersave Offload Case
5392 * Disable Idle Power Save Mode
5393 */
5394 hdd_set_idle_ps_config(hdd_ctx, false);
5395
Arun Khandavallifae92942016-08-01 13:31:08 +05305396 if (driver_status != DRIVER_MODULES_CLOSED) {
5397 hdd_unregister_wext_all_adapters(hdd_ctx);
5398 /*
5399 * Cancel any outstanding scan requests. We are about to close
5400 * all of our adapters, but an adapter structure is what SME
5401 * passes back to our callback function. Hence if there
5402 * are any outstanding scan requests then there is a
5403 * race condition between when the adapter is closed and
5404 * when the callback is invoked. We try to resolve that
5405 * race condition here by canceling any outstanding scans
5406 * before we close the adapters.
5407 * Note that the scans may be cancelled in an asynchronous
5408 * manner, so ideally there needs to be some kind of
5409 * synchronization. Rather than introduce a new
5410 * synchronization here, we will utilize the fact that we are
5411 * about to Request Full Power, and since that is synchronized,
5412 * the expectation is that by the time Request Full Power has
5413 * completed, all scans will be cancelled
5414 */
Sandeep Puligilla8de3c1c2017-04-13 17:56:18 -07005415 wlan_cfg80211_cleanup_scan_queue(hdd_ctx->hdd_pdev);
Arun Khandavallifae92942016-08-01 13:31:08 +05305416 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07005417 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305418 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005419 }
5420
5421 /*
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305422 * Close the scheduler before calling cds_close to make sure
5423 * no thread is scheduled after the each module close is
5424 * is called i.e after all the data structures are freed.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305426 qdf_status = cds_sched_close(p_cds_context);
5427 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005428 hdd_err("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305429 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07005432 hdd_wlan_stop_modules(hdd_ctx, false);
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05305433
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305434 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
5435 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
5436 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
5437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 /*
5439 * Close CDS
5440 * This frees pMac(HAL) context. There should not be any call
5441 * that requires pMac access after this.
5442 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07005444 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08005445 hdd_request_manager_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446
Komal Seelam8634b772016-09-29 12:12:24 +05305447 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005448 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449
5450 hdd_ipa_cleanup(hdd_ctx);
5451
5452 /* Free up RoC request queue and flush workqueue */
5453 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05305455 wlansap_global_deinit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05305456 wlan_hdd_deinit_chan_info(hdd_ctx);
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305457 /*
5458 * If there is re_init failure wiphy would have already de-registered
5459 * check the wiphy status before un-registering again
5460 */
Ashish Kumar Dhanotiyae16feb72017-03-31 19:39:37 +05305461 if (wiphy && wiphy->registered) {
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305462 wiphy_unregister(wiphy);
5463 wlan_hdd_cfg80211_deinit(wiphy);
5464 hdd_lpass_notify_stop(hdd_ctx);
5465 }
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07005466
Arun Khandavallifae92942016-08-01 13:31:08 +05305467 hdd_exit_netlink_services(hdd_ctx);
5468 mutex_destroy(&hdd_ctx->iface_change_lock);
Abhishek Singhe9068f12017-03-31 14:14:52 +05305469
5470 driver_status = hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
5471 if (driver_status)
5472 hdd_err("Pdev delete failed");
5473
5474 driver_status = hdd_objmgr_release_and_destroy_psoc(hdd_ctx);
5475 if (driver_status)
5476 hdd_err("Psoc delete failed");
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005477 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005478}
5479
5480void __hdd_wlan_exit(void)
5481{
5482 hdd_context_t *hdd_ctx;
5483
5484 ENTER();
5485
Anurag Chouhan6d760662016-02-20 16:05:43 +05305486 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 if (!hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005488 hdd_err("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489 EXIT();
5490 return;
5491 }
5492
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005493 /* Check IPA HW Pipe shutdown */
5494 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
5495
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005496 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05305497 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005499 /* Do all the cleanup before deregistering the driver */
5500 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07005501
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005502 EXIT();
5503}
5504
5505#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04005506/**
5507 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
5508 * @data: pointer to hdd_context_t
5509 *
5510 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
5511 * Then new ACS request will do a fresh scan without reusing the cached
5512 * scan information.
5513 *
5514 * Return: void
5515 */
Tang Yingying523322d2017-01-17 23:28:43 +08005516static void hdd_skip_acs_scan_timer_handler(void *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517{
5518 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
5519
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005520 hdd_debug("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04005522 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5523 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5524 hdd_ctx->last_acs_channel_list = NULL;
5525 hdd_ctx->num_of_channels = 0;
5526 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527
5528 if (!hdd_ctx->hHal)
5529 return;
5530 sme_scan_flush_result(hdd_ctx->hHal);
5531}
5532#endif
5533
5534#ifdef QCA_HT_2040_COEX
5535/**
5536 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5537 * @adapter: pointer to adapter
5538 * @staId: station id
5539 * @macAddrSTA: station MAC address
5540 * @channel_type: channel type
5541 *
5542 * This function notifies FW with HT20/HT40 mode
5543 *
5544 * Return: 0 if successful, error number otherwise
5545 */
5546int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305547 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548{
5549 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305550 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551 hdd_context_t *hdd_ctx = NULL;
5552
5553 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5554
5555 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305556 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305558
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 if (!hdd_ctx->hHal)
5560 return -EINVAL;
5561
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305562 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005563 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305564 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005565 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 return -EINVAL;
5567 }
5568
5569 return 0;
5570}
5571#endif
5572
5573/**
5574 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5575 * @state: state
5576 *
5577 * This function notifies FW with modem power status
5578 *
5579 * Return: 0 if successful, error number otherwise
5580 */
5581int hdd_wlan_notify_modem_power_state(int state)
5582{
5583 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305584 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 hdd_context_t *hdd_ctx;
5586
Anurag Chouhan6d760662016-02-20 16:05:43 +05305587 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305589 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305591
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592 if (!hdd_ctx->hHal)
5593 return -EINVAL;
5594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305595 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5596 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005597 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 state);
5599 return -EINVAL;
5600 }
5601 return 0;
5602}
5603
5604/**
5605 *
5606 * hdd_post_cds_enable_config() - HDD post cds start config helper
5607 * @adapter - Pointer to the HDD
5608 *
5609 * Return: None
5610 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305611QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005612{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305613 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614
5615 /*
5616 * Send ready indication to the HDD. This will kick off the MAC
5617 * into a 'running' state and should kick off an initial scan.
5618 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305619 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5620 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005621 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5622 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305623 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624 }
5625
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305626 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627}
5628
5629/* wake lock APIs for HDD */
5630void hdd_prevent_suspend(uint32_t reason)
5631{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305632 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005633}
5634
5635void hdd_allow_suspend(uint32_t reason)
5636{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305637 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638}
5639
5640void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5641{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305642 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5643 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644}
5645
5646/**
5647 * hdd_exchange_version_and_caps() - exchange version and capability with target
5648 * @hdd_ctx: Pointer to HDD context
5649 *
5650 * This is the HDD function to exchange version and capability information
5651 * between Host and Target
5652 *
5653 * This function gets reported version of FW.
5654 * It also finds the version of target headers used to compile the host;
5655 * It compares the above two and prints a warning if they are different;
5656 * It gets the SW and HW version string;
5657 * Finally, it exchanges capabilities between host and target i.e. host
5658 * and target exchange a msg indicating the features they support through a
5659 * bitmap
5660 *
5661 * Return: None
5662 */
5663void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5664{
5665
5666 tSirVersionType versionCompiled;
5667 tSirVersionType versionReported;
5668 tSirVersionString versionString;
5669 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305670 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005671
5672 memset(&versionCompiled, 0, sizeof(versionCompiled));
5673 memset(&versionReported, 0, sizeof(versionReported));
5674
5675 /* retrieve and display WCNSS version information */
5676 do {
5677
5678 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5679 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305680 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005681 hdd_err("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682 break;
5683 }
5684
5685 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5686 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305687 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005688 hdd_err("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689 break;
5690 }
5691
5692 if ((versionCompiled.major != versionReported.major) ||
5693 (versionCompiled.minor != versionReported.minor) ||
5694 (versionCompiled.version != versionReported.version) ||
5695 (versionCompiled.revision != versionReported.revision)) {
5696 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5697 "Host expected %u.%u.%u.%u\n",
5698 WLAN_MODULE_NAME,
5699 (int)versionReported.major,
5700 (int)versionReported.minor,
5701 (int)versionReported.version,
5702 (int)versionReported.revision,
5703 (int)versionCompiled.major,
5704 (int)versionCompiled.minor,
5705 (int)versionCompiled.version,
5706 (int)versionCompiled.revision);
5707 } else {
5708 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5709 WLAN_MODULE_NAME,
5710 (int)versionReported.major,
5711 (int)versionReported.minor,
5712 (int)versionReported.version,
5713 (int)versionReported.revision);
5714 }
5715
5716 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5717 versionString,
5718 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305719 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005720 hdd_err("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 break;
5722 }
5723
5724 pr_info("%s: WCNSS software version %s\n",
5725 WLAN_MODULE_NAME, versionString);
5726
5727 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5728 versionString,
5729 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305730 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005731 hdd_err("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005732 break;
5733 }
5734
5735 pr_info("%s: WCNSS hardware version %s\n",
5736 WLAN_MODULE_NAME, versionString);
5737
5738 /*
5739 * 1.Check if FW version is greater than 0.1.1.0. Only then
5740 * send host-FW capability exchange message
5741 * 2.Host-FW capability exchange message is only present on
5742 * target 1.1 so send the message only if it the target is 1.1
5743 * minor numbers for different target branches:
5744 * 0 -> (1.0)Mainline Build
5745 * 1 -> (1.1)Mainline Build
5746 * 2->(1.04) Stability Build
5747 */
5748 if (((versionReported.major > 0) || (versionReported.minor > 1)
5749 || ((versionReported.minor >= 1)
5750 && (versionReported.version >= 1)))
5751 && ((versionReported.major == 1)
5752 && (versionReported.minor >= 1)))
5753 fwFeatCapsMsgSupported = 1;
5754
5755 if (fwFeatCapsMsgSupported) {
5756 /*
5757 * Indicate if IBSS heartbeat monitoring needs to be
5758 * offloaded
5759 */
5760 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5761 sme_disable_feature_capablity
5762 (IBSS_HEARTBEAT_OFFLOAD);
5763 }
5764
5765 sme_feature_caps_exchange(hdd_ctx->hHal);
5766 }
5767
5768 } while (0);
5769
5770}
5771
5772/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305773QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005774{
Amar Singhal5cccafe2017-02-15 12:42:58 -08005775
5776 if (hdd_ctx->reg_offload)
5777 return sme_init_chan_list(hdd_ctx->hHal,
5778 hdd_ctx->reg.alpha2,
5779 0);
5780 else
5781 return sme_init_chan_list(hdd_ctx->hHal,
5782 hdd_ctx->reg.alpha2,
5783 hdd_ctx->reg.cc_src);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784}
5785
5786/**
5787 * hdd_is_5g_supported() - check if hardware supports 5GHz
5788 * @hdd_ctx: Pointer to the hdd context
5789 *
5790 * HDD function to know if hardware supports 5GHz
5791 *
5792 * Return: true if hardware supports 5GHz
5793 */
5794bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5795{
zdingf54169a2016-10-12 17:08:45 +08005796 if (!hdd_ctx || !hdd_ctx->config)
5797 return true;
5798
5799 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5800 return true;
5801 else
5802 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803}
5804
Amar Singhale4f28ee2015-10-21 14:36:56 -07005805static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806{
5807 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005808 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809
5810 wiphy = hdd_ctx->wiphy;
5811
5812 /*
5813 * The channel information in
5814 * wiphy needs to be initialized before wiphy registration
5815 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005816 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5817 if (ret_val) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005818 hdd_err("regulatory init failed");
Amar Singhale4f28ee2015-10-21 14:36:56 -07005819 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820 }
5821
5822#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5823 wiphy->wowlan = &wowlan_support_reg_init;
5824#else
5825 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5826 WIPHY_WOWLAN_MAGIC_PKT |
5827 WIPHY_WOWLAN_DISCONNECT |
5828 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5829 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5830 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5831 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5832 WIPHY_WOWLAN_RFKILL_RELEASE;
5833
5834 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5835 WOW_MAX_FILTERS_PER_LIST);
5836 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5837 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5838#endif
5839
5840 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005841 ret_val = wlan_hdd_cfg80211_register(wiphy);
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305842 if (0 > ret_val) {
Amar Singhale4f28ee2015-10-21 14:36:56 -07005843 hdd_err("wiphy registration failed");
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305844 return ret_val;
5845 }
5846
Amar Singhal5cccafe2017-02-15 12:42:58 -08005847 if (!hdd_ctx->reg_offload)
5848 hdd_program_country_code(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849
Amar Singhale4f28ee2015-10-21 14:36:56 -07005850 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005851}
5852
Ravi Joshie2331e82015-07-01 18:18:54 -07005853/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005854 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005855 * @hdd_ctx - handle to hdd context
5856 * @tx_packets - transmit packet count
5857 * @rx_packets - receive packet count
5858 *
5859 * The function controls the bus bandwidth and dynamic control of
5860 * tcp delayed ack configuration
5861 *
5862 * Returns: None
5863 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005865static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5866 const uint64_t tx_packets,
5867 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005868{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005870 uint64_t temp_rx = 0;
5871 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005872 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannac3da7062017-02-08 21:08:56 -08005873 static enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005874 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005875 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005876 uint16_t index = 0;
5877 bool vote_level_change = false;
5878 bool rx_level_change = false;
5879 bool tx_level_change = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005881 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005882 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005883 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005884 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005885 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005886 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005887 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005888 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005889
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005890 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005891 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5892 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893 hdd_ctx->cur_vote_level = next_vote_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005894 vote_level_change = true;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005895 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305896 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305897 if (hdd_ctx->hbw_requested) {
5898 pld_remove_pm_qos(hdd_ctx->parent_dev);
5899 hdd_ctx->hbw_requested = false;
5900 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305901 if (cds_sched_handle_throughput_req(false))
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005902 hdd_warn("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305903 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305904 if (!hdd_ctx->hbw_requested) {
5905 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5906 hdd_ctx->hbw_requested = true;
5907 }
5908
Nirav Shah3bbfa512016-05-12 16:43:49 +05305909 if (cds_sched_handle_throughput_req(true))
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005910 hdd_warn("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305911 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005912 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005914
5915 /* fine-tuning parameters for RX Flows */
5916 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005918 hdd_ctx->prev_rx = rx_packets;
Mohit Khannab1dd1e82017-02-04 15:14:38 -08005919
Ravi Joshifed83572016-10-07 16:20:37 -07005920 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5921 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5922 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5923 next_rx_level = WLAN_SVC_TP_HIGH;
5924 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005925 } else {
Ravi Joshib89e7f72016-09-07 13:43:15 -07005926 hdd_ctx->rx_high_ind_cnt = 0;
Mohit Khannac3da7062017-02-08 21:08:56 -08005927 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005928 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005930 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005931 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005932 next_rx_level, temp_rx);
5933 hdd_ctx->cur_rx_level = next_rx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005934 rx_level_change = true;
Ravi Joshie2331e82015-07-01 18:18:54 -07005935 /* Send throughput indication only if it is enabled.
5936 * Disabling tcp_del_ack will revert the tcp stack behavior
5937 * to default delayed ack. Note that this will disable the
5938 * dynamic delayed ack mechanism across the system
5939 */
5940 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305941 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5942 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943 &next_rx_level,
5944 sizeof(next_rx_level));
5945 }
5946
Mohit Khannae71e2262015-11-10 09:37:24 -08005947 /* fine-tuning parameters for TX Flows */
5948 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5949 hdd_ctx->prev_tx = tx_packets;
5950 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5951 next_tx_level = WLAN_SVC_TP_HIGH;
5952 else
5953 next_tx_level = WLAN_SVC_TP_LOW;
5954
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005955 if (hdd_ctx->cur_tx_level != next_tx_level) {
Mohit Khannae71e2262015-11-10 09:37:24 -08005956 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5957 next_tx_level, temp_tx);
5958 hdd_ctx->cur_tx_level = next_tx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005959 tx_level_change = true;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305960 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5961 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005962 &next_tx_level,
5963 sizeof(next_tx_level));
5964 }
5965
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005966 index = hdd_ctx->hdd_txrx_hist_idx;
5967
5968 if (vote_level_change || tx_level_change || rx_level_change) {
5969 hdd_ctx->hdd_txrx_hist[index].next_tx_level = next_tx_level;
5970 hdd_ctx->hdd_txrx_hist[index].next_rx_level = next_rx_level;
5971 hdd_ctx->hdd_txrx_hist[index].next_vote_level = next_vote_level;
5972 hdd_ctx->hdd_txrx_hist[index].interval_rx = rx_packets;
5973 hdd_ctx->hdd_txrx_hist[index].interval_tx = tx_packets;
5974 hdd_ctx->hdd_txrx_hist[index].qtime = qdf_get_log_timestamp();
5975 hdd_ctx->hdd_txrx_hist_idx++;
5976 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
5977 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978}
5979
5980#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305981static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005982{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305983 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5984 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005985 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305986 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305987 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5988 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005989 uint64_t total_tx = 0, total_rx = 0;
5990 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305991 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305992 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993 bool connected = false;
5994 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5995
Prashanth Bhattaab004382016-10-11 16:08:11 -07005996 if (wlan_hdd_validate_context(hdd_ctx))
5997 return;
5998
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005999 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306000 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006001 status =
6002 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
6003
6004 if (adapterNode->pAdapter == NULL)
6005 continue;
6006 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05306007 /*
6008 * Validate magic so we don't end up accessing
6009 * an invalid adapter.
6010 */
6011 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
6012 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006013
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006014 if ((adapter->device_mode == QDF_STA_MODE ||
6015 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006016 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
6017 != eConnectionState_Associated) {
6018
6019 continue;
6020 }
6021
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006022 if ((adapter->device_mode == QDF_SAP_MODE ||
6023 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006024 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
6025
6026 continue;
6027 }
6028
6029 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
6030 adapter->prev_tx_packets);
6031 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
6032 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306033
6034 if (adapter->device_mode == QDF_SAP_MODE ||
6035 adapter->device_mode == QDF_P2P_GO_MODE ||
6036 adapter->device_mode == QDF_IBSS_MODE) {
6037
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08006038 ret = cdp_get_intra_bss_fwd_pkts_count(
6039 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306040 adapter->sessionId,
6041 &fwd_tx_packets, &fwd_rx_packets);
6042 if (ret == A_OK) {
6043 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
6044 fwd_tx_packets,
6045 adapter->prev_fwd_tx_packets);
6046 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
6047 fwd_tx_packets,
6048 adapter->prev_fwd_rx_packets);
6049 }
6050 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051
6052 total_rx += adapter->stats.rx_packets;
6053 total_tx += adapter->stats.tx_packets;
6054
6055 spin_lock_bh(&hdd_ctx->bus_bw_lock);
6056 adapter->prev_tx_packets = adapter->stats.tx_packets;
6057 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306058 adapter->prev_fwd_tx_packets = fwd_tx_packets;
6059 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006060 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
6061 connected = true;
6062 }
6063
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306064 /* add intra bss forwarded tx and rx packets */
6065 tx_packets += fwd_tx_packets_diff;
6066 rx_packets += fwd_rx_packets_diff;
6067
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006068 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
6069 tx_packets += (uint64_t)ipa_tx_packets;
6070 rx_packets += (uint64_t)ipa_rx_packets;
6071
6072 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006073 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006074 return;
6075 }
6076
Yuanyuan Liu13738502016-04-06 17:41:37 -07006077 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006078
6079 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
6080 hdd_ipa_uc_stat_request(adapter, 2);
6081
Dustin Brown2ed60362017-01-18 12:25:50 -08006082 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08006083 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08006084 if (hdd_ctx->bus_bw_timer_running)
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05306085 qdf_timer_mod(&hdd_ctx->bus_bw_timer,
Dustin Brownfce08d12017-01-17 16:29:38 -08006086 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08006087 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006088}
Prashanth Bhattaab004382016-10-11 16:08:11 -07006089
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306090/**
6091 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
6092 * @arg: Argument of timer function
6093 *
6094 * Schedule a workqueue in this function where all the processing is done.
6095 *
6096 * Return: None.
6097 */
6098static void __hdd_bus_bw_cbk(void *arg)
6099{
6100 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
6101
6102 if (wlan_hdd_validate_context(hdd_ctx))
6103 return;
6104
6105 schedule_work(&hdd_ctx->bus_bw_work);
6106}
6107
6108/**
6109 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
6110 * @arg: Argument of timer function
6111 *
6112 * Return: None.
6113 */
6114static void hdd_bus_bw_cbk(void *arg)
6115{
6116 cds_ssr_protect(__func__);
6117 __hdd_bus_bw_cbk(arg);
6118 cds_ssr_unprotect(__func__);
6119}
6120
Prashanth Bhattaab004382016-10-11 16:08:11 -07006121int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
6122{
6123 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306124 INIT_WORK(&hdd_ctx->bus_bw_work,
6125 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08006126 hdd_ctx->bus_bw_timer_running = false;
6127 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306128 qdf_timer_init(NULL,
6129 &hdd_ctx->bus_bw_timer,
6130 hdd_bus_bw_cbk, (void *)hdd_ctx,
6131 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006132
6133 return 0;
6134}
6135
6136void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
6137{
Dustin Brownfce08d12017-01-17 16:29:38 -08006138 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07006139 hdd_reset_tcp_delack(hdd_ctx);
6140
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006141 hdd_debug("wait for bus bw work to flush");
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306142 cancel_work_sync(&hdd_ctx->bus_bw_work);
6143 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08006144 hdd_ctx->bus_bw_timer_running = false;
6145 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006146}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006147#endif
6148
6149/**
Nirav Shahed34b212016-04-25 10:59:16 +05306150 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
6151 * @hdd_ctx: hdd context
6152 *
6153 * Return: 0 for success or error code
6154 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006155static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05306156{
6157 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
6158 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
6159 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006160 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05306161 return -ENOMEM;
6162 }
6163 return 0;
6164}
6165
6166/**
6167 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
6168 * @hdd_ctx: hdd context
6169 *
6170 * Return: none
6171 */
6172void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
6173{
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05306174 if (!hdd_ctx || hdd_ctx->hdd_txrx_hist == NULL)
6175 return;
6176
6177 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
6178 hdd_ctx->hdd_txrx_hist = NULL;
Nirav Shahed34b212016-04-25 10:59:16 +05306179}
6180
Nirav Shahda008342016-05-17 18:50:40 +05306181static uint8_t *convert_level_to_string(uint32_t level)
6182{
6183 switch (level) {
6184 /* initialize the wlan sub system */
6185 case WLAN_SVC_TP_NONE:
6186 return "NONE";
6187 case WLAN_SVC_TP_LOW:
6188 return "LOW";
6189 case WLAN_SVC_TP_MEDIUM:
6190 return "MED";
6191 case WLAN_SVC_TP_HIGH:
6192 return "HIGH";
6193 default:
6194 return "INVAL";
6195 }
6196}
6197
Nirav Shahed34b212016-04-25 10:59:16 +05306198
6199/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006200 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
6201 * @hdd_ctx: hdd context
6202 *
6203 * Return: none
6204 */
6205void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
6206{
6207 int i;
6208
6209#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006210 hdd_debug("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05306211 hdd_ctx->config->busBandwidthComputeInterval);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006212 hdd_debug("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006213 hdd_ctx->config->busBandwidthHighThreshold,
6214 hdd_ctx->config->busBandwidthMediumThreshold,
6215 hdd_ctx->config->busBandwidthLowThreshold);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006216 hdd_debug("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306217 hdd_ctx->config->enable_tcp_delack);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006218 hdd_debug("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006219 hdd_ctx->config->tcpDelackThresholdHigh,
6220 hdd_ctx->config->tcpDelackThresholdLow);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006221 hdd_debug("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05306222 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006223#endif
6224
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006225 hdd_debug("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306226 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
6227
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006228 hdd_debug("[index][timestamp]: interval_rx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006229
6230 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006231 /* using hdd_log to avoid printing function name */
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006232 if (hdd_ctx->hdd_txrx_hist[i].qtime > 0)
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006233 hdd_log(QDF_TRACE_LEVEL_ERROR,
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006234 "[%3d][%15llu]: %6llu, %6llu, %s, %s, %s",
6235 i, hdd_ctx->hdd_txrx_hist[i].qtime,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006236 hdd_ctx->hdd_txrx_hist[i].interval_rx,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006237 hdd_ctx->hdd_txrx_hist[i].interval_tx,
6238 convert_level_to_string(
6239 hdd_ctx->hdd_txrx_hist[i].
6240 next_vote_level),
6241 convert_level_to_string(
6242 hdd_ctx->hdd_txrx_hist[i].
6243 next_rx_level),
6244 convert_level_to_string(
6245 hdd_ctx->hdd_txrx_hist[i].
6246 next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006247 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006248}
6249
6250/**
6251 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
6252 * @hdd_ctx: hdd context
6253 *
6254 * Return: none
6255 */
6256void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
6257{
6258 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05306259 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
6260 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006261}
6262
6263/**
Srinivas Girigowdab841da72017-03-25 18:04:39 -07006264 * wlan_hdd_display_netif_queue_history() - display netif queue history
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006265 * @pHddCtx: hdd context
6266 *
6267 * Return: none
6268 */
6269void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
6270{
6271
6272 hdd_adapter_t *adapter = NULL;
6273 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306274 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006275 int i;
Nirav Shahda008342016-05-17 18:50:40 +05306276 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006277
6278 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306279 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006280 adapter = adapter_node->pAdapter;
6281
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006282 hdd_debug("Netif queue operation statistics:");
6283 hdd_debug("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05306284 adapter->sessionId, adapter->device_mode);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006285 hdd_debug("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05306286 curr_time = qdf_system_ticks();
6287 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05306288 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05306289 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05306290 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306291 unpause = adapter->total_unpause_time;
6292 } else {
Nirav Shahda008342016-05-17 18:50:40 +05306293 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306294 pause = adapter->total_pause_time;
6295 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006296 hdd_debug("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05306297 qdf_system_ticks_to_msecs(total),
6298 qdf_system_ticks_to_msecs(pause),
6299 qdf_system_ticks_to_msecs(unpause));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006300 hdd_debug("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006301
Nirav Shahda008342016-05-17 18:50:40 +05306302 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
6303 qdf_time_t pause_delta = 0;
6304
6305 if (adapter->pause_map & (1 << i))
6306 pause_delta = delta;
6307
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006308 /* using hdd_log to avoid printing function name */
6309 hdd_log(QDF_TRACE_LEVEL_ERROR,
6310 "%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006311 hdd_reason_type_to_string(i),
6312 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05306313 adapter->queue_oper_stats[i].unpause_count,
6314 qdf_system_ticks_to_msecs(
6315 adapter->queue_oper_stats[i].total_pause_time +
6316 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006317 }
6318
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006319 hdd_debug("Netif queue operation history:");
6320 hdd_debug("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05306321 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
6322
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006323 hdd_debug("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006324
6325 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006326 /* using hdd_log to avoid printing function name */
6327 if (adapter->queue_oper_history[i].time == 0)
6328 continue;
6329 hdd_log(QDF_TRACE_LEVEL_ERROR,
6330 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05306331 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006332 adapter->queue_oper_history[i].time),
6333 hdd_action_type_to_string(
6334 adapter->queue_oper_history[i].netif_action),
6335 hdd_reason_type_to_string(
6336 adapter->queue_oper_history[i].netif_reason),
6337 adapter->queue_oper_history[i].pause_map);
6338 }
6339
6340 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6341 adapter_node = next;
6342 }
6343
6344
6345}
6346
6347/**
6348 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
6349 * @hdd_ctx: hdd context
6350 *
6351 * Return: none
6352 */
6353void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
6354{
6355 hdd_adapter_t *adapter = NULL;
6356 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306357 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006358
6359 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306360 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006361 adapter = adapter_node->pAdapter;
6362
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306363 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006364 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306365 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006366 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05306367 adapter->history_index = 0;
6368 adapter->start_time = adapter->last_time = qdf_system_ticks();
6369 adapter->total_pause_time = 0;
6370 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006371 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6372 adapter_node = next;
6373 }
6374}
6375
6376/**
6377 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
6378 * @halHandle: Hal handle
6379 * @pContext: Pointer to the context
6380 * @sessionId: Session ID
6381 * @scanId: Scan ID
6382 * @status: Status
6383 *
6384 * This is the callback to be executed when 11d scan is completed to flush out
6385 * the scan results
6386 *
6387 * 11d scan is done during driver load and is a passive scan on all
6388 * channels supported by the device, 11d scans may find some APs on
6389 * frequencies which are forbidden to be used in the regulatory domain
6390 * the device is operating in. If these APs are notified to the supplicant
6391 * it may try to connect to these APs, thus flush out all the scan results
6392 * which are present in SME after 11d scan is done.
6393 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306394 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006395 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306396static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006397 uint8_t sessionId, uint32_t scanId,
6398 eCsrScanStatus status)
6399{
6400 ENTER();
6401
6402 sme_scan_flush_result(halHandle);
6403
6404 EXIT();
6405
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306406 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006407}
6408
6409#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6410/**
6411 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
6412 * @hdd_ctx: hdd global context
6413 *
6414 * Return: none
6415 */
6416static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6417{
6418 uint8_t i;
6419
6420 mutex_init(&hdd_ctx->op_ctx.op_lock);
6421 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6422 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6423 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
6424 }
6425}
6426#else
6427static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6428{
6429}
6430#endif
6431
Yingying Tang95409972016-10-20 15:16:15 +08006432#ifdef WLAN_FEATURE_WOW_PULSE
6433/**
6434 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
6435 * @phddctx: hdd_context_t structure pointer
6436 * @enable: enable or disable this behaviour
6437 *
6438 * Return: int
6439 */
6440static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6441{
6442 struct hdd_config *pcfg_ini = phddctx->config;
6443 struct wow_pulse_mode wow_pulse_set_info;
6444 QDF_STATUS status;
6445
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006446 hdd_debug("wow pulse enable flag is %d", enable);
Yingying Tang95409972016-10-20 15:16:15 +08006447
6448 if (false == phddctx->config->wow_pulse_support)
6449 return 0;
6450
6451 /* prepare the request to send to SME */
6452 if (enable == true) {
6453 wow_pulse_set_info.wow_pulse_enable = true;
6454 wow_pulse_set_info.wow_pulse_pin =
6455 pcfg_ini->wow_pulse_pin;
6456 wow_pulse_set_info.wow_pulse_interval_low =
6457 pcfg_ini->wow_pulse_interval_low;
6458 wow_pulse_set_info.wow_pulse_interval_high =
6459 pcfg_ini->wow_pulse_interval_high;
6460 } else {
6461 wow_pulse_set_info.wow_pulse_enable = false;
6462 wow_pulse_set_info.wow_pulse_pin = 0;
6463 wow_pulse_set_info.wow_pulse_interval_low = 0;
6464 wow_pulse_set_info.wow_pulse_interval_high = 0;
6465 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006466 hdd_debug("enable %d pin %d low %d high %d",
Yingying Tang95409972016-10-20 15:16:15 +08006467 wow_pulse_set_info.wow_pulse_enable,
6468 wow_pulse_set_info.wow_pulse_pin,
6469 wow_pulse_set_info.wow_pulse_interval_low,
6470 wow_pulse_set_info.wow_pulse_interval_high);
6471
6472 status = sme_set_wow_pulse(&wow_pulse_set_info);
6473 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006474 hdd_debug("sme_set_wow_pulse failure!");
Yingying Tang95409972016-10-20 15:16:15 +08006475 return -EIO;
6476 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006477 hdd_debug("sme_set_wow_pulse success!");
Yingying Tang95409972016-10-20 15:16:15 +08006478 return 0;
6479}
6480#else
6481static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6482{
6483 return 0;
6484}
6485#endif
6486
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006487#ifdef WLAN_FEATURE_FASTPATH
6488/**
6489 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
6490 * @hdd_cfg: hdd config
6491 * @context: lower layer context
6492 *
6493 * Return: none
6494 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306495void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006496 void *context)
6497{
6498 if (hdd_cfg->fastpath_enable)
6499 hif_enable_fastpath(context);
6500}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006501#endif
6502
Yuanyuan Liu13738502016-04-06 17:41:37 -07006503#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006504/**
6505 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006506 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006507 * @level: thermal level
6508 *
6509 * Change IPA data path to SW path when the thermal throttle level greater
6510 * than 0, and restore the original data path when throttle level is 0
6511 *
6512 * Return: none
6513 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006514static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006515{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006516 hdd_context_t *hdd_ctx = context;
6517
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006518 /* Change IPA to SW path when throttle level greater than 0 */
6519 if (level > THROTTLE_LEVEL_0)
6520 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
6521 else
6522 /* restore original concurrency mode */
6523 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
6524}
6525
6526/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306527 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
6528 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05306529 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006530 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306531 * Get a safe channel to restart SAP. PCL already takes into account the
6532 * unsafe channels. So, the PCL is validated with the ACS range to provide
6533 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006534 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306535 * Return: Channel number to restart SAP in case of success. In case of any
6536 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006537 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306538static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
6539 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006540{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306541 struct sir_pcl_list pcl;
6542 QDF_STATUS status;
6543 uint32_t i, j;
6544 tHalHandle *hal_handle;
6545 hdd_context_t *hdd_ctx;
6546 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006547
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306548 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6549 if (!hdd_ctx) {
6550 hdd_err("invalid HDD context");
6551 return INVALID_CHANNEL_ID;
6552 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006553
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306554 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6555 if (!hal_handle) {
6556 hdd_err("invalid HAL handle");
6557 return INVALID_CHANNEL_ID;
6558 }
6559
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006560 status = policy_mgr_get_pcl_for_existing_conn(hdd_ctx->hdd_psoc,
6561 PM_SAP_MODE, pcl.pcl_list, &pcl.pcl_len,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306562 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6563 if (QDF_IS_STATUS_ERROR(status)) {
6564 hdd_err("Get PCL failed");
6565 return INVALID_CHANNEL_ID;
6566 }
6567
6568 if (!pcl.pcl_len) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006569 hdd_err("pcl length is zero. this is not expected");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306570 return INVALID_CHANNEL_ID;
6571 }
6572
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006573 hdd_debug("start:%d end:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306574 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6575 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6576
6577 /* PCL already takes unsafe channel into account */
6578 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006579 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306580 if ((pcl.pcl_list[i] >=
6581 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6582 (pcl.pcl_list[i] <=
6583 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006584 hdd_debug("found PCL safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306585 return pcl.pcl_list[i];
6586 }
6587 }
6588
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006589 hdd_debug("no safe channel from PCL found in ACS range");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306590
6591 /* Try for safe channel from all valid channel */
6592 pcl.pcl_len = MAX_NUM_CHAN;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006593 status = sme_get_cfg_valid_channels(pcl.pcl_list,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306594 &pcl.pcl_len);
6595 if (QDF_IS_STATUS_ERROR(status)) {
6596 hdd_err("error in getting valid channel list");
6597 return INVALID_CHANNEL_ID;
6598 }
6599
6600 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006601 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306602 found = false;
6603 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006604 if (pcl.pcl_list[i] ==
6605 hdd_ctx->unsafe_channel_list[j]) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006606 hdd_debug("unsafe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306607 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608 break;
6609 }
6610 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306611
6612 if (found)
6613 continue;
6614
6615 if ((pcl.pcl_list[i] >=
6616 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6617 (pcl.pcl_list[i] <=
6618 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006619 hdd_debug("found safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306620 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006621 }
6622 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306623
6624 return INVALID_CHANNEL_ID;
6625}
6626
6627/**
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006628 * hdd_switch_sap_channel() - Move SAP to the given channel
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306629 * @adapter: AP adapter
6630 * @channel: Channel
6631 *
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006632 * Moves the SAP interface by invoking the function which
6633 * executes the callback to perform channel switch using (E)CSA.
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306634 *
6635 * Return: None
6636 */
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006637void hdd_switch_sap_channel(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306638{
6639 hdd_ap_ctx_t *hdd_ap_ctx;
6640 tHalHandle *hal_handle;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006641 hdd_context_t *hdd_ctx;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306642
6643 if (!adapter) {
6644 hdd_err("invalid adapter");
6645 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006646 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306647
6648 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6649
6650 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6651 if (!hal_handle) {
6652 hdd_err("invalid HAL handle");
6653 return;
6654 }
6655
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006656 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6657
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306658 hdd_ap_ctx->sapConfig.channel = channel;
6659 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6660 hdd_ap_ctx->sapConfig.ch_width_orig;
6661
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006662 hdd_debug("chan:%d width:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306663 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6664
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006665 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306666 hdd_ap_ctx->sapConfig.sec_ch,
6667 &hdd_ap_ctx->sapConfig.ch_params);
6668
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006669 policy_mgr_change_sap_channel_with_csa(hdd_ctx->hdd_psoc,
6670 adapter->sessionId, channel,
6671 hdd_ap_ctx->sapConfig.ch_width_orig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006672}
Kapil Gupta8878ad92017-02-13 11:56:04 +05306673
6674int hdd_update_acs_timer_reason(hdd_adapter_t *adapter, uint8_t reason)
6675{
6676 struct hdd_external_acs_timer_context *timer_context;
6677
6678 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6679
6680 if (QDF_TIMER_STATE_RUNNING ==
6681 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
6682 ap.vendor_acs_timer)) {
6683 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
6684 }
6685 timer_context = (struct hdd_external_acs_timer_context *)
6686 adapter->sessionCtx.ap.vendor_acs_timer.user_data;
6687 timer_context->reason = reason;
6688 qdf_mc_timer_start(&adapter->sessionCtx.ap.vendor_acs_timer,
6689 WLAN_VENDOR_ACS_WAIT_TIME);
6690 /* Update config to application */
6691 hdd_cfg80211_update_acs_config(adapter, reason);
6692 hdd_notice("Updated ACS config to nl with reason %d", reason);
6693
6694 return 0;
6695}
6696
Agrawal Ashish467dde42016-09-08 18:44:22 +05306697/**
6698 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6699 * @hdd_ctx: hdd context pointer
6700 *
6701 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6702 * and if ACS is enabled, driver will ask userspace to restart the
6703 * sap. User space on LTE coex indication restart driver.
6704 *
6705 * Return - none
6706 */
6707void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6708{
6709 QDF_STATUS status;
6710 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6711 hdd_adapter_t *adapter_temp;
6712 uint32_t i;
6713 bool found = false;
6714 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006715
Agrawal Ashish467dde42016-09-08 18:44:22 +05306716 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6717 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6718 adapter_temp = adapter_node->pAdapter;
6719
6720 if (!adapter_temp) {
6721 hdd_err("adapter is NULL, moving to next one");
6722 goto next_adapater;
6723 }
6724
6725 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6726 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006727 hdd_debug("skip device mode:%d acs:%d",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306728 adapter_temp->device_mode,
6729 adapter_temp->sessionCtx.ap.sapConfig.
6730 acs_cfg.acs_mode);
6731 goto next_adapater;
6732 }
6733
6734 found = false;
6735 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006736 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306737 hdd_ctxt->unsafe_channel_list[i]) {
6738 found = true;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006739 hdd_debug("operating ch:%d is unsafe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306740 adapter_temp->sessionCtx.ap.operatingChannel);
6741 break;
6742 }
6743 }
6744
6745 if (!found) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006746 hdd_debug("ch:%d is safe. no need to change channel",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306747 adapter_temp->sessionCtx.ap.operatingChannel);
6748 goto next_adapater;
6749 }
6750
Kapil Gupta8878ad92017-02-13 11:56:04 +05306751 if (hdd_ctxt->config->vendor_acs_support &&
6752 hdd_ctxt->config->acs_support_for_dfs_ltecoex) {
6753 hdd_update_acs_timer_reason(adapter_temp,
6754 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
6755 goto next_adapater;
6756 } else
6757 restart_chan =
6758 hdd_get_safe_channel_from_pcl_and_acs_range(
Agrawal Ashish467dde42016-09-08 18:44:22 +05306759 adapter_temp);
6760 if (!restart_chan) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006761 hdd_err("fail to restart SAP");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306762 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006763 /*
6764 * SAP restart due to unsafe channel. While
6765 * restarting the SAP, make sure to clear
6766 * acs_channel, channel to reset to
6767 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306768 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006769 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306770 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6771 adapter_temp->sessionCtx.ap.sapConfig.channel =
6772 AUTO_CHANNEL_SELECT;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006773 hdd_debug("sending coex indication");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306774 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6775 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006776 hdd_switch_sap_channel(adapter_temp, restart_chan);
Agrawal Ashish467dde42016-09-08 18:44:22 +05306777 }
6778
6779next_adapater:
6780 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6781 adapter_node = next;
6782 }
6783}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006784/**
6785 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6786 * @adapter: HDD adapter pointer
6787 * @indParam: Channel avoid notification parameter
6788 *
6789 * Avoid channel notification from FW handler.
6790 * FW will send un-safe channel list to avoid over wrapping.
6791 * hostapd should not use notified channel
6792 *
6793 * Return: None
6794 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306795void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006796{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006797 hdd_context_t *hdd_ctxt;
6798 tSirChAvoidIndType *ch_avoid_indi;
6799 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006800 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6801 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006802 uint16_t start_channel;
6803 uint16_t end_channel;
6804 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006805 tHddAvoidFreqList hdd_avoid_freq_list;
6806 uint32_t i;
6807
6808 /* Basic sanity */
6809 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006810 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006811 return;
6812 }
6813
6814 hdd_ctxt = (hdd_context_t *) hdd_context;
6815 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6816 cds_context = hdd_ctxt->pcds_context;
6817
6818 /* Make unsafe channel list */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006819 hdd_debug("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006820 ch_avoid_indi->avoid_range_count);
6821
6822 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306823 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006824 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6825 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6826 ch_avoid_indi->avoid_freq_range[i].start_freq;
6827 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6828 ch_avoid_indi->avoid_freq_range[i].end_freq;
6829 }
6830 hdd_avoid_freq_list.avoidFreqRangeCount =
6831 ch_avoid_indi->avoid_range_count;
6832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006833 /* clear existing unsafe channel cache */
6834 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306835 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006836 sizeof(hdd_ctxt->unsafe_channel_list));
6837
6838 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6839 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006840 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006841 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006842 break;
6843 }
6844
6845 start_channel = ieee80211_frequency_to_channel(
6846 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6847 end_channel = ieee80211_frequency_to_channel(
6848 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006849 hdd_debug("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006850 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6851 start_channel,
6852 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6853 end_channel);
6854
6855 /* do not process frequency bands that are not mapped to
6856 * predefined channels
6857 */
6858 if (start_channel == 0 || end_channel == 0)
6859 continue;
6860
Amar Singhalb8d4f152016-02-10 10:21:43 -08006861 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6862 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006863 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006864 ch_avoid_indi->avoid_freq_range[
6865 range_loop].start_freq) {
6866 start_channel_idx = channel_loop;
6867 break;
6868 }
6869 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006870 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6871 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006872 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873 ch_avoid_indi->avoid_freq_range[
6874 range_loop].end_freq) {
6875 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006876 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006877 ch_avoid_indi->avoid_freq_range[
6878 range_loop].end_freq)
6879 end_channel_idx--;
6880 break;
6881 }
6882 }
6883
Amar Singhalb8d4f152016-02-10 10:21:43 -08006884 if (start_channel_idx == INVALID_CHANNEL ||
6885 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006886 continue;
6887
6888 for (channel_loop = start_channel_idx; channel_loop <=
6889 end_channel_idx; channel_loop++) {
6890 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006891 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006892 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006893 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006894 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006895 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006896 break;
6897 }
6898 }
6899 }
6900
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006901 hdd_debug("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006902 hdd_ctxt->unsafe_channel_count);
6903
Yuanyuan Liu13738502016-04-06 17:41:37 -07006904 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6905 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006906 hdd_ctxt->unsafe_channel_count)) {
6907 hdd_err("Failed to set unsafe channel");
6908
6909 /* clear existing unsafe channel cache */
6910 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306911 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006912 sizeof(hdd_ctxt->unsafe_channel_list));
6913
6914 return;
6915 }
6916
6917 for (channel_loop = 0;
6918 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006919 hdd_debug("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006920 hdd_ctxt->unsafe_channel_list[channel_loop]);
6921 }
6922
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306923 /*
6924 * first update the unsafe channel list to the platform driver and
6925 * send the avoid freq event to the application
6926 */
6927 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6928
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306929 if (!hdd_ctxt->unsafe_channel_count) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006930 hdd_debug("no unsafe channels - not restarting SAP");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306931 return;
6932 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306933 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006934}
6935
6936/**
6937 * hdd_init_channel_avoidance() - Initialize channel avoidance
6938 * @hdd_ctx: HDD global context
6939 *
6940 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006941 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006942 * down to the lower layers. Then subscribe to subsequent channel
6943 * avoidance events.
6944 *
6945 * Return: None
6946 */
6947static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6948{
6949 uint16_t unsafe_channel_count;
6950 int index;
6951
Yuanyuan Liu13738502016-04-06 17:41:37 -07006952 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6953 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006954 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006955 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006956
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006957 hdd_debug("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006958 hdd_ctx->unsafe_channel_count);
6959
Anurag Chouhan6d760662016-02-20 16:05:43 +05306960 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006961 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006962
6963 for (index = 0; index < unsafe_channel_count; index++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006964 hdd_debug("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006965 hdd_ctx->unsafe_channel_list[index]);
6966
6967 }
6968
6969 /* Plug in avoid channel notification callback */
6970 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6971}
6972#else
6973static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6974{
6975}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006976static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006977{
6978}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006979#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006980
6981/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006982 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6983 * user space
6984 * @frame_ind: Management frame data to be informed.
6985 *
6986 * This function is used to indicate management frame to
6987 * user space
6988 *
6989 * Return: None
6990 *
6991 */
6992void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6993{
6994 hdd_context_t *hdd_ctx = NULL;
6995 hdd_adapter_t *adapter = NULL;
6996 void *cds_context = NULL;
6997 int i;
6998
6999 /* Get the global VOSS context.*/
7000 cds_context = cds_get_global_context();
7001 if (!cds_context) {
7002 hdd_err("Global CDS context is Null");
7003 return;
7004 }
7005 /* Get the HDD context.*/
7006 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
7007
7008 if (0 != wlan_hdd_validate_context(hdd_ctx))
7009 return;
7010
7011 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
7012 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
7013 adapter =
7014 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
7015 if (adapter)
7016 break;
7017 }
7018 } else {
7019 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
7020 frame_ind->sessionId);
7021 }
7022
7023 if ((NULL != adapter) &&
7024 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
7025 __hdd_indicate_mgmt_frame(adapter,
7026 frame_ind->frame_len,
7027 frame_ind->frameBuf,
7028 frame_ind->frameType,
7029 frame_ind->rxChan,
7030 frame_ind->rxRssi);
Rajeev Kumard004abc2016-02-17 12:09:56 -08007031}
7032
Kapil Gupta8878ad92017-02-13 11:56:04 +05307033static void hdd_lte_coex_restart_sap(hdd_adapter_t *adapter,
7034 hdd_context_t *hdd_ctx)
7035{
7036 uint8_t restart_chan = 0;
7037
7038 restart_chan =
7039 hdd_get_safe_channel_from_pcl_and_acs_range(adapter);
7040 if (!restart_chan) {
7041 hdd_alert("fail to restart SAP");
7042 } else {
7043 /* SAP restart due to unsafe channel. While restarting
7044 * the SAP, make sure to clear acs_channel, channel to
7045 * reset to 0. Otherwise these settings will override
7046 * the ACS while restart.
7047 */
7048 hdd_ctx->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
7049 adapter->sessionCtx.ap.sapConfig.channel =
7050 AUTO_CHANNEL_SELECT;
7051 hdd_info("sending coex indication");
7052 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
7053 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08007054 hdd_switch_sap_channel(adapter, restart_chan);
Kapil Gupta8878ad92017-02-13 11:56:04 +05307055 }
7056}
7057
7058void hdd_acs_response_timeout_handler(void *context)
7059{
7060 struct hdd_external_acs_timer_context *timer_context =
7061 (struct hdd_external_acs_timer_context *)context;
7062 hdd_adapter_t *adapter;
7063 hdd_context_t *hdd_ctx;
7064 uint8_t reason;
7065
7066 ENTER();
7067 if (!timer_context) {
7068 hdd_err("invlaid timer context");
7069 return;
7070 }
7071 adapter = timer_context->adapter;
7072 reason = timer_context->reason;
7073
7074
7075 if ((!adapter) ||
7076 (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
7077 hdd_err("invalid adapter or adapter has invalid magic");
7078 return;
7079 }
7080 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7081 if (wlan_hdd_validate_context(hdd_ctx))
7082 return;
7083
7084 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
7085 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
7086 else
7087 return;
7088
7089 hdd_err("ACS timeout happened for %s reason %d",
7090 adapter->dev->name, reason);
7091 switch (reason) {
7092 /* SAP init case */
7093 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
7094 wlan_sap_set_vendor_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7095 false);
7096 wlan_hdd_cfg80211_start_acs(adapter);
7097 break;
7098 /* DFS detected on current channel */
7099 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
7100 wlan_sap_update_next_channel(
7101 WLAN_HDD_GET_SAP_CTX_PTR(adapter), 0, 0);
7102 sme_update_new_channel_event(WLAN_HDD_GET_HAL_CTX(adapter),
7103 adapter->sessionId);
7104 break;
7105 /* LTE coex event on current channel */
7106 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
7107 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
7108 break;
7109 default:
7110 hdd_info("invalid reason for timer invoke");
7111
7112 }
7113}
7114
Rajeev Kumard004abc2016-02-17 12:09:56 -08007115/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007116 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
7117 * @hdd_ctx: HDD context
7118 *
7119 * Disables all the dual mac features like DBS, Agile DFS etc.
7120 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307121 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007122 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307123static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007124{
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007125 struct policy_mgr_dual_mac_config cfg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307126 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007127
7128 if (!hdd_ctx) {
7129 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307130 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007131 }
7132
7133 cfg.scan_config = 0;
7134 cfg.fw_mode_config = 0;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007135 cfg.set_dual_mac_cb = policy_mgr_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007136
7137 hdd_debug("Disabling all dual mac features...");
7138
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007139 status = sme_soc_set_dual_mac_config(cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307140 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007141 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
7142 return status;
7143 }
7144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307145 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007146}
7147
7148/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007149 * hdd_override_ini_config - Override INI config
7150 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007151 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007152 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007153 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007154 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007155 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007156static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007157{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007158
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007159 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
7160 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007161 hdd_debug("Module enable_dfs_chan_scan set to %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007162 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007163 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007164 if (0 == enable_11d || 1 == enable_11d) {
7165 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007166 hdd_debug("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007167 }
Leo Chang11545d62016-10-17 14:53:50 -07007168
7169 if (!hdd_ipa_is_present(hdd_ctx))
7170 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007171}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007172
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007173/**
7174 * hdd_set_trace_level_for_each - Set trace level for each INI config
7175 * @hdd_ctx - HDD context
7176 *
7177 * Set trace level for each module based on INI config.
7178 *
7179 * Return: None
7180 */
7181static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
7182{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307183 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
7184 hdd_ctx->config->qdf_trace_enable_wdi);
7185 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
7186 hdd_ctx->config->qdf_trace_enable_hdd);
7187 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
7188 hdd_ctx->config->qdf_trace_enable_sme);
7189 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
7190 hdd_ctx->config->qdf_trace_enable_pe);
7191 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
7192 hdd_ctx->config->qdf_trace_enable_wma);
7193 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
7194 hdd_ctx->config->qdf_trace_enable_sys);
7195 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
7196 hdd_ctx->config->qdf_trace_enable_qdf);
7197 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
7198 hdd_ctx->config->qdf_trace_enable_sap);
7199 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
7200 hdd_ctx->config->qdf_trace_enable_hdd_sap);
7201 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
7202 hdd_ctx->config->qdf_trace_enable_bmi);
7203 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
7204 hdd_ctx->config->qdf_trace_enable_cfg);
7205 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
7206 hdd_ctx->config->qdf_trace_enable_epping);
7207 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
7208 hdd_ctx->config->qdf_trace_enable_qdf_devices);
7209 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05307210 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307211 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
7212 hdd_ctx->config->qdf_trace_enable_htc);
7213 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
7214 hdd_ctx->config->qdf_trace_enable_hif);
7215 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
7216 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
7217 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
7218 hdd_ctx->config->qdf_trace_enable_hdd_data);
Naveen Rawat7df31862017-03-01 17:09:30 -08007219 hdd_qdf_trace_enable(QDF_MODULE_ID_WIFIPOS,
7220 hdd_ctx->config->qdf_trace_enable_wifi_pos);
Naveen Rawatf2b0dbd2017-03-27 10:00:15 -07007221 hdd_qdf_trace_enable(QDF_MODULE_ID_NAN,
7222 hdd_ctx->config->qdf_trace_enable_nan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007223 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007224}
7225
7226/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007227 * hdd_context_init() - Initialize HDD context
7228 * @hdd_ctx: HDD context.
7229 *
7230 * Initialize HDD context along with all the feature specific contexts.
7231 *
7232 * return: 0 on success and errno on failure.
7233 */
7234static int hdd_context_init(hdd_context_t *hdd_ctx)
7235{
7236 int ret;
7237
7238 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
7239 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
7240
7241 hdd_init_ll_stats_ctx();
7242
7243 init_completion(&hdd_ctx->mc_sus_event_var);
7244 init_completion(&hdd_ctx->ready_to_suspend);
7245
7246 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307247 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007248 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307249
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007250 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
7251
7252 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
7253
7254 ret = hdd_scan_context_init(hdd_ctx);
7255 if (ret)
7256 goto list_destroy;
7257
Nitesh Shahd1266d72017-01-25 22:07:07 +05307258 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007259
7260 hdd_rx_wake_lock_create(hdd_ctx);
7261
7262 ret = hdd_sap_context_init(hdd_ctx);
7263 if (ret)
7264 goto scan_destroy;
7265
7266 ret = hdd_roc_context_init(hdd_ctx);
7267 if (ret)
7268 goto sap_destroy;
7269
7270 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
7271
7272 hdd_init_offloaded_packets_ctx(hdd_ctx);
7273
7274 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
7275 hdd_ctx->config);
7276 if (ret)
7277 goto roc_destroy;
7278
7279 return 0;
7280
7281roc_destroy:
7282 hdd_roc_context_destroy(hdd_ctx);
7283
7284sap_destroy:
7285 hdd_sap_context_destroy(hdd_ctx);
7286
7287scan_destroy:
7288 hdd_scan_context_destroy(hdd_ctx);
7289 hdd_rx_wake_lock_destroy(hdd_ctx);
7290 hdd_tdls_context_destroy(hdd_ctx);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007291list_destroy:
7292 qdf_list_destroy(&hdd_ctx->hddAdapters);
Sandeep Puligillad0004212017-02-26 18:34:56 -08007293
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007294 return ret;
7295}
7296
7297/**
7298 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05307299 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007300 *
7301 * Allocate and initialize HDD context. HDD context is allocated as part of
7302 * wiphy allocation and then context is initialized.
7303 *
7304 * Return: HDD context on success and ERR_PTR on failure
7305 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007306static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007307{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307308 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007309 int ret = 0;
7310 hdd_context_t *hdd_ctx;
7311 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307312 int qdf_print_idx = -1;
7313
7314 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
7315 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
7316 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
7317 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
7318 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
7319 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
7320 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
7321 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
7322 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
7323 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
7324 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
7325 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
7326 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7327 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7328 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
7329 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
7330 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
7331 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
7332 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
7333 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
7334 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiyaf928edf2017-02-06 14:43:24 +05307335 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
7336 [QDF_MODULE_ID_DP] = {QDF_TRACE_LEVEL_ALL},
7337 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
7338 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
7339 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
7340 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
Mukul Sharma4d7d6b02017-02-13 20:45:22 +05307341 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
Abhishek Singh9679dbf2017-02-15 11:35:41 +05307342 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
Tushnim Bhattacharyya6796d8d2017-03-17 11:06:03 -07007343 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL},
7344 [QDF_MODULE_ID_POLICY_MGR] = {QDF_TRACE_LEVEL_ALL},
Wu Gao9a704f42017-03-10 18:42:11 +08007345 [QDF_MODULE_ID_P2P] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307346 };
7347
7348 status = qdf_print_setup();
7349 if (status != QDF_STATUS_SUCCESS) {
7350 pr_err("QDF print control object setup failed\n");
7351 ret = -EINVAL;
7352 goto err_out;
7353 }
7354 /* Register the module here with QDF */
7355 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
7356 "MCL_WLAN");
7357
7358 /* if qdf_print_idx is negative */
7359 if (qdf_print_idx < 0) {
7360 pr_err("QDF print control can not be registered %d\n",
7361 qdf_print_idx);
7362 ret = -EINVAL;
7363 goto err_out;
7364 }
7365
7366 /* Store the qdf_pidx information into qdf module */
7367 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007368
7369 ENTER();
7370
7371 p_cds_context = cds_get_global_context();
7372 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007373 hdd_err("Failed to get CDS global context");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007374 ret = -EINVAL;
7375 goto err_out;
7376 }
7377
7378 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
7379
7380 if (hdd_ctx == NULL) {
7381 ret = -ENOMEM;
7382 goto err_out;
7383 }
7384
7385 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007386 hdd_ctx->parent_dev = dev;
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05307387 hdd_ctx->last_scan_reject_session_id = 0xFF;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007388
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307389 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007390 if (hdd_ctx->config == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007391 hdd_err("Failed to alloc memory for HDD config!");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007392 ret = -ENOMEM;
7393 goto err_free_hdd_context;
7394 }
7395
7396 /* Read and parse the qcom_cfg.ini file */
7397 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307398 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307399 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007400 WLAN_INI_FILE);
7401 ret = -EINVAL;
7402 goto err_free_config;
7403 }
7404
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007405 hdd_debug("Setting configuredMcastBcastFilter: %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007406 hdd_ctx->config->mcastBcastFilterSetting);
7407
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307408 if (hdd_ctx->config->fhostNSOffload)
7409 hdd_ctx->ns_offload_enable = true;
7410
Abhishek Singh5ea86532016-04-27 14:10:53 +05307411 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
7412
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007413 hdd_override_ini_config(hdd_ctx);
7414
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007415 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007416
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007417 ret = hdd_context_init(hdd_ctx);
7418
7419 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007420 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007421
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007422
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -08007423 pld_set_fw_log_mode(hdd_ctx->parent_dev,
7424 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007425
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007426
7427 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05307428 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007429
Anurag Chouhan6d760662016-02-20 16:05:43 +05307430 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007431 goto skip_multicast_logging;
7432
7433 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
7434
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007435 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
7436 if (ret)
7437 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05307438
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007439 ret = hdd_logging_sock_activate_svc(hdd_ctx);
7440 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05307441 goto err_free_histogram;
7442
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007443skip_multicast_logging:
7444 hdd_set_trace_level_for_each(hdd_ctx);
7445
7446 return hdd_ctx;
7447
Nirav Shahed34b212016-04-25 10:59:16 +05307448err_free_histogram:
7449 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
7450
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007451err_deinit_hdd_context:
7452 hdd_context_deinit(hdd_ctx);
7453
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007454err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307455 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007456
7457err_free_hdd_context:
7458 wiphy_free(hdd_ctx->wiphy);
7459
7460err_out:
7461 return ERR_PTR(ret);
7462}
7463
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007464#ifdef WLAN_OPEN_P2P_INTERFACE
7465/**
7466 * hdd_open_p2p_interface - Open P2P interface
7467 * @hdd_ctx: HDD context
7468 * @rtnl_held: True if RTNL lock held
7469 *
7470 * Open P2P interface during probe. This function called to open the P2P
7471 * interface at probe along with STA interface.
7472 *
7473 * Return: 0 on success and errno on failure
7474 */
7475static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7476{
7477 hdd_adapter_t *adapter;
7478 uint8_t *p2p_dev_addr;
7479
7480 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
7481 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307482 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007483 hdd_ctx->config->intfMacAddr[0].bytes,
7484 sizeof(tSirMacAddr));
7485
7486 /*
7487 * Generate the P2P Device Address. This consists of
7488 * the device's primary MAC address with the locally
7489 * administered bit set.
7490 */
7491 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
7492 } else {
7493 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7494 if (p2p_dev_addr == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007495 hdd_err("Failed to allocate mac_address for p2p_device");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007496 return -ENOSPC;
7497 }
7498
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307499 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307500 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007501 }
7502
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007503 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007504 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08007505 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007506
7507 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007508 hdd_err("Failed to do hdd_open_adapter for P2P Device Interface");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007509 return -ENOSPC;
7510 }
7511
7512 return 0;
7513}
7514#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05307515static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007516 bool rtnl_held)
7517{
7518 return 0;
7519}
7520#endif
7521
Jeff Johnson957bc272017-02-02 08:54:48 -08007522static int hdd_open_ocb_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7523{
7524 hdd_adapter_t *adapter;
7525 int ret = 0;
7526
7527 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
7528 wlan_hdd_get_intf_addr(hdd_ctx),
7529 NET_NAME_UNKNOWN, rtnl_held);
7530 if (adapter == NULL) {
7531 hdd_err("Failed to open 802.11p interface");
7532 ret = -ENOSPC;
7533 }
7534
7535 return ret;
7536}
7537
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007538/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307539 * hdd_start_station_adapter()- Start the Station Adapter
7540 * @adapter: HDD adapter
7541 *
7542 * This function initializes the adapter for the station mode.
7543 *
7544 * Return: 0 on success or errno on failure.
7545 */
7546int hdd_start_station_adapter(hdd_adapter_t *adapter)
7547{
7548 QDF_STATUS status;
7549
7550 ENTER_DEV(adapter->dev);
7551
7552 status = hdd_init_station_mode(adapter);
7553
7554 if (QDF_STATUS_SUCCESS != status) {
7555 hdd_err("Error Initializing station mode: %d", status);
7556 return qdf_status_to_os_return(status);
7557 }
7558
Arun Khandavallifae92942016-08-01 13:31:08 +05307559 hdd_register_tx_flow_control(adapter,
7560 hdd_tx_resume_timer_expired_handler,
7561 hdd_tx_resume_cb);
7562
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307563 EXIT();
7564 return 0;
7565}
7566
7567/**
7568 * hdd_start_ap_adapter()- Start AP Adapter
7569 * @adapter: HDD adapter
7570 *
7571 * This function initializes the adapter for the AP mode.
7572 *
7573 * Return: 0 on success errno on failure.
7574 */
7575int hdd_start_ap_adapter(hdd_adapter_t *adapter)
7576{
7577 QDF_STATUS status;
7578
7579 ENTER();
7580
Arun Khandavallicc544b32017-01-30 19:52:16 +05307581 status = hdd_init_ap_mode(adapter, false);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307582
7583 if (QDF_STATUS_SUCCESS != status) {
7584 hdd_err("Error Initializing the AP mode: %d", status);
7585 return qdf_status_to_os_return(status);
7586 }
7587
Arun Khandavallifae92942016-08-01 13:31:08 +05307588 hdd_register_tx_flow_control(adapter,
7589 hdd_softap_tx_resume_timer_expired_handler,
7590 hdd_softap_tx_resume_cb);
7591
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307592 EXIT();
7593 return 0;
7594}
7595
7596/**
7597 * hdd_start_ftm_adapter()- Start FTM adapter
7598 * @adapter: HDD adapter
7599 *
7600 * This function initializes the adapter for the FTM mode.
7601 *
7602 * Return: 0 on success or errno on failure.
7603 */
7604int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
7605{
7606 QDF_STATUS qdf_status;
7607
7608 ENTER_DEV(adapter->dev);
7609
7610 qdf_status = hdd_init_tx_rx(adapter);
7611
7612 if (QDF_STATUS_SUCCESS != qdf_status) {
7613 hdd_err("Failed to start FTM adapter: %d", qdf_status);
7614 return qdf_status_to_os_return(qdf_status);
7615 }
7616
7617 return 0;
7618 EXIT();
7619}
7620
7621/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007622 * hdd_open_interfaces - Open all required interfaces
7623 * hdd_ctx: HDD context
7624 * rtnl_held: True if RTNL lock is held
7625 *
7626 * Open all the interfaces like STA, P2P and OCB based on the configuration.
7627 *
Jeff Johnson957bc272017-02-02 08:54:48 -08007628 * Return: 0 if all interfaces were created, otherwise negative errno
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007629 */
Jeff Johnson957bc272017-02-02 08:54:48 -08007630static int hdd_open_interfaces(hdd_context_t *hdd_ctx, bool rtnl_held)
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007631{
Jeff Johnson957bc272017-02-02 08:54:48 -08007632 hdd_adapter_t *adapter;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007633 int ret;
7634
Jeff Johnson957bc272017-02-02 08:54:48 -08007635 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
Arun Khandavallifae92942016-08-01 13:31:08 +05307636 /* Create only 802.11p interface */
Jeff Johnson957bc272017-02-02 08:54:48 -08007637 return hdd_open_ocb_interface(hdd_ctx, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007638
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007639 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007640 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08007641 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007642
7643 if (adapter == NULL)
Jeff Johnson957bc272017-02-02 08:54:48 -08007644 return -ENOSPC;
7645
Deepak Dhamdherea2785822016-11-17 01:17:45 -08007646 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
7647 adapter->fast_roaming_allowed = true;
7648
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007649 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
7650 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08007651 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007652
7653 /* Open 802.11p Interface */
7654 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Jeff Johnson957bc272017-02-02 08:54:48 -08007655 ret = hdd_open_ocb_interface(hdd_ctx, rtnl_held);
7656 if (ret)
7657 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007658 }
7659
Jeff Johnson957bc272017-02-02 08:54:48 -08007660 return 0;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007661
Jeff Johnson957bc272017-02-02 08:54:48 -08007662err_close_adapters:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007663 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Jeff Johnson957bc272017-02-02 08:54:48 -08007664 return ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007665}
7666
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007667/**
7668 * hdd_update_country_code - Update country code
7669 * @hdd_ctx: HDD context
7670 * @adapter: Primary adapter context
7671 *
7672 * Update country code based on module parameter country_code at SME and wait
7673 * for the settings to take effect.
7674 *
7675 * Return: 0 on success and errno on failure
7676 */
7677static int hdd_update_country_code(hdd_context_t *hdd_ctx,
7678 hdd_adapter_t *adapter)
7679{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307680 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007681 int ret = 0;
7682 unsigned long rc;
7683
7684 if (country_code == NULL)
7685 return 0;
7686
7687 INIT_COMPLETION(adapter->change_country_code);
7688
7689 status = sme_change_country_code(hdd_ctx->hHal,
7690 wlan_hdd_change_country_code_callback,
7691 country_code, adapter,
7692 hdd_ctx->pcds_context, eSIR_TRUE,
7693 eSIR_TRUE);
7694
7695
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307696 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007697 hdd_err("SME Change Country code from module param fail ret=%d",
7698 ret);
7699 return -EINVAL;
7700 }
7701
7702 rc = wait_for_completion_timeout(&adapter->change_country_code,
7703 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
7704 if (!rc) {
7705 hdd_err("SME while setting country code timed out");
7706 ret = -ETIMEDOUT;
7707 }
7708
7709 return ret;
7710}
7711
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307712#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7713/**
7714 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7715 * @cds_cfg: CDS Configuration
7716 * @hdd_ctx: Pointer to hdd context
7717 *
7718 * Return: none
7719 */
7720static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7721 *cds_cfg,
7722 hdd_context_t *hdd_ctx)
7723{
7724 cds_cfg->tx_flow_stop_queue_th =
7725 hdd_ctx->config->TxFlowStopQueueThreshold;
7726 cds_cfg->tx_flow_start_queue_offset =
7727 hdd_ctx->config->TxFlowStartQueueOffset;
7728}
7729#else
7730static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7731 *cds_cfg,
7732 hdd_context_t *hdd_ctx)
7733{
7734}
7735#endif
7736
7737#ifdef FEATURE_WLAN_RA_FILTERING
7738/**
7739 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7740 * @cds_cfg: CDS Configuration
7741 * @hdd_ctx: Pointer to hdd context
7742 *
7743 * Return: none
7744 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307745static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307746 hdd_context_t *hdd_ctx)
7747{
7748 cds_cfg->ra_ratelimit_interval =
7749 hdd_ctx->config->RArateLimitInterval;
7750 cds_cfg->is_ra_ratelimit_enabled =
7751 hdd_ctx->config->IsRArateLimitEnabled;
7752}
7753#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307754static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307755 hdd_context_t *hdd_ctx)
7756{
7757}
7758#endif
7759
7760/**
7761 * hdd_update_cds_config() - API to update cds configuration parameters
7762 * @hdd_ctx: HDD Context
7763 *
7764 * Return: 0 for Success, errno on failure
7765 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007766static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307767{
7768 struct cds_config_info *cds_cfg;
7769
7770 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7771 if (!cds_cfg) {
7772 hdd_err("failed to allocate cds config");
7773 return -ENOMEM;
7774 }
7775
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307776 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08007777 if (!hdd_ctx->config->nMaxPsPoll ||
7778 !hdd_ctx->config->enablePowersaveOffload) {
7779 cds_cfg->powersave_offload_enabled =
7780 hdd_ctx->config->enablePowersaveOffload;
7781 } else {
7782 if ((hdd_ctx->config->enablePowersaveOffload ==
7783 PS_QPOWER_NODEEPSLEEP) ||
7784 (hdd_ctx->config->enablePowersaveOffload ==
7785 PS_LEGACY_NODEEPSLEEP))
7786 cds_cfg->powersave_offload_enabled =
7787 PS_LEGACY_NODEEPSLEEP;
7788 else
7789 cds_cfg->powersave_offload_enabled =
7790 PS_LEGACY_DEEPSLEEP;
7791 hdd_info("Qpower disabled in cds config, %d",
7792 cds_cfg->powersave_offload_enabled);
7793 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307794 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7795 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7796 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7797 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7798 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7799
7800 /* Here ol_ini_info is used to store ini status of arp offload
7801 * ns offload and others. Currently 1st bit is used for arp
7802 * off load and 2nd bit for ns offload currently, rest bits are unused
7803 */
7804 if (hdd_ctx->config->fhostArpOffload)
7805 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7806 if (hdd_ctx->config->fhostNSOffload)
7807 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7808
7809 /*
7810 * Copy the DFS Phyerr Filtering Offload status.
7811 * This parameter reflects the value of the
7812 * dfs_phyerr_filter_offload flag as set in the ini.
7813 */
7814 cds_cfg->dfs_phyerr_filter_offload =
7815 hdd_ctx->config->fDfsPhyerrFilterOffload;
7816 if (hdd_ctx->config->ssdp)
7817 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7818
7819 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7820 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7821
7822 cds_cfg->ap_maxoffload_reorderbuffs =
7823 hdd_ctx->config->apMaxOffloadReorderBuffs;
7824
7825 cds_cfg->ap_disable_intrabss_fwd =
7826 hdd_ctx->config->apDisableIntraBssFwd;
7827
7828 cds_cfg->dfs_pri_multiplier =
7829 hdd_ctx->config->dfsRadarPriMultiplier;
7830 cds_cfg->reorder_offload =
7831 hdd_ctx->config->reorderOffloadSupport;
7832
7833 /* IPA micro controller data path offload resource config item */
7834 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007835 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7836 /* IpaUcTxBufCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007837 hdd_debug("Round down IpaUcTxBufCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007838 hdd_ctx->config->IpaUcTxBufCount);
7839 hdd_ctx->config->IpaUcTxBufCount =
7840 rounddown_pow_of_two(
7841 hdd_ctx->config->IpaUcTxBufCount);
7842 if (!hdd_ctx->config->IpaUcTxBufCount) {
7843 hdd_err("Failed to round down IpaUcTxBufCount");
7844 return -EINVAL;
7845 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007846 hdd_debug("IpaUcTxBufCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007847 hdd_ctx->config->IpaUcTxBufCount);
7848 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307849 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7850 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007851 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7852 /* IpaUcRxIndRingCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007853 hdd_debug("Round down IpaUcRxIndRingCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007854 hdd_ctx->config->IpaUcRxIndRingCount);
7855 hdd_ctx->config->IpaUcRxIndRingCount =
7856 rounddown_pow_of_two(
7857 hdd_ctx->config->IpaUcRxIndRingCount);
7858 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7859 hdd_err("Failed to round down IpaUcRxIndRingCount");
7860 return -EINVAL;
7861 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007862 hdd_debug("IpaUcRxIndRingCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007863 hdd_ctx->config->IpaUcRxIndRingCount);
7864 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307865 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007866 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307867 cds_cfg->uc_tx_partition_base =
7868 hdd_ctx->config->IpaUcTxPartitionBase;
7869 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7870
7871 cds_cfg->ip_tcp_udp_checksum_offload =
7872 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307873 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307874 cds_cfg->ce_classify_enabled =
7875 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007876 cds_cfg->bpf_packet_filter_enable =
7877 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307878 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7879 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7880 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007881 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007882 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007883 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007884 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Dustin Brown13995f02017-01-12 15:38:42 -08007885 cds_cfg->active_bpf_mode = hdd_ctx->config->active_bpf_mode;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307886
7887 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7888 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7889 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007890 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307891 cds_init_ini_config(cds_cfg);
7892 return 0;
7893}
7894
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007895/**
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007896 * hdd_update_user_config() - API to update user configuration
7897 * parameters to obj mgr which are used by multiple components
7898 * @hdd_ctx: HDD Context
7899 *
7900 * Return: 0 for Success, errno on failure
7901 */
7902static int hdd_update_user_config(hdd_context_t *hdd_ctx)
7903{
7904 struct wlan_objmgr_psoc_user_config *user_config;
7905
7906 user_config = qdf_mem_malloc(sizeof(*user_config));
7907 if (user_config == NULL) {
7908 hdd_alert("Failed to alloc memory for user_config!");
7909 return -ENOMEM;
7910 }
7911
7912 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
7913 user_config->dual_mac_feature_disable =
7914 hdd_ctx->config->dual_mac_feature_disable;
7915 user_config->indoor_channel_support =
7916 hdd_ctx->config->indoor_channel_support;
7917 user_config->is_11d_support_enabled =
7918 hdd_ctx->config->Is11dSupportEnabled;
7919 user_config->is_11h_support_enabled =
7920 hdd_ctx->config->Is11hSupportEnabled;
7921 user_config->optimize_chan_avoid_event =
7922 hdd_ctx->config->goptimize_chan_avoid_event;
7923 user_config->skip_dfs_chnl_in_p2p_search =
7924 hdd_ctx->config->skipDfsChnlInP2pSearch;
Naveen Rawat222b2e92017-03-16 09:52:21 -07007925 user_config->band_capability = hdd_ctx->config->nBandCapability;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007926 wlan_objmgr_psoc_set_user_config(hdd_ctx->hdd_psoc, user_config);
7927
7928 qdf_mem_free(user_config);
7929 return 0;
7930}
7931
7932/**
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007933 * hdd_init_thermal_info - Initialize thermal level
7934 * @hdd_ctx: HDD context
7935 *
7936 * Initialize thermal level at SME layer and set the thermal level callback
7937 * which would be called when a configured thermal threshold is hit.
7938 *
7939 * Return: 0 on success and errno on failure
7940 */
7941static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7942{
7943 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307944 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007945
7946 thermal_param.smeThermalMgmtEnabled =
7947 hdd_ctx->config->thermalMitigationEnable;
7948 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7949
Poddar, Siddarth83905022016-04-16 17:56:08 -07007950 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7951 hdd_ctx->config->throttle_dutycycle_level0;
7952 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7953 hdd_ctx->config->throttle_dutycycle_level1;
7954 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7955 hdd_ctx->config->throttle_dutycycle_level2;
7956 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7957 hdd_ctx->config->throttle_dutycycle_level3;
7958
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007959 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7960 hdd_ctx->config->thermalTempMinLevel0;
7961 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7962 hdd_ctx->config->thermalTempMaxLevel0;
7963 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7964 hdd_ctx->config->thermalTempMinLevel1;
7965 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7966 hdd_ctx->config->thermalTempMaxLevel1;
7967 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7968 hdd_ctx->config->thermalTempMinLevel2;
7969 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7970 hdd_ctx->config->thermalTempMaxLevel2;
7971 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7972 hdd_ctx->config->thermalTempMinLevel3;
7973 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7974 hdd_ctx->config->thermalTempMaxLevel3;
7975
7976 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7977
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307978 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307979 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007980
7981 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7982 hdd_set_thermal_level_cb);
7983
7984 return 0;
7985
7986}
7987
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007988#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7989/**
7990 * hdd_hold_rtnl_lock - Hold RTNL lock
7991 *
7992 * Hold RTNL lock
7993 *
7994 * Return: True if held and false otherwise
7995 */
7996static inline bool hdd_hold_rtnl_lock(void)
7997{
7998 rtnl_lock();
7999 return true;
8000}
8001
8002/**
8003 * hdd_release_rtnl_lock - Release RTNL lock
8004 *
8005 * Release RTNL lock
8006 *
8007 * Return: None
8008 */
8009static inline void hdd_release_rtnl_lock(void)
8010{
8011 rtnl_unlock();
8012}
8013#else
8014static inline bool hdd_hold_rtnl_lock(void) { return false; }
8015static inline void hdd_release_rtnl_lock(void) { }
8016#endif
8017
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008018#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008019
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308020/* MAX iwpriv command support */
8021#define PKTLOG_SET_BUFF_SIZE 3
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308022#define PKTLOG_CLEAR_BUFF 4
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308023#define MAX_PKTLOG_SIZE 16
8024
8025/**
8026 * hdd_pktlog_set_buff_size() - set pktlog buffer size
8027 * @hdd_ctx: hdd context
8028 * @set_value2: pktlog buffer size value
8029 *
8030 *
8031 * Return: 0 for success or error.
8032 */
8033static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
8034{
8035 struct sir_wifi_start_log start_log = { 0 };
8036 QDF_STATUS status;
8037
8038 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8039 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
8040 start_log.ini_triggered = cds_is_packet_log_enabled();
8041 start_log.user_triggered = 1;
8042 start_log.size = set_value2;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308043 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308044
8045 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8046 if (!QDF_IS_STATUS_SUCCESS(status)) {
8047 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8048 EXIT();
8049 return -EINVAL;
8050 }
8051
8052 return 0;
8053}
8054
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008055/**
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308056 * hdd_pktlog_clear_buff() - clear pktlog buffer
8057 * @hdd_ctx: hdd context
8058 *
8059 * Return: 0 for success or error.
8060 */
8061static int hdd_pktlog_clear_buff(hdd_context_t *hdd_ctx)
8062{
8063 struct sir_wifi_start_log start_log;
8064 QDF_STATUS status;
8065
8066 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8067 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
8068 start_log.ini_triggered = cds_is_packet_log_enabled();
8069 start_log.user_triggered = 1;
8070 start_log.size = 0;
8071 start_log.is_pktlog_buff_clear = true;
8072
8073 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8074 if (!QDF_IS_STATUS_SUCCESS(status)) {
8075 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8076 EXIT();
8077 return -EINVAL;
8078 }
8079
8080 return 0;
8081}
8082
8083
8084/**
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008085 * hdd_process_pktlog_command() - process pktlog command
8086 * @hdd_ctx: hdd context
8087 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308088 * @set_value2: pktlog buffer size value
8089 *
8090 * This function process pktlog command.
8091 * set_value2 only matters when set_value is 3 (set buff size)
8092 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008093 *
8094 * Return: 0 for success or error.
8095 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308096int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
8097 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008098{
8099 int ret;
8100 bool enable;
8101 uint8_t user_triggered = 0;
8102
8103 ret = wlan_hdd_validate_context(hdd_ctx);
8104 if (0 != ret)
8105 return ret;
8106
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008107 hdd_debug("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008108
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308109 if (set_value > PKTLOG_CLEAR_BUFF) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008110 hdd_err("invalid pktlog value %d", set_value);
8111 return -EINVAL;
8112 }
8113
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308114 if (set_value == PKTLOG_SET_BUFF_SIZE) {
8115 if (set_value2 <= 0) {
8116 hdd_err("invalid pktlog size %d", set_value2);
8117 return -EINVAL;
8118 } else if (set_value2 > MAX_PKTLOG_SIZE) {
8119 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
8120 return -EINVAL;
8121 }
8122 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308123 } else if (set_value == PKTLOG_CLEAR_BUFF) {
8124 return hdd_pktlog_clear_buff(hdd_ctx);
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308125 }
8126
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008127 /*
8128 * set_value = 0 then disable packetlog
8129 * set_value = 1 enable packetlog forcefully
8130 * set_vlaue = 2 then disable packetlog if disabled through ini or
8131 * enable packetlog with AUTO type.
8132 */
8133 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
8134 true : false;
8135
8136 if (1 == set_value) {
8137 enable = true;
8138 user_triggered = 1;
8139 }
8140
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308141 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008142}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008143/**
8144 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
8145 * @hdd_ctx: HDD context
8146 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308147 * @user_triggered: triggered through iwpriv
8148 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008149 *
8150 * Return: 0 on success; error number otherwise
8151 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008152int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308153 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008154{
8155 struct sir_wifi_start_log start_log;
8156 QDF_STATUS status;
8157
8158 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8159 start_log.verbose_level =
8160 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008161 start_log.ini_triggered = cds_is_packet_log_enabled();
8162 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308163 start_log.size = size;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308164 start_log.is_pktlog_buff_clear = false;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05308165 /*
8166 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
8167 * commands. Host uses this flag to decide whether to send pktlog
8168 * disable command to fw without sending pktlog enable command
8169 * previously. For eg, If vendor sends pktlog disable command without
8170 * sending pktlog enable command, then host discards the packet
8171 * but for iwpriv command, host will send it to fw.
8172 */
8173 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008174 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8175 if (!QDF_IS_STATUS_SUCCESS(status)) {
8176 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8177 EXIT();
8178 return -EINVAL;
8179 }
8180
8181 return 0;
8182}
8183#endif /* REMOVE_PKT_LOG */
8184
Komal Seelam92fff912016-03-24 11:51:41 +05308185/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008186 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
8187 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05308188 * @dev: Device Pointer
8189 * @num: Number of Valid Mac address
8190 *
8191 * Return: Pointer to MAC address buffer
8192 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008193static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
8194 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05308195{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008196 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05308197}
Komal Seelam92fff912016-03-24 11:51:41 +05308198
8199/**
8200 * hdd_populate_random_mac_addr() - API to populate random mac addresses
8201 * @hdd_ctx: HDD Context
8202 * @num: Number of random mac addresses needed
8203 *
8204 * Generate random addresses using bit manipulation on the base mac address
8205 *
8206 * Return: None
8207 */
8208static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
8209{
8210 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
8211 uint32_t iter;
8212 struct hdd_config *ini = hdd_ctx->config;
8213 uint8_t *buf = NULL;
8214 uint8_t macaddr_b3, tmp_br3;
8215 uint8_t *src = ini->intfMacAddr[0].bytes;
8216
8217 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
8218 buf = ini->intfMacAddr[iter].bytes;
8219 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
8220 macaddr_b3 = buf[3];
8221 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
8222 INTF_MACADDR_MASK;
8223 macaddr_b3 += tmp_br3;
8224 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
8225 buf[0] |= 0x02;
8226 buf[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008227 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308228 }
8229}
8230
8231/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008232 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05308233 * @hdd_ctx: HDD Context
8234 *
8235 * API to get mac addresses from platform driver and update the driver
8236 * structures and configure FW with the base mac address.
8237 * Return: int
8238 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008239static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05308240{
8241 uint32_t no_of_mac_addr, iter;
8242 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
8243 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
8244 uint8_t *addr, *buf;
8245 struct device *dev = hdd_ctx->parent_dev;
8246 struct hdd_config *ini = hdd_ctx->config;
8247 tSirMacAddr mac_addr;
8248 QDF_STATUS status;
8249
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008250 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05308251
8252 if (no_of_mac_addr == 0 || !addr) {
8253 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
8254 return -EINVAL;
8255 }
8256
8257 if (no_of_mac_addr > max_mac_addr)
8258 no_of_mac_addr = max_mac_addr;
8259
8260 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
8261
8262 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
8263 buf = ini->intfMacAddr[iter].bytes;
8264 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008265 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308266 }
8267
8268 status = sme_set_custom_mac_addr(mac_addr);
8269
8270 if (!QDF_IS_STATUS_SUCCESS(status))
8271 return -EAGAIN;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07008272
Komal Seelam92fff912016-03-24 11:51:41 +05308273 if (no_of_mac_addr < max_mac_addr)
8274 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
8275 no_of_mac_addr);
8276 return 0;
8277}
8278
8279/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008280 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
8281 * @hdd_ctx: HDD Context
8282 *
8283 * Update MAC address to FW. If MAC address passed by FW is invalid, host
8284 * will generate its own MAC and update it to FW.
8285 *
8286 * Return: 0 for success
8287 * Non-zero error code for failure
8288 */
8289static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
8290{
8291 tSirMacAddr customMacAddr;
8292 QDF_STATUS status;
8293
8294 qdf_mem_copy(&customMacAddr,
8295 &hdd_ctx->config->intfMacAddr[0].bytes[0],
8296 sizeof(tSirMacAddr));
8297 status = sme_set_custom_mac_addr(customMacAddr);
8298 if (!QDF_IS_STATUS_SUCCESS(status))
8299 return -EAGAIN;
8300 return 0;
8301}
8302
8303/**
Komal Seelam92fff912016-03-24 11:51:41 +05308304 * hdd_initialize_mac_address() - API to get wlan mac addresses
8305 * @hdd_ctx: HDD Context
8306 *
8307 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
8308 * is provisioned with mac addresses, driver uses it, else it will use
8309 * wlan_mac.bin to update HW MAC addresses.
8310 *
8311 * Return: None
8312 */
8313static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
8314{
8315 QDF_STATUS status;
8316 int ret;
8317
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008318 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05308319 if (ret == 0)
8320 return;
8321
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008322 hdd_warn("Can't update mac config via platform driver ret: %d", ret);
Komal Seelam92fff912016-03-24 11:51:41 +05308323
8324 status = hdd_update_mac_config(hdd_ctx);
8325
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008326 if (QDF_IS_STATUS_SUCCESS(status))
8327 return;
8328
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008329 hdd_warn("Can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008330
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008331 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008332 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008333 if (ret != 0) {
8334 hdd_err("MAC address out-of-sync, ret:%d", ret);
8335 QDF_ASSERT(ret);
8336 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008337 }
Komal Seelam92fff912016-03-24 11:51:41 +05308338}
8339
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008340/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008341 * hdd_tsf_init() - Initialize the TSF synchronization interface
8342 * @hdd_ctx: HDD global context
8343 *
8344 * When TSF synchronization via GPIO is supported by the driver and
8345 * has been enabled in the configuration file, this function plumbs
8346 * the GPIO value down to firmware via SME.
8347 *
8348 * Return: None
8349 */
8350#ifdef WLAN_FEATURE_TSF
8351static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8352{
8353 QDF_STATUS status;
8354
8355 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
8356 return;
8357
8358 status = sme_set_tsf_gpio(hdd_ctx->hHal,
8359 hdd_ctx->config->tsf_gpio_pin);
8360 if (!QDF_IS_STATUS_SUCCESS(status))
8361 hdd_err("Set tsf GPIO failed, status: %d", status);
8362}
8363#else
8364static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8365{
8366}
8367#endif
8368
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008369static int hdd_set_smart_chainmask_enabled(hdd_context_t *hdd_ctx)
8370{
8371 int vdev_id = 0;
8372 int param_id = WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME;
8373 int value = hdd_ctx->config->smart_chainmask_enabled;
8374 int vpdev = PDEV_CMD;
8375 int ret;
8376
8377 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8378 if (ret)
8379 hdd_err("WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME failed %d", ret);
8380
8381 return ret;
8382}
8383
8384static int hdd_set_alternative_chainmask_enabled(hdd_context_t *hdd_ctx)
8385{
8386 int vdev_id = 0;
8387 int param_id = WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME;
8388 int value = hdd_ctx->config->alternative_chainmask_enabled;
8389 int vpdev = PDEV_CMD;
8390 int ret;
8391
8392 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8393 if (ret)
8394 hdd_err("WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME failed %d",
8395 ret);
8396
8397 return ret;
8398}
8399
Jeff Johnson12a744b2017-04-04 08:19:37 -07008400static int hdd_set_ani_enabled(hdd_context_t *hdd_ctx)
8401{
8402 int vdev_id = 0;
8403 int param_id = WMI_PDEV_PARAM_ANI_ENABLE;
8404 int value = hdd_ctx->config->ani_enabled;
8405 int vpdev = PDEV_CMD;
8406 int ret;
8407
8408 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8409 if (ret)
8410 hdd_err("WMI_PDEV_PARAM_ANI_ENABLE failed %d", ret);
8411
8412 return ret;
8413}
8414
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008415/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07008416 * hdd_pre_enable_configure() - Configurations prior to cds_enable
8417 * @hdd_ctx: HDD context
8418 *
8419 * Pre configurations to be done at lower layer before calling cds enable.
8420 *
8421 * Return: 0 on success and errno on failure.
8422 */
8423static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
8424{
8425 int ret;
8426 QDF_STATUS status;
8427 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07008428 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008429
Leo Changfdb45c32016-10-28 11:09:23 -07008430 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008431 /*
8432 * Set 802.11p config
8433 * TODO-OCB: This has been temporarily added here to ensure this
8434 * parameter is set in CSR when we init the channel list. This should
8435 * be removed once the 5.9 GHz channels are added to the regulatory
8436 * domain.
8437 */
8438 hdd_set_dot11p_config(hdd_ctx);
8439
8440 /*
8441 * Note that the cds_pre_enable() sequence triggers the cfg download.
8442 * The cfg download must occur before we update the SME config
8443 * since the SME config operation must access the cfg database
8444 */
8445 status = hdd_set_sme_config(hdd_ctx);
8446
8447 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008448 hdd_err("Failed hdd_set_sme_config: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008449 ret = qdf_status_to_os_return(status);
8450 goto out;
8451 }
8452
Tushnim Bhattacharyyaba8ee932017-03-23 09:27:40 -07008453 status = hdd_set_policy_mgr_user_cfg(hdd_ctx);
8454 if (QDF_STATUS_SUCCESS != status) {
8455 hdd_alert("Failed hdd_set_policy_mgr_user_cfg: %d", status);
8456 ret = qdf_status_to_os_return(status);
8457 goto out;
8458 }
8459
Prashanth Bhatta07998752016-04-28 12:35:33 -07008460 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
8461 hdd_ctx->config->tx_chain_mask_1ss,
8462 PDEV_CMD);
8463 if (0 != ret) {
8464 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
8465 goto out;
8466 }
8467
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008468 ret = hdd_set_smart_chainmask_enabled(hdd_ctx);
8469 if (ret)
8470 goto out;
8471
8472 ret = hdd_set_alternative_chainmask_enabled(hdd_ctx);
8473 if (ret)
8474 goto out;
8475
Jeff Johnson12a744b2017-04-04 08:19:37 -07008476 ret = hdd_set_ani_enabled(hdd_ctx);
8477 if (ret)
8478 goto out;
8479
Srinivas Girigowda70e169a2017-03-07 23:55:57 -08008480 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
8481 hdd_ctx->config->arp_ac_category,
8482 PDEV_CMD);
8483 if (0 != ret) {
8484 hdd_err("WMI_PDEV_PARAM_ARP_AC_OVERRIDE ac: %d ret: %d",
8485 hdd_ctx->config->arp_ac_category, ret);
8486 goto out;
8487 }
8488
8489
Prashanth Bhatta07998752016-04-28 12:35:33 -07008490 status = hdd_set_sme_chan_list(hdd_ctx);
8491 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008492 hdd_err("Failed to init channel list: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008493 ret = qdf_status_to_os_return(status);
8494 goto out;
8495 }
8496
8497 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07008498 if (!hdd_update_config_cfg(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008499 hdd_err("config update failed");
Prashanth Bhatta07998752016-04-28 12:35:33 -07008500 ret = -EINVAL;
8501 goto out;
8502 }
8503
Prashanth Bhatta07998752016-04-28 12:35:33 -07008504 /*
8505 * Set the MAC Address Currently this is used by HAL to add self sta.
8506 * Remove this once self sta is added as part of session open.
8507 */
8508 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
8509 hdd_ctx->config->intfMacAddr[0].bytes,
8510 sizeof(hdd_ctx->config->intfMacAddr[0]));
8511
8512 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
8513 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
8514 hal_status, hal_status);
8515 ret = -EINVAL;
8516 goto out;
8517 }
8518
8519 hdd_init_channel_avoidance(hdd_ctx);
8520
8521out:
8522 return ret;
8523}
8524
8525/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008526 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
8527 * @context_ptr - hdd context pointer
8528 * @event_ptr - event structure pointer
8529 *
8530 * This is the p2p listen offload stop event handler, it sends vendor
8531 * event back to supplicant to notify the stop reason.
8532 *
8533 * Return: None
8534 */
8535static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
8536 void *event_ptr)
8537{
8538 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
8539 struct sir_p2p_lo_event *evt = event_ptr;
8540 struct sk_buff *vendor_event;
8541
8542 ENTER();
8543
8544 if (hdd_ctx == NULL) {
8545 hdd_err("Invalid HDD context pointer");
8546 return;
8547 }
8548
8549 vendor_event =
8550 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8551 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
8552 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
8553 GFP_KERNEL);
8554
8555 if (!vendor_event) {
8556 hdd_err("cfg80211_vendor_event_alloc failed");
8557 return;
8558 }
8559
8560 if (nla_put_u32(vendor_event,
8561 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
8562 evt->reason_code)) {
8563 hdd_err("nla put failed");
8564 kfree_skb(vendor_event);
8565 return;
8566 }
8567
8568 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8569}
8570
8571/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308572 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
8573 * @hdd_ctx: HDD context
8574 *
8575 * This function sends the adaptive dwell time config configuration to the
8576 * firmware via WMA
8577 *
8578 * Return: 0 - success, < 0 - failure
8579 */
8580static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
8581{
8582 QDF_STATUS status;
8583 struct adaptive_dwelltime_params dwelltime_params;
8584
8585 dwelltime_params.is_enabled =
8586 hdd_ctx->config->adaptive_dwell_mode_enabled;
8587 dwelltime_params.dwelltime_mode =
8588 hdd_ctx->config->global_adapt_dwelltime_mode;
8589 dwelltime_params.lpf_weight =
8590 hdd_ctx->config->adapt_dwell_lpf_weight;
8591 dwelltime_params.passive_mon_intval =
8592 hdd_ctx->config->adapt_dwell_passive_mon_intval;
8593 dwelltime_params.wifi_act_threshold =
8594 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
8595
8596 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
8597 &dwelltime_params);
8598
8599 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
8600 if (!QDF_IS_STATUS_SUCCESS(status)) {
8601 hdd_err("Failed to send Adaptive Dwelltime configuration!");
8602 return -EAGAIN;
8603 }
8604 return 0;
8605}
8606
Arun Khandavallid4349a92016-07-25 11:10:43 +05308607#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8608/**
8609 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
8610 * @hdd_ctx: HDD context
8611 *
8612 * Set auto shutdown callback to get indications from firmware to indicate
8613 * userspace to shutdown WLAN after a configured amount of inactivity.
8614 *
8615 * Return: 0 on success and errno on failure.
8616 */
8617static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8618{
8619 QDF_STATUS status;
8620
8621 if (!hdd_ctx->config->WlanAutoShutdown)
8622 return 0;
8623
8624 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
8625 wlan_hdd_auto_shutdown_cb);
8626 if (status != QDF_STATUS_SUCCESS)
8627 hdd_err("Auto shutdown feature could not be enabled: %d",
8628 status);
8629
8630 return qdf_status_to_os_return(status);
8631}
8632#else
8633static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8634{
8635 return 0;
8636}
8637#endif
8638
8639/**
8640 * hdd_features_init() - Init features
8641 * @hdd_ctx: HDD context
8642 * @adapter: Primary adapter context
8643 *
8644 * Initialize features and their feature context after WLAN firmware is up.
8645 *
8646 * Return: 0 on success and errno on failure.
8647 */
8648static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8649{
8650 tSirTxPowerLimit hddtxlimit;
8651 QDF_STATUS status;
8652 int ret;
8653
8654 ENTER();
8655
8656 ret = hdd_update_country_code(hdd_ctx, adapter);
8657 if (ret) {
8658 hdd_err("Failed to update country code: %d", ret);
8659 goto out;
8660 }
8661
8662 /* FW capabilities received, Set the Dot11 mode */
8663 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07008664 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
8665 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308666
Arun Khandavallid4349a92016-07-25 11:10:43 +05308667
8668 if (hdd_ctx->config->fIsImpsEnabled)
8669 hdd_set_idle_ps_config(hdd_ctx, true);
8670 else
8671 hdd_set_idle_ps_config(hdd_ctx, false);
8672
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308673 if (hdd_ctx->config->enable_go_cts2self_for_sta)
Srinivas Girigowdab841da72017-03-25 18:04:39 -07008674 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308675
Arun Khandavallid4349a92016-07-25 11:10:43 +05308676 if (hdd_lro_init(hdd_ctx))
8677 hdd_err("Unable to initialize LRO in fw");
8678
8679 if (hdd_adaptive_dwelltime_init(hdd_ctx))
8680 hdd_err("Unable to send adaptive dwelltime setting to FW");
8681
8682 ret = hdd_init_thermal_info(hdd_ctx);
8683 if (ret) {
8684 hdd_err("Error while initializing thermal information");
8685 goto deregister_frames;
8686 }
8687
Poddar, Siddarth66a46592017-02-22 11:44:44 +05308688 if (cds_is_packet_log_enabled())
8689 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
8690
Arun Khandavallid4349a92016-07-25 11:10:43 +05308691 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
8692 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
8693 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
8694 if (!QDF_IS_STATUS_SUCCESS(status))
8695 hdd_err("Error setting txlimit in sme: %d", status);
8696
8697 hdd_tsf_init(hdd_ctx);
8698
Arun Khandavallid4349a92016-07-25 11:10:43 +05308699 ret = hdd_register_cb(hdd_ctx);
8700 if (ret) {
8701 hdd_err("Failed to register HDD callbacks!");
8702 goto deregister_frames;
8703 }
8704
8705 if (hdd_ctx->config->dual_mac_feature_disable) {
8706 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
8707 if (status != QDF_STATUS_SUCCESS) {
8708 hdd_err("Failed to disable dual mac features");
8709 goto deregister_cb;
8710 }
8711 }
Selvaraj, Sridhar371f55e2017-02-21 10:36:15 +05308712 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8713 status = sme_enable_disable_chanavoidind_event(
8714 hdd_ctx->hHal, 0);
8715 if (!QDF_IS_STATUS_SUCCESS(status)) {
8716 hdd_err("Failed to disable Chan Avoidance Indication");
8717 goto deregister_cb;
8718 }
8719 }
Arun Khandavallid4349a92016-07-25 11:10:43 +05308720
8721 /* register P2P Listen Offload event callback */
8722 if (wma_is_p2p_lo_capable())
8723 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
8724 wlan_hdd_p2p_lo_event_callback);
8725
8726 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
8727
8728 if (ret)
8729 goto deregister_cb;
8730
8731 EXIT();
8732 return 0;
8733
8734deregister_cb:
8735 hdd_deregister_cb(hdd_ctx);
8736deregister_frames:
8737 wlan_hdd_cfg80211_deregister_frames(adapter);
8738out:
8739 return -EINVAL;
8740
8741}
8742
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308743#ifdef NAPIER_SCAN
8744/**
8745 *
8746 * hdd_post_cds_enable_config() - HDD post cds start config helper
8747 * @adapter - Pointer to the HDD
8748 *
8749 * Return: None
8750 */
8751static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8752{
8753 QDF_STATUS status;
8754
8755 status = ucfg_scan_register_bcn_cb(hdd_ctx->hdd_psoc,
8756 wlan_cfg80211_inform_bss_frame,
8757 SCAN_CB_TYPE_INFORM_BCN);
8758 if (!QDF_IS_STATUS_SUCCESS(status)) {
8759 hdd_err("failed with status code %08d [x%08x]",
8760 status, status);
8761 return status;
8762 }
8763
8764 return QDF_STATUS_SUCCESS;
8765}
8766#else
8767static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8768{
8769 return QDF_STATUS_SUCCESS;
8770}
8771
8772#endif
Arun Khandavallid4349a92016-07-25 11:10:43 +05308773
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308774/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308775 * hdd_configure_cds() - Configure cds modules
8776 * @hdd_ctx: HDD context
8777 * @adapter: Primary adapter context
8778 *
8779 * Enable Cds modules after WLAN firmware is up.
8780 *
8781 * Return: 0 on success and errno on failure.
8782 */
8783int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8784{
8785 int ret;
8786 QDF_STATUS status;
Arun Khandavallifae92942016-08-01 13:31:08 +05308787
8788 ret = hdd_pre_enable_configure(hdd_ctx);
8789 if (ret) {
8790 hdd_err("Failed to pre-configure cds");
8791 goto out;
8792 }
8793
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008794 /* Always get latest IPA resources allocated from cds_open and configure
8795 * IPA module before configuring them to FW. Sequence required as crash
8796 * observed otherwise.
8797 */
Manikandan Mohan2e803a02017-02-14 14:57:53 -08008798 if (hdd_ipa_uc_ol_init(hdd_ctx)) {
8799 hdd_err("Failed to setup pipes");
8800 goto out;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008801 }
8802
Arun Khandavallifae92942016-08-01 13:31:08 +05308803 /*
8804 * Start CDS which starts up the SME/MAC/HAL modules and everything
8805 * else
8806 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308807 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308808
8809 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008810 hdd_err("cds_enable failed");
Arun Khandavallifae92942016-08-01 13:31:08 +05308811 goto out;
8812 }
8813
8814 status = hdd_post_cds_enable_config(hdd_ctx);
8815 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008816 hdd_err("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008817 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308818 }
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308819 status = hdd_register_bcn_cb(hdd_ctx);
8820 if (!QDF_IS_STATUS_SUCCESS(status)) {
8821 hdd_alert("hdd_post_cds_enable_config failed");
8822 goto cds_disable;
8823 }
Arun Khandavallifae92942016-08-01 13:31:08 +05308824
8825 ret = hdd_features_init(hdd_ctx, adapter);
8826 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008827 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308828
Arun Khandavallifae92942016-08-01 13:31:08 +05308829
8830 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008831
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008832cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308833 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008834
Arun Khandavallifae92942016-08-01 13:31:08 +05308835out:
8836 return -EINVAL;
8837}
8838
8839/**
8840 * hdd_deconfigure_cds() -De-Configure cds
8841 * @hdd_ctx: HDD context
8842 *
8843 * Deconfigure Cds modules before WLAN firmware is down.
8844 *
8845 * Return: 0 on success and errno on failure.
8846 */
Jeff Johnson590e2012016-10-05 16:16:24 -07008847static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308848{
8849 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07008850 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308851
8852 ENTER();
8853 /* De-register the SME callbacks */
8854 hdd_deregister_cb(hdd_ctx);
8855
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308856 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308857 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8858 hdd_err("Failed to Disable the CDS Modules! :%d",
8859 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07008860 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308861 }
8862
8863 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07008864 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308865}
8866
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008867#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
8868static void hdd_deregister_policy_manager_callback(
8869 struct wlan_objmgr_psoc *psoc)
8870{
8871 if (QDF_STATUS_SUCCESS !=
8872 policy_mgr_deregister_hdd_cb(psoc)) {
8873 hdd_err("HDD callback deregister with policy manager failed");
8874 }
8875}
8876#else
8877static void hdd_deregister_policy_manager_callback(
8878 struct wlan_objmgr_psoc *psoc)
8879{
8880}
8881#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05308882
8883/**
8884 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
8885 * @hdd_ctx: HDD context
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008886 * @ftm_mode: ftm mode
Arun Khandavallifae92942016-08-01 13:31:08 +05308887 *
8888 * This function maintains the driver state machine it will be invoked from
8889 * exit, shutdown and con_mode change handler. Depending on the driver state
8890 * shall perform the stopping/closing of the modules.
8891 *
8892 * Return: 0 for success; non-zero for failure
8893 */
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008894int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
Arun Khandavallifae92942016-08-01 13:31:08 +05308895{
8896 void *hif_ctx;
8897 qdf_device_t qdf_ctx;
8898 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308899 int ret = 0;
Dustin Brown70111822017-03-30 15:31:40 -07008900 bool is_idle_stop = !cds_is_driver_unloading() &&
8901 !cds_is_driver_recovering();
8902 int active_threads;
Arun Khandavallifae92942016-08-01 13:31:08 +05308903
8904 ENTER();
8905
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008906 hdd_deregister_policy_manager_callback(hdd_ctx->hdd_psoc);
8907
Arun Khandavallifae92942016-08-01 13:31:08 +05308908 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8909 if (!qdf_ctx) {
8910 hdd_err("QDF device context NULL");
8911 return -EINVAL;
8912 }
8913
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308914 mutex_lock(&hdd_ctx->iface_change_lock);
8915 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05308916
Dustin Brown70111822017-03-30 15:31:40 -07008917 active_threads = cds_return_external_threads_count();
8918 if (active_threads > 0 || hdd_ctx->isWiphySuspended) {
Rajeev Kumar86177c22017-03-16 19:44:39 -07008919 hdd_warn("External threads %d wiphy suspend %d",
Dustin Brown70111822017-03-30 15:31:40 -07008920 active_threads, hdd_ctx->isWiphySuspended);
8921
8922 cds_print_external_threads();
8923
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008924 if (is_idle_stop && !ftm_mode) {
Dustin Brown70111822017-03-30 15:31:40 -07008925 mutex_unlock(&hdd_ctx->iface_change_lock);
8926 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008927 hdd_ctx->config->iface_change_wait_time);
8928 hdd_ctx->stop_modules_in_progress = false;
Dustin Brown70111822017-03-30 15:31:40 -07008929 return 0;
8930 }
Rajeev Kumar86177c22017-03-16 19:44:39 -07008931 }
8932
Arun Khandavallifae92942016-08-01 13:31:08 +05308933 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
8934
8935 switch (hdd_ctx->driver_status) {
8936 case DRIVER_MODULES_UNINITIALIZED:
8937 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308938 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308939 case DRIVER_MODULES_CLOSED:
8940 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308941 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308942 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05308943 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308944 if (hdd_deconfigure_cds(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008945 hdd_err("Failed to de-configure CDS");
Arun Khandavallifae92942016-08-01 13:31:08 +05308946 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308947 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308948 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008949 hdd_debug("successfully Disabled the CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05308950 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8951 break;
8952 case DRIVER_MODULES_OPENED:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008953 hdd_debug("Closing CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05308954 break;
8955 default:
8956 hdd_err("Trying to stop wlan in a wrong state: %d",
8957 hdd_ctx->driver_status);
8958 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308959 ret = -EINVAL;
8960 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308961 }
8962
Govind Singhb048e872016-09-27 22:07:43 +05308963 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8964 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8965 hdd_err("Failed to process post CDS disable Modules! :%d",
8966 qdf_status);
8967 ret = -EINVAL;
8968 QDF_ASSERT(0);
8969 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308970 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308971 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008972 hdd_warn("Failed to stop CDS: %d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308973 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308974 QDF_ASSERT(0);
8975 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008976
Arun Khandavallifae92942016-08-01 13:31:08 +05308977 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8978 if (!hif_ctx) {
8979 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308980 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308981 }
8982
8983 hdd_hif_close(hif_ctx);
8984
8985 ol_cds_free();
8986
Dustin Brown70111822017-03-30 15:31:40 -07008987 if (is_idle_stop) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308988 ret = pld_power_off(qdf_ctx->dev);
8989 if (ret)
8990 hdd_err("CNSS power down failed put device into Low power mode:%d",
8991 ret);
8992 }
8993 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07008994 /*
8995 * Reset total mac phy during module stop such that during
8996 * next module start same psoc is used to populate new service
8997 * ready data
8998 */
8999 hdd_ctx->hdd_psoc->total_mac_phy = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05309000
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309001done:
9002 hdd_ctx->stop_modules_in_progress = false;
9003 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05309004 EXIT();
9005
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309006 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309007
9008}
9009
9010/**
9011 * hdd_iface_change_callback() - Function invoked when stop modules expires
9012 * @priv: pointer to hdd context
9013 *
9014 * This function is invoked when the timer waiting for the interface change
9015 * expires, it shall cut-down the power to wlan and stop all the modules.
9016 *
9017 * Return: void
9018 */
9019static void hdd_iface_change_callback(void *priv)
9020{
9021 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
9022 int ret;
9023 int status = wlan_hdd_validate_context(hdd_ctx);
9024
9025 if (status)
9026 return;
9027
9028 ENTER();
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009029 hdd_debug("Interface change timer expired close the modules!");
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009030 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309031 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009032 hdd_err("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05309033 EXIT();
9034}
9035
9036/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309037 * hdd_state_info_dump() - prints state information of hdd layer
9038 * @buf: buffer pointer
9039 * @size: size of buffer to be filled
9040 *
9041 * This function is used to dump state information of hdd layer
9042 *
9043 * Return: None
9044 */
9045static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
9046{
9047 hdd_context_t *hdd_ctx;
9048 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
9049 QDF_STATUS status;
9050 hdd_station_ctx_t *hdd_sta_ctx;
9051 hdd_adapter_t *adapter;
9052 uint16_t len = 0;
9053 char *buf = *buf_ptr;
9054
9055 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9056 if (!hdd_ctx) {
9057 hdd_err("Failed to get hdd context ");
9058 return;
9059 }
9060
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009061 hdd_debug("size of buffer: %d", *size);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309062
9063 len += scnprintf(buf + len, *size - len,
9064 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
9065 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08009066 "\n is_scheduler_suspended %d",
9067 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309068
9069 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
9070
9071 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
9072 adapter = adapter_node->pAdapter;
9073 if (adapter->dev)
9074 len += scnprintf(buf + len, *size - len,
9075 "\n device name: %s", adapter->dev->name);
9076 len += scnprintf(buf + len, *size - len,
9077 "\n device_mode: %d", adapter->device_mode);
9078 switch (adapter->device_mode) {
9079 case QDF_STA_MODE:
9080 case QDF_P2P_CLIENT_MODE:
9081 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9082 len += scnprintf(buf + len, *size - len,
9083 "\n connState: %d",
9084 hdd_sta_ctx->conn_info.connState);
9085 break;
9086
9087 default:
9088 break;
9089 }
9090 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
9091 adapter_node = next;
9092 }
9093
9094 *size -= len;
9095 *buf_ptr += len;
9096}
9097
9098/**
9099 * hdd_register_debug_callback() - registration function for hdd layer
9100 * to print hdd state information
9101 *
9102 * Return: None
9103 */
9104static void hdd_register_debug_callback(void)
9105{
9106 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
9107}
9108
9109/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009110 * hdd_wlan_startup() - HDD init function
9111 * @dev: Pointer to the underlying device
9112 *
9113 * This is the driver startup code executed once a WLAN device has been detected
9114 *
9115 * Return: 0 for success, < 0 for failure
9116 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309117int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009118{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309119 QDF_STATUS status;
Jeff Johnson957bc272017-02-02 08:54:48 -08009120 hdd_context_t *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009121 int ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009122 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309123 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009124
9125 ENTER();
9126
Arun Khandavallifae92942016-08-01 13:31:08 +05309127 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009128
9129 if (IS_ERR(hdd_ctx))
9130 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009131
Abhishek Singhe9068f12017-03-31 14:14:52 +05309132 ret = hdd_objmgr_create_and_store_psoc(hdd_ctx,
9133 DEFAULT_PSOC_ID);
9134 if (ret) {
9135 hdd_err("Psoc creation fails!");
9136 QDF_BUG(0);
9137 goto err_hdd_free_context;
9138 }
9139
Arun Khandavallifae92942016-08-01 13:31:08 +05309140 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
9141 hdd_iface_change_callback, (void *)hdd_ctx);
9142
9143 mutex_init(&hdd_ctx->iface_change_lock);
9144
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009145 ret = hdd_init_netlink_services(hdd_ctx);
9146 if (ret)
9147 goto err_hdd_free_context;
9148
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009149 hdd_request_manager_init();
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07009150 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309151
Jeff Johnson957bc272017-02-02 08:54:48 -08009152 ret = hdd_wlan_start_modules(hdd_ctx, NULL, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309153 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009154 hdd_err("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009155 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009156 }
9157
Yingying Tang80e15f32016-09-27 18:23:01 +08009158 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009159
Yingying Tang95409972016-10-20 15:16:15 +08009160 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009161 hdd_debug("Failed to set wow pulse");
Yingying Tang95409972016-10-20 15:16:15 +08009162
Anurag Chouhan6d760662016-02-20 16:05:43 +05309163 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009164
9165 if (NULL == hdd_ctx->hHal) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009166 hdd_err("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05309167 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009168 }
9169
Prashanth Bhatta07998752016-04-28 12:35:33 -07009170 ret = hdd_wiphy_init(hdd_ctx);
9171 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009172 hdd_err("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05309173 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009174 }
9175
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05309176 if (hdd_ctx->config->enable_dp_trace)
9177 qdf_dp_trace_init();
9178
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309179 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009180 goto err_wiphy_unregister;
9181
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05309182 wlan_hdd_init_chan_info(hdd_ctx);
9183
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07009184 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08009185
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009186 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009187
Jeff Johnson957bc272017-02-02 08:54:48 -08009188 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
9189 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009190 hdd_err("Failed to open interfaces: %d", ret);
Jeff Johnson46bde382017-02-01 15:31:16 -08009191 goto err_release_rtnl_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009192 }
9193
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009194 hdd_release_rtnl_lock();
9195 rtnl_held = false;
9196
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009197 wlan_hdd_update_11n_mode(hdd_ctx->config);
9198
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009199#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05309200 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309201 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009202 hdd_skip_acs_scan_timer_handler,
9203 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309204 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07009205 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04009206 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009207#endif
9208
Nitesh Shah61c10d92016-10-19 19:29:15 +05309209 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
9210 QDF_TIMER_TYPE_SW,
9211 wlan_hdd_change_tdls_mode,
9212 hdd_ctx);
9213
Prashanth Bhattaab004382016-10-11 16:08:11 -07009214 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009215
Jeff Johnson9afc5012016-09-23 13:56:27 -07009216 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009217
Nirav Shahbd36b062016-07-18 11:12:59 +05309218 if (hdd_ctx->rps)
9219 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07009220
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009221 ret = hdd_register_notifiers(hdd_ctx);
9222 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08009223 goto err_close_adapters;
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05309224
9225 status = wlansap_global_init();
9226 if (QDF_IS_STATUS_ERROR(status))
Jeff Johnson957bc272017-02-02 08:54:48 -08009227 goto err_close_adapters;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009228
Komal Seelam8634b772016-09-29 12:12:24 +05309229 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009230 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309231 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009232
bings612b9c42016-11-07 10:52:03 +08009233 if (hdd_enable_egap(hdd_ctx))
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009234 hdd_debug("enhance green ap is not enabled");
bings612b9c42016-11-07 10:52:03 +08009235
Arun Khandavallifae92942016-08-01 13:31:08 +05309236 if (hdd_ctx->config->fIsImpsEnabled)
9237 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309238
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309239 if (hdd_ctx->config->sifs_burst_duration) {
9240 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
9241 hdd_ctx->config->sifs_burst_duration;
9242
9243 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
9244 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
9245 set_value, PDEV_CMD);
9246 }
9247
Arun Khandavallifae92942016-08-01 13:31:08 +05309248 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
9249 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309250
Sachin Ahujadddd2632017-03-07 19:07:24 +05309251 hdd_start_complete(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009252 goto success;
9253
Jeff Johnson957bc272017-02-02 08:54:48 -08009254err_close_adapters:
Jeff Johnson46bde382017-02-01 15:31:16 -08009255 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009256
Jeff Johnson46bde382017-02-01 15:31:16 -08009257err_release_rtnl_lock:
Arun Khandavallid4349a92016-07-25 11:10:43 +05309258 if (rtnl_held)
9259 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009260
Anurag Chouhance6a4052016-09-14 18:20:42 +05309261 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08009262
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009263err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009264 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009265
Arun Khandavallifae92942016-08-01 13:31:08 +05309266err_stop_modules:
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009267 hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309268
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05309269err_exit_nl_srv:
Arunk Khandavallifbc1ef02017-03-14 21:25:05 +05309270 if (DRIVER_MODULES_CLOSED == hdd_ctx->driver_status) {
9271 status = cds_sched_close(hdd_ctx->pcds_context);
9272 if (!QDF_IS_STATUS_SUCCESS(status)) {
9273 hdd_err("Failed to close CDS Scheduler");
9274 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
9275 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009276 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009277
Houston Hoffman47a4a052016-11-14 23:22:44 -08009278 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009279 hdd_request_manager_deinit();
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009280 hdd_exit_netlink_services(hdd_ctx);
9281
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309282 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009283err_hdd_free_context:
Sachin Ahujadddd2632017-03-07 19:07:24 +05309284 hdd_start_complete(ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05309285 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
9286 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07009287 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309288 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009289 return -EIO;
9290
9291success:
9292 EXIT();
9293 return 0;
9294}
9295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009296/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309297 * hdd_wlan_update_target_info() - update target type info
9298 * @hdd_ctx: HDD context
9299 * @context: hif context
9300 *
9301 * Update target info received from firmware in hdd context
9302 * Return:None
9303 */
9304
9305void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
9306{
9307 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
9308
9309 if (!tgt_info) {
9310 hdd_err("Target info is Null");
9311 return;
9312 }
9313
9314 hdd_ctx->target_type = tgt_info->target_type;
9315}
9316
9317/**
9318 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309319 * @hdd_ctx: HDD context
9320 *
9321 * Register the HDD callbacks to CDS/SME.
9322 *
9323 * Return: 0 for success or Error code for failure
9324 */
9325int hdd_register_cb(hdd_context_t *hdd_ctx)
9326{
9327 QDF_STATUS status;
9328 int ret = 0;
9329
9330 ENTER();
9331
9332 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
9333
9334 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
9335 hdd_send_oem_data_rsp_msg);
9336
9337 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
9338 wlan_hdd_cfg80211_fw_mem_dump_cb);
9339 if (!QDF_IS_STATUS_SUCCESS(status)) {
9340 hdd_err("Failed to register memdump callback");
9341 ret = -EINVAL;
9342 return ret;
9343 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05309344 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
9345 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309346 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
9347 sme_nan_register_callback(hdd_ctx->hHal,
9348 wlan_hdd_cfg80211_nan_callback);
9349 sme_stats_ext_register_callback(hdd_ctx->hHal,
9350 wlan_hdd_cfg80211_stats_ext_callback);
9351
9352 sme_ext_scan_register_callback(hdd_ctx->hHal,
9353 wlan_hdd_cfg80211_extscan_callback);
9354
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309355 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
9356 hdd_rssi_threshold_breached);
9357
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309358 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
9359 wlan_hdd_cfg80211_link_layer_stats_callback);
9360
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309361 sme_rso_cmd_status_cb(hdd_ctx->hHal, wlan_hdd_rso_cmd_status_cb);
9362
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05309363 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
9364 hdd_lost_link_info_cb);
9365 /* print error and not block the startup process */
9366 if (!QDF_IS_STATUS_SUCCESS(status))
9367 hdd_err("set lost link info callback failed");
9368
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309369 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
9370
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009371 sme_register_set_connection_info_cb(hdd_ctx->hHal,
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009372 hdd_set_connection_in_progress,
9373 hdd_is_connection_in_progress);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309374 EXIT();
9375
9376 return ret;
9377}
9378
9379/**
9380 * hdd_deregister_cb() - De-Register HDD callbacks.
9381 * @hdd_ctx: HDD context
9382 *
9383 * De-Register the HDD callbacks to CDS/SME.
9384 *
9385 * Return: void
9386 */
9387void hdd_deregister_cb(hdd_context_t *hdd_ctx)
9388{
9389 QDF_STATUS status;
9390
9391 ENTER();
9392
9393 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
9394 if (!QDF_IS_STATUS_SUCCESS(status))
9395 hdd_err("De-register of dcc stats callback failed: %d",
9396 status);
9397
9398 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309399 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
9400
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309401 sme_stats_ext_register_callback(hdd_ctx->hHal,
9402 wlan_hdd_cfg80211_stats_ext_callback);
9403
9404 sme_nan_deregister_callback(hdd_ctx->hHal);
9405 status = sme_reset_tsfcb(hdd_ctx->hHal);
9406 if (!QDF_IS_STATUS_SUCCESS(status))
9407 hdd_err("Failed to de-register tsfcb the callback:%d",
9408 status);
9409 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
9410 if (!QDF_IS_STATUS_SUCCESS(status))
9411 hdd_err("Failed to de-register the fw mem dump callback: %d",
9412 status);
9413
9414 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
9415 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
9416
9417 EXIT();
9418}
9419
9420/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009421 * hdd_softap_sta_deauth() - handle deauth req from HDD
9422 * @adapter: Pointer to the HDD
9423 * @enable: bool value
9424 *
9425 * This to take counter measure to handle deauth req from HDD
9426 *
9427 * Return: None
9428 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309429QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009430 struct tagCsrDelStaParams *pDelStaParams)
9431{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309432 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009433
9434 ENTER();
9435
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009436 hdd_debug("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009437 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9438
9439 /* Ignore request to deauth bcmc station */
9440 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309441 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009442
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309443 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009444 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9445 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446
9447 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309448 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009449}
9450
9451/**
9452 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
9453 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309454 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009455 *
9456 * This to take counter measure to handle deauth req from HDD
9457 *
9458 * Return: None
9459 */
9460void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309461 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009462{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009463 ENTER();
9464
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009465 hdd_debug("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009466 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9467
9468 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309469 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009470 return;
9471
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009472 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309473 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009474}
9475
9476void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
9477 bool enable)
9478{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009479 ENTER();
9480
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009481 hdd_debug("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009482 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9483
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009484 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9485 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009486}
9487
9488/**
9489 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
9490 * @hdd_ctx: HDD Context
9491 *
9492 * API to find if there is any STA or P2P-Client is connected
9493 *
9494 * Return: true if connected; false otherwise
9495 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309496QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009497{
9498 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
9499}
9500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009501/**
9502 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
9503 * @adapter: HDD adapter pointer
9504 *
9505 * This function loop through each adapter and disable roaming on each STA
9506 * device mode except the input adapter.
9507 *
9508 * Note: On the input adapter roaming is not enabled yet hence no need to
9509 * disable.
9510 *
9511 * Return: None
9512 */
9513void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
9514{
9515 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9516 hdd_adapter_t *adapterIdx = NULL;
9517 hdd_adapter_list_node_t *adapterNode = NULL;
9518 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309519 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009520
9521 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009522 hdd_ctx->config->isRoamOffloadScanEnabled &&
9523 QDF_STA_MODE == adapter->device_mode &&
9524 policy_mgr_is_sta_active_connection_exists(
9525 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009526 hdd_debug("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009527 adapter->sessionId);
9528 /*
9529 * Loop through adapter and disable roaming for each STA device
9530 * mode except the input adapter.
9531 */
9532 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9533
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309534 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009535 adapterIdx = adapterNode->pAdapter;
9536
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009537 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009538 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009539 hdd_debug("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009540 adapterIdx->sessionId);
9541 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
9542 (adapterIdx),
9543 adapterIdx->sessionId, 0);
9544 }
9545
9546 status = hdd_get_next_adapter(hdd_ctx,
9547 adapterNode,
9548 &pNext);
9549 adapterNode = pNext;
9550 }
9551 }
9552}
9553
9554/**
9555 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
9556 * @adapter: HDD adapter pointer
9557 *
9558 * This function loop through each adapter and enable roaming on each STA
9559 * device mode except the input adapter.
9560 * Note: On the input adapter no need to enable roaming because link got
9561 * disconnected on this.
9562 *
9563 * Return: None
9564 */
9565void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
9566{
9567 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9568 hdd_adapter_t *adapterIdx = NULL;
9569 hdd_adapter_list_node_t *adapterNode = NULL;
9570 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309571 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009572
9573 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009574 hdd_ctx->config->isRoamOffloadScanEnabled &&
9575 QDF_STA_MODE == adapter->device_mode &&
9576 policy_mgr_is_sta_active_connection_exists(
9577 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009578 hdd_debug("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009579 adapter->sessionId);
9580 /*
9581 * Loop through adapter and enable roaming for each STA device
9582 * mode except the input adapter.
9583 */
9584 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9585
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309586 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009587 adapterIdx = adapterNode->pAdapter;
9588
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009589 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009590 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009591 hdd_debug("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009592 adapterIdx->sessionId);
9593 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
9594 (adapterIdx),
9595 adapterIdx->sessionId,
9596 REASON_CONNECT);
9597 }
9598
9599 status = hdd_get_next_adapter(hdd_ctx,
9600 adapterNode,
9601 &pNext);
9602 adapterNode = pNext;
9603 }
9604 }
9605}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009606
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309607/**
9608 * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
9609 * @skb: sk buffer pointer
9610 *
9611 * Sends the bcast message to SVC multicast group with generic nl socket
9612 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
9613 *
9614 * Return: None
9615 */
9616static void nl_srv_bcast_svc(struct sk_buff *skb)
9617{
9618#ifdef CNSS_GENL
9619 nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
9620#else
9621 nl_srv_bcast(skb);
9622#endif
9623}
9624
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309625void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009626{
9627 struct sk_buff *skb;
9628 struct nlmsghdr *nlh;
9629 tAniMsgHdr *ani_hdr;
9630 void *nl_data = NULL;
9631 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309632 struct radio_index_tlv *radio_info;
9633 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634
9635 if (in_interrupt() || irqs_disabled() || in_atomic())
9636 flags = GFP_ATOMIC;
9637
9638 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
9639
Srinivas Girigowdab841da72017-03-25 18:04:39 -07009640 if (skb == NULL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009641 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642
9643 nlh = (struct nlmsghdr *)skb->data;
9644 nlh->nlmsg_pid = 0; /* from kernel */
9645 nlh->nlmsg_flags = 0;
9646 nlh->nlmsg_seq = 0;
9647 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
9648
9649 ani_hdr = NLMSG_DATA(nlh);
9650 ani_hdr->type = type;
9651
9652 switch (type) {
9653 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05309654 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009655 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009656 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009657 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009658 ani_hdr->length = 0;
9659 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009660 break;
9661 case WLAN_SVC_WLAN_STATUS_IND:
9662 case WLAN_SVC_WLAN_VERSION_IND:
9663 case WLAN_SVC_DFS_CAC_START_IND:
9664 case WLAN_SVC_DFS_CAC_END_IND:
9665 case WLAN_SVC_DFS_RADAR_DETECT_IND:
9666 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
9667 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08009668 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05309669 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009670 ani_hdr->length = len;
9671 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
9672 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
9673 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009674 break;
9675
9676 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07009677 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009678 type);
9679 kfree_skb(skb);
9680 return;
9681 }
9682
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309683 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08009684 * Add radio index at the end of the svc event in TLV format
9685 * to maintain the backward compatibility with userspace
9686 * applications.
9687 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309688
9689 tlv_len = 0;
9690
9691 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
9692 < WLAN_NL_MAX_PAYLOAD) {
9693 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
9694 sizeof(*ani_hdr) + len);
9695 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
9696 radio_info->length = (unsigned short) sizeof(radio_info->radio);
9697 radio_info->radio = radio;
9698 tlv_len = sizeof(*radio_info);
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009699 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309700 "Added radio index tlv - radio index %d",
9701 radio_info->radio);
9702 }
9703
9704 nlh->nlmsg_len += tlv_len;
9705 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
9706
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309707 nl_srv_bcast_svc(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009708}
9709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009710#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
9711void wlan_hdd_auto_shutdown_cb(void)
9712{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07009713 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309714
9715 if (!hdd_ctx)
9716 return;
9717
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009718 hdd_debug("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309719 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
9720 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009721}
9722
9723void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
9724{
9725 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309726 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009727 hdd_adapter_t *adapter;
9728 bool ap_connected = false, sta_connected = false;
9729 tHalHandle hal_handle;
9730
9731 hal_handle = hdd_ctx->hHal;
9732 if (hal_handle == NULL)
9733 return;
9734
9735 if (hdd_ctx->config->WlanAutoShutdown == 0)
9736 return;
9737
9738 if (enable == false) {
9739 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309740 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009741 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009742 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309743 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009744 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009745 return;
9746 }
9747
9748 /* To enable shutdown timer check conncurrency */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009749 if (policy_mgr_concurrent_open_sessions_running(
9750 hdd_ctx->hdd_psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009751 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9752
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309753 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009754 adapter = adapterNode->pAdapter;
9755 if (adapter
9756 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009757 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9759 conn_info.connState ==
9760 eConnectionState_Associated) {
9761 sta_connected = true;
9762 break;
9763 }
9764 }
9765 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009766 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009767 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
9768 bApActive == true) {
9769 ap_connected = true;
9770 break;
9771 }
9772 }
9773 status = hdd_get_next_adapter(hdd_ctx,
9774 adapterNode,
9775 &pNext);
9776 adapterNode = pNext;
9777 }
9778 }
9779
9780 if (ap_connected == true || sta_connected == true) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009781 hdd_debug("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009782 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009783 }
Jeff Johnson68755312017-02-10 11:46:55 -08009784
9785 if (sme_set_auto_shutdown_timer(hal_handle,
9786 hdd_ctx->config->WlanAutoShutdown)
9787 != QDF_STATUS_SUCCESS)
9788 hdd_err("Failed to start wlan auto shutdown timer");
9789 else
9790 hdd_notice("Auto Shutdown timer for %d seconds enabled",
9791 hdd_ctx->config->WlanAutoShutdown);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009792}
9793#endif
9794
9795hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
9796 bool check_start_bss)
9797{
9798 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
9799 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309800 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009801 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
9802
9803 con_sap_adapter = NULL;
9804
9805 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309806 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009807 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009808 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
9809 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810 adapter != this_sap_adapter) {
9811 if (check_start_bss) {
9812 if (test_bit(SOFTAP_BSS_STARTED,
9813 &adapter->event_flags)) {
9814 con_sap_adapter = adapter;
9815 break;
9816 }
9817 } else {
9818 con_sap_adapter = adapter;
9819 break;
9820 }
9821 }
9822 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
9823 adapterNode = pNext;
9824 }
9825
9826 return con_sap_adapter;
9827}
9828
9829#ifdef MSM_PLATFORM
Dustin Brown5ec6b552017-03-31 12:11:40 -07009830static inline bool hdd_adapter_is_sta(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009831{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009832 return adapter->device_mode == QDF_STA_MODE ||
9833 adapter->device_mode == QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834}
9835
Dustin Brown5ec6b552017-03-31 12:11:40 -07009836static inline bool hdd_adapter_is_ap(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009837{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009838 return adapter->device_mode == QDF_SAP_MODE ||
9839 adapter->device_mode == QDF_P2P_GO_MODE;
9840}
9841
9842static bool hdd_any_adapter_is_assoc(hdd_context_t *hdd_ctx)
9843{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309844 QDF_STATUS status;
Dustin Brown5ec6b552017-03-31 12:11:40 -07009845 hdd_adapter_list_node_t *node;
9846
9847 status = hdd_get_front_adapter(hdd_ctx, &node);
9848 while (QDF_IS_STATUS_SUCCESS(status) && node) {
9849 hdd_adapter_t *adapter = node->pAdapter;
9850
9851 if (adapter &&
9852 hdd_adapter_is_sta(adapter) &&
9853 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9854 conn_info.connState == eConnectionState_Associated) {
9855 return true;
9856 }
9857
9858 if (adapter &&
9859 hdd_adapter_is_ap(adapter) &&
9860 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive) {
9861 return true;
9862 }
9863
9864 status = hdd_get_next_adapter(hdd_ctx, node, &node);
9865 }
9866
9867 return false;
9868}
9869
9870static bool hdd_bus_bw_compute_timer_is_running(hdd_context_t *hdd_ctx)
9871{
9872 bool is_running;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009873
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309874 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown5ec6b552017-03-31 12:11:40 -07009875 is_running = hdd_ctx->bus_bw_timer_running;
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309876 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009877
Dustin Brown5ec6b552017-03-31 12:11:40 -07009878 return is_running;
9879}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009880
Dustin Brown5ec6b552017-03-31 12:11:40 -07009881static void __hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9882{
9883 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9884 hdd_ctx->bus_bw_timer_running = true;
9885 qdf_timer_start(&hdd_ctx->bus_bw_timer,
9886 hdd_ctx->config->busBandwidthComputeInterval);
9887 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9888}
9889
9890void hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9891{
9892 ENTER();
9893
9894 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9895 hdd_debug("Bandwidth compute timer already started");
9896 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009897 }
9898
Dustin Brown5ec6b552017-03-31 12:11:40 -07009899 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9900
9901 EXIT();
9902}
9903
9904void hdd_bus_bw_compute_timer_try_start(hdd_context_t *hdd_ctx)
9905{
9906 ENTER();
9907
9908 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9909 hdd_debug("Bandwidth compute timer already started");
9910 return;
Ravi Joshib89e7f72016-09-07 13:43:15 -07009911 }
Dustin Brown5ec6b552017-03-31 12:11:40 -07009912
9913 if (hdd_any_adapter_is_assoc(hdd_ctx))
9914 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9915
9916 EXIT();
9917}
9918
9919static void __hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9920{
9921 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
9922
9923 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9924 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
9925 hdd_ctx->bus_bw_timer_running = false;
9926 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9927
9928 hdd_reset_tcp_delack(hdd_ctx);
9929}
9930
9931void hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9932{
9933 ENTER();
9934
9935 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9936 hdd_debug("Bandwidth compute timer already stopped");
9937 return;
9938 }
9939
9940 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9941
9942 EXIT();
9943}
9944
9945void hdd_bus_bw_compute_timer_try_stop(hdd_context_t *hdd_ctx)
9946{
9947 ENTER();
9948
9949 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9950 hdd_debug("Bandwidth compute timer already stopped");
9951 return;
9952 }
9953
9954 if (!hdd_any_adapter_is_assoc(hdd_ctx))
9955 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9956
9957 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009958}
9959#endif
9960
9961/**
9962 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
9963 * and sta's operating channel.
9964 * @sta_adapter: Describe the first argument to foobar.
9965 * @ap_adapter: Describe the second argument to foobar.
9966 * @roam_profile: Roam profile of AP to which STA wants to connect.
9967 * @concurrent_chnl_same: If both SAP and STA channels are same then
9968 * set this flag to true else false.
9969 *
9970 * This function checks the sap's operating channel and sta's operating channel.
9971 * if both are same then it will return false else it will restart the sap in
9972 * sta's channel and return true.
9973 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309974 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009975 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309976QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009977 hdd_adapter_t *ap_adapter,
9978 tCsrRoamProfile *roam_profile,
9979 tScanResultHandle *scan_cache,
9980 bool *concurrent_chnl_same)
9981{
9982 hdd_ap_ctx_t *hdd_ap_ctx;
9983 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309984 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009985 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 *concurrent_chnl_same = true;
9987
9988 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9989 status =
Archana Ramachandran2eb7a612017-03-23 22:58:42 -07009990 sme_get_ap_channel_from_scan_cache(roam_profile,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009991 scan_cache,
9992 &channel_id);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07009993 if (QDF_STATUS_SUCCESS == status) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009994 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009995 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9996 if (hdd_ap_ctx->operatingChannel != channel_id) {
9997 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009998 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009999 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010000 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010001 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
10002 if (hdd_ap_ctx->operatingChannel != channel_id) {
10003 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010004 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010005 }
10006 }
10007 } else {
10008 /*
10009 * Lets handle worst case scenario here, Scan cache lookup is
10010 * failed so we have to stop the SAP to avoid any channel
10011 * discrepancy between SAP's channel and STA's channel.
10012 * Return the status as failure so caller function could know
10013 * that scan look up is failed.
10014 */
Jeff Johnson28f8a772016-08-15 15:30:36 -070010015 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010016 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010018 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010019}
10020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010021/**
10022 * wlan_hdd_stop_sap() - This function stops bss of SAP.
10023 * @ap_adapter: SAP adapter
10024 *
10025 * This function will process the stopping of sap adapter.
10026 *
10027 * Return: None
10028 */
10029void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
10030{
10031 hdd_ap_ctx_t *hdd_ap_ctx;
10032 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010033 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010034 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010035
10036 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010037 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010038 return;
10039 }
10040
10041 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10042 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053010043 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010044 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +053010045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010046 mutex_lock(&hdd_ctx->sap_lock);
10047 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010048 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010049 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
10050 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010051 hdd_debug("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010052 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010053 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010054 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +053010055 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -080010056 qdf_stop_bss_event,
10057 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010058 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010059 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -070010060 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061 return;
10062 }
10063 }
10064 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080010065 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
10066 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010067 ap_adapter->sessionId);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010068 hdd_debug("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010069 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010070 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010071 }
10072 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010073}
10074
10075/**
10076 * wlan_hdd_start_sap() - this function starts bss of SAP.
10077 * @ap_adapter: SAP adapter
10078 *
10079 * This function will process the starting of sap adapter.
10080 *
10081 * Return: None
10082 */
Arun Khandavallicc544b32017-01-30 19:52:16 +053010083void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010084{
10085 hdd_ap_ctx_t *hdd_ap_ctx;
10086 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010087 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010088 hdd_context_t *hdd_ctx;
10089 tsap_Config_t *sap_config;
10090
10091 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010092 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 return;
10094 }
10095
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010096 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -070010097 hdd_err("SoftAp role has not been enabled");
10098 return;
10099 }
10100
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
10102 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10103 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10104 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
10105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010106 mutex_lock(&hdd_ctx->sap_lock);
10107 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
10108 goto end;
10109
10110 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010111 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010112 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
10113 goto end;
10114 }
10115
Wei Song2f76f642016-11-18 16:32:53 +080010116 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
10118 &hdd_ap_ctx->sapConfig,
10119 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010120 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010121 goto end;
10122
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010123 hdd_debug("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010124 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -080010125 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010126 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010127 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 goto end;
10129 }
Jeff Johnson28f8a772016-08-15 15:30:36 -070010130 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -080010132 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080010133 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
10134 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010135 ap_adapter->sessionId);
10136 hostapd_state->bCommit = true;
10137
10138end:
10139 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010141
10142/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010143 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
10144 * mac scan config
10145 * @status: Status of set antenna mode
10146 *
10147 * Callback on setting the dual mac configuration
10148 *
10149 * Return: None
10150 */
10151void wlan_hdd_soc_set_antenna_mode_cb(
10152 enum set_antenna_mode_status status)
10153{
10154 hdd_context_t *hdd_ctx;
10155
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010156 hdd_debug("Status: %d", status);
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010157
10158 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10159 if (0 != wlan_hdd_validate_context(hdd_ctx))
10160 return;
10161
10162 /* Signal the completion of set dual mac config */
10163 complete(&hdd_ctx->set_antenna_mode_cmpl);
10164}
10165
10166/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167 * hdd_get_fw_version() - Get FW version
10168 * @hdd_ctx: pointer to HDD context.
10169 * @major_spid: FW version - major spid.
10170 * @minor_spid: FW version - minor spid
10171 * @ssid: FW version - ssid
10172 * @crmid: FW version - crmid
10173 *
10174 * This function is called to get the firmware build version stored
10175 * as part of the HDD context
10176 *
10177 * Return: None
10178 */
10179void hdd_get_fw_version(hdd_context_t *hdd_ctx,
10180 uint32_t *major_spid, uint32_t *minor_spid,
10181 uint32_t *siid, uint32_t *crmid)
10182{
10183 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
10184 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
10185 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
10186 *crmid = hdd_ctx->target_fw_version & 0x7fff;
10187}
10188
10189#ifdef QCA_CONFIG_SMP
10190/**
10191 * wlan_hdd_get_cpu() - get cpu_index
10192 *
10193 * Return: cpu_index
10194 */
10195int wlan_hdd_get_cpu(void)
10196{
10197 int cpu_index = get_cpu();
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010198
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199 put_cpu();
10200 return cpu_index;
10201}
10202#endif
10203
10204/**
10205 * hdd_get_fwpath() - get framework path
10206 *
10207 * This function is used to get the string written by
10208 * userspace to start the wlan driver
10209 *
10210 * Return: string
10211 */
10212const char *hdd_get_fwpath(void)
10213{
10214 return fwpath.string;
10215}
10216
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010217/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010218 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010219 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010220 * This function initilizes CDS global context with the help of cds_init. This
10221 * has to be the first function called after probe to get a valid global
10222 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010223 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010224 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010225 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010226int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010227{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010228 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010229 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010230
Houston Hoffman9e06e542016-12-12 12:06:26 -080010231 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010232#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10233 wlan_logging_sock_init_svc();
10234#endif
10235
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010236 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010237 hdd_err("Failed to allocate CDS context");
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010238 ret = -ENOMEM;
10239 goto err_out;
10240 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010241
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010242 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +053010243 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010244
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010245err_out:
10246 return ret;
10247}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010248
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010249/**
10250 * hdd_deinit() - Deinitialize Driver
10251 *
10252 * This function frees CDS global context with the help of cds_deinit. This
10253 * has to be the last function call in remove callback to free the global
10254 * context.
10255 */
10256void hdd_deinit(void)
10257{
10258 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010259
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010260#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10261 wlan_logging_sock_deinit_svc();
10262#endif
10263}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010264
Yue Ma6e7b1a02017-04-03 14:17:46 -070010265#ifdef QCA_WIFI_NAPIER_EMULATION
10266#define HDD_WLAN_START_WAIT_TIME ((CDS_WMA_TIMEOUT + 5000) * 100)
10267#else
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010268#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
Yue Ma6e7b1a02017-04-03 14:17:46 -070010269#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010270
Sachin Ahujadddd2632017-03-07 19:07:24 +053010271static int wlan_hdd_state_ctrl_param_open(struct inode *inode,
10272 struct file *file)
10273{
10274 return 0;
10275}
10276
10277static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
10278 const char __user *user_buf,
10279 size_t count,
10280 loff_t *f_pos)
10281{
10282 char buf;
10283 static const char wlan_off_str[] = "OFF";
10284 static const char wlan_on_str[] = "ON";
10285 int ret;
10286 unsigned long rc;
10287
10288 if (copy_from_user(&buf, user_buf, 3)) {
10289 pr_err("Failed to read buffer\n");
10290 return -EINVAL;
10291 }
10292
10293 if (strncmp(&buf, wlan_off_str, strlen(wlan_off_str)) == 0) {
10294 pr_debug("Wifi turning off from UI\n");
10295 goto exit;
10296 }
10297
10298 if (strncmp(&buf, wlan_on_str, strlen(wlan_on_str)) != 0) {
10299 pr_err("Invalid value received from framework");
10300 goto exit;
10301 }
10302
10303 if (!cds_is_driver_loaded()) {
10304 rc = wait_for_completion_timeout(&wlan_start_comp,
10305 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
10306 if (!rc) {
10307 hdd_alert("Timed-out waiting in wlan_hdd_state_ctrl_param_write");
10308 ret = -EINVAL;
10309 hdd_start_complete(ret);
10310 return ret;
10311 }
10312
10313 hdd_start_complete(0);
10314 }
10315
10316exit:
10317 return count;
10318}
10319
10320
10321const struct file_operations wlan_hdd_state_fops = {
10322 .owner = THIS_MODULE,
10323 .open = wlan_hdd_state_ctrl_param_open,
10324 .write = wlan_hdd_state_ctrl_param_write,
10325};
10326
10327static int wlan_hdd_state_ctrl_param_create(void)
10328{
10329 unsigned int wlan_hdd_state_major = 0;
10330 int ret;
10331 struct device *dev;
10332
10333 device = MKDEV(wlan_hdd_state_major, 0);
10334
10335 ret = alloc_chrdev_region(&device, 0, dev_num, "qcwlanstate");
10336 if (ret) {
10337 pr_err("Failed to register qcwlanstate");
10338 goto dev_alloc_err;
10339 }
10340 wlan_hdd_state_major = MAJOR(device);
10341
10342 class = class_create(THIS_MODULE, WLAN_MODULE_NAME);
10343 if (IS_ERR(class)) {
10344 pr_err("wlan_hdd_state class_create error");
10345 goto class_err;
10346 }
10347
10348 dev = device_create(class, NULL, device, NULL, WLAN_MODULE_NAME);
10349 if (IS_ERR(dev)) {
10350 pr_err("wlan_hdd_statedevice_create error");
10351 goto err_class_destroy;
10352 }
10353
10354 cdev_init(&wlan_hdd_state_cdev, &wlan_hdd_state_fops);
10355 ret = cdev_add(&wlan_hdd_state_cdev, device, dev_num);
10356 if (ret) {
10357 pr_err("Failed to add cdev error");
10358 goto cdev_add_err;
10359 }
10360
10361 pr_info("wlan_hdd_state %s major(%d) initialized",
10362 WLAN_MODULE_NAME, wlan_hdd_state_major);
10363
10364 return 0;
10365
10366cdev_add_err:
10367 device_destroy(class, device);
10368err_class_destroy:
10369 class_destroy(class);
10370class_err:
10371 unregister_chrdev_region(device, dev_num);
10372dev_alloc_err:
10373 return -ENODEV;
10374}
10375
10376static void wlan_hdd_state_ctrl_param_destroy(void)
10377{
10378 cdev_del(&wlan_hdd_state_cdev);
10379 device_destroy(class, device);
10380 class_destroy(class);
10381 unregister_chrdev_region(device, dev_num);
10382
10383 pr_info("Device node unregistered");
10384}
10385
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010386/**
10387 * __hdd_module_init - Module init helper
10388 *
10389 * Module init helper function used by both module and static driver.
10390 *
10391 * Return: 0 for success, errno on failure
10392 */
10393static int __hdd_module_init(void)
10394{
10395 int ret = 0;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010396 unsigned long rc;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010397
Arun Khandavallifae92942016-08-01 13:31:08 +053010398 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010399 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010400
Sachin Ahujadddd2632017-03-07 19:07:24 +053010401 ret = wlan_hdd_state_ctrl_param_create();
10402 if (ret) {
10403 pr_err("wlan_hdd_state_create:%x\n", ret);
10404 goto err_dev_state;
10405 }
10406
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010407 pld_init();
10408
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010409 ret = hdd_init();
10410 if (ret) {
10411 pr_err("hdd_init failed %x\n", ret);
10412 goto err_hdd_init;
10413 }
10414
Rajeev Kumar97767a02016-11-30 11:20:40 -080010415 dispatcher_init();
10416
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010417 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010418
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010419 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010420
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010421 init_completion(&wlan_start_comp);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010422 ret = wlan_hdd_register_driver();
10423 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -070010424 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
10425 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010426 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010427 }
10428
Sachin Ahujadddd2632017-03-07 19:07:24 +053010429 /*
10430 * This wait is temporarily introduced till
10431 * boardconfig changes for dev node are merged
10432 */
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010433 rc = wait_for_completion_timeout(&wlan_start_comp,
Sachin Ahujadddd2632017-03-07 19:07:24 +053010434 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010435 if (!rc) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010436 hdd_err("Timed-out waiting for wlan_hdd_register_driver");
Sachin Ahujadddd2632017-03-07 19:07:24 +053010437 ret = -ETIMEDOUT;
10438 wlan_hdd_unregister_driver();
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010439 goto out;
10440 }
10441
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010442 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010443
10444 return 0;
10445out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010446 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -080010447 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010448 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010449
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010450err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010451 pld_deinit();
Sachin Ahujadddd2632017-03-07 19:07:24 +053010452 wlan_hdd_state_ctrl_param_destroy();
10453err_dev_state:
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010454 return ret;
10455}
10456
10457/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010458 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
10459 *
10460 * Block the unloading of the driver until the cds recovery is completed
10461 *
10462 * Return: None
10463 */
10464static void hdd_wait_for_recovery_completion(void)
10465{
10466 int retry = 0;
10467
10468 /* Wait for recovery to complete */
10469 while (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010470 hdd_err("Recovery in progress; wait here!!!");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010471 msleep(1000);
10472 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010473 hdd_err("SSR never completed, error");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010474 QDF_BUG(0);
10475 }
10476 }
10477}
10478
10479/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010480 * __hdd_module_exit - Module exit helper
10481 *
10482 * Module exit helper function used by both module and static driver.
10483 */
10484static void __hdd_module_exit(void)
10485{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010486 int qdf_print_idx = -1;
10487
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010488 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
10489 QWLAN_VERSIONSTR);
10490
bings6028ee82017-03-29 07:51:40 +080010491 cds_set_unload_in_progress(true);
10492
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010493 hdd_wait_for_recovery_completion();
10494
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010495 wlan_hdd_unregister_driver();
10496
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010497 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010498
Rajeev Kumar97767a02016-11-30 11:20:40 -080010499 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010500 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010501 pld_deinit();
10502
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010503 qdf_print_idx = qdf_get_pidx();
10504 qdf_print_ctrl_cleanup(qdf_print_idx);
Sachin Ahujadddd2632017-03-07 19:07:24 +053010505 wlan_hdd_state_ctrl_param_destroy();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010506}
10507
Arun Khandavallifae92942016-08-01 13:31:08 +053010508#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010509/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010510 * wlan_boot_cb() - Wlan boot callback
10511 * @kobj: object whose directory we're creating the link in.
10512 * @attr: attribute the user is interacting with
10513 * @buff: the buffer containing the user data
10514 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010515 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010516 * This callback is invoked when the fs is ready to start the
10517 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010518 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010519 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010520 */
Arun Khandavallifae92942016-08-01 13:31:08 +053010521static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010522 struct kobj_attribute *attr,
10523 const char *buf,
10524 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010525{
Arun Khandavallifae92942016-08-01 13:31:08 +053010526
Arun Khandavallifae92942016-08-01 13:31:08 +053010527 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010528 pr_err("%s: wlan driver already initialized\n", __func__);
10529 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +053010530 }
10531
Arun Khandavallifae92942016-08-01 13:31:08 +053010532 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010533 pr_err("%s: wlan driver initialization failed\n", __func__);
10534 return -EIO;
10535 }
10536
10537 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +053010538
10539 return count;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010540}
Arun Khandavallifae92942016-08-01 13:31:08 +053010541
10542/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010543 * hdd_sysfs_cleanup() - cleanup sysfs
10544 *
10545 * Return: None
10546 *
10547 */
10548static void hdd_sysfs_cleanup(void)
10549{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010550 /* remove from group */
10551 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
10552 sysfs_remove_group(wlan_loader->boot_wlan_obj,
10553 wlan_loader->attr_group);
10554
10555 /* unlink the object from parent */
10556 kobject_del(wlan_loader->boot_wlan_obj);
10557
10558 /* free the object */
10559 kobject_put(wlan_loader->boot_wlan_obj);
10560
10561 kfree(wlan_loader->attr_group);
10562 kfree(wlan_loader);
10563
10564 wlan_loader = NULL;
10565}
10566
10567/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010568 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
10569 * ready
10570 *
10571 * This is creates the syfs entry boot_wlan. Which shall be invoked
10572 * when the filesystem is ready.
10573 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010574 * QDF API cannot be used here since this function is called even before
10575 * initializing WLAN driver.
10576 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010577 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +053010578 */
10579static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010580{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010581 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010582
10583 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010584 if (!wlan_loader)
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010585 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010586
10587 wlan_loader->boot_wlan_obj = NULL;
10588 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
10589 GFP_KERNEL);
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010590 if (!wlan_loader->attr_group)
Arun Khandavallifae92942016-08-01 13:31:08 +053010591 goto error_return;
Arun Khandavallifae92942016-08-01 13:31:08 +053010592
10593 wlan_loader->loaded_state = 0;
10594 wlan_loader->attr_group->attrs = attrs;
10595
10596 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
10597 kernel_kobj);
10598 if (!wlan_loader->boot_wlan_obj) {
10599 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010600 goto error_return;
10601 }
10602
10603 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
10604 wlan_loader->attr_group);
10605 if (ret) {
10606 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
10607 goto error_return;
10608 }
10609
10610 return 0;
10611
10612error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010613 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +053010614
10615 return ret;
10616}
10617
10618/**
10619 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
10620 *
10621 * Return: 0 on success or errno on failure
10622 */
10623static int wlan_deinit_sysfs(void)
10624{
Arun Khandavallifae92942016-08-01 13:31:08 +053010625 if (!wlan_loader) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010626 hdd_err("wlan loader context is Null!");
Arun Khandavallifae92942016-08-01 13:31:08 +053010627 return -EINVAL;
10628 }
10629
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010630 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010631 return 0;
10632}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010633
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010634#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +053010635
10636#ifdef MODULE
10637/**
10638 * __hdd_module_init - Module init helper
10639 *
10640 * Module init helper function used by both module and static driver.
10641 *
10642 * Return: 0 for success, errno on failure
10643 */
10644static int hdd_module_init(void)
10645{
10646 int ret = 0;
10647
10648 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
10649 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
10650
10651 if (__hdd_module_init()) {
10652 pr_err("%s: Failed to register handler\n", __func__);
10653 ret = -EINVAL;
10654 }
10655
10656 return ret;
10657}
10658#else
10659static int __init hdd_module_init(void)
10660{
10661 int ret = -EINVAL;
10662
10663 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010664 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +053010665 pr_err("Failed to create sysfs entry for loading wlan");
10666
10667 return ret;
10668}
10669#endif
10670
10671
10672#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010673/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010674 * hdd_module_exit() - Exit function
10675 *
10676 * This is the driver exit point (invoked when module is unloaded using rmmod)
10677 *
10678 * Return: None
10679 */
10680static void __exit hdd_module_exit(void)
10681{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010682 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010683}
Arun Khandavallifae92942016-08-01 13:31:08 +053010684#else
10685static void __exit hdd_module_exit(void)
10686{
10687 __hdd_module_exit();
10688 wlan_deinit_sysfs();
10689}
10690#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010691
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010692static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
10693{
10694 return param_set_copystring(kmessage, kp);
10695}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010696
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010697/**
10698 * is_con_mode_valid() check con mode is valid or not
10699 * @mode: global con mode
10700 *
10701 * Return: TRUE on success FALSE on failure
10702 */
10703static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
10704{
10705 switch (mode) {
10706 case QDF_GLOBAL_MONITOR_MODE:
10707 case QDF_GLOBAL_FTM_MODE:
10708 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010709 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010710 return true;
10711 default:
10712 return false;
10713 }
10714}
10715
10716/**
10717 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
10718 * @mode: global con mode
10719 *
10720 * Return: adapter mode
10721 */
10722static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
10723 enum tQDF_GLOBAL_CON_MODE mode)
10724{
10725
10726 switch (mode) {
10727 case QDF_GLOBAL_MISSION_MODE:
10728 return QDF_STA_MODE;
10729 case QDF_GLOBAL_MONITOR_MODE:
10730 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010731 case QDF_GLOBAL_EPPING_MODE:
10732 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010733 case QDF_GLOBAL_FTM_MODE:
10734 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010735 case QDF_GLOBAL_QVIT_MODE:
10736 return QDF_QVIT_MODE;
10737 default:
10738 return QDF_MAX_NO_OF_MODE;
10739 }
10740}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010741
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010742static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
10743 enum tQDF_GLOBAL_CON_MODE curr_mode)
10744{
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010745 int driver_status;
10746
10747 driver_status = hdd_ctx->driver_status;
10748
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010749 switch (curr_mode) {
10750 case QDF_GLOBAL_MISSION_MODE:
10751 case QDF_GLOBAL_MONITOR_MODE:
10752 case QDF_GLOBAL_FTM_MODE:
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010753 if (driver_status != DRIVER_MODULES_CLOSED) {
10754 hdd_abort_mac_scan_all_adapters(hdd_ctx);
10755 hdd_stop_all_adapters(hdd_ctx);
10756 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010757 hdd_deinit_all_adapters(hdd_ctx, false);
10758 hdd_close_all_adapters(hdd_ctx, false);
10759 break;
10760 case QDF_GLOBAL_EPPING_MODE:
10761 epping_disable();
10762 epping_close();
10763 break;
10764 default:
10765 return;
10766 }
10767}
10768
10769static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
10770 enum tQDF_GLOBAL_CON_MODE mode)
10771{
10772 hdd_adapter_t *adapter;
10773 int ret = 0;
10774 bool rtnl_held;
10775 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
10776 QDF_STATUS status;
10777
10778 if (!qdf_dev) {
10779 hdd_err("qdf device context is Null return!");
10780 return -EINVAL;
10781 }
10782
10783 rtnl_held = hdd_hold_rtnl_lock();
10784 switch (mode) {
10785 case QDF_GLOBAL_MISSION_MODE:
Jeff Johnson957bc272017-02-02 08:54:48 -080010786 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
10787 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010788 hdd_err("Failed to open interfaces: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010789 break;
10790 case QDF_GLOBAL_FTM_MODE:
10791 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
10792 wlan_hdd_get_intf_addr(hdd_ctx),
10793 NET_NAME_UNKNOWN, rtnl_held);
10794 if (adapter == NULL)
10795 ret = -EINVAL;
10796 break;
10797 case QDF_GLOBAL_MONITOR_MODE:
10798 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
10799 wlan_hdd_get_intf_addr(hdd_ctx),
10800 NET_NAME_UNKNOWN, rtnl_held);
10801 if (adapter == NULL)
10802 ret = -EINVAL;
10803 break;
10804 case QDF_GLOBAL_EPPING_MODE:
10805 status = epping_open();
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010806 if (status != QDF_STATUS_SUCCESS) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010807 hdd_err("Failed to open in eeping mode: %d", status);
10808 ret = -EINVAL;
10809 break;
10810 }
10811 ret = epping_enable(qdf_dev->dev);
10812 if (ret) {
10813 hdd_err("Failed to enable in epping mode : %d", ret);
10814 epping_close();
10815 }
10816 break;
10817 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010818 hdd_err("Mode not supported");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010819 ret = -ENOTSUPP;
10820 break;
10821 }
10822 hdd_release_rtnl_lock();
10823 rtnl_held = false;
10824 return ret;
10825}
10826
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010827/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010828 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010829 * @kmessage: con mode name on which driver to be bring up
10830 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010831 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010832 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010833 * This function is invoked when user updates con mode using sys entry,
10834 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010835 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010836 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010837 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010838static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
10839 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010840{
10841 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +053010842 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010843 enum tQDF_GLOBAL_CON_MODE curr_mode;
10844 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010845
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010846 ret = wlan_hdd_validate_context(hdd_ctx);
10847 if (ret)
10848 return ret;
10849
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010850 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010851
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010852 hdd_debug("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010853 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +053010854
Arun Khandavallifae92942016-08-01 13:31:08 +053010855
Arun Khandavallia172c3e2016-08-26 17:33:13 +053010856
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010857 if (!(is_con_mode_valid(con_mode))) {
10858 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010859 ret = -EINVAL;
10860 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010861 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010862
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010863 curr_mode = hdd_get_conparam();
10864 if (curr_mode == con_mode) {
10865 hdd_err("curr mode: %d is same as user triggered mode %d",
10866 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010867 ret = 0;
10868 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010869 }
10870
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010871 /* Cleanup present mode before switching to new mode */
10872 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +053010873
Rajeev Kumar3fef4e82017-03-31 20:25:23 -070010874 ret = hdd_wlan_stop_modules(hdd_ctx, true);
Arun Khandavallifae92942016-08-01 13:31:08 +053010875 if (ret) {
10876 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010877 goto reset_flags;
10878 }
10879
10880 hdd_set_conparam(con_mode);
10881
10882 /* Register for new con_mode & then kick_start modules again */
10883 ret = hdd_register_req_mode(hdd_ctx, con_mode);
10884 if (ret) {
10885 hdd_err("Failed to register for new mode");
10886 goto reset_flags;
10887 }
10888
10889 adapter_mode = hdd_get_adpter_mode(con_mode);
10890 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
10891 hdd_err("invalid adapter");
10892 ret = -EINVAL;
10893 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010894 }
10895
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010896 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +053010897 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010898 hdd_err("Failed to get adapter:%d", adapter_mode);
10899 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010900 }
10901
10902 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
10903 if (ret) {
10904 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010905 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010906 }
10907
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010908 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
10909 con_mode == QDF_GLOBAL_FTM_MODE) {
10910 if (hdd_start_adapter(adapter)) {
10911 hdd_err("Failed to start %s adapter", kmessage);
10912 ret = -EINVAL;
10913 goto reset_flags;
10914 }
Arun Khandavallifae92942016-08-01 13:31:08 +053010915 }
10916
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010917 hdd_info("Mode successfully changed to %s", kmessage);
10918 ret = 0;
10919
10920reset_flags:
10921 cds_set_load_in_progress(false);
10922 return ret;
10923}
10924
10925
10926static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
10927{
10928 int ret;
10929 hdd_context_t *hdd_ctx;
10930
10931 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10932 ret = wlan_hdd_validate_context(hdd_ctx);
10933 if (ret)
10934 return ret;
10935
10936 cds_ssr_protect(__func__);
10937 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
10938 cds_ssr_unprotect(__func__);
10939
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010940 return ret;
10941}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010942
10943/**
10944 * hdd_get_conparam() - driver exit point
10945 *
10946 * This is the driver exit point (invoked when module is unloaded using rmmod)
10947 *
Anurag Chouhan6d760662016-02-20 16:05:43 +053010948 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010949 */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010950enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010951{
Anurag Chouhan6d760662016-02-20 16:05:43 +053010952 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010953}
10954
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010955void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010956{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010957 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010958}
10959
Komal Seelamc11bb222016-01-27 18:57:10 +053010960/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010961 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
10962 * @hdd_ctx: HDD context
10963 *
10964 * Cleans up the pre cac interface, if it exists
10965 *
10966 * Return: None
10967 */
10968void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
10969{
10970 uint8_t session_id;
10971 QDF_STATUS status;
10972 struct hdd_adapter_s *precac_adapter;
10973
10974 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
10975 if (QDF_IS_STATUS_ERROR(status)) {
10976 hdd_err("failed to get pre cac vdev id");
10977 return;
10978 }
10979
10980 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
10981 if (!precac_adapter) {
10982 hdd_err("invalid pre cac adapater");
10983 return;
10984 }
10985
10986 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
10987 wlan_hdd_sap_pre_cac_failure,
10988 (void *)precac_adapter);
10989 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
10990
10991}
10992
10993/**
Komal Seelamec702b02016-02-24 18:42:16 +053010994 * hdd_update_ol_config - API to update ol configuration parameters
10995 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +053010996 *
Komal Seelamc11bb222016-01-27 18:57:10 +053010997 * Return: void
10998 */
Komal Seelamec702b02016-02-24 18:42:16 +053010999static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +053011000{
Komal Seelamec702b02016-02-24 18:42:16 +053011001 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +053011002 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +053011003
Komal Seelamec702b02016-02-24 18:42:16 +053011004 if (!ol_ctx)
11005 return;
11006
11007 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
11008 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
11009 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
11010 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -070011011 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +053011012
11013 ol_init_ini_config(ol_ctx, &cfg);
11014}
11015
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070011016#ifdef FEATURE_RUNTIME_PM
11017/**
11018 * hdd_populate_runtime_cfg() - populate runtime configuration
11019 * @hdd_ctx: hdd context
11020 * @cfg: pointer to the configuration memory being populated
11021 *
11022 * Return: void
11023 */
11024static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
11025 struct hif_config_info *cfg)
11026{
11027 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
11028 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
11029}
11030#else
11031static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
11032 struct hif_config_info *cfg)
11033{
11034}
11035#endif
11036
Komal Seelamec702b02016-02-24 18:42:16 +053011037/**
11038 * hdd_update_hif_config - API to update HIF configuration parameters
11039 * @hdd_ctx: HDD Context
11040 *
11041 * Return: void
11042 */
11043static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
11044{
Anurag Chouhandf2b2682016-02-29 14:15:27 +053011045 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +053011046 struct hif_config_info cfg;
11047
11048 if (!scn)
11049 return;
11050
11051 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070011052 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053011053 hif_init_ini_config(scn, &cfg);
11054}
11055
11056/**
11057 * hdd_update_config() - Initialize driver per module ini parameters
11058 * @hdd_ctx: HDD Context
11059 *
11060 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011061 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053011062 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011063int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053011064{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011065 int ret;
11066
Komal Seelamec702b02016-02-24 18:42:16 +053011067 hdd_update_ol_config(hdd_ctx);
11068 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011069 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
11070 ret = hdd_update_cds_config_ftm(hdd_ctx);
11071 else
11072 ret = hdd_update_cds_config(hdd_ctx);
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -080011073 ret = hdd_update_user_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053011074
11075 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053011076}
11077
Mukul Sharma9d797a02017-01-05 20:26:03 +053011078#ifdef FEATURE_WLAN_RA_FILTERING
11079/**
11080 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
11081 * @psoc_cfg: pmo psoc Configuration
11082 * @hdd_ctx: Pointer to hdd context
11083 *
11084 * Return: none
11085 */
11086static inline void hdd_ra_populate_pmo_config(
11087 struct pmo_psoc_cfg *psoc_cfg,
11088 hdd_context_t *hdd_ctx)
11089{
11090 psoc_cfg->ra_ratelimit_interval =
11091 hdd_ctx->config->RArateLimitInterval;
11092 psoc_cfg->ra_ratelimit_enable =
11093 hdd_ctx->config->IsRArateLimitEnabled;
11094}
11095#else
11096static inline void hdd_ra_populate_pmo_config(
11097 struct cds_config_info *cds_cfg,
11098 hdd_context_t *hdd_ctx)
11099{
11100}
11101#endif
11102/**
11103 * hdd_update_pmo_config - API to update pmo configuration parameters
11104 * @hdd_ctx: HDD context
11105 *
11106 * Return: void
11107 */
11108static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
11109{
11110 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
11111 struct pmo_psoc_cfg psoc_cfg;
11112 QDF_STATUS status;
11113
11114 /*
11115 * Value of hdd_ctx->wowEnable can be,
11116 * 0 - Disable both magic pattern match and pattern byte match.
11117 * 1 - Enable magic pattern match on all interfaces.
11118 * 2 - Enable pattern byte match on all interfaces.
11119 * 3 - Enable both magic patter and pattern byte match on
11120 * all interfaces.
11121 */
11122 psoc_cfg.magic_ptrn_enable =
11123 (hdd_ctx->config->wowEnable & 0x01) ? true : false;
11124 psoc_cfg.ptrn_match_enable_all_vdev =
11125 (hdd_ctx->config->wowEnable & 0x02) ? true : false;
11126 psoc_cfg.bpf_enable =
11127 hdd_ctx->config->bpf_packet_filter_enable;
11128 psoc_cfg.arp_offload_enable = hdd_ctx->config->fhostArpOffload;
Ravi Kumar Bokka794fd712017-03-21 20:52:46 +053011129 psoc_cfg.hw_bcast_filter = hdd_ctx->config->hw_broadcast_filter;
Mukul Sharma9d797a02017-01-05 20:26:03 +053011130 psoc_cfg.ns_offload_enable_static = hdd_ctx->config->fhostNSOffload;
11131 if (hdd_ctx->config->fhostNSOffload)
11132 psoc_cfg.ns_offload_enable_dynamic = true;
11133 psoc_cfg.ssdp = hdd_ctx->config->ssdp;
11134 psoc_cfg.enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
11135 psoc_cfg.active_mode_offload =
11136 hdd_ctx->config->active_mode_offload;
11137 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
11138 psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters;
Mukul Sharma9223f232017-03-08 18:42:27 +053011139 psoc_cfg.sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
11140 psoc_cfg.sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
11141 psoc_cfg.sta_max_li_mod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
11142 psoc_cfg.power_save_mode =
11143 hdd_ctx->config->enablePowersaveOffload;
Mukul Sharma9d797a02017-01-05 20:26:03 +053011144
11145 hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9223f232017-03-08 18:42:27 +053011146 hdd_nan_populate_pmo_config(&psoc_cfg, hdd_ctx);
11147 hdd_lpass_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053011148 status = pmo_ucfg_update_psoc_config(psoc, &psoc_cfg);
11149 if (status != QDF_STATUS_SUCCESS) {
11150 hdd_err("failed pmo psoc configuration");
11151 return -EINVAL;
11152 }
11153
11154 return 0;
11155}
11156
Abhishek Singh257a9482017-03-06 16:52:39 +053011157#ifdef NAPIER_SCAN
Abhishek Singhb20db962017-03-03 21:28:46 +053011158
11159#ifdef FEATURE_WLAN_SCAN_PNO
11160static inline void hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
11161 struct hdd_config *cfg)
11162{
11163 pno_cfg->channel_prediction = cfg->pno_channel_prediction;
11164 pno_cfg->top_k_num_of_channels = cfg->top_k_num_of_channels;
11165 pno_cfg->stationary_thresh = cfg->stationary_thresh;
11166 pno_cfg->adaptive_dwell_mode = cfg->adaptive_dwell_mode_enabled;
11167 pno_cfg->channel_prediction_full_scan =
11168 cfg->channel_prediction_full_scan;
11169}
11170#else
11171static inline void
11172hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
11173 struct hdd_config *cfg)
11174{
11175 return;
11176}
11177#endif
11178
Abhishek Singh257a9482017-03-06 16:52:39 +053011179/**
11180 * hdd_update_scan_config - API to update scan configuration parameters
11181 * @hdd_ctx: HDD context
11182 *
11183 * Return: 0 if success else err
11184 */
11185static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
11186{
11187 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
11188 struct scan_user_cfg scan_cfg;
11189 struct hdd_config *cfg = hdd_ctx->config;
11190 QDF_STATUS status;
11191
11192 scan_cfg.active_dwell = cfg->nActiveMaxChnTime;
11193 scan_cfg.passive_dwell = cfg->nPassiveMaxChnTime;
11194 scan_cfg.conc_active_dwell = cfg->nActiveMaxChnTimeConc;
11195 scan_cfg.conc_passive_dwell = cfg->nPassiveMaxChnTimeConc;
11196 scan_cfg.conc_max_rest_time = cfg->nRestTimeConc;
11197 scan_cfg.conc_min_rest_time = cfg->min_rest_time_conc;
11198 scan_cfg.conc_idle_time = cfg->idle_time_conc;
11199 scan_cfg.scan_cache_aging_time = cfg->scanAgingTimeout;
11200 scan_cfg.scan_dwell_time_mode = cfg->scan_adaptive_dwell_mode;
Kapil Guptafa9a8c62017-04-10 15:25:40 +053011201 scan_cfg.is_snr_monitoring_enabled = cfg->fEnableSNRMonitoring;
Abhishek Singh257a9482017-03-06 16:52:39 +053011202
Abhishek Singhb20db962017-03-03 21:28:46 +053011203 hdd_update_pno_config(&scan_cfg.pno_cfg, cfg);
11204
Abhishek Singh257a9482017-03-06 16:52:39 +053011205 status = ucfg_scan_update_user_config(psoc, &scan_cfg);
11206 if (status != QDF_STATUS_SUCCESS) {
11207 hdd_err("failed pmo psoc configuration");
11208 return -EINVAL;
11209 }
11210
11211 return 0;
11212}
11213#else
11214static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
11215{
11216 return 0;
11217}
11218#endif
11219
Mukul Sharma9d797a02017-01-05 20:26:03 +053011220int hdd_update_components_config(hdd_context_t *hdd_ctx)
11221{
11222 int ret;
11223
11224 ret = hdd_update_pmo_config(hdd_ctx);
Abhishek Singh257a9482017-03-06 16:52:39 +053011225 if (ret)
11226 return ret;
11227 ret = hdd_update_scan_config(hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053011228
11229 return ret;
11230}
11231
Agrawal Ashish65634612016-08-18 13:24:32 +053011232/**
11233 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
11234 * @mode : cfg80211 DFS mode
11235 *
11236 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
11237 */
11238enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
11239{
11240 switch (mode) {
11241 case DFS_MODE_ENABLE:
11242 return ACS_DFS_MODE_ENABLE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011243 case DFS_MODE_DISABLE:
11244 return ACS_DFS_MODE_DISABLE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011245 case DFS_MODE_DEPRIORITIZE:
11246 return ACS_DFS_MODE_DEPRIORITIZE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011247 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011248 hdd_debug("ACS dfs mode is NONE");
11249 return ACS_DFS_MODE_NONE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011250 }
11251}
11252
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011253/**
11254 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
11255 * @hddctx: pointer to hdd context
11256 * @set_value: enable/disable
11257 *
11258 * When Host sends vendor command enable, FW will send *ONE* CA ind to
11259 * Host(even though it is duplicate). When Host send vendor command
11260 * disable,FW doesn't perform any action. Whenever any change in
11261 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
11262 *
11263 * return - 0 on success, appropriate error values on failure.
11264 */
11265int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
11266{
11267 QDF_STATUS status;
11268
Srinivas Girigowdab841da72017-03-25 18:04:39 -070011269 if (0 != wlan_hdd_validate_context(hddctx))
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011270 return -EAGAIN;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011271
11272 if (!hddctx->config->goptimize_chan_avoid_event) {
11273 hdd_warn("goptimize_chan_avoid_event ini param disabled");
11274 return -EINVAL;
11275 }
11276
11277 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
11278 if (!QDF_IS_STATUS_SUCCESS(status)) {
11279 hdd_err("Failed to send chan avoid command to SME");
11280 return -EINVAL;
11281 }
11282 return 0;
11283}
Agrawal Ashish65634612016-08-18 13:24:32 +053011284
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011285/**
11286 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
11287 * @value: value to set
11288 *
11289 * This function will set the passed value to roaming in progress flag.
11290 *
11291 * Return: None
11292 */
11293void hdd_set_roaming_in_progress(bool value)
11294{
11295 hdd_context_t *hdd_ctx;
11296
11297 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11298 if (!hdd_ctx) {
11299 hdd_err("HDD context is NULL");
11300 return;
11301 }
11302
11303 hdd_ctx->roaming_in_progress = value;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011304 hdd_debug("Roaming in Progress set to %d", value);
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011305}
11306
11307/**
11308 * hdd_is_roaming_in_progress() - check if roaming is in progress
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011309 * @adapter - HDD adapter
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011310 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011311 * Return: true if roaming is in progress for STA type, else false
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011312 */
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011313bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter)
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011314{
11315 hdd_context_t *hdd_ctx;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011316 bool ret_status = false;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011317
11318 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11319 if (!hdd_ctx) {
11320 hdd_err("HDD context is NULL");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011321 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011322 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011323 hdd_debug("dev mode = %d, roaming_in_progress = %d",
11324 adapter->device_mode, hdd_ctx->roaming_in_progress);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011325 ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
11326 hdd_ctx->roaming_in_progress);
11327
11328 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011329}
11330
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011331/**
11332 * hdd_is_connection_in_progress() - check if connection is in
11333 * progress
11334 * @session_id: session id
11335 * @reason: scan reject reason
11336 *
11337 * Go through each adapter and check if Connection is in progress
11338 *
11339 * Return: true if connection is in progress else false
11340 */
11341bool hdd_is_connection_in_progress(uint8_t *session_id,
11342 enum scan_reject_states *reason)
11343{
11344 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
11345 hdd_station_ctx_t *hdd_sta_ctx = NULL;
11346 hdd_adapter_t *adapter = NULL;
11347 QDF_STATUS status = 0;
11348 uint8_t sta_id = 0;
11349 uint8_t *sta_mac = NULL;
11350 hdd_context_t *hdd_ctx;
11351
11352 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11353 if (!hdd_ctx) {
11354 hdd_err("HDD context is NULL");
11355 return false;
11356 }
11357
11358 if (true == hdd_ctx->btCoexModeSet) {
11359 hdd_info("BTCoex Mode operation in progress");
11360 return true;
11361 }
11362 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
11363 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
11364 adapter = adapter_node->pAdapter;
11365 if (!adapter)
11366 goto end;
11367
11368 hdd_info("Adapter with device mode %s(%d) exists",
11369 hdd_device_mode_to_string(adapter->device_mode),
11370 adapter->device_mode);
11371 if (((QDF_STA_MODE == adapter->device_mode)
11372 || (QDF_P2P_CLIENT_MODE == adapter->device_mode)
11373 || (QDF_P2P_DEVICE_MODE == adapter->device_mode))
11374 && (eConnectionState_Connecting ==
11375 (WLAN_HDD_GET_STATION_CTX_PTR(adapter))->
11376 conn_info.connState)) {
11377 hdd_err("%p(%d) Connection is in progress",
11378 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11379 adapter->sessionId);
11380 if (session_id && reason) {
11381 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011382 *reason = CONNECTION_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011383 }
11384 return true;
11385 }
Archana Ramachandran62886ce2017-03-24 14:46:32 -070011386 /*
11387 * sme_neighbor_middle_of_roaming is for LFR2
11388 * hdd_is_roaming_in_progress is for LFR3
11389 */
11390 if (((QDF_STA_MODE == adapter->device_mode) &&
11391 sme_neighbor_middle_of_roaming(
11392 WLAN_HDD_GET_HAL_CTX(adapter),
11393 adapter->sessionId)) ||
11394 hdd_is_roaming_in_progress(adapter)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011395 hdd_err("%p(%d) Reassociation in progress",
11396 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11397 adapter->sessionId);
11398 if (session_id && reason) {
11399 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011400 *reason = REASSOC_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011401 }
11402 return true;
11403 }
11404 if ((QDF_STA_MODE == adapter->device_mode) ||
11405 (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
11406 (QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
11407 hdd_sta_ctx =
11408 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
11409 if ((eConnectionState_Associated ==
11410 hdd_sta_ctx->conn_info.connState)
11411 && (false ==
11412 hdd_sta_ctx->conn_info.uIsAuthenticated)) {
11413 sta_mac = (uint8_t *)
11414 &(adapter->macAddressCurrent.bytes[0]);
11415 hdd_err("client " MAC_ADDRESS_STR
11416 " is in middle of WPS/EAPOL exchange.",
11417 MAC_ADDR_ARRAY(sta_mac));
11418 if (session_id && reason) {
11419 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011420 *reason = EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011421 }
11422 return true;
11423 }
11424 } else if ((QDF_SAP_MODE == adapter->device_mode) ||
11425 (QDF_P2P_GO_MODE == adapter->device_mode)) {
11426 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
11427 sta_id++) {
11428 if (!((adapter->aStaInfo[sta_id].isUsed)
11429 && (OL_TXRX_PEER_STATE_CONN ==
11430 adapter->aStaInfo[sta_id].tlSTAState)))
11431 continue;
11432
11433 sta_mac = (uint8_t *)
11434 &(adapter->aStaInfo[sta_id].
11435 macAddrSTA.bytes[0]);
11436 hdd_err("client " MAC_ADDRESS_STR
11437 " of SAP/GO is in middle of WPS/EAPOL exchange",
11438 MAC_ADDR_ARRAY(sta_mac));
11439 if (session_id && reason) {
11440 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011441 *reason = SAP_EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011442 }
11443 return true;
11444 }
11445 if (hdd_ctx->connection_in_progress) {
11446 hdd_err("AP/GO: connection is in progress");
11447 return true;
11448 }
11449 }
11450end:
11451 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
11452 adapter_node = next;
11453 }
11454 return false;
11455}
11456
11457/**
11458 * hdd_restart_sap() - to restart SAP in driver internally
11459 * @ap_adapter: Pointer to SAP hdd_adapter_t structure
11460 *
11461 * Return: None
11462 */
11463void hdd_restart_sap(hdd_adapter_t *ap_adapter)
11464{
11465 hdd_ap_ctx_t *hdd_ap_ctx;
11466 hdd_hostapd_state_t *hostapd_state;
11467 QDF_STATUS qdf_status;
11468 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
11469 tsap_Config_t *sap_config;
11470 void *sap_ctx;
11471
11472 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11473 sap_config = &hdd_ap_ctx->sapConfig;
11474 sap_ctx = hdd_ap_ctx->sapContext;
11475
11476 mutex_lock(&hdd_ctx->sap_lock);
11477 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
11478 wlan_hdd_del_station(ap_adapter);
11479 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
11480 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11481 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
11482 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {
11483 qdf_status =
11484 qdf_wait_single_event(&hostapd_state->
11485 qdf_stop_bss_event,
11486 SME_CMD_TIMEOUT_VALUE);
11487
11488 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11489 cds_err("SAP Stop Failed");
11490 goto end;
11491 }
11492 }
11493 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011494 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011495 ap_adapter->device_mode, ap_adapter->sessionId);
11496 cds_err("SAP Stop Success");
11497
11498 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
11499 cds_err("SAP Not able to set AP IEs");
11500 wlansap_reset_sap_config_add_ie(sap_config,
11501 eUPDATE_IE_ALL);
11502 goto end;
11503 }
11504
11505 qdf_event_reset(&hostapd_state->qdf_event);
11506 if (wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb,
11507 sap_config,
11508 ap_adapter->dev) != QDF_STATUS_SUCCESS) {
11509 cds_err("SAP Start Bss fail");
11510 wlansap_reset_sap_config_add_ie(sap_config,
11511 eUPDATE_IE_ALL);
11512 goto end;
11513 }
11514
11515 cds_info("Waiting for SAP to start");
11516 qdf_status =
11517 qdf_wait_single_event(&hostapd_state->qdf_event,
11518 SME_CMD_TIMEOUT_VALUE);
11519 wlansap_reset_sap_config_add_ie(sap_config,
11520 eUPDATE_IE_ALL);
11521 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11522 cds_err("SAP Start failed");
11523 goto end;
11524 }
11525 cds_err("SAP Start Success");
11526 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
11527 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011528 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
11529 ap_adapter->device_mode,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011530 ap_adapter->sessionId);
11531 hostapd_state->bCommit = true;
11532 }
11533end:
11534 mutex_unlock(&hdd_ctx->sap_lock);
11535 return;
11536}
11537
11538/**
11539 * hdd_check_and_restart_sap_with_non_dfs_acs() - Restart SAP
11540 * with non dfs acs
11541 *
11542 * Restarts SAP in non-DFS ACS mode when STA-AP mode DFS is not supported
11543 *
11544 * Return: None
11545 */
11546void hdd_check_and_restart_sap_with_non_dfs_acs(void)
11547{
11548 hdd_adapter_t *ap_adapter;
11549 hdd_context_t *hdd_ctx;
11550 cds_context_type *cds_ctx;
11551
11552 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11553 if (!hdd_ctx) {
11554 cds_err("HDD context is NULL");
11555 return;
11556 }
11557
11558 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
11559 if (!cds_ctx) {
11560 cds_err("Invalid CDS Context");
11561 return;
11562 }
11563
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011564 if (policy_mgr_get_concurrency_mode(hdd_ctx->hdd_psoc)
11565 != (QDF_STA_MASK | QDF_SAP_MASK)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011566 cds_info("Concurrency mode is not SAP");
11567 return;
11568 }
11569
11570 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11571 if (ap_adapter != NULL &&
11572 test_bit(SOFTAP_BSS_STARTED,
11573 &ap_adapter->event_flags)
11574 && CDS_IS_DFS_CH(ap_adapter->sessionCtx.ap.
11575 operatingChannel)) {
11576
11577 cds_warn("STA-AP Mode DFS not supported. Restart SAP with Non DFS ACS");
11578 ap_adapter->sessionCtx.ap.sapConfig.channel =
11579 AUTO_CHANNEL_SELECT;
11580 ap_adapter->sessionCtx.ap.sapConfig.
11581 acs_cfg.acs_mode = true;
11582
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011583 hdd_restart_sap(ap_adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011584 }
11585}
11586
11587/**
11588 * hdd_set_connection_in_progress() - to set the connection in
11589 * progress flag
11590 * @value: value to set
11591 *
11592 * This function will set the passed value to connection in progress flag.
11593 * If value is previously being set to true then no need to set it again.
11594 *
11595 * Return: true if value is being set correctly and false otherwise.
11596 */
11597bool hdd_set_connection_in_progress(bool value)
11598{
11599 bool status = true;
11600 hdd_context_t *hdd_ctx;
11601
11602 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11603 if (!hdd_ctx) {
11604 cds_err("HDD context is NULL");
11605 return false;
11606 }
11607
11608 qdf_spin_lock(&hdd_ctx->connection_status_lock);
11609 /*
11610 * if the value is set to true previously and if someone is
11611 * trying to make it true again then it could be some race
11612 * condition being triggered. Avoid this situation by returning
11613 * false
11614 */
11615 if (hdd_ctx->connection_in_progress && value)
11616 status = false;
11617 else
11618 hdd_ctx->connection_in_progress = value;
11619 qdf_spin_unlock(&hdd_ctx->connection_status_lock);
11620 return status;
11621}
11622
Archana Ramachandranb8c04f92017-03-17 20:05:47 -070011623int wlan_hdd_send_p2p_quota(hdd_adapter_t *adapter, int set_value)
11624{
11625 if (!adapter) {
11626 hdd_err("Invalid adapter");
11627 return -EINVAL;
11628 }
11629 hdd_info("Send MCC P2P QUOTA to WMA: %d", set_value);
11630 wma_cli_set_command(adapter->sessionId,
11631 WMA_VDEV_MCC_SET_TIME_QUOTA,
11632 set_value, VDEV_CMD);
11633 return 0;
11634
11635}
11636
11637int wlan_hdd_send_mcc_latency(hdd_adapter_t *adapter, int set_value)
11638{
11639 if (!adapter) {
11640 hdd_err("Invalid adapter");
11641 return -EINVAL;
11642 }
11643
11644 hdd_info("Send MCC latency WMA: %d", set_value);
11645 wma_cli_set_command(adapter->sessionId,
11646 WMA_VDEV_MCC_SET_TIME_LATENCY,
11647 set_value, VDEV_CMD);
11648 return 0;
11649}
11650
Archana Ramachandranea34c4f2017-03-19 18:56:18 -070011651hdd_adapter_t *wlan_hdd_get_adapter_from_vdev(struct wlan_objmgr_psoc
11652 *psoc, uint8_t vdev_id)
11653{
11654 hdd_adapter_t *adapter = NULL;
11655 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11656
11657 /*
11658 * Currently PSOC is not being used. But this logic will
11659 * change once we have the converged implementation of
11660 * HDD context per PSOC in place. This would break if
11661 * multiple vdev objects reuse the vdev id.
11662 */
11663 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
11664 if (!adapter)
11665 hdd_err("Get adapter by vdev id failed");
11666
11667 return adapter;
11668}
11669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011670/* Register the module init/exit functions */
11671module_init(hdd_module_init);
11672module_exit(hdd_module_exit);
11673
11674MODULE_LICENSE("Dual BSD/GPL");
11675MODULE_AUTHOR("Qualcomm Atheros, Inc.");
11676MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
11677
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011678module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
11679 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011680
11681module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
11682 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
11683
11684module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
11685
11686module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
11687
11688module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);