blob: 55a90a91bccab657ea2702b28c3336c3b7d63d98 [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
126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
Arun Khandavallifae92942016-08-01 13:31:08 +0530145#ifndef MODULE
146static struct gwlan_loader *wlan_loader;
147static ssize_t wlan_boot_cb(struct kobject *kobj,
148 struct kobj_attribute *attr,
149 const char *buf, size_t count);
150struct gwlan_loader {
151 bool loaded_state;
152 struct kobject *boot_wlan_obj;
153 struct attribute_group *attr_group;
154};
155
156static struct kobj_attribute wlan_boot_attribute =
157 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
158
159static struct attribute *attrs[] = {
160 &wlan_boot_attribute.attr,
161 NULL,
162};
163
164#define MODULE_INITIALIZED 1
165#endif
166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167/* the Android framework expects this param even though we don't use it */
168#define BUF_LEN 20
169static char fwpath_buffer[BUF_LEN];
170static struct kparam_string fwpath = {
171 .string = fwpath_buffer,
172 .maxlen = BUF_LEN,
173};
174
175static char *country_code;
176static int enable_11d = -1;
177static int enable_dfs_chan_scan = -1;
178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179/*
180 * spinlock for synchronizing asynchronous request/response
181 * (full description of use in wlan_hdd_main.h)
182 */
183DEFINE_SPINLOCK(hdd_context_lock);
184
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800185#define WLAN_NLINK_CESIUM 30
186
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530187static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188
189#define WOW_MAX_FILTER_LISTS 1
190#define WOW_MAX_FILTERS_PER_LIST 4
191#define WOW_MIN_PATTERN_SIZE 6
192#define WOW_MAX_PATTERN_SIZE 64
193
194#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
195static const struct wiphy_wowlan_support wowlan_support_reg_init = {
196 .flags = WIPHY_WOWLAN_ANY |
197 WIPHY_WOWLAN_MAGIC_PKT |
198 WIPHY_WOWLAN_DISCONNECT |
199 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
200 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
201 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
202 WIPHY_WOWLAN_4WAY_HANDSHAKE |
203 WIPHY_WOWLAN_RFKILL_RELEASE,
204 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
205 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
206 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
207};
208#endif
209
210/* internal function declaration */
211
212struct sock *cesium_nl_srv_sock;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +0530213struct completion wlan_start_comp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700215static void wlan_hdd_auto_shutdown_cb(void);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216#endif
217
218/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530219 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
220 * @hdd_ctx: pointer to hdd_context_t
221 *
222 * Return: none
223 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700224static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530225{
226 hdd_adapter_t *adapter;
227 hdd_adapter_list_node_t *adapter_node, *next;
228 QDF_STATUS status = QDF_STATUS_SUCCESS;
229
230 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
231 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
232 adapter = adapter_node->pAdapter;
233 if (NULL != adapter)
234 hdd_send_rps_ind(adapter);
235 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
236 adapter_node = next;
237 }
238}
239
240/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800241 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
242 * @vdev_id: vdev_id
243 * @action: action type
244 * @reason: reason type
245 *
246 * Return: none
247 */
248void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
249 enum netif_action_type action, enum netif_reason_type reason)
250{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530251 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 hdd_adapter_t *adapter;
253
254 if (!hdd_ctx) {
255 hdd_err("hdd ctx is NULL");
256 return;
257 }
258 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
259
260 wlan_hdd_netif_queue_control(adapter, action, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800261}
262
263/*
264 * Store WLAN driver version info in a global variable such that crash debugger
265 * can extract it from driver debug symbol and crashdump for post processing
266 */
267uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
268
269/**
270 * hdd_device_mode_to_string() - return string conversion of device mode
271 * @device_mode: device mode
272 *
273 * This utility function helps log string conversion of device mode.
274 *
275 * Return: string conversion of device mode, if match found;
276 * "Unknown" otherwise.
277 */
278const char *hdd_device_mode_to_string(uint8_t device_mode)
279{
280 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800281 CASE_RETURN_STRING(QDF_STA_MODE);
282 CASE_RETURN_STRING(QDF_SAP_MODE);
283 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
284 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
285 CASE_RETURN_STRING(QDF_FTM_MODE);
286 CASE_RETURN_STRING(QDF_IBSS_MODE);
287 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
288 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700289 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290 default:
291 return "Unknown";
292 }
293}
294
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530295/**
296 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
297 * @adapter: HDD adapter
298 * @chan_number: Channel number
299 * @chan_bw: Bandwidth
300 *
301 * Checks if the given bandwidth is valid for the given channel number.
302 *
303 * Return: 0 for success, non-zero for failure
304 */
305int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
306 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800307 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530308{
309 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
310 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
311 bool found = false;
312 tHalHandle hal;
313
314 hal = WLAN_HDD_GET_HAL_CTX(adapter);
315 if (!hal) {
316 hdd_err("Invalid HAL context");
317 return -EINVAL;
318 }
319
320 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
321 hdd_err("No valid channel list");
322 return -EOPNOTSUPP;
323 }
324
325 for (i = 0; i < len; i++) {
326 if (chan[i] == chan_number) {
327 found = true;
328 break;
329 }
330 }
331
332 if (found == false) {
333 hdd_err("Channel not in driver's valid channel list");
334 return -EOPNOTSUPP;
335 }
336
337 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
338 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
339 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
340 return -EINVAL;
341 }
342
343 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
344 if (chan_bw == CH_WIDTH_80MHZ) {
345 hdd_err("BW80 not possible in 2.4GHz band");
346 return -EINVAL;
347 }
348 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
349 (chan_bw != CH_WIDTH_MAX)) {
350 hdd_err("Only BW20 possible on channel 14");
351 return -EINVAL;
352 }
353 }
354
355 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
356 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
357 (chan_bw != CH_WIDTH_MAX)) {
358 hdd_err("Only BW20 possible on channel 165");
359 return -EINVAL;
360 }
361 }
362
363 return 0;
364}
365
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366static int __hdd_netdev_notifier_call(struct notifier_block *nb,
367 unsigned long state, void *data)
368{
369#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
370 struct netdev_notifier_info *dev_notif_info = data;
371 struct net_device *dev = dev_notif_info->dev;
372#else
373 struct net_device *dev = data;
374#endif
375 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
376 hdd_context_t *hdd_ctx;
377
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800378 ENTER_DEV(dev);
379
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 /* Make sure that this callback corresponds to our device. */
381 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
382 return NOTIFY_DONE;
383
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530384 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700386 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 return NOTIFY_DONE;
388 }
389
390 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700391 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800392 return NOTIFY_DONE;
393 }
394
395 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
396 if (NULL == hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800397 hdd_err("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530398 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800399 return NOTIFY_DONE;
400 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800401 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800402 return NOTIFY_DONE;
403
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800404 hdd_debug("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405 dev->name, state);
406
407 switch (state) {
408 case NETDEV_REGISTER:
409 break;
410
411 case NETDEV_UNREGISTER:
412 break;
413
414 case NETDEV_UP:
415 sme_ch_avoid_update_req(hdd_ctx->hHal);
416 break;
417
418 case NETDEV_DOWN:
419 break;
420
421 case NETDEV_CHANGE:
422 if (true == adapter->isLinkUpSvcNeeded)
423 complete(&adapter->linkup_event_var);
424 break;
425
426 case NETDEV_GOING_DOWN:
427 if (adapter->scan_info.mScanPending != false) {
428 unsigned long rc;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430 INIT_COMPLETION(adapter->scan_info.
431 abortscan_event_var);
432 hdd_abort_mac_scan(adapter->pHddCtx,
433 adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530434 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435 eCSR_SCAN_ABORT_DEFAULT);
436 rc = wait_for_completion_timeout(
437 &adapter->scan_info.abortscan_event_var,
438 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700439 if (!rc)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700440 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 } else {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800442 hdd_debug("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 }
444 break;
445
446 default:
447 break;
448 }
449
450 return NOTIFY_DONE;
451}
452
453/**
454 * hdd_netdev_notifier_call() - netdev notifier callback function
455 * @nb: pointer to notifier block
456 * @state: state
457 * @ndev: ndev pointer
458 *
459 * Return: 0 on success, error number otherwise.
460 */
461static int hdd_netdev_notifier_call(struct notifier_block *nb,
462 unsigned long state,
463 void *ndev)
464{
465 int ret;
466
467 cds_ssr_protect(__func__);
468 ret = __hdd_netdev_notifier_call(nb, state, ndev);
469 cds_ssr_unprotect(__func__);
470
471 return ret;
472}
473
474struct notifier_block hdd_netdev_notifier = {
475 .notifier_call = hdd_netdev_notifier_call,
476};
477
478/* variable to hold the insmod parameters */
479static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800480
481/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530484/**
485 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
486 * @ch_width: NL channel width
487 *
488 * Converts the NL channel width to the driver's internal representation
489 *
490 * Return: Converted channel width. In case of non matching NL channel width,
491 * CH_WIDTH_MAX will be returned.
492 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800493enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530494{
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800495 uint8_t fw_ch_bw;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700496
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800497 fw_ch_bw = wma_get_vht_ch_width();
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530498 switch (ch_width) {
499 case NL80211_CHAN_WIDTH_20_NOHT:
500 case NL80211_CHAN_WIDTH_20:
501 return CH_WIDTH_20MHZ;
502 case NL80211_CHAN_WIDTH_40:
503 return CH_WIDTH_40MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530504 case NL80211_CHAN_WIDTH_80:
505 return CH_WIDTH_80MHZ;
506 case NL80211_CHAN_WIDTH_80P80:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800507 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
508 return CH_WIDTH_80P80MHZ;
509 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
510 return CH_WIDTH_160MHZ;
511 else
512 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530513 case NL80211_CHAN_WIDTH_160:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800514 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
515 return CH_WIDTH_160MHZ;
516 else
517 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530518 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800519 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530520 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800521 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530522 default:
523 hdd_err("Invalid channel width %d, setting to default",
524 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800525 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530526 }
527}
528
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530529/* wlan_hdd_find_opclass() - Find operating class for a channel
530 * @hal: handler to HAL
531 * @channel: channel id
532 * @bw_offset: bandwidth offset
533 *
534 * Function invokes sme api to find the operating class
535 *
536 * Return: operating class
537 */
538uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
539 uint8_t bw_offset)
540{
541 uint8_t opclass = 0;
542
543 sme_get_opclass(hal, channel, bw_offset, &opclass);
544 return opclass;
545}
546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530548 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530549 * @module_id: Module whose trace level is being configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 * @bitmask: Bitmask of log levels to be enabled
551 *
552 * Called immediately after the cfg.ini is read in order to configure
553 * the desired trace levels.
554 *
555 * Return: None
556 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530557int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530559 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530560 int qdf_print_idx = -1;
561 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562 /*
563 * if the bitmask is the default value, then a bitmask was not
564 * specified in cfg.ini, so leave the logging level alone (it
565 * will remain at the "compiled in" default value)
566 */
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700567 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530568 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530570 qdf_print_idx = qdf_get_pidx();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530572 /* a mask was specified. start by disabling all logging */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530573 status = qdf_print_set_category_verbose(qdf_print_idx, module_id,
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530574 QDF_TRACE_LEVEL_NONE, 0);
575
576 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530577 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530579 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 while (0 != bitmask) {
581 if (bitmask & 1) {
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530582 status = qdf_print_set_category_verbose(qdf_print_idx,
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530583 module_id, level, 1);
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530584 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530585 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 level++;
589 bitmask >>= 1;
590 }
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530591 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592}
593
594/**
595 * wlan_hdd_validate_context() - check the HDD context
596 * @hdd_ctx: HDD context pointer
597 *
598 * Return: 0 if the context is valid. Error code otherwise
599 */
600int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
601{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530603 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604 return -ENODEV;
605 }
606
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800607 if (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800608 hdd_debug("%pS Recovery in Progress. State: 0x%x Ignore!!!",
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530609 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 return -EAGAIN;
611 }
612
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800613 if (cds_is_load_or_unload_in_progress()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800614 hdd_debug("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530615 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 return -EAGAIN;
617 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530618
619 if (hdd_ctx->start_modules_in_progress ||
620 hdd_ctx->stop_modules_in_progress) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800621 hdd_debug("%pS Start/Stop Modules in progress. Ignore!!!",
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530622 (void *)_RET_IP_);
623 return -EAGAIN;
624 }
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626 return 0;
627}
628
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629/**
630 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
631 * @hdd_adapter_t Hdd adapter.
632 *
633 * This function sets the IBSS power save config parameters to WMA
634 * which will send it to firmware if FW supports IBSS power save
635 * before vdev start.
636 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530637 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 * on failure.
639 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530640QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641{
642 int ret;
643 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
644
645 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700646 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530647 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 }
649
650 ret = wma_cli_set_command(adapter->sessionId,
651 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
652 hdd_ctx->config->ibssATIMWinSize,
653 VDEV_CMD);
654 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700655 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530656 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 }
658
659 ret = wma_cli_set_command(adapter->sessionId,
660 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
661 hdd_ctx->config->isIbssPowerSaveAllowed,
662 VDEV_CMD);
663 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700664 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
665 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530666 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 }
668
669 ret = wma_cli_set_command(adapter->sessionId,
670 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
671 hdd_ctx->config->
672 isIbssPowerCollapseAllowed, VDEV_CMD);
673 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700674 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
675 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 }
678
679 ret = wma_cli_set_command(adapter->sessionId,
680 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
681 hdd_ctx->config->isIbssAwakeOnTxRx,
682 VDEV_CMD);
683 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700684 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530685 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 }
687
688 ret = wma_cli_set_command(adapter->sessionId,
689 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
690 hdd_ctx->config->ibssInactivityCount,
691 VDEV_CMD);
692 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700693 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530694 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 }
696
697 ret = wma_cli_set_command(adapter->sessionId,
698 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
699 hdd_ctx->config->ibssTxSpEndInactivityTime,
700 VDEV_CMD);
701 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700702 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
703 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530704 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 }
706
707 ret = wma_cli_set_command(adapter->sessionId,
708 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
709 hdd_ctx->config->ibssPsWarmupTime,
710 VDEV_CMD);
711 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700712 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
713 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530714 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 }
716
717 ret = wma_cli_set_command(adapter->sessionId,
718 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
719 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
720 VDEV_CMD);
721 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700722 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
723 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530724 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725 }
726
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530727 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800728}
729
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730#define INTF_MACADDR_MASK 0x7
731
732/**
733 * hdd_update_macaddr() - update mac address
734 * @config: hdd configuration
735 * @hw_macaddr: mac address
736 *
737 * Mac address for multiple virtual interface is found as following
738 * i) The mac address of the first interface is just the actual hw mac address.
739 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
740 * define the mac address for the remaining interfaces and locally
741 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
742 * supported virtual interfaces, right now this is 0x07 (meaning 8
743 * interface).
744 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
745 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
746 *
747 * Return: None
748 */
749void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530750 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751{
752 int8_t i;
753 uint8_t macaddr_b3, tmp_br3;
754
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530755 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530756 QDF_MAC_ADDR_SIZE);
757 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530758 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530759 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760 macaddr_b3 = config->intfMacAddr[i].bytes[3];
761 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
762 INTF_MACADDR_MASK;
763 macaddr_b3 += tmp_br3;
764
765 /* XOR-ing bit-24 of the mac address. This will give enough
766 * mac address range before collision
767 */
768 macaddr_b3 ^= (1 << 7);
769
770 /* Set locally administered bit */
771 config->intfMacAddr[i].bytes[0] |= 0x02;
772 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800773 hdd_debug("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774 MAC_ADDRESS_STR, i,
775 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
776 }
777}
778
779static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
780 struct wma_tgt_services *cfg)
781{
782 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783
784 /* Set up UAPSD */
785 config->apUapsdEnabled &= cfg->uapsd;
786
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800787 /* 11AX mode support */
788 if ((config->dot11Mode == eHDD_DOT11_MODE_11ax ||
789 config->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY) && !cfg->en_11ax)
790 config->dot11Mode = eHDD_DOT11_MODE_11ac;
791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792 /* 11AC mode support */
793 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
794 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
795 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796
797 /* ARP offload: override user setting if invalid */
798 config->fhostArpOffload &= cfg->arp_offload;
799
800#ifdef FEATURE_WLAN_SCAN_PNO
801 /* PNO offload */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800802 hdd_debug("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800803 if (cfg->pno_offload)
804 config->PnoOffload = true;
805#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806#ifdef FEATURE_WLAN_TDLS
807 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530808 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
809 cfg->en_tdls_offchan;
810 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
811 cfg->en_tdls_uapsd_buf_sta;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700812 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 config->fEnableTDLSSleepSta = true;
Srinivas Girigowdab841da72017-03-25 18:04:39 -0700814 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 config->fEnableTDLSSleepSta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817#ifdef WLAN_FEATURE_ROAM_OFFLOAD
818 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
819#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700820 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821
822}
823
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700824/**
825 * hdd_update_vdev_nss() - sets the vdev nss
826 * @hdd_ctx: HDD context
827 *
828 * Sets the Nss per vdev type based on INI
829 *
830 * Return: None
831 */
832static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
833{
834 struct hdd_config *cfg_ini = hdd_ctx->config;
835 uint8_t max_supp_nss = 1;
836
Naveen Rawat10b1c152017-01-18 11:16:06 -0800837 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700838 max_supp_nss = 2;
839
840 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
841 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
842
843 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
844 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
845}
846
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530847/**
848 * hdd_update_hw_dbs_capable() - sets the dbs capability of the device
849 * @hdd_ctx: HDD context
850 *
851 * Sets the DBS capability as per INI and firmware capability
852 *
853 * Return: None
854 */
855static void hdd_update_hw_dbs_capable(hdd_context_t *hdd_ctx)
856{
857 struct hdd_config *cfg_ini = hdd_ctx->config;
858 uint8_t hw_dbs_capable = 0;
859
860 if ((!cfg_ini->dual_mac_feature_disable)
Archana Ramachandran62886ce2017-03-24 14:46:32 -0700861 && policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc))
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530862 hw_dbs_capable = 1;
863
864 sme_update_hw_dbs_capable(hdd_ctx->hHal, hw_dbs_capable);
865}
866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
868 struct wma_tgt_ht_cap *cfg)
869{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530870 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871 uint32_t value, val32;
872 uint16_t val16;
873 struct hdd_config *pconfig = hdd_ctx->config;
874 tSirMacHTCapabilityInfo *phtCapInfo;
875 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
876 uint8_t enable_tx_stbc;
877
878 /* check and update RX STBC */
879 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
880 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
881
882 /* get the MPDU density */
883 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
884
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530885 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700886 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800887 value = 0;
888 }
889
890 /*
891 * MPDU density:
892 * override user's setting if value is larger
893 * than the one supported by target
894 */
895 if (value > cfg->mpdu_density) {
896 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
897 cfg->mpdu_density);
898
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530899 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800900 hdd_err("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901 }
902
903 /* get the HT capability info */
904 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530905 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700906 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800907 return;
908 }
909 val16 = (uint16_t) val32;
910 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
911
912 /* Set the LDPC capability */
913 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
914
915 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
916 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
917
918 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
919 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
920
921 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
922 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
923
924 enable_tx_stbc = pconfig->enableTxSTBC;
925
926 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
927 pconfig->enable2x2 = 1;
928 } else {
929 pconfig->enable2x2 = 0;
930 enable_tx_stbc = 0;
931
932 /* 1x1 */
933 /* Update Rx Highest Long GI data Rate */
934 if (sme_cfg_set_int(hdd_ctx->hHal,
935 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700936 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530937 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700938 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 }
940
941 /* Update Tx Highest Long GI data Rate */
942 if (sme_cfg_set_int
943 (hdd_ctx->hHal,
944 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700945 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530946 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700947 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948 }
949 }
950 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
951 enable_tx_stbc = 0;
952 phtCapInfo->txSTBC = enable_tx_stbc;
953
954 val32 = val16;
955 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530956 if (status != QDF_STATUS_SUCCESS)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800957 hdd_err("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800958#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
959 value = SIZE_OF_SUPPORTED_MCS_SET;
960 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961 &value) == QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800962 hdd_debug("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963
964 if (pconfig->enable2x2) {
965 for (value = 0; value < cfg->num_rf_chains; value++)
966 mcs_set[value] =
967 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
968
969 status =
970 sme_cfg_set_str(hdd_ctx->hHal,
971 WNI_CFG_SUPPORTED_MCS_SET,
972 mcs_set,
973 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530974 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800975 hdd_err("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 }
977 }
978#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
979}
980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800981static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
982 struct wma_tgt_vht_cap *cfg)
983{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530984 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985 uint32_t value = 0;
986 struct hdd_config *pconfig = hdd_ctx->config;
987 struct wiphy *wiphy = hdd_ctx->wiphy;
988 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700989 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700990 uint32_t temp = 0;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800991 uint32_t ch_width = eHT_CHANNEL_WIDTH_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992
Dustin Brown5e06bd32016-10-04 12:49:10 -0700993 if (!band_5g) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800994 hdd_debug("5GHz band disabled, skipping capability population");
Dustin Brown5e06bd32016-10-04 12:49:10 -0700995 return;
996 }
997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998 /* Get the current MPDU length */
999 status =
1000 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1001 &value);
1002
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301003 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001004 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001005 value = 0;
1006 }
1007
1008 /*
1009 * VHT max MPDU length:
1010 * override if user configured value is too high
1011 * that the target cannot support
1012 */
1013 if (value > cfg->vht_max_mpdu) {
1014 status = sme_cfg_set_int(hdd_ctx->hHal,
1015 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1016 cfg->vht_max_mpdu);
1017
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001018 if (status == QDF_STATUS_E_FAILURE)
1019 hdd_err("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001020 }
1021
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001022 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1023 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1024
1025 if (pconfig->enable2x2)
1026 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1027
1028 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1029 QDF_STATUS_E_FAILURE) {
1030 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1031 }
1032
1033 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1034 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1035 if (pconfig->enable2x2)
1036 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1037
1038 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1039 QDF_STATUS_E_FAILURE) {
1040 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1041 }
1042
1043 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1044 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1045 if (pconfig->enable2x2)
1046 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1047
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001048 hdd_debug("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001049 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1050
1051 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1052 QDF_STATUS_E_FAILURE) {
1053 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1054 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001055 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001056 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001057 &value);
1058
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301059 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001060 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001061 value = 0;
1062 }
1063
1064 /* Set the LDPC capability */
1065 if (value && !cfg->vht_rx_ldpc) {
1066 status = sme_cfg_set_int(hdd_ctx->hHal,
1067 WNI_CFG_VHT_LDPC_CODING_CAP,
1068 cfg->vht_rx_ldpc);
1069
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001070 if (status == QDF_STATUS_E_FAILURE)
1071 hdd_err("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001072 }
1073
1074 /* Get current GI 80 value */
1075 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1076 &value);
1077
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301078 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001079 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001080 value = 0;
1081 }
1082
1083 /* set the Guard interval 80MHz */
1084 if (value && !cfg->vht_short_gi_80) {
1085 status = sme_cfg_set_int(hdd_ctx->hHal,
1086 WNI_CFG_VHT_SHORT_GI_80MHZ,
1087 cfg->vht_short_gi_80);
1088
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001089 if (status == QDF_STATUS_E_FAILURE)
1090 hdd_err("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001091 }
1092
1093 /* Get current GI 160 value */
1094 status = sme_cfg_get_int(hdd_ctx->hHal,
1095 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1096 &value);
1097
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301098 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001099 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001100 value = 0;
1101 }
1102
1103 /* Get VHT TX STBC cap */
1104 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301106 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001107 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 value = 0;
1109 }
1110
1111 /* VHT TX STBC cap */
1112 if (value && !cfg->vht_tx_stbc) {
1113 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1114 cfg->vht_tx_stbc);
1115
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001116 if (status == QDF_STATUS_E_FAILURE)
1117 hdd_err("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118 }
1119
1120 /* Get VHT RX STBC cap */
1121 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1122
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301123 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001124 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001125 value = 0;
1126 }
1127
1128 /* VHT RX STBC cap */
1129 if (value && !cfg->vht_rx_stbc) {
1130 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1131 cfg->vht_rx_stbc);
1132
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001133 if (status == QDF_STATUS_E_FAILURE)
1134 hdd_err("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135 }
1136
1137 /* Get VHT SU Beamformer cap */
1138 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1139 &value);
1140
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301141 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001142 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143 value = 0;
1144 }
1145
1146 /* set VHT SU Beamformer cap */
1147 if (value && !cfg->vht_su_bformer) {
1148 status = sme_cfg_set_int(hdd_ctx->hHal,
1149 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1150 cfg->vht_su_bformer);
1151
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001152 if (status == QDF_STATUS_E_FAILURE)
1153 hdd_err("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 }
1155
1156 /* check and update SU BEAMFORMEE capabality */
1157 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1158 pconfig->enableTxBF = cfg->vht_su_bformee;
1159
1160 status = sme_cfg_set_int(hdd_ctx->hHal,
1161 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1162 pconfig->enableTxBF);
1163
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001164 if (status == QDF_STATUS_E_FAILURE)
1165 hdd_err("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166
1167 /* Get VHT MU Beamformer cap */
1168 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1169 &value);
1170
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301171 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001172 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001173 value = 0;
1174 }
1175
1176 /* set VHT MU Beamformer cap */
1177 if (value && !cfg->vht_mu_bformer) {
1178 status = sme_cfg_set_int(hdd_ctx->hHal,
1179 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1180 cfg->vht_mu_bformer);
1181
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001182 if (status == QDF_STATUS_E_FAILURE)
1183 hdd_err("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001184 }
1185
1186 /* Get VHT MU Beamformee cap */
1187 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1188 &value);
1189
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301190 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001191 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 value = 0;
1193 }
1194
1195 /* set VHT MU Beamformee cap */
1196 if (value && !cfg->vht_mu_bformee) {
1197 status = sme_cfg_set_int(hdd_ctx->hHal,
1198 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1199 cfg->vht_mu_bformee);
1200
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001201 if (status == QDF_STATUS_E_FAILURE)
1202 hdd_err("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203 }
1204
1205 /* Get VHT MAX AMPDU Len exp */
1206 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1207 &value);
1208
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301209 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001210 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211 value = 0;
1212 }
1213
1214 /*
1215 * VHT max AMPDU len exp:
1216 * override if user configured value is too high
1217 * that the target cannot support.
1218 * Even though Rome publish ampdu_len=7, it can
1219 * only support 4 because of some h/w bug.
1220 */
1221
1222 if (value > cfg->vht_max_ampdu_len_exp) {
1223 status = sme_cfg_set_int(hdd_ctx->hHal,
1224 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1225 cfg->vht_max_ampdu_len_exp);
1226
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001227 if (status == QDF_STATUS_E_FAILURE)
1228 hdd_err("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 }
1230
1231 /* Get VHT TXOP PS CAP */
1232 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1233
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301234 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001235 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 value = 0;
1237 }
1238
1239 /* set VHT TXOP PS cap */
1240 if (value && !cfg->vht_txop_ps) {
1241 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1242 cfg->vht_txop_ps);
1243
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001244 if (status == QDF_STATUS_E_FAILURE)
1245 hdd_err("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 }
1247
1248 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1249 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1250 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1251 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1252 else
1253 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1254
1255
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001256 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1257 status = sme_cfg_set_int(hdd_ctx->hHal,
1258 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1259 VHT_CAP_160_AND_80P80_SUPP);
1260 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001261 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001262 band_5g->vht_cap.cap |=
1263 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001264 ch_width = eHT_CHANNEL_WIDTH_80P80MHZ;
1265 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1266 status = sme_cfg_set_int(hdd_ctx->hHal,
1267 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1268 VHT_CAP_160_SUPP);
1269 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001270 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 band_5g->vht_cap.cap |=
1272 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001273 ch_width = eHT_CHANNEL_WIDTH_160MHZ;
1274 }
1275 pconfig->vhtChannelWidth = QDF_MIN(pconfig->vhtChannelWidth,
1276 ch_width);
1277 /* Get the current supported chan width */
1278 status = sme_cfg_get_int(hdd_ctx->hHal,
1279 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1280 &value);
1281 if (status != QDF_STATUS_SUCCESS) {
1282 hdd_err("could not get CH BW");
1283 value = 0;
1284 }
1285 /* set the Guard interval 80MHz */
1286 if (value) {
1287 status = sme_cfg_set_int(hdd_ctx->hHal,
1288 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1289 cfg->vht_short_gi_160);
1290
1291 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001292 hdd_err("failed to set SHORT GI 80MHZ");
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001293 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294
1295 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1296 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1297
1298 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1299 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1300 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1301 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1302
1303 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1304 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1305
1306 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1307 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1308 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1309 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1310 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1311 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1312
1313 band_5g->vht_cap.cap |=
1314 (cfg->vht_max_ampdu_len_exp <<
1315 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1316
1317 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1318 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1319 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1320 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1321 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1322 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1323 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1324 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1325
1326 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1327 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1328
1329}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001331/**
1332 * hdd_generate_macaddr_auto() - Auto-generate mac address
1333 * @hdd_ctx: Pointer to the HDD context
1334 *
1335 * Auto-generate mac address using device serial number.
1336 * Keep the first 3 bytes of OUI as before and replace
1337 * the last 3 bytes with the lower 3 bytes of serial number.
1338 *
1339 * Return: 0 for success
1340 * Non zero failure code for errors
1341 */
1342static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1343{
1344 unsigned int serialno = 0;
1345 struct qdf_mac_addr mac_addr = {
1346 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1347 };
1348
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001349 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001350 if (serialno == 0)
1351 return -EINVAL;
1352
1353 serialno &= 0x00ffffff;
1354
1355 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1356 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1357 mac_addr.bytes[5] = serialno & 0xff;
1358
1359 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1360 return 0;
1361}
1362
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301363/**
1364 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1365 * configuration to cfg_ini in HDD
1366 * @hdd_ctx: Pointer to hdd_ctx
1367 * @cfg: target configuration
1368 *
1369 * Return: None
1370 */
1371#ifdef FEATURE_WLAN_RA_FILTERING
1372static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1373 struct wma_tgt_cfg *cfg)
1374{
1375 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1376}
1377#else
1378static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1379 struct wma_tgt_cfg *cfg)
1380{
1381}
1382#endif
1383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384void hdd_update_tgt_cfg(void *context, void *param)
1385{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001386 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1388 struct wma_tgt_cfg *cfg = param;
1389 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001390 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301391
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07001392 /* Reuse same pdev for module stop and start */
1393 if ((hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) ||
1394 (!cds_is_driver_loading())) {
1395 hdd_err("Reuse pdev for module start/stop");
1396 } else {
1397 ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
1398 if (ret) {
1399 hdd_err("pdev creation fails!");
1400 QDF_BUG(0);
1401 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301402 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001403 if (cds_cfg) {
1404 if (hdd_ctx->config->enable_sub_20_channel_width !=
1405 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1406 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1407 cds_cfg->sub_20_channel_width =
1408 WLAN_SUB_20_CH_WIDTH_NONE;
1409 } else {
1410 cds_cfg->sub_20_channel_width =
1411 hdd_ctx->config->enable_sub_20_channel_width;
1412 }
1413 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001414
1415 /* first store the INI band capability */
1416 temp_band_cap = hdd_ctx->config->nBandCapability;
1417
1418 hdd_ctx->config->nBandCapability = cfg->band_cap;
1419
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001420 /*
1421 * now overwrite the target band capability with INI
1422 * setting if INI setting is a subset
1423 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001424
1425 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1426 (temp_band_cap != eCSR_BAND_ALL))
1427 hdd_ctx->config->nBandCapability = temp_band_cap;
1428 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1429 (temp_band_cap != eCSR_BAND_ALL) &&
1430 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001431 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001432 }
1433
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001434 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1436 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1437 }
1438
1439 /* This can be extended to other configurations like ht, vht cap... */
1440
Anurag Chouhanc5548422016-02-24 18:33:27 +05301441 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001443 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001445 static struct qdf_mac_addr default_mac_addr = {
1446 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1447 };
1448 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1449 &default_mac_addr)) {
1450 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1451 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1452 MAC_ADDRESS_STR,
1453 MAC_ADDR_ARRAY(hdd_ctx->config->
1454 intfMacAddr[0].bytes));
1455 } else {
1456 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1457 MAC_ADDRESS_STR,
1458 MAC_ADDR_ARRAY(hdd_ctx->config->
1459 intfMacAddr[0].bytes));
1460 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001461 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 }
1463
1464 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001465 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466
1467 hdd_ctx->max_intf_count = cfg->max_intf_count;
1468
Jeff Johnsonc875e242016-09-23 18:12:34 -07001469 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001470 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001471
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1473 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1474
1475 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajaned1efd92016-09-24 18:05:47 -07001478 if (cfg->services.en_11ax) {
1479 hdd_info("11AX: 11ax is enabled - update HDD config");
1480 hdd_update_tgt_he_cap(hdd_ctx, cfg);
1481 }
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001482
1483 hdd_update_vdev_nss(hdd_ctx);
1484
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +05301485 hdd_update_hw_dbs_capable(hdd_ctx);
1486
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001487 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001488 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001489 hdd_debug("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001490 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001491
1492 hdd_ctx->current_antenna_mode =
1493 (hdd_ctx->config->enable2x2 == 0x01) ?
1494 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001495 hdd_debug("Init current antenna mode: %d",
Archana Ramachandran393f3792015-11-13 17:13:21 -08001496 hdd_ctx->current_antenna_mode);
1497
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001498 hdd_debug("Target BPF %d Host BPF %d",
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001499 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1500 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1501 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301502 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301503
Arun Khandavallid454d422016-08-17 12:47:05 +05301504 /*
1505 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1506 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1507 * configure the STA mode wow pattern.
1508 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301509 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301510 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301511
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301512 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1513
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001514 /* Configure NAN datapath features */
1515 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Arif Hussain759a0232017-03-20 13:17:18 -07001516 hdd_ctx->dfs_cac_offload = cfg->dfs_cac_offload;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001517}
1518
1519/**
1520 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1521 * @context: HDD context pointer
1522 * @param: HDD radar indication pointer
1523 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001524 * This function is invoked in atomic context when a radar
1525 * is found on the SAP current operating channel and Data Tx
1526 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001527 * Actions: Stop the netif Tx queues,Indicate Radar present
1528 * in HDD context for future usage.
1529 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301530 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001531 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301532bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533{
1534 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1535 struct wma_dfs_radar_ind *hdd_radar_event =
1536 (struct wma_dfs_radar_ind *)param;
1537 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1538 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301539 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301540 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301542 if (!hdd_ctx || !hdd_radar_event ||
1543 hdd_ctx->config->disableDFSChSwitch)
1544 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545
1546 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001547 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301548 /*
1549 * Application already triggered channel switch
1550 * on current channel, so return here.
1551 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301552 return false;
1553 }
1554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301556 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301558 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1559 if ((QDF_SAP_MODE == adapter->device_mode ||
1560 QDF_P2P_GO_MODE == adapter->device_mode) &&
1561 (CHANNEL_STATE_DFS ==
1562 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1564 dfs_cac_block_tx = true;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001565 hdd_debug("tx blocked for session:%d",
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301566 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 }
1568
1569 status = hdd_get_next_adapter(hdd_ctx,
1570 adapterNode,
1571 &pNext);
1572 adapterNode = pNext;
1573 }
1574 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301575
1576 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001578
1579/**
1580 * hdd_is_valid_mac_address() - validate MAC address
1581 * @pMacAddr: Pointer to the input MAC address
1582 *
1583 * This function validates whether the given MAC address is valid or not
1584 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1585 * where X is the hexa decimal digit character and separated by ':'
1586 * This algorithm works even if MAC address is not separated by ':'
1587 *
1588 * This code checks given input string mac contains exactly 12 hexadecimal
1589 * digits and a separator colon : appears in the input string only after
1590 * an even number of hex digits.
1591 *
1592 * Return: 1 for valid and 0 for invalid
1593 */
1594bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1595{
1596 int xdigit = 0;
1597 int separator = 0;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07001598
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599 while (*pMacAddr) {
1600 if (isxdigit(*pMacAddr)) {
1601 xdigit++;
1602 } else if (':' == *pMacAddr) {
1603 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1604 break;
1605
1606 ++separator;
1607 } else {
1608 /* Invalid MAC found */
1609 return 0;
1610 }
1611 ++pMacAddr;
1612 }
1613 return xdigit == 12 && (separator == 5 || separator == 0);
1614}
1615
1616/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301617 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1618 * @dev: Handle to struct net_device to be updated.
1619 *
1620 * Return: None
1621 */
1622static void hdd_mon_mode_ether_setup(struct net_device *dev)
1623{
1624 dev->header_ops = NULL;
1625 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1626 dev->hard_header_len = ETH_HLEN;
1627 dev->mtu = ETH_DATA_LEN;
1628 dev->addr_len = ETH_ALEN;
1629 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1630 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1631 dev->priv_flags |= IFF_TX_SKB_SHARING;
1632
1633 memset(dev->broadcast, 0xFF, ETH_ALEN);
1634}
1635
1636/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001637 * __hdd__mon_open() - HDD Open function
1638 * @dev: Pointer to net_device structure
1639 *
1640 * This is called in response to ifconfig up
1641 *
1642 * Return: 0 for success; non-zero for failure
1643 */
1644static int __hdd_mon_open(struct net_device *dev)
1645{
1646 int ret;
1647
1648 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301649 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001650 ret = hdd_set_mon_rx_cb(dev);
1651 return ret;
1652}
1653
1654/**
1655 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1656 * @dev: Pointer to net_device structure
1657 *
1658 * This is called in response to ifconfig up
1659 *
1660 * Return: 0 for success; non-zero for failure
1661 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001662static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001663{
1664 int ret;
1665
1666 cds_ssr_protect(__func__);
1667 ret = __hdd_mon_open(dev);
1668 cds_ssr_unprotect(__func__);
1669
1670 return ret;
1671}
1672
1673/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301674 * hdd_start_adapter() - Wrapper function for device specific adapter
1675 * @adapter: pointer to HDD adapter
1676 *
1677 * This function is called to start the device specific adapter for
1678 * the mode passed in the adapter's device_mode.
1679 *
1680 * Return: 0 for success; non-zero for failure
1681 */
1682int hdd_start_adapter(hdd_adapter_t *adapter)
1683{
1684
1685 int ret;
1686 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1687
1688 ENTER_DEV(adapter->dev);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001689 hdd_debug("Start_adapter for mode : %d", adapter->device_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05301690
1691 switch (device_mode) {
1692 case QDF_P2P_CLIENT_MODE:
1693 case QDF_P2P_DEVICE_MODE:
1694 case QDF_OCB_MODE:
1695 case QDF_STA_MODE:
1696 case QDF_MONITOR_MODE:
1697 ret = hdd_start_station_adapter(adapter);
1698 if (ret)
1699 goto err_start_adapter;
1700 break;
1701 case QDF_P2P_GO_MODE:
1702 case QDF_SAP_MODE:
1703 ret = hdd_start_ap_adapter(adapter);
1704 if (ret)
1705 goto err_start_adapter;
1706 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301707 case QDF_IBSS_MODE:
1708 /*
1709 * For IBSS interface is initialized as part of
1710 * hdd_init_station_mode()
1711 */
1712 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301713 case QDF_FTM_MODE:
1714 ret = hdd_start_ftm_adapter(adapter);
1715 if (ret)
1716 goto err_start_adapter;
1717 break;
1718 default:
1719 hdd_err("Invalid session type %d", device_mode);
1720 QDF_ASSERT(0);
1721 goto err_start_adapter;
1722 }
1723 if (hdd_set_fw_params(adapter))
1724 hdd_err("Failed to set the FW params for the adapter!");
1725
1726 /*
1727 * Action frame registered in one adapter which will
1728 * applicable to all interfaces
1729 */
1730 wlan_hdd_cfg80211_register_frames(adapter);
1731 EXIT();
1732 return 0;
1733err_start_adapter:
1734 return -EINVAL;
1735}
1736
1737/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301738 * hdd_enable_power_management() - API to Enable Power Management
1739 *
1740 * API invokes Bus Interface Layer power management functionality
1741 *
1742 * Return: None
1743 */
1744static void hdd_enable_power_management(void)
1745{
1746 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1747
1748 if (!hif_ctx) {
1749 hdd_err("Bus Interface Context is Invalid");
1750 return;
1751 }
1752
1753 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1754}
1755
1756/**
1757 * hdd_disable_power_management() - API to disable Power Management
1758 *
1759 * API disable Bus Interface Layer Power management functionality
1760 *
1761 * Return: None
1762 */
1763static void hdd_disable_power_management(void)
1764{
1765 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1766
1767 if (!hif_ctx) {
1768 hdd_err("Bus Interface Context is Invalid");
1769 return;
1770 }
1771
1772 hif_disable_power_management(hif_ctx);
1773}
1774
1775/**
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301776 * hdd_update_hw_sw_info() - API to update the HW/SW information
1777 *
1778 * API to update the HW and SW information in the driver
1779 *
1780 * Return: None
1781 */
1782static void hdd_update_hw_sw_info(hdd_context_t *hdd_ctx)
1783{
1784 void *hif_sc;
1785
1786 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
1787 if (!hif_sc) {
1788 hdd_err("HIF context is NULL");
1789 return;
1790 }
1791
1792 /*
1793 * target hw version/revision would only be retrieved after firmware
1794 * download
1795 */
1796 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
1797 &hdd_ctx->target_hw_revision,
1798 &hdd_ctx->target_hw_name);
1799
1800 /* Get the wlan hw/fw version */
1801 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
1802
1803 return;
1804}
1805
1806/**
gbian62edd7e2017-03-07 13:12:13 +08001807 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
1808 * @hdd_ctx: Pointer to hdd context
1809 *
1810 * Return: none
1811 */
1812static void
1813hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
1814{
1815 uint8_t num_entries = 0;
1816 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
1817 uint8_t *tx_sched_wrr_ac;
1818 int i;
1819 cds_context_type *cds_ctx;
1820
1821 if (NULL == hdd_ctx)
1822 return;
1823
1824 if (NULL == hdd_ctx->config) {
1825 /* Do nothing if hdd_ctx is invalid */
1826 hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
1827 return;
1828 }
1829
1830 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1831
1832 if (!cds_ctx) {
1833 hdd_err("Invalid CDS Context");
1834 return;
1835 }
1836
1837 for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
1838 switch (i) {
1839 case OL_TX_WMM_AC_BE:
1840 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
1841 break;
1842 case OL_TX_WMM_AC_BK:
1843 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
1844 break;
1845 case OL_TX_WMM_AC_VI:
1846 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
1847 break;
1848 case OL_TX_WMM_AC_VO:
1849 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
1850 break;
1851 default:
1852 tx_sched_wrr_ac = NULL;
1853 break;
1854 }
1855
1856 hdd_string_to_u8_array(tx_sched_wrr_ac,
1857 tx_sched_wrr_param,
1858 &num_entries,
1859 sizeof(tx_sched_wrr_param));
1860
1861 if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
1862 cds_ctx->ac_specs[i].wrr_skip_weight =
1863 tx_sched_wrr_param[0];
1864 cds_ctx->ac_specs[i].credit_threshold =
1865 tx_sched_wrr_param[1];
1866 cds_ctx->ac_specs[i].send_limit =
1867 tx_sched_wrr_param[2];
1868 cds_ctx->ac_specs[i].credit_reserve =
1869 tx_sched_wrr_param[3];
1870 cds_ctx->ac_specs[i].discard_weight =
1871 tx_sched_wrr_param[4];
1872 }
1873
1874 num_entries = 0;
1875 }
1876}
1877
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001878#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001879static enum policy_mgr_con_mode wlan_hdd_get_mode_for_non_connected_vdev(
1880 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
1881{
1882 hdd_adapter_t *adapter = NULL;
1883 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1884
1885 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
1886 if (!adapter) {
1887 hdd_err("Adapter is NULL");
1888 return PM_MAX_NUM_OF_MODE;
1889 }
1890
1891 return policy_mgr_convert_device_mode_to_qdf_type(
1892 adapter->device_mode);
1893}
1894
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001895static void hdd_register_policy_manager_callback(
1896 struct wlan_objmgr_psoc *psoc)
1897{
1898 struct policy_mgr_hdd_cbacks hdd_cbacks;
1899 hdd_cbacks.sap_restart_chan_switch_cb =
1900 sap_restart_chan_switch_cb;
1901 hdd_cbacks.wlan_hdd_get_channel_for_sap_restart =
1902 wlan_hdd_get_channel_for_sap_restart;
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001903 hdd_cbacks.get_mode_for_non_connected_vdev =
1904 wlan_hdd_get_mode_for_non_connected_vdev;
1905
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001906 if (QDF_STATUS_SUCCESS !=
1907 policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {
1908 hdd_err("HDD callback registration with policy manager failed");
1909 }
1910}
1911#else
1912static void hdd_register_policy_manager_callback(
1913 struct wlan_objmgr_psoc *psoc)
1914{
1915}
1916#endif
1917
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001918#ifdef WLAN_FEATURE_NAN_CONVERGENCE
1919static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1920{
1921 struct nan_callbacks cb_obj = {0};
1922
1923 cb_obj.ndi_open = hdd_ndi_open;
1924 cb_obj.ndi_close = hdd_ndi_close;
1925 cb_obj.ndi_start = hdd_ndi_start;
1926 cb_obj.ndi_delete = hdd_ndi_delete;
1927 cb_obj.drv_ndi_create_rsp_handler = hdd_ndi_drv_ndi_create_rsp_handler;
1928 cb_obj.drv_ndi_delete_rsp_handler = hdd_ndi_drv_ndi_delete_rsp_handler;
1929
Naveen Rawat37f62c82017-03-26 22:24:43 -07001930 cb_obj.new_peer_ind = hdd_ndp_new_peer_handler;
1931 cb_obj.get_peer_idx = hdd_ndp_get_peer_idx;
Naveen Rawatb3143ea2017-03-26 22:25:46 -07001932 cb_obj.peer_departed_ind = hdd_ndp_peer_departed_handler;
Naveen Rawat37f62c82017-03-26 22:24:43 -07001933
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001934 os_if_nan_register_hdd_callbacks(hdd_ctx->hdd_psoc, &cb_obj);
1935}
1936#else
1937static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1938{
1939}
1940#endif
1941
gbian62edd7e2017-03-07 13:12:13 +08001942/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301943 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1944 * @hdd_ctx: HDD context
1945 * @adapter: HDD adapter
1946 * @reinit: flag to indicate from SSR or normal path
1947 *
1948 * This function maintains the driver state machine it will be invoked from
1949 * startup, reinit and change interface. Depending on the driver state shall
1950 * perform the opening of the modules.
1951 *
1952 * Return: 0 for success; non-zero for failure
1953 */
1954int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1955 bool reinit)
1956{
1957 int ret;
1958 qdf_device_t qdf_dev;
1959 QDF_STATUS status;
1960 p_cds_contextType p_cds_context;
1961 bool unint = false;
1962 void *hif_ctx;
1963
1964 ENTER();
1965
1966 p_cds_context = cds_get_global_context();
1967 if (!p_cds_context) {
1968 hdd_err("Global Context is NULL");
1969 QDF_ASSERT(0);
1970 return -EINVAL;
1971 }
1972
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001973 hdd_debug("start modules called in state! :%d reinit: %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05301974 hdd_ctx->driver_status, reinit);
1975
1976 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1977 if (!qdf_dev) {
1978 hdd_err("QDF Device Context is Invalid return");
1979 return -EINVAL;
1980 }
1981
1982 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301983 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301984
1985 if (QDF_TIMER_STATE_RUNNING ==
1986 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1987
1988 hdd_set_idle_ps_config(hdd_ctx, false);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001989 hdd_debug("Interface change Timer running Stop timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05301990 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1991 }
1992
1993 switch (hdd_ctx->driver_status) {
1994 case DRIVER_MODULES_UNINITIALIZED:
1995 unint = true;
1996 /* Fall through dont add break here */
1997 case DRIVER_MODULES_CLOSED:
1998 if (!reinit && !unint) {
1999 ret = pld_power_on(qdf_dev->dev);
2000 if (ret) {
2001 hdd_err("Failed to Powerup the device: %d", ret);
2002 goto release_lock;
2003 }
2004 }
2005 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
2006 qdf_dev->bus_type,
2007 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
2008 HIF_ENABLE_TYPE_PROBE);
2009 if (ret) {
2010 hdd_err("Failed to open hif: %d", ret);
2011 goto power_down;
2012 }
2013
2014 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05302015 if (!hif_ctx) {
2016 hdd_err("hif context is null!!");
2017 goto power_down;
2018 }
2019
Arun Khandavallifae92942016-08-01 13:31:08 +05302020 status = ol_cds_init(qdf_dev, hif_ctx);
2021 if (status != QDF_STATUS_SUCCESS) {
2022 hdd_err("No Memory to Create BMI Context :%d", status);
2023 goto hif_close;
2024 }
2025
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002026 ret = hdd_update_config(hdd_ctx);
2027 if (ret) {
2028 hdd_err("Failed to update configuration :%d", ret);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302029 goto ol_cds_free;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002030 }
2031
gbian62edd7e2017-03-07 13:12:13 +08002032 hdd_update_cds_ac_specs_params(hdd_ctx);
2033
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302034 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05302035 if (!QDF_IS_STATUS_SUCCESS(status)) {
2036 hdd_err("Failed to Open CDS: %d", status);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302037 goto ol_cds_free;
Arun Khandavallifae92942016-08-01 13:31:08 +05302038 }
2039
Mukul Sharma9d797a02017-01-05 20:26:03 +05302040 /* initalize components configurations after psoc open */
2041 ret = hdd_update_components_config(hdd_ctx);
2042 if (ret) {
2043 hdd_err("Failed to update components configs :%d",
2044 ret);
2045 goto close;
2046 }
2047
Naveen Rawatcb5c5402017-03-22 10:12:19 -07002048 /*
2049 * NAN compoenet requires certian operations like, open adapter,
2050 * close adapter, etc. to be initiated by HDD, for those
2051 * register HDD callbacks with UMAC's NAN componenet.
2052 */
2053 hdd_nan_register_callbacks(hdd_ctx);
2054
Arun Khandavallifae92942016-08-01 13:31:08 +05302055 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
2056
2057 status = cds_pre_enable(hdd_ctx->pcds_context);
2058 if (!QDF_IS_STATUS_SUCCESS(status)) {
2059 hdd_err("Failed to pre-enable CDS: %d", status);
2060 goto close;
2061 }
2062
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07002063 hdd_register_policy_manager_callback(
2064 hdd_ctx->hdd_psoc);
2065
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302066 hdd_update_hw_sw_info(hdd_ctx);
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05302067 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302068
Arun Khandavallifae92942016-08-01 13:31:08 +05302069 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2070 sme_register_ftm_msg_processor(hdd_ctx->hHal,
2071 hdd_ftm_mc_process_msg);
2072 break;
2073 }
2074 if (unint) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002075 hdd_debug("In phase-1 initialization don't enable modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05302076 break;
2077 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302078
2079 if (reinit) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08002080 if (hdd_ipa_uc_ssr_reinit(hdd_ctx)) {
2081 hdd_err("HDD IPA UC reinit failed");
2082 goto close;
2083 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302084 }
2085
Arun Khandavallifae92942016-08-01 13:31:08 +05302086 /* Fall through dont add break here */
2087 case DRIVER_MODULES_OPENED:
2088 if (!adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002089 hdd_err("adapter is Null");
Arun Khandavallifae92942016-08-01 13:31:08 +05302090 goto close;
2091 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05302092 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2093 hdd_err("in ftm mode, no need to configure cds modules");
2094 break;
2095 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302096 if (hdd_configure_cds(hdd_ctx, adapter)) {
2097 hdd_err("Failed to Enable cds modules");
2098 goto close;
2099 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05302100 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05302101 hdd_info("Driver Modules Successfully Enabled");
2102 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
2103 break;
2104 case DRIVER_MODULES_ENABLED:
2105 hdd_info("Driver modules already Enabled");
2106 break;
2107 default:
2108 hdd_err("WLAN start invoked in wrong state! :%d\n",
2109 hdd_ctx->driver_status);
2110 goto release_lock;
2111 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302112 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302113 mutex_unlock(&hdd_ctx->iface_change_lock);
2114 EXIT();
2115 return 0;
2116
2117close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302118 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05302119
2120ol_cds_free:
2121 ol_cds_free();
2122
2123hif_close:
2124 hdd_hif_close(p_cds_context->pHIFContext);
2125power_down:
2126 if (!reinit && !unint)
2127 pld_power_off(qdf_dev->dev);
2128release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302129 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302130 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302131 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05302132 return -EINVAL;
2133}
2134
Naveen Rawat910726a2017-03-06 11:42:51 -08002135#ifdef WIFI_POS_CONVERGED
2136static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2137{
2138 int ret = os_if_wifi_pos_register_nl();
2139
2140 if (ret)
2141 hdd_err("os_if_wifi_pos_register_nl failed");
2142
2143 return ret;
2144}
2145
2146static int hdd_deactivate_wifi_pos(void)
2147{
2148 int ret = os_if_wifi_pos_deregister_nl();
2149
2150 if (ret)
2151 hdd_err("os_if_wifi_pos_deregister_nl failed");
2152
2153 return ret;
2154}
2155
2156/**
2157 * hdd_populate_wifi_pos_cfg - populates wifi_pos parameters
2158 * @hdd_ctx: hdd context
2159 *
2160 * Return: status of operation
2161 */
2162static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2163{
2164 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2165 struct hdd_config *cfg = hdd_ctx->config;
2166
2167 wifi_pos_set_oem_target_type(psoc, hdd_ctx->target_type);
2168 wifi_pos_set_oem_fw_version(psoc, hdd_ctx->target_fw_version);
2169 wifi_pos_set_drv_ver_major(psoc, QWLAN_VERSION_MAJOR);
2170 wifi_pos_set_drv_ver_minor(psoc, QWLAN_VERSION_MINOR);
2171 wifi_pos_set_drv_ver_patch(psoc, QWLAN_VERSION_PATCH);
2172 wifi_pos_set_drv_ver_build(psoc, QWLAN_VERSION_BUILD);
2173 wifi_pos_set_dwell_time_min(psoc, cfg->nNeighborScanMinChanTime);
2174 wifi_pos_set_dwell_time_max(psoc, cfg->nNeighborScanMaxChanTime);
2175}
2176#else
2177static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2178{
2179 return oem_activate_service(hdd_ctx);
2180}
2181
2182static int hdd_deactivate_wifi_pos(void)
2183{
2184 return 0;
2185}
2186
2187static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2188{
2189}
2190#endif
2191
Arun Khandavallifae92942016-08-01 13:31:08 +05302192/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 * __hdd_open() - HDD Open function
2194 * @dev: Pointer to net_device structure
2195 *
2196 * This is called in response to ifconfig up
2197 *
2198 * Return: 0 for success; non-zero for failure
2199 */
2200static int __hdd_open(struct net_device *dev)
2201{
2202 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2203 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2204 int ret;
2205
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002206 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302207 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05302208 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209
2210 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302211 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214
Arun Khandavallifae92942016-08-01 13:31:08 +05302215 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
2216 if (ret) {
2217 hdd_err("Failed to start WLAN modules return");
2218 return -ret;
2219 }
2220
2221
2222 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2223 ret = hdd_start_adapter(adapter);
2224 if (ret) {
2225 hdd_err("Failed to start adapter :%d",
2226 adapter->device_mode);
2227 return ret;
2228 }
2229 }
2230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002231 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2232 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302233 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 /* Enable TX queues only when we are connected */
2235 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05302236 WLAN_START_ALL_NETIF_QUEUE,
2237 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238 }
2239
Naveen Rawat286def52016-09-23 15:38:02 -07002240 /* Enable carrier and transmit queues for NDI */
2241 if (WLAN_HDD_IS_NDI(adapter)) {
2242 hdd_notice("Enabling Tx Queues");
2243 wlan_hdd_netif_queue_control(adapter,
2244 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
2245 WLAN_CONTROL_PATH);
2246 }
2247
Naveen Rawat910726a2017-03-06 11:42:51 -08002248 hdd_populate_wifi_pos_cfg(hdd_ctx);
2249
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002250 return ret;
2251}
2252
Arun Khandavallifae92942016-08-01 13:31:08 +05302253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254/**
2255 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
2256 * @dev: Pointer to net_device structure
2257 *
2258 * This is called in response to ifconfig up
2259 *
2260 * Return: 0 for success; non-zero for failure
2261 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002262static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002263{
2264 int ret;
2265
2266 cds_ssr_protect(__func__);
2267 ret = __hdd_open(dev);
2268 cds_ssr_unprotect(__func__);
2269
2270 return ret;
2271}
2272
2273/**
2274 * __hdd_stop() - HDD stop function
2275 * @dev: Pointer to net_device structure
2276 *
2277 * This is called in response to ifconfig down
2278 *
2279 * Return: 0 for success; non-zero for failure
2280 */
2281static int __hdd_stop(struct net_device *dev)
2282{
2283 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2284 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2285 int ret;
2286
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002287 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002288
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302289 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290 adapter->sessionId, adapter->device_mode));
2291
2292 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302293 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295
2296 /* Nothing to be done if the interface is not opened */
2297 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002298 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002299 return -ENODEV;
2300 }
2301
2302 /* Make sure the interface is marked as closed */
2303 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002304 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002305
2306 /*
2307 * Disable TX on the interface, after this hard_start_xmit() will not
2308 * be called on that interface
2309 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002310 hdd_notice("Disabling queues");
Himanshu Agarwal865201d2017-04-12 15:45:31 +05302311 wlan_hdd_netif_queue_control(adapter,
2312 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
2313 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314
2315 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002316 * NAN data interface is different in some sense. The traffic on NDI is
2317 * bursty in nature and depends on the need to transfer. The service
2318 * layer may down the interface after the usage and up again when
2319 * required. In some sense, the NDI is expected to be available
2320 * (like SAP) iface until NDI delete request is issued by the service
2321 * layer. Skip BSS termination and adapter deletion for NAN Data
2322 * interface (NDI).
2323 */
2324 if (WLAN_HDD_IS_NDI(adapter))
2325 return 0;
2326
2327 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 * The interface is marked as down for outside world (aka kernel)
2329 * But the driver is pretty much alive inside. The driver needs to
2330 * tear down the existing connection on the netdev (session)
2331 * cleanup the data pipes and wait until the control plane is stabilized
2332 * for this interface. The call also needs to wait until the above
2333 * mentioned actions are completed before returning to the caller.
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002334 * Notice that hdd_stop_adapter is requested not to close the session
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 * That is intentional to be able to scan if it is a STA/P2P interface
2336 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302337 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338
2339 /* DeInit the adapter. This ensures datapath cleanup as well */
2340 hdd_deinit_adapter(hdd_ctx, adapter, true);
2341
Arun Khandavallifae92942016-08-01 13:31:08 +05302342
2343 /*
2344 * Find if any iface is up. If any iface is up then can't put device to
2345 * sleep/power save mode
2346 */
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05302347 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002348 hdd_debug("Closing all modules from the hdd_stop");
Arun Khandavallifae92942016-08-01 13:31:08 +05302349 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2350 hdd_ctx->config->iface_change_wait_time
2351 * 50000);
2352 }
2353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 EXIT();
2355 return 0;
2356}
2357
2358/**
2359 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2360 * @dev: pointer to net_device structure
2361 *
2362 * This is called in response to ifconfig down
2363 *
2364 * Return: 0 for success and error number for failure
2365 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002366static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367{
2368 int ret;
2369
2370 cds_ssr_protect(__func__);
2371 ret = __hdd_stop(dev);
2372 cds_ssr_unprotect(__func__);
2373
2374 return ret;
2375}
2376
2377/**
2378 * __hdd_uninit() - HDD uninit function
2379 * @dev: Pointer to net_device structure
2380 *
2381 * This is called during the netdev unregister to uninitialize all data
2382 * associated with the device
2383 *
2384 * Return: None
2385 */
2386static void __hdd_uninit(struct net_device *dev)
2387{
2388 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2389
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002390 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391
2392 do {
2393 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002394 hdd_err("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 break;
2396 }
2397
2398 if (NULL == adapter->pHddCtx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002399 hdd_err("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 break;
2401 }
2402
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002403 if (dev != adapter->dev)
2404 hdd_err("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405
2406 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2407
2408 /* after uninit our adapter structure will no longer be valid */
2409 adapter->dev = NULL;
2410 adapter->magic = 0;
2411 } while (0);
2412
2413 EXIT();
2414}
2415
2416/**
2417 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2418 * @dev: pointer to net_device structure
2419 *
2420 * This is called during the netdev unregister to uninitialize all data
2421 * associated with the device
2422 *
2423 * Return: none
2424 */
2425static void hdd_uninit(struct net_device *dev)
2426{
2427 cds_ssr_protect(__func__);
2428 __hdd_uninit(dev);
2429 cds_ssr_unprotect(__func__);
2430}
2431
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002432static int hdd_open_cesium_nl_sock(void)
2433{
2434#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2435 struct netlink_kernel_cfg cfg = {
2436 .groups = WLAN_NLINK_MCAST_GRP_ID,
2437 .input = NULL
2438 };
2439#endif
2440 int ret = 0;
2441
2442#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2443 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2444#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2445 THIS_MODULE,
2446#endif
2447 &cfg);
2448#else
2449 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2450 WLAN_NLINK_MCAST_GRP_ID,
2451 NULL, NULL, THIS_MODULE);
2452#endif
2453
2454 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002455 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002456 ret = -ECONNREFUSED;
2457 }
2458
2459 return ret;
2460}
2461
2462static void hdd_close_cesium_nl_sock(void)
2463{
2464 if (NULL != cesium_nl_srv_sock) {
2465 netlink_kernel_release(cesium_nl_srv_sock);
2466 cesium_nl_srv_sock = NULL;
2467 }
2468}
2469
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470/**
2471 * __hdd_set_mac_address() - set the user specified mac address
2472 * @dev: Pointer to the net device.
2473 * @addr: Pointer to the sockaddr.
2474 *
2475 * This function sets the user specified mac address using
2476 * the command ifconfig wlanX hw ether <mac adress>.
2477 *
2478 * Return: 0 for success, non zero for failure
2479 */
2480static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2481{
2482 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2483 hdd_context_t *hdd_ctx;
2484 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302485 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 int ret;
2487
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002488 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489
2490 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2491 ret = wlan_hdd_validate_context(hdd_ctx);
2492 if (0 != ret)
2493 return ret;
2494
2495 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2496 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2497
2498 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302499 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002500}
2501
2502/**
2503 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2504 * function from SSR
2505 * @dev: pointer to net_device structure
2506 * @addr: Pointer to the sockaddr
2507 *
2508 * This function sets the user specified mac address using
2509 * the command ifconfig wlanX hw ether <mac adress>.
2510 *
2511 * Return: 0 for success.
2512 */
2513static int hdd_set_mac_address(struct net_device *dev, void *addr)
2514{
2515 int ret;
2516
2517 cds_ssr_protect(__func__);
2518 ret = __hdd_set_mac_address(dev, addr);
2519 cds_ssr_unprotect(__func__);
2520
2521 return ret;
2522}
2523
2524uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2525{
2526 int i;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002527
Anurag Chouhan6d760662016-02-20 16:05:43 +05302528 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2530 break;
2531 }
2532
Anurag Chouhan6d760662016-02-20 16:05:43 +05302533 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 return NULL;
2535
2536 hdd_ctx->config->intfAddrMask |= (1 << i);
2537 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2538}
2539
2540void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2541{
2542 int i;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002543
Anurag Chouhan6d760662016-02-20 16:05:43 +05302544 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 if (!memcmp(releaseAddr,
2546 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2547 6)) {
2548 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2549 break;
2550 }
2551 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552}
2553
2554#ifdef WLAN_FEATURE_PACKET_FILTERING
2555/**
2556 * __hdd_set_multicast_list() - set the multicast address list
2557 * @dev: Pointer to the WLAN device.
2558 * @skb: Pointer to OS packet (sk_buff).
2559 *
2560 * This funciton sets the multicast address list.
2561 *
2562 * Return: None
2563 */
2564static void __hdd_set_multicast_list(struct net_device *dev)
2565{
2566 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 int i = 0, status;
2568 struct netdev_hw_addr *ha;
2569 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302570 struct pmo_mc_addr_list_params *mc_list_request = NULL;
2571 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2572 int mc_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002574 ENTER_DEV(dev);
Anurag Chouhan6d760662016-02-20 16:05:43 +05302575 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302576 goto out;
Mukul Sharma51c44942015-10-30 19:30:19 +05302577
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302579 if (0 != status)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302580 goto out;
2581
2582 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
2583 if (!mc_list_request) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002584 hdd_err("Cannot allocate mc_list_request");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302585 goto out;
2586 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587
2588 if (dev->flags & IFF_ALLMULTI) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002589 hdd_debug("allow all multicast frames");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302590 hdd_disable_and_flush_mc_addr_list(adapter,
2591 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 } else {
2593 mc_count = netdev_mc_count(dev);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302594 if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002595 hdd_debug("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302596 pmo_ucfg_max_mc_addr_supported(psoc));
2597 hdd_disable_and_flush_mc_addr_list(adapter,
2598 pmo_mc_list_change_notify);
2599 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601 netdev_for_each_mc_addr(ha, dev) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002602 hdd_debug("ha_addr[%d] "MAC_ADDRESS_STR,
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302603 i, MAC_ADDR_ARRAY(ha->addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 if (i == mc_count)
2605 break;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302606 memset(&(mc_list_request->mc_addr[i].bytes),
2607 0, ETH_ALEN);
2608 memcpy(&(mc_list_request->mc_addr[i].bytes),
2609 ha->addr, ETH_ALEN);
2610 hdd_info("mlist[%d] = %pM", i,
2611 mc_list_request->mc_addr[i].bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 i++;
2613 }
2614 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302615
2616 mc_list_request->psoc = psoc;
2617 mc_list_request->vdev_id = adapter->sessionId;
2618 mc_list_request->count = mc_count;
2619 status = hdd_cache_mc_addr_list(mc_list_request);
2620 if (status == 0) {
2621 hdd_enable_mc_addr_filtering(adapter,
2622 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002623 } else {
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302624 hdd_err("error while caching mc list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302626out:
2627 if (mc_list_request)
2628 qdf_mem_free(mc_list_request);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302629 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630}
2631
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633/**
2634 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2635 * @dev: pointer to net_device
2636 *
2637 * Return: none
2638 */
2639static void hdd_set_multicast_list(struct net_device *dev)
2640{
2641 cds_ssr_protect(__func__);
2642 __hdd_set_multicast_list(dev);
2643 cds_ssr_unprotect(__func__);
2644}
2645#endif
2646
2647/**
2648 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2649 * @dev: Pointer to the WLAN device.
2650 * @skb: Pointer to OS packet (sk_buff).
2651 *
2652 * This function is registered with the Linux OS for network
2653 * core to decide which queue to use first.
2654 *
2655 * Return: ac, Queue Index/access category corresponding to UP in IP header
2656 */
2657static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2658#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2659 , void *accel_priv
2660#endif
2661#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2662 , select_queue_fallback_t fallback
2663#endif
2664)
2665{
2666 return hdd_wmm_select_queue(dev, skb);
2667}
2668
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002669static const struct net_device_ops wlan_drv_ops = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 .ndo_open = hdd_open,
2671 .ndo_stop = hdd_stop,
2672 .ndo_uninit = hdd_uninit,
2673 .ndo_start_xmit = hdd_hard_start_xmit,
2674 .ndo_tx_timeout = hdd_tx_timeout,
2675 .ndo_get_stats = hdd_get_stats,
2676 .ndo_do_ioctl = hdd_ioctl,
2677 .ndo_set_mac_address = hdd_set_mac_address,
2678 .ndo_select_queue = hdd_select_queue,
2679#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681#endif
2682};
2683
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002684/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
Srinivas Girigowdab841da72017-03-25 18:04:39 -07002685static const struct net_device_ops wlan_mon_drv_ops = {
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002686 .ndo_open = hdd_mon_open,
2687 .ndo_stop = hdd_stop,
2688 .ndo_get_stats = hdd_get_stats,
2689};
2690
2691/**
2692 * hdd_set_station_ops() - update net_device ops for monitor mode
2693 * @pWlanDev: Handle to struct net_device to be updated.
2694 * Return: None
2695 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696void hdd_set_station_ops(struct net_device *pWlanDev)
2697{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002698 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2699 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2700 else
2701 pWlanDev->netdev_ops = &wlan_drv_ops;
2702}
2703
Komal Seelama89be8d2016-09-29 11:09:26 +05302704#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302705/**
2706 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2707 * @hdd_ctx: HDD context
2708 *
2709 * Return: None
2710 */
2711static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2712{
2713 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2714
2715 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302716 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302717 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302718}
2719
2720/**
2721 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2722 * @hdd_ctx: HDD Context
2723 *
2724 * Return: None
2725 */
2726static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2727{
2728 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2729
2730 qdf_runtime_lock_deinit(ctx->scan);
2731 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302732 qdf_runtime_lock_deinit(ctx->roc);
2733 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302734 qdf_runtime_lock_deinit(ctx->dfs);
2735 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302736}
2737
Komal Seelama89be8d2016-09-29 11:09:26 +05302738static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2739{
2740 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2741
2742 ctx->connect = qdf_runtime_lock_init("connect");
2743}
2744
2745static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2746{
2747 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2748
2749 qdf_runtime_lock_deinit(ctx->connect);
2750 ctx->connect = NULL;
2751}
2752#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302753static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2754static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302755static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2756static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2757#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002758/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002759 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2760 * @hdd_ctx: global hdd context
2761 * @macAddr: mac address to assign to the interface
2762 * @name: User-visible name of the interface
2763 *
2764 * hdd adapter pointer would point to the netdev->priv space, this function
2765 * would retrive the pointer, and setup the hdd adapter configuration.
2766 *
2767 * Return: the pointer to hdd adapter, otherwise NULL
2768 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2770 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002771 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 const char *name)
2773{
2774 struct net_device *pWlanDev = NULL;
2775 hdd_adapter_t *adapter = NULL;
2776 /*
2777 * cfg80211 initialization and registration....
2778 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002779 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2780#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2781 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002783 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2784 hdd_mon_mode_ether_setup : ether_setup),
2785 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786
2787 if (pWlanDev != NULL) {
2788
2789 /* Save the pointer to the net_device in the HDD adapter */
2790 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2791
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302792 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793
2794 adapter->dev = pWlanDev;
2795 adapter->pHddCtx = hdd_ctx;
2796 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302797 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798
2799 init_completion(&adapter->session_open_comp_var);
2800 init_completion(&adapter->session_close_comp_var);
2801 init_completion(&adapter->disconnect_comp_var);
2802 init_completion(&adapter->linkup_event_var);
2803 init_completion(&adapter->cancel_rem_on_chan_var);
2804 init_completion(&adapter->rem_on_chan_ready_event);
2805 init_completion(&adapter->sta_authorized_event);
2806 init_completion(&adapter->offchannel_tx_event);
2807 init_completion(&adapter->tx_action_cnf_event);
2808#ifdef FEATURE_WLAN_TDLS
2809 init_completion(&adapter->tdls_add_station_comp);
2810 init_completion(&adapter->tdls_del_station_comp);
2811 init_completion(&adapter->tdls_mgmt_comp);
2812 init_completion(&adapter->tdls_link_establish_req_comp);
2813#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002814 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002815 init_completion(&adapter->change_country_code);
2816
2817
2818 init_completion(&adapter->scan_info.abortscan_event_var);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05302819 init_completion(&adapter->lfr_fw_status.disable_lfr_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820
2821 adapter->offloads_configured = false;
2822 adapter->isLinkUpSvcNeeded = false;
2823 adapter->higherDtimTransition = true;
2824 /* Init the net_device structure */
2825 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2826
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302827 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302829 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 sizeof(tSirMacAddr));
2831 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832
2833 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2834 pWlanDev->features |=
2835 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2836 pWlanDev->features |= NETIF_F_RXCSUM;
2837
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002838 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2839
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 hdd_set_station_ops(adapter->dev);
2841
2842 pWlanDev->destructor = free_netdev;
2843 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002844 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002845 adapter->wdev.wiphy = hdd_ctx->wiphy;
2846 adapter->wdev.netdev = pWlanDev;
2847 /* set pWlanDev's parent to underlying device */
2848 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2849 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302850 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302852 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002853 }
2854
2855 return adapter;
2856}
2857
Jeff Johnson590e2012016-10-05 16:16:24 -07002858static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2859 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002860{
2861 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002863 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002864 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2865 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002866 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302867 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002868 }
2869 }
2870 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002871 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302872 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002873 }
2874 } else {
2875 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002876 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302877 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002878 }
2879 }
2880 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2881
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302882 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883}
2884
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002885QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886{
2887 hdd_adapter_t *adapter = pContext;
2888
2889 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002890 hdd_err("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302891 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 }
2893
2894 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002895 hdd_err("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302896 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 }
2898
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002899 /*
2900 * For NAN Data interface, the close session results in the final
2901 * indication to the userspace
2902 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002903 if (adapter->device_mode == QDF_NDI_MODE)
2904 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002906 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2907
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002908 /*
2909 * We can be blocked while waiting for scheduled work to be
2910 * flushed, and the adapter structure can potentially be freed, in
2911 * which case the magic will have been reset. So make sure the
2912 * magic is still good, and hence the adapter structure is still
2913 * valid, before signaling completion
2914 */
2915 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2916 complete(&adapter->session_close_comp_var);
2917
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302918 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919}
2920
Krunal Soni8c37e322016-02-03 16:08:37 -08002921/**
2922 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2923 * @adapter: pointer to device adapter
Krunal Soni8c37e322016-02-03 16:08:37 -08002924 *
2925 * This routine will check the mode of adapter and if it is required then it
2926 * will initialize the TDLS operations
2927 *
2928 * Return: QDF_STATUS
2929 */
2930#ifdef FEATURE_WLAN_TDLS
Dustin Brownd28772b2017-03-17 14:16:07 -07002931static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002932{
Dustin Brownd28772b2017-03-17 14:16:07 -07002933 if (adapter->device_mode == QDF_IBSS_MODE)
2934 return QDF_STATUS_SUCCESS;
2935
2936 if (wlan_hdd_tdls_init(adapter)) {
2937 hdd_err("wlan_hdd_tdls_init failed");
2938 return QDF_STATUS_E_FAILURE;
Krunal Soni8c37e322016-02-03 16:08:37 -08002939 }
Dustin Brownd28772b2017-03-17 14:16:07 -07002940 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2941
Krunal Soni8c37e322016-02-03 16:08:37 -08002942 return QDF_STATUS_SUCCESS;
2943}
2944#else
Dustin Brownd28772b2017-03-17 14:16:07 -07002945static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002946{
2947 return QDF_STATUS_SUCCESS;
2948}
2949#endif
2950
Dustin Brownd28772b2017-03-17 14:16:07 -07002951int hdd_vdev_ready(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952{
Dustin Brownd28772b2017-03-17 14:16:07 -07002953 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954
Dustin Brownd28772b2017-03-17 14:16:07 -07002955 status = pmo_vdev_ready(adapter->hdd_vdev);
2956
2957 return qdf_status_to_os_return(status);
2958}
2959
2960int hdd_vdev_destroy(hdd_adapter_t *adapter)
2961{
2962 QDF_STATUS status;
2963 int errno;
2964 hdd_context_t *hdd_ctx;
2965 unsigned long rc;
2966
2967 hdd_info("destroying vdev %d", adapter->sessionId);
2968
2969 /* vdev created sanity check */
2970 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2971 hdd_err("vdev for Id %d does not exist", adapter->sessionId);
2972 return -EINVAL;
2973 }
2974
Dustin Brown0d2eeae2017-03-24 15:21:32 -07002975 /* do vdev logical destroy via objmgr */
2976 errno = hdd_objmgr_destroy_vdev(adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07002977 if (errno) {
2978 hdd_err("failed to destroy objmgr vdev: %d", errno);
2979 return errno;
2980 }
2981
2982 /* close sme session (destroy vdev in firmware via legacy API) */
2983 INIT_COMPLETION(adapter->session_close_comp_var);
2984 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2985 status = sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2986 hdd_sme_close_session_callback, adapter);
2987 if (QDF_IS_STATUS_ERROR(status)) {
2988 hdd_err("failed to close sme session: %d", status);
2989 return qdf_status_to_os_return(status);
2990 }
2991
2992 /* block on a completion variable until sme session is closed */
2993 rc = wait_for_completion_timeout(
2994 &adapter->session_close_comp_var,
2995 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2996 if (!rc) {
2997 hdd_err("timed out waiting for close sme session: %ld", rc);
2998 if (adapter->device_mode == QDF_NDI_MODE)
2999 hdd_ndp_session_end_handler(adapter);
3000 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
3001 return -ETIMEDOUT;
3002 }
3003
Dustin Brown0d2eeae2017-03-24 15:21:32 -07003004 /* now that sme session is closed, allow physical vdev destroy */
3005 errno = hdd_objmgr_release_vdev(adapter);
3006 if (errno) {
3007 hdd_err("failed to release objmgr vdev: %d", errno);
3008 return errno;
3009 }
3010
Dustin Brownd28772b2017-03-17 14:16:07 -07003011 hdd_info("vdev destroyed successfully");
3012
3013 return 0;
3014}
3015
3016int hdd_vdev_create(hdd_adapter_t *adapter)
3017{
3018 QDF_STATUS status;
3019 int errno;
3020 hdd_context_t *hdd_ctx;
3021 uint32_t type;
3022 uint32_t sub_type;
3023 unsigned long rc;
3024
3025 hdd_info("creating new vdev");
3026
3027 /* determine vdev (sub)type */
3028 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303029 if (QDF_STATUS_SUCCESS != status) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003030 hdd_err("failed to get vdev type: %d", status);
3031 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003032 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003033
3034 /* do vdev create via objmgr */
3035 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown7d043f62017-03-27 12:07:36 -07003036 errno = hdd_objmgr_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07003037 if (errno) {
3038 hdd_err("failed to create objmgr vdev: %d", errno);
3039 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003041
3042 /* Open a SME session (prepare vdev in firmware via legacy API) */
3043 INIT_COMPLETION(adapter->session_open_comp_var);
3044 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
3045 (uint8_t *)&adapter->macAddressCurrent,
3046 adapter->sessionId, type, sub_type);
3047 if (QDF_IS_STATUS_ERROR(status)) {
3048 hdd_err("failed to open sme session: %d", status);
3049 errno = qdf_status_to_os_return(status);
3050 goto objmgr_vdev_destroy;
3051 }
3052
3053 /* block on a completion variable until sme session is opened */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 rc = wait_for_completion_timeout(
3055 &adapter->session_open_comp_var,
3056 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3057 if (!rc) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003058 hdd_err("timed out waiting for open sme session: %ld", rc);
3059 errno = -ETIMEDOUT;
3060 goto objmgr_vdev_destroy;
3061 }
3062
3063 /* firmware ready for component communication, raise vdev_ready event */
3064 errno = hdd_vdev_ready(adapter);
3065 if (errno) {
3066 hdd_err("failed to dispatch vdev ready event: %d", errno);
3067 goto hdd_vdev_destroy;
3068 }
3069
3070 hdd_info("vdev %d created successfully", adapter->sessionId);
3071
3072 return 0;
3073
3074 /*
3075 * Due to legacy constraints, we need to destroy in the same order as
3076 * create. So, split error handling into 2 cases to accommodate.
3077 */
3078
3079objmgr_vdev_destroy:
Dustin Brown7d043f62017-03-27 12:07:36 -07003080 QDF_BUG(!hdd_objmgr_release_and_destroy_vdev(adapter));
Dustin Brownd28772b2017-03-17 14:16:07 -07003081
3082 return errno;
3083
3084hdd_vdev_destroy:
3085 QDF_BUG(!hdd_vdev_destroy(adapter));
3086
3087 return errno;
3088}
3089
3090QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
3091{
3092 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
3093 hdd_context_t *hdd_ctx;
3094 QDF_STATUS status;
3095 int ret_val;
3096
3097 ret_val = hdd_vdev_create(adapter);
3098 if (ret_val) {
3099 hdd_err("failed to create vdev: %d", ret_val);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303100 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101 }
3102
Dustin Brownd28772b2017-03-17 14:16:07 -07003103 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3104 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
3105 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Naveen Rawata410c5a2016-09-19 14:22:33 -07003106 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Dustin Brownd28772b2017-03-17 14:16:07 -07003107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003108 /* Register wireless extensions */
Dustin Brownd28772b2017-03-17 14:16:07 -07003109 status = hdd_register_wext(adapter->dev);
3110 if (QDF_IS_STATUS_ERROR(status)) {
3111 hdd_err("failed to register wireless extensions: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 goto error_register_wext;
3113 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 /* Set the Connection State to Not Connected */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003116 hdd_debug("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003117 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3118
Deepak Dhamdherea2785822016-11-17 01:17:45 -08003119 /* set fast roaming capability in sme session */
3120 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
3121 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122 /* Set the default operation channel */
3123 pHddStaCtx->conn_info.operationChannel =
3124 hdd_ctx->config->OperatingChannel;
3125
3126 /* Make the default Auth Type as OPEN */
3127 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3128
3129 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303130 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003131 hdd_err("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003132 status, status);
3133 goto error_init_txrx;
3134 }
3135
3136 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3137
3138 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303139 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003140 hdd_err("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 status, status);
3142 goto error_wmm_init;
3143 }
3144
3145 set_bit(WMM_INIT_DONE, &adapter->event_flags);
3146
3147 ret_val = wma_cli_set_command(adapter->sessionId,
3148 WMI_PDEV_PARAM_BURST_ENABLE,
3149 hdd_ctx->config->enableSifsBurst,
3150 PDEV_CMD);
Dustin Brownd28772b2017-03-17 14:16:07 -07003151 if (ret_val)
3152 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003153
Dustin Brownd28772b2017-03-17 14:16:07 -07003154 status = hdd_check_and_init_tdls(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08003155 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303158 status = hdd_lro_enable(hdd_ctx, adapter);
3159 if (status != QDF_STATUS_SUCCESS)
3160 goto error_lro_enable;
3161
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303162 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303164error_lro_enable:
3165 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166error_tdls_init:
3167 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3168 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169error_wmm_init:
3170 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3171 hdd_deinit_tx_rx(adapter);
3172error_init_txrx:
Dustin Brownd28772b2017-03-17 14:16:07 -07003173 hdd_unregister_wext(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174error_register_wext:
Dustin Brownd28772b2017-03-17 14:16:07 -07003175 QDF_BUG(!hdd_vdev_destroy(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177 return status;
3178}
3179
3180void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
3181{
3182 hdd_cfg80211_state_t *cfgState;
3183
3184 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3185
3186 if (NULL != cfgState->buf) {
3187 unsigned long rc;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003188
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189 rc = wait_for_completion_timeout(
3190 &adapter->tx_action_cnf_event,
3191 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3192 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003193 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05303194 /*
3195 * Inform tx status as FAILURE to upper layer and free
3196 * cfgState->buf
3197 */
3198 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199 }
3200 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201}
3202
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303203/**
3204 * hdd_station_adapter_deinit() - De-initialize the station adapter
3205 * @hdd_ctx: global hdd context
3206 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07003207 * @rtnl_held: Used to indicate whether or not the caller is holding
3208 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303209 *
3210 * This function De-initializes the STA/P2P/OCB adapter.
3211 *
3212 * Return: None.
3213 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003214static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
3215 hdd_adapter_t *adapter,
3216 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303217{
3218 ENTER_DEV(adapter->dev);
3219
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303220 if (adapter->dev) {
3221 if (rtnl_held)
3222 adapter->dev->wireless_handlers = NULL;
3223 else {
3224 rtnl_lock();
3225 adapter->dev->wireless_handlers = NULL;
3226 rtnl_unlock();
3227 }
3228 }
3229
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303230 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
3231 hdd_deinit_tx_rx(adapter);
3232 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3233 }
3234
3235 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3236 hdd_wmm_adapter_close(adapter);
3237 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3238 }
3239
3240 hdd_cleanup_actionframe(hdd_ctx, adapter);
3241 wlan_hdd_tdls_exit(adapter);
3242
3243 EXIT();
3244}
3245
3246/**
3247 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
3248 * @hdd_ctx: global hdd context
3249 * @adapter: HDD adapter
3250 * @rtnl_held: the rtnl lock hold flag
3251 * This function De-initializes the AP/P2PGo adapter.
3252 *
3253 * Return: None.
3254 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003255static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
3256 hdd_adapter_t *adapter,
3257 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303258{
3259 ENTER_DEV(adapter->dev);
3260
3261 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3262 hdd_wmm_adapter_close(adapter);
3263 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3264 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003265 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303266
3267 hdd_cleanup_actionframe(hdd_ctx, adapter);
3268
3269 hdd_unregister_hostapd(adapter, rtnl_held);
3270
3271 EXIT();
3272}
3273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3275 bool rtnl_held)
3276{
3277 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303278
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003280 case QDF_STA_MODE:
3281 case QDF_P2P_CLIENT_MODE:
3282 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003283 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303284 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285 break;
3286 }
3287
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003288 case QDF_SAP_MODE:
3289 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290 {
3291
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303292 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003293 break;
3294 }
3295
3296 default:
3297 break;
3298 }
3299
3300 EXIT();
3301}
3302
Jeff Johnson590e2012016-10-05 16:16:24 -07003303static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3304 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305{
3306 struct net_device *pWlanDev = NULL;
3307
3308 if (adapter)
3309 pWlanDev = adapter->dev;
3310 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003311 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 return;
3313 }
3314
Rajeev Kumardca5f812016-02-04 17:28:06 -08003315 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303316
3317 if (adapter->scan_info.default_scan_ies) {
3318 qdf_mem_free(adapter->scan_info.default_scan_ies);
3319 adapter->scan_info.default_scan_ies = NULL;
3320 }
3321
Komal Seelama89be8d2016-09-29 11:09:26 +05303322 hdd_adapter_runtime_suspend_denit(adapter);
3323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003324 /*
3325 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
3326 * the driver is almost closed and cannot handle either control
3327 * messages or data. However, unregister_netdevice() call above will
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003328 * eventually invoke hdd_stop(ndo_close) driver callback, which attempts
3329 * to close the active connections(basically excites control path) which
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003330 * is not right. Setting this flag helps hdd_stop() to recognize that
3331 * the interface is closed and restricts any operations on that
3332 */
3333 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3334
3335 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003336 if (rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337 unregister_netdevice(pWlanDev);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003338 else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339 unregister_netdev(pWlanDev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340 /*
3341 * Note that the adapter is no longer valid at this point
3342 * since the memory has been reclaimed
3343 */
3344 }
3345}
3346
Jeff Johnson590e2012016-10-05 16:16:24 -07003347static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
3348 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349{
3350 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3351 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303352 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303355 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003356 adapter = adapterNode->pAdapter;
3357 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303358 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303360 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003361 }
3362 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3363 adapterNode = pNext;
3364 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303365 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003366}
Ryan Hsu07495ea2016-01-21 15:25:39 -08003367
Arun Khandavalli2358d522016-05-16 18:05:37 +05303368#ifdef CONFIG_FW_LOGS_BASED_ON_INI
3369/**
3370 * hdd_set_fw_log_params() - Set log parameters to FW
3371 * @hdd_ctx: HDD Context
3372 * @adapter: HDD Adapter
3373 *
3374 * This function set the FW Debug log level based on the INI.
3375 *
3376 * Return: None
3377 */
3378static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3379 hdd_adapter_t *adapter)
3380{
3381 uint8_t count = 0, numentries = 0,
3382 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3383 uint32_t value = 0;
3384 int ret;
3385
Arun Khandavallifae92942016-08-01 13:31:08 +05303386 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3387 (!hdd_ctx->config->enable_fw_log)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003388 hdd_debug("enable_fw_log not enabled in INI or in FTM mode return");
Arun Khandavalli2358d522016-05-16 18:05:37 +05303389 return;
3390 }
3391
Arun Khandavallifae92942016-08-01 13:31:08 +05303392 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303393 hdd_ctx->fw_log_settings.dl_type =
3394 hdd_ctx->config->enableFwLogType;
3395 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303396 WMI_DBGLOG_TYPE,
3397 hdd_ctx->config->enableFwLogType,
3398 DBG_CMD);
3399 if (ret != 0)
3400 hdd_err("Failed to enable FW log type ret %d",
3401 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303402
3403 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303404 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303405 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303406 WMI_DBGLOG_LOG_LEVEL,
3407 hdd_ctx->config->enableFwLogLevel,
3408 DBG_CMD);
3409 if (ret != 0)
3410 hdd_err("Failed to enable FW log level ret %d",
3411 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303412
3413 hdd_string_to_u8_array(
3414 hdd_ctx->config->enableFwModuleLogLevel,
3415 moduleloglevel,
3416 &numentries,
3417 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3418
3419 while (count < numentries) {
3420 /*
3421 * FW module log level input string looks like
3422 * below:
3423 * gFwDebugModuleLoglevel=<FW Module ID>,
3424 * <Log Level>,...
3425 * For example:
3426 * gFwDebugModuleLoglevel=
3427 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3428 * Above input string means :
3429 * For FW module ID 1 enable log level 0
3430 * For FW module ID 2 enable log level 1
3431 * For FW module ID 3 enable log level 2
3432 * For FW module ID 4 enable log level 3
3433 * For FW module ID 5 enable log level 4
3434 * For FW module ID 6 enable log level 5
3435 * For FW module ID 7 enable log level 6
3436 */
3437
Nishank Aggarwale239d962017-03-03 12:26:02 +05303438 if ((moduleloglevel[count] > WLAN_MODULE_ID_MAX)
3439 || (moduleloglevel[count + 1] > DBGLOG_LVL_MAX)) {
3440 hdd_err("Module id %d and dbglog level %d input length is more than max",
3441 moduleloglevel[count],
3442 moduleloglevel[count + 1]);
3443 return;
3444 }
3445
3446 value = moduleloglevel[count] << 16;
3447 value |= moduleloglevel[count + 1];
Arun Khandavalli2358d522016-05-16 18:05:37 +05303448 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303449 WMI_DBGLOG_MOD_LOG_LEVEL,
3450 value, DBG_CMD);
3451 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303452 hdd_err("Failed to enable FW module log level %d ret %d",
3453 value, ret);
3454
3455 count += 2;
3456 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303457
Arun Khandavalli2358d522016-05-16 18:05:37 +05303458}
3459#else
3460static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3461 hdd_adapter_t *adapter)
3462{
3463}
3464
3465#endif
3466
3467/**
3468 * hdd_set_fw_params() - Set parameters to firmware
3469 * @adapter: HDD adapter
3470 *
3471 * This function Sets various parameters to fw once the
3472 * adapter is started.
3473 *
3474 * Return: 0 on success or errno on failure
3475 */
3476int hdd_set_fw_params(hdd_adapter_t *adapter)
3477{
3478 int ret;
3479 hdd_context_t *hdd_ctx;
3480
3481 ENTER_DEV(adapter->dev);
3482
3483 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3484 if (!hdd_ctx)
3485 return -EINVAL;
3486
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003487 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303488 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303489#define HDD_DTIM_1CHAIN_RX_ID 0x5
3490#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003491 /*
3492 * Disable DTIM 1 chain Rx when in 1x1,
3493 * we are passing two value
3494 * as param_id << 29 | param_value.
3495 * Below param_value = 0(disable)
3496 */
3497 ret = wma_cli_set_command(adapter->sessionId,
3498 WMI_STA_SMPS_PARAM_CMDID,
3499 HDD_DTIM_1CHAIN_RX_ID <<
3500 HDD_SMPS_PARAM_VALUE_S,
3501 VDEV_CMD);
3502 if (ret) {
3503 hdd_err("DTIM 1 chain set failed %d", ret);
3504 goto error;
3505 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303506
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003507 ret = wma_cli_set_command(adapter->sessionId,
3508 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3509 hdd_ctx->config->txchainmask1x1,
3510 PDEV_CMD);
3511 if (ret) {
3512 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3513 ret);
3514 goto error;
3515 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303516
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003517 ret = wma_cli_set_command(adapter->sessionId,
3518 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3519 hdd_ctx->config->rxchainmask1x1,
3520 PDEV_CMD);
3521 if (ret) {
3522 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3523 ret);
3524 goto error;
3525 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303526#undef HDD_DTIM_1CHAIN_RX_ID
3527#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003528 } else {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003529 hdd_debug("FTM Mode or 2x2 mode - Do not set 1x1 params");
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003530 }
3531
Arun Khandavallifae92942016-08-01 13:31:08 +05303532 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3533 ret = wma_cli_set_command(adapter->sessionId,
3534 WMI_PDEV_PARAM_HYST_EN,
3535 hdd_ctx->config->enableMemDeepSleep,
3536 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303537
Arun Khandavallifae92942016-08-01 13:31:08 +05303538 if (ret) {
3539 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3540 ret);
3541 goto error;
3542 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303543
3544 ret = wma_cli_set_command(adapter->sessionId,
3545 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3546 hdd_ctx->config->rts_profile,
3547 VDEV_CMD);
3548 if (ret) {
3549 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3550 goto error;
3551 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303552 }
3553
3554 hdd_set_fw_log_params(hdd_ctx, adapter);
3555
3556 EXIT();
3557 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303558
Arun Khandavalli2358d522016-05-16 18:05:37 +05303559error:
3560 return -EINVAL;
3561}
3562
Ryan Hsu07495ea2016-01-21 15:25:39 -08003563/**
3564 * hdd_open_adapter() - open and setup the hdd adatper
3565 * @hdd_ctx: global hdd context
3566 * @session_type: type of the interface to be created
3567 * @iface_name: User-visible name of the interface
3568 * @macAddr: MAC address to assign to the interface
3569 * @name_assign_type: the name of assign type of the netdev
3570 * @rtnl_held: the rtnl lock hold flag
3571 *
3572 * This function open and setup the hdd adpater according to the device
3573 * type request, assign the name, the mac address assigned, and then prepared
3574 * the hdd related parameters, queue, lock and ready to start.
3575 *
3576 * Return: the pointer of hdd adapter, otherwise NULL.
3577 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3579 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003580 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003581 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003582{
3583 hdd_adapter_t *adapter = NULL;
3584 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303585 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08003588 hdd_info("%s interface created. iftype: %d", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589
3590 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3591 /*
3592 * Max limit reached on the number of vdevs configured by the
3593 * host. Return error
3594 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303595 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3596 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003597 return NULL;
3598 }
3599
3600 if (macAddr == NULL) {
3601 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303602 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003603 return NULL;
3604 }
3605 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303606 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303607 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3608 " already exists",
3609 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 return NULL;
3611 }
3612
3613 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003614 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003615 /* Reset locally administered bit if the device mode is STA */
3616 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3617 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003618 case QDF_P2P_CLIENT_MODE:
3619 case QDF_P2P_DEVICE_MODE:
3620 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003621 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303622 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003623 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3624 name_assign_type,
3625 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626
3627 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303628 hdd_err("failed to allocate adapter for session %d",
3629 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003630 return NULL;
3631 }
3632
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003633 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003635 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303637 else if (QDF_MONITOR_MODE == session_type)
3638 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003639 else
3640 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3641
3642 adapter->device_mode = session_type;
3643
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303644 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003645 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303646 if (QDF_STATUS_SUCCESS != status)
3647 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303648 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 /*
3651 * Workqueue which gets scheduled in IPv4 notification
3652 * callback
3653 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3655 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656
3657#ifdef WLAN_NS_OFFLOAD
3658 /*
3659 * Workqueue which gets scheduled in IPv6
3660 * notification callback.
3661 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3663 hdd_ipv6_notifier_work_queue);
3664#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303666 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303668 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669 }
3670
3671 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303672 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303674 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3675 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003676 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303677
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003679 case QDF_P2P_GO_MODE:
3680 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003681 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3682 name_assign_type,
3683 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003684 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003685 hdd_err("failed to allocate adapter for session %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05303686 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687 return NULL;
3688 }
3689
3690 adapter->wdev.iftype =
3691 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003692 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003693 NL80211_IFTYPE_P2P_GO;
3694 adapter->device_mode = session_type;
3695
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303697 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3699 goto err_free_netdev;
3700 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303701 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303703 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3704 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303706 case QDF_FTM_MODE:
3707 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3708 name_assign_type,
3709 "wlan0");
3710 if (NULL == adapter) {
3711 hdd_err("Failed to allocate adapter for FTM mode");
3712 return NULL;
3713 }
3714 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3715 adapter->device_mode = session_type;
3716 status = hdd_register_interface(adapter, rtnl_held);
3717 if (QDF_STATUS_SUCCESS != status) {
3718 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3719 goto err_free_netdev;
3720 }
3721 /* Stop the Interface TX queue. */
3722 hdd_info("Disabling queues");
3723 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303724 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3725 WLAN_CONTROL_PATH);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303726 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003727 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003728 hdd_err("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303729 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 return NULL;
3731 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732
3733 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3734 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3735
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303736 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 /* Add it to the hdd's session list. */
3738 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303739 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003740 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303741 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742 } else {
3743 pHddAdapterNode->pAdapter = adapter;
3744 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3745 }
3746 }
3747
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303748 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 if (NULL != adapter) {
3750 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3751 adapter = NULL;
3752 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003753 if (NULL != pHddAdapterNode)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303754 qdf_mem_free(pHddAdapterNode);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003755
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003756 return NULL;
3757 }
3758
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303759 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003760 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
3761 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762
3763 /* Initialize the WoWL service */
3764 if (!hdd_init_wowl(adapter)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003765 hdd_err("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303766 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003767 }
3768
3769 /* Adapter successfully added. Increment the vdev count */
3770 hdd_ctx->current_intf_count++;
3771
Jeff Johnson5880d792016-08-15 13:32:30 -07003772 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003773 hdd_ctx->current_intf_count);
3774
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003775 hdd_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 }
3777
Rajeev Kumardca5f812016-02-04 17:28:06 -08003778 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3779 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780
3781 return adapter;
3782
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303783err_close_adapter:
3784 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003786 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303787 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788
3789 return NULL;
3790}
3791
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303792QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003793 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003794{
3795 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303796 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797
3798 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303799 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003800 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 status);
3802 return status;
3803 }
3804
3805 while (pCurrent->pAdapter != adapter) {
3806 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303807 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808 break;
3809
3810 pCurrent = pNext;
3811 }
3812 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303813 if (QDF_STATUS_SUCCESS == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003814 hdd_debug("wait for bus bw work to flush");
Dustin Brown5ec6b552017-03-31 12:11:40 -07003815 hdd_bus_bw_compute_timer_stop(hdd_ctx);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303816 cancel_work_sync(&hdd_ctx->bus_bw_work);
Dustin Brown5ec6b552017-03-31 12:11:40 -07003817
3818 /* cleanup adapter */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003819 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
3820 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303823 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003824 adapterNode = NULL;
3825
Dustin Brown5ec6b552017-03-31 12:11:40 -07003826 /* conditionally restart the bw timer */
3827 hdd_bus_bw_compute_timer_try_start(hdd_ctx);
3828
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003829 /* Adapter removed. Decrement vdev count */
3830 if (hdd_ctx->current_intf_count != 0)
3831 hdd_ctx->current_intf_count--;
3832
3833 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303834 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003835 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303836
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303837 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838}
3839
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003840/**
3841 * hdd_close_all_adapters - Close all open adapters
3842 * @hdd_ctx: Hdd context
3843 * rtnl_held: True if RTNL lock held
3844 *
3845 * Close all open adapters.
3846 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303847 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003848 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303849QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850{
3851 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303852 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853
3854 ENTER();
3855
3856 do {
3857 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303858 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303859 wlan_hdd_release_intf_addr(hdd_ctx,
3860 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003861 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003862 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303863 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303864 /* Adapter removed. Decrement vdev count */
3865 if (hdd_ctx->current_intf_count != 0)
3866 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003867 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303868 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869
3870 EXIT();
3871
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303872 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003873}
3874
3875void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3876{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303877 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 tSirUpdateIE updateIE;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003879
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003881 case QDF_STA_MODE:
3882 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883 {
3884 hdd_station_ctx_t *pHddStaCtx =
3885 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003886 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003887 break;
3888 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003889 case QDF_SAP_MODE:
3890 case QDF_P2P_GO_MODE:
3891 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003893 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 break;
3895 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003896 case QDF_FTM_MODE:
3897 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 default:
3899 /*
3900 * wlan_hdd_reset_prob_rspies should not have been called
3901 * for these kind of devices
3902 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003903 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003904 pHostapdAdapter->device_mode);
3905 return;
3906 }
3907
Anurag Chouhanc5548422016-02-24 18:33:27 +05303908 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3910 updateIE.ieBufferlength = 0;
3911 updateIE.pAdditionIEBuffer = NULL;
3912 updateIE.append = true;
3913 updateIE.notify = false;
3914 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3915 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303916 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003917 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003918 }
3919}
3920
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303921QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922 const bool bCloseSession)
3923{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303924 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3926 union iwreq_data wrqu;
3927 tSirUpdateIE updateIE;
3928 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303929 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930
3931 ENTER();
3932
Sachin Ahuja988fd102016-09-15 17:16:25 +05303933 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003934 hdd_notice("Disabling queues");
Himanshu Agarwal865201d2017-04-12 15:45:31 +05303935 wlan_hdd_netif_queue_control(adapter,
3936 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
3937 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003939 case QDF_STA_MODE:
3940 case QDF_P2P_CLIENT_MODE:
3941 case QDF_IBSS_MODE:
3942 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003943 case QDF_NDI_MODE:
3944 if ((QDF_NDI_MODE == adapter->device_mode) ||
3945 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003946 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3947 hdd_is_connecting(
3948 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003949 INIT_COMPLETION(adapter->disconnect_comp_var);
3950 /*
3951 * For NDI do not use pWextState from sta_ctx, if needed
3952 * extract from ndi_ctx.
3953 */
3954 if (QDF_NDI_MODE == adapter->device_mode)
3955 qdf_ret_status = sme_roam_disconnect(
3956 hdd_ctx->hHal,
3957 adapter->sessionId,
3958 eCSR_DISCONNECT_REASON_NDI_DELETE);
3959 else if (pWextState->roamProfile.BSSType ==
3960 eCSR_BSS_TYPE_START_IBSS)
3961 qdf_ret_status = sme_roam_disconnect(
3962 hdd_ctx->hHal,
3963 adapter->sessionId,
3964 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003965 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003966 qdf_ret_status = sme_roam_disconnect(
3967 hdd_ctx->hHal,
3968 adapter->sessionId,
3969 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003970 /* success implies disconnect command got
3971 * queued up successfully
3972 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303973 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003974 rc = wait_for_completion_timeout(
3975 &adapter->disconnect_comp_var,
3976 msecs_to_jiffies
3977 (WLAN_WAIT_TIME_DISCONNECT));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003978 if (!rc)
3979 hdd_warn("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003980 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003981 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982 }
3983 memset(&wrqu, '\0', sizeof(wrqu));
3984 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3985 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3986 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3987 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303988 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003989 if (scan_info != NULL && scan_info->mScanPending)
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303990 wlan_hdd_scan_abort(adapter);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07003991
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303992 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303993 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994
3995#ifdef WLAN_OPEN_SOURCE
3996 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3997#endif
3998
3999 hdd_deregister_tx_flow_control(adapter);
4000
4001#ifdef WLAN_NS_OFFLOAD
4002#ifdef WLAN_OPEN_SOURCE
4003 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
4004#endif
4005#endif
4006
4007 /*
4008 * It is possible that the caller of this function does not
4009 * wish to close the session
4010 */
Krunal Soni985b8132017-02-10 18:49:08 -08004011 if (true == bCloseSession) {
4012 if (0 != wlan_hdd_try_disconnect(adapter)) {
4013 hdd_err("Error: Can't disconnect adapter");
4014 return QDF_STATUS_E_FAILURE;
4015 }
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004016 hdd_vdev_destroy(adapter);
Krunal Soni985b8132017-02-10 18:49:08 -08004017 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018 break;
4019
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004020 case QDF_SAP_MODE:
4021 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004023 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
4025
4026 hdd_deregister_tx_flow_control(adapter);
4027
4028 mutex_lock(&hdd_ctx->sap_lock);
4029 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304030 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05304031 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032
4033 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004034 status = wlansap_stop_bss(
4035 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304037 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038 hdd_hostapd_state_t *hostapd_state =
4039 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304040 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304041 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304042 qdf_status =
4043 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08004044 qdf_stop_bss_event,
4045 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046
Anurag Chouhance0dc992016-02-16 18:18:03 +05304047 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004048 hdd_err("failure waiting for wlansap_stop_bss %d",
4049 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004050 }
4051 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07004052 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053 }
4054 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004055 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4056 adapter->device_mode,
4057 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004058
Anurag Chouhanc5548422016-02-24 18:33:27 +05304059 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08004060 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 updateIE.smeSessionId = adapter->sessionId;
4062 updateIE.ieBufferlength = 0;
4063 updateIE.pAdditionIEBuffer = NULL;
4064 updateIE.append = false;
4065 updateIE.notify = false;
4066 /* Probe bcn reset */
4067 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4068 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304069 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004070 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071 }
4072 /* Assoc resp reset */
4073 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4074 &updateIE,
4075 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304076 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004077 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078 }
4079 /* Reset WNI_CFG_PROBE_RSP Flags */
4080 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304081 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 adapter->sessionCtx.ap.beacon = NULL;
4083 }
Peng Xu66162de2016-02-11 17:01:20 -08004084 if (true == bCloseSession)
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004085 hdd_vdev_destroy(adapter);
Manikandan Mohan5df78272017-03-22 16:28:50 -07004086 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004087 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004088 case QDF_OCB_MODE:
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -08004089 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004090 (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
Leo Changfdb45c32016-10-28 11:09:23 -07004091 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 break;
4093 default:
4094 break;
4095 }
4096
4097 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304098 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004099}
4100
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05304101/**
4102 * hdd_deinit_all_adapters - deinit all adapters
4103 * @hdd_ctx: HDD context
4104 * @rtnl_held: True if RTNL lock held
4105 *
4106 */
4107void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
4108{
4109 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4110 QDF_STATUS status;
4111 hdd_adapter_t *adapter;
4112
4113 ENTER();
4114
4115 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4116
4117 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4118 adapter = adapter_node->pAdapter;
4119 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
4120 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4121 adapter_node = next;
4122 }
4123
4124 EXIT();
4125}
4126
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304127QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128{
4129 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304130 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004131 hdd_adapter_t *adapter;
4132
4133 ENTER();
4134
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304135 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4138
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304139 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 adapter = adapterNode->pAdapter;
4141 hdd_stop_adapter(hdd_ctx, adapter, true);
4142 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4143 adapterNode = pNext;
4144 }
4145
4146 EXIT();
4147
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304148 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004149}
4150
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304151QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152{
4153 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304154 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004155 hdd_adapter_t *adapter;
4156
4157 ENTER();
4158
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304159 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4162
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304163 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07004165 hdd_notice("Disabling queues");
Arun Khandavallicc544b32017-01-30 19:52:16 +05304166 if (hdd_ctx->config->sap_internal_restart &&
4167 adapter->device_mode == QDF_SAP_MODE) {
4168 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05304169 WLAN_STOP_ALL_NETIF_QUEUE,
Arun Khandavallicc544b32017-01-30 19:52:16 +05304170 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004171 if (test_bit(SOFTAP_BSS_STARTED,
4172 &adapter->event_flags)) {
4173 hdd_sap_indicate_disconnect_for_sta(adapter);
4174 hdd_cleanup_actionframe(hdd_ctx, adapter);
4175 hdd_sap_destroy_events(adapter);
4176 }
4177 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
4178 } else {
Arun Khandavallicc544b32017-01-30 19:52:16 +05304179 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05304180 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004181 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004182 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183
4184 adapter->sessionCtx.station.hdd_ReassocScenario = false;
4185
4186 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004187 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4188 adapter->device_mode, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
4190 hdd_wmm_adapter_close(adapter);
4191 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
4192 }
4193
Wu Gao36717432016-11-21 15:09:48 +08004194 /*
4195 * If adapter is SAP, set session ID to invalid since SAP
4196 * session will be cleanup during SSR.
4197 */
4198 if (adapter->device_mode == QDF_SAP_MODE)
4199 wlansap_set_invalid_session(
4200 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
4201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4203 adapterNode = pNext;
4204 }
4205
4206 EXIT();
4207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304208 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209}
4210
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304211bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
4212{
4213 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4214 QDF_STATUS status;
4215 bool close_modules = true;
4216
4217 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4218 while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
4219 if (test_bit(DEVICE_IFACE_OPENED,
4220 &adapter_node->pAdapter->event_flags)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004221 hdd_debug("Still other ifaces are up cannot close modules");
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304222 close_modules = false;
4223 break;
4224 }
4225 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4226 adapter_node = next;
4227 }
4228
4229 return close_modules;
4230}
4231
Arun Khandavallifae92942016-08-01 13:31:08 +05304232/**
4233 * hdd_is_interface_up()- Checkfor interface up before ssr
4234 * @hdd_ctx: HDD context
4235 *
4236 * check if there are any wlan interfaces before SSR accordingly start
4237 * the interface.
4238 *
4239 * Return: 0 if interface was opened else false
4240 */
4241static bool hdd_is_interface_up(hdd_adapter_t *adapter)
4242{
4243 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
4244 return true;
4245 else
4246 return false;
4247}
4248
Anurag Chouhanc4092922016-09-08 15:56:11 +05304249#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05304250 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304251struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4252 struct ieee80211_channel *channel,
4253 const u8 *bssid, const u8 *ssid,
4254 size_t ssid_len)
4255{
4256 return cfg80211_get_bss(wiphy, channel, bssid,
4257 ssid, ssid_len,
4258 WLAN_CAPABILITY_ESS,
4259 WLAN_CAPABILITY_ESS);
4260}
4261#else
4262struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4263 struct ieee80211_channel *channel,
4264 const u8 *bssid, const u8 *ssid,
4265 size_t ssid_len)
4266{
4267 return cfg80211_get_bss(wiphy, channel, bssid,
4268 ssid, ssid_len,
4269 IEEE80211_BSS_TYPE_ESS,
4270 IEEE80211_PRIVACY_ANY);
4271}
4272#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304273
Abhishek Singha84d3952016-09-13 13:45:05 +05304274#if defined CFG80211_CONNECT_BSS
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304275#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
4276 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
4277/**
4278 * hdd_convert_timeout_reason() - Convert to kernel specific enum
4279 * @timeout_reason: reason for connect timeout
4280 *
4281 * This function is used to convert host timeout
4282 * reason enum to kernel specific enum.
4283 *
4284 * Return: nl timeout enum
4285 */
4286static enum nl80211_timeout_reason hdd_convert_timeout_reason(
4287 tSirResultCodes timeout_reason)
4288{
4289 switch (timeout_reason) {
4290 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
4291 return NL80211_TIMEOUT_SCAN;
4292 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
4293 return NL80211_TIMEOUT_AUTH;
4294 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
4295 return NL80211_TIMEOUT_ASSOC;
4296 default:
4297 return NL80211_TIMEOUT_UNSPECIFIED;
4298 }
4299}
4300
4301/**
4302 * hdd_cfg80211_connect_timeout() - API to send connection timeout reason
4303 * @dev: network device
4304 * @bssid: bssid to which we want to associate
4305 * @timeout_reason: reason for connect timeout
4306 *
4307 * This API is used to send connection timeout reason to supplicant
4308 *
4309 * Return: void
4310 */
4311static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4312 const u8 *bssid,
4313 tSirResultCodes timeout_reason)
4314{
4315 enum nl80211_timeout_reason nl_timeout_reason;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004316
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304317 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4318
4319 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
4320 nl_timeout_reason);
4321}
4322
4323/**
4324 * __hdd_connect_bss() - API to send connection status to supplicant
4325 * @dev: network device
4326 * @bssid: bssid to which we want to associate
4327 * @req_ie: Request Information Element
4328 * @req_ie_len: len of the req IE
4329 * @resp_ie: Response IE
4330 * @resp_ie_len: len of ht response IE
4331 * @status: status
4332 * @gfp: Kernel Flag
4333 * @timeout_reason: reason for connect timeout
4334 *
4335 * Return: void
4336 */
4337static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4338 struct cfg80211_bss *bss, const u8 *req_ie,
4339 size_t req_ie_len, const u8 *resp_ie,
4340 size_t resp_ie_len, int status, gfp_t gfp,
4341 tSirResultCodes timeout_reason)
4342{
4343 enum nl80211_timeout_reason nl_timeout_reason;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004344
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304345 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4346
4347 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4348 resp_ie, resp_ie_len, status, gfp,
4349 nl_timeout_reason);
4350}
4351#else
4352#if defined CFG80211_CONNECT_TIMEOUT
4353static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4354 const u8 *bssid,
4355 tSirResultCodes timeout_reason)
4356{
4357 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
4358}
4359#endif
4360
4361static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4362 struct cfg80211_bss *bss, const u8 *req_ie,
4363 size_t req_ie_len, const u8 *resp_ie,
4364 size_t resp_ie_len, int status, gfp_t gfp,
4365 tSirResultCodes timeout_reason)
4366{
4367 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4368 resp_ie, resp_ie_len, status, gfp);
4369}
4370#endif
4371
Abhishek Singha84d3952016-09-13 13:45:05 +05304372/**
4373 * hdd_connect_bss() - API to send connection status to supplicant
4374 * @dev: network device
4375 * @bssid: bssid to which we want to associate
4376 * @req_ie: Request Information Element
4377 * @req_ie_len: len of the req IE
4378 * @resp_ie: Response IE
4379 * @resp_ie_len: len of ht response IE
4380 * @status: status
4381 * @gfp: Kernel Flag
4382 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304383 * @timeout_reason: reason for connect timeout
Abhishek Singha84d3952016-09-13 13:45:05 +05304384 *
4385 * The API is a wrapper to send connection status to supplicant
4386 *
4387 * Return: Void
4388 */
4389#if defined CFG80211_CONNECT_TIMEOUT
4390static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4391 struct cfg80211_bss *bss, const u8 *req_ie,
4392 size_t req_ie_len, const u8 *resp_ie,
4393 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304394 bool connect_timeout,
4395 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304396{
4397 if (connect_timeout)
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304398 hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304399 else
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304400 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4401 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304402}
4403#else
4404static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4405 struct cfg80211_bss *bss, const u8 *req_ie,
4406 size_t req_ie_len, const u8 *resp_ie,
4407 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304408 bool connect_timeout,
4409 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304410{
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304411 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4412 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304413}
4414#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304415
4416/**
4417 * hdd_connect_result() - API to send connection status to supplicant
4418 * @dev: network device
4419 * @bssid: bssid to which we want to associate
4420 * @roam_info: information about connected bss
4421 * @req_ie: Request Information Element
4422 * @req_ie_len: len of the req IE
4423 * @resp_ie: Response IE
4424 * @resp_ie_len: len of ht response IE
4425 * @status: status
4426 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05304427 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304428 * @timeout_reason: reason for connect timeout
Anurag Chouhanc4092922016-09-08 15:56:11 +05304429 *
4430 * The API is a wrapper to send connection status to supplicant
4431 * and allow runtime suspend
4432 *
4433 * Return: Void
4434 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304435void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4436 tCsrRoamInfo *roam_info, const u8 *req_ie,
4437 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304438 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304439 bool connect_timeout,
4440 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304441{
4442 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4443 struct cfg80211_bss *bss = NULL;
4444
4445 if (WLAN_STATUS_SUCCESS == status) {
4446 struct ieee80211_channel *chan;
4447 int freq;
4448 int chan_no = roam_info->pBssDesc->channelId;
4449
4450 if (chan_no <= 14)
4451 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004452 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304453 else
4454 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004455 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304456
4457 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
4458 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
4459 roam_info->u.pConnectedProfile->SSID.ssId,
4460 roam_info->u.pConnectedProfile->SSID.length);
4461 }
Komal Seelama89be8d2016-09-29 11:09:26 +05304462
Abhishek Singha84d3952016-09-13 13:45:05 +05304463 hdd_connect_bss(dev, bssid, bss, req_ie,
4464 req_ie_len, resp_ie, resp_ie_len,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304465 status, gfp, connect_timeout, timeout_reason);
Komal Seelama89be8d2016-09-29 11:09:26 +05304466
4467 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304468}
4469#else
4470void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4471 tCsrRoamInfo *roam_info, const u8 *req_ie,
4472 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304473 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304474 bool connect_timeout,
4475 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304476{
Komal Seelama89be8d2016-09-29 11:09:26 +05304477 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4478
Anurag Chouhanc4092922016-09-08 15:56:11 +05304479 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4480 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304481 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304482}
4483#endif
4484
4485
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304486QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004487{
4488 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304489 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 hdd_adapter_t *adapter;
4491#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304492 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493#endif
4494 eConnectionState connState;
4495
4496 ENTER();
4497
4498 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304499 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 adapter = adapterNode->pAdapter;
4501
Arun Khandavallifae92942016-08-01 13:31:08 +05304502 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304503 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304504
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505 hdd_wmm_init(adapter);
4506
4507 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004508 case QDF_STA_MODE:
4509 case QDF_P2P_CLIENT_MODE:
4510 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004511
4512 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4513 ->conn_info.connState;
4514
4515 hdd_init_station_mode(adapter);
4516 /* Open the gates for HDD to receive Wext commands */
4517 adapter->isLinkUpSvcNeeded = false;
4518 adapter->scan_info.mScanPending = false;
4519
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004520 /* Indicate disconnect event to supplicant
4521 * if associated previously
4522 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004524 eConnectionState_IbssConnected == connState ||
4525 eConnectionState_NotConnected == connState ||
4526 eConnectionState_IbssDisconnected == connState ||
4527 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 union iwreq_data wrqu;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530 memset(&wrqu, '\0', sizeof(wrqu));
4531 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4532 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4533 wireless_send_event(adapter->dev, SIOCGIWAP,
4534 &wrqu, NULL);
4535 adapter->sessionCtx.station.
4536 hdd_ReassocScenario = false;
4537
4538 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304539 wlan_hdd_cfg80211_indicate_disconnect(
4540 adapter->dev, false,
4541 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004542 } else if (eConnectionState_Connecting == connState) {
4543 /*
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004544 * Indicate connect failure to supplicant if we
4545 * were in the process of connecting
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304547 hdd_connect_result(adapter->dev, NULL, NULL,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304548 NULL, 0, NULL, 0,
4549 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004550 GFP_KERNEL, false, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 }
4552
4553 hdd_register_tx_flow_control(adapter,
4554 hdd_tx_resume_timer_expired_handler,
4555 hdd_tx_resume_cb);
4556
4557 break;
4558
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004559 case QDF_SAP_MODE:
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004560 if (hdd_ctx->config->sap_internal_restart)
Arun Khandavallicc544b32017-01-30 19:52:16 +05304561 hdd_init_ap_mode(adapter, true);
4562
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563 break;
4564
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004565 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004566#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004567 hdd_debug("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4569#else
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004570 hdd_debug("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 /* event supplicant to restart */
4572 cfg80211_del_sta(adapter->dev,
4573 (const u8 *)&bcastMac.bytes[0],
4574 GFP_KERNEL);
4575#endif
4576 break;
4577
4578 default:
4579 break;
4580 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304581get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4583 adapterNode = pNext;
4584 }
4585
4586 EXIT();
4587
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304588 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589}
4590
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304591QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592 hdd_adapter_list_node_t **padapterNode)
4593{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304594 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004595
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004596 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304597 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4598 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004599 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004600 return status;
4601}
4602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304603QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004604 hdd_adapter_list_node_t *adapterNode,
4605 hdd_adapter_list_node_t **pNextAdapterNode)
4606{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304607 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004608
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004609 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304610 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4611 (qdf_list_node_t *) adapterNode,
4612 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004614 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004615 return status;
4616}
4617
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304618QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004619 hdd_adapter_list_node_t *adapterNode)
4620{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304621 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004622
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004623 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304624 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004626 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004627 return status;
4628}
4629
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304630QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004631 hdd_adapter_list_node_t **padapterNode)
4632{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304633 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004634
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004635 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304636 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4637 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004638 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 return status;
4640}
4641
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304642QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004643 hdd_adapter_list_node_t *adapterNode)
4644{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304645 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004646
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004647 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304648 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4649 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004650 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 return status;
4652}
4653
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304654QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 hdd_adapter_list_node_t *adapterNode)
4656{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304657 QDF_STATUS status;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004658
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004659 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304660 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4661 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004662 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 return status;
4664}
4665
4666hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4667 tSirMacAddr macAddr)
4668{
4669 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4670 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304671 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672
4673 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4674
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304675 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676 adapter = adapterNode->pAdapter;
4677
4678 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304679 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004680 macAddr, sizeof(tSirMacAddr)))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 return adapter;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004682
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4684 adapterNode = pNext;
4685 }
4686
4687 return NULL;
4688
4689}
4690
4691hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4692 uint32_t vdev_id)
4693{
4694 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4695 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304696 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304698 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304700 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 adapter = adapterNode->pAdapter;
4702
4703 if (adapter->sessionId == vdev_id)
4704 return adapter;
4705
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304706 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4708 adapterNode = pNext;
4709 }
4710
Jeff Johnson5880d792016-08-15 13:32:30 -07004711 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712
4713 return NULL;
4714}
4715
Abhishek Singh7996eb72015-12-30 17:24:02 +05304716/**
4717 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4718 * the sessionid
4719 * @hdd_ctx: hdd context.
4720 * @sme_session_id: sme session is for the adapter to get.
4721 *
4722 * This function is used to get the adapter with provided session id
4723 *
4724 * Return: adapter pointer if found
4725 *
4726 */
4727hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4728 uint32_t sme_session_id)
4729{
4730 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4731 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304732 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304733
4734
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304735 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304736
4737 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304738 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304739 adapter = adapter_node->pAdapter;
4740
4741 if (adapter &&
4742 adapter->sessionId == sme_session_id)
4743 return adapter;
4744
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304745 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304746 hdd_get_next_adapter(hdd_ctx,
4747 adapter_node, &next);
4748 adapter_node = next;
4749 }
4750 return NULL;
4751}
4752
Naveen Rawat4edb6822017-04-12 10:09:17 -07004753hdd_adapter_t *hdd_get_adapter_by_iface_name(hdd_context_t *hdd_ctx,
4754 const char *iface_name)
4755{
4756 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4757 hdd_adapter_t *adapter;
4758 QDF_STATUS qdf_status;
4759
4760 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4761
4762 while ((NULL != adapter_node) &&
4763 (QDF_STATUS_SUCCESS == qdf_status)) {
4764 adapter = adapter_node->pAdapter;
4765
4766 if (adapter &&
4767 !qdf_str_cmp(adapter->dev->name, iface_name))
4768 return adapter;
4769
4770 qdf_status =
4771 hdd_get_next_adapter(hdd_ctx,
4772 adapter_node, &next);
4773 adapter_node = next;
4774 }
4775 return NULL;
4776}
4777
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004778/**
4779 * hdd_get_adapter() - to get adapter matching the mode
4780 * @hdd_ctx: hdd context
4781 * @mode: adapter mode
4782 *
4783 * This routine will return the pointer to adapter matching
4784 * with the passed mode.
4785 *
4786 * Return: pointer to adapter or null
4787 */
4788hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4789 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004790{
4791 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4792 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304793 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794
4795 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4796
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304797 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 adapter = adapterNode->pAdapter;
4799
4800 if (adapter && (mode == adapter->device_mode))
4801 return adapter;
4802
4803 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4804 adapterNode = pNext;
4805 }
4806
4807 return NULL;
4808
4809}
4810
4811/**
4812 * hdd_get_operating_channel() - return operating channel of the device mode
4813 * @hdd_ctx: Pointer to the HDD context.
4814 * @mode: Device mode for which operating channel is required.
4815 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004816 * QDF_STA_MODE,
4817 * QDF_P2P_CLIENT_MODE,
4818 * QDF_SAP_MODE,
4819 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 *
4821 * This API returns the operating channel of the requested device mode
4822 *
4823 * Return: channel number. "0" id the requested device is not found OR it is
4824 * not connected.
4825 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004826uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4827 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004828{
4829 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304830 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 hdd_adapter_t *adapter;
4832 uint8_t operatingChannel = 0;
4833
4834 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4835
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304836 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 adapter = adapterNode->pAdapter;
4838
4839 if (mode == adapter->device_mode) {
4840 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004841 case QDF_STA_MODE:
4842 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 if (hdd_conn_is_connected
4844 (WLAN_HDD_GET_STATION_CTX_PTR
4845 (adapter))) {
4846 operatingChannel =
4847 (WLAN_HDD_GET_STATION_CTX_PTR
4848 (adapter))->conn_info.
4849 operationChannel;
4850 }
4851 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004852 case QDF_SAP_MODE:
4853 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 /* softap connection info */
4855 if (test_bit
4856 (SOFTAP_BSS_STARTED,
4857 &adapter->event_flags))
4858 operatingChannel =
4859 (WLAN_HDD_GET_AP_CTX_PTR
4860 (adapter))->operatingChannel;
4861 break;
4862 default:
4863 break;
4864 }
4865
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004866 /* Found the device of interest. break the loop */
4867 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004868 }
4869
4870 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4871 adapterNode = pNext;
4872 }
4873 return operatingChannel;
4874}
4875
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304876static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 hdd_ctx)
4878{
4879 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304880 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 hdd_adapter_t *adapter;
4882
4883 ENTER();
4884
4885 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4886
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304887 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004889 if ((adapter->device_mode == QDF_STA_MODE) ||
4890 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4891 (adapter->device_mode == QDF_IBSS_MODE) ||
4892 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4893 (adapter->device_mode == QDF_SAP_MODE) ||
4894 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 wlan_hdd_cfg80211_deregister_frames(adapter);
4896 hdd_unregister_wext(adapter->dev);
4897 }
4898 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4899 adapterNode = pNext;
4900 }
4901
4902 EXIT();
4903
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304904 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905}
4906
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304907QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908{
4909 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304910 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 hdd_adapter_t *adapter;
4912
4913 ENTER();
4914
4915 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4916
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304917 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004919 if ((adapter->device_mode == QDF_STA_MODE) ||
4920 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4921 (adapter->device_mode == QDF_IBSS_MODE) ||
4922 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4923 (adapter->device_mode == QDF_SAP_MODE) ||
4924 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05304926 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 eCSR_SCAN_ABORT_DEFAULT);
4928 }
4929 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4930 adapterNode = pNext;
4931 }
4932
4933 EXIT();
4934
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304935 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004936}
4937
Dustin Brownf27bce82016-11-03 12:52:27 -07004938/**
4939 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4940 * adapters
4941 * @hdd_ctx: The HDD context containing the adapters to operate on
4942 *
4943 * return: QDF_STATUS_SUCCESS
4944 */
4945static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4946{
4947 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4948 QDF_STATUS status;
4949 hdd_adapter_t *adapter;
4950 int err;
4951
4952 ENTER();
4953
4954 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4955
4956 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4957 adapter = adapter_node->pAdapter;
4958 if ((adapter->device_mode == QDF_STA_MODE) ||
4959 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4960 (adapter->device_mode == QDF_IBSS_MODE) ||
4961 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4962 (adapter->device_mode == QDF_SAP_MODE) ||
4963 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4964 err = wlan_hdd_sched_scan_stop(adapter->dev);
4965 if (err)
4966 hdd_err("Unable to stop scheduled scan");
4967 }
Srinivas Girigowdab841da72017-03-25 18:04:39 -07004968 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
4969 &next_node);
Dustin Brownf27bce82016-11-03 12:52:27 -07004970 adapter_node = next_node;
4971 }
4972
4973 EXIT();
4974
4975 return QDF_STATUS_SUCCESS;
4976}
4977
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004978#ifdef WLAN_NS_OFFLOAD
4979/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004980 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981 * @hdd_ctx: Pointer to hdd context
4982 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004983 * Unregister for IPv6 address change notifications.
4984 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004985 * Return: None
4986 */
4987static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4988{
4989 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990}
4991
4992/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004993 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004994 * @hdd_ctx: Pointer to hdd context
4995 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004996 * Register for IPv6 address change notifications.
4997 *
4998 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005000static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005001{
5002 int ret;
5003
5004 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
5005 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005006 if (ret) {
5007 hdd_err("Failed to register IPv6 notifier: %d", ret);
5008 goto out;
5009 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005011 hdd_debug("Registered IPv6 notifier");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005012out:
5013 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014}
5015#else
5016/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005017 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 * @hdd_ctx: Pointer to hdd context
5019 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005020 * Unregister for IPv6 address change notifications.
5021 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005022 * Return: None
5023 */
5024static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
5025{
5026}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005029 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030 * @hdd_ctx: Pointer to hdd context
5031 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005032 * Register for IPv6 address change notifications.
5033 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005034 * Return: None
5035 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005036static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005037{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005038 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039}
5040#endif
5041
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305042#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
5043/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005044 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305045 * @hdd_ctx: HDD context
5046 *
5047 * Activates the logging service
5048 *
5049 * Return: Zero in case of success, negative value otherwise
5050 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005051static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305052{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005053 int ret;
5054 struct hdd_config *config = hdd_ctx->config;
5055
5056 if (!config->wlanLoggingEnable)
5057 return 0;
5058
Srinivas Girigowda8187e792017-03-03 11:50:59 -08005059 ret = wlan_logging_sock_activate_svc(config->wlanLoggingToConsole,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005060 config->wlanLoggingNumBuf);
5061 if (ret)
5062 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
5063 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305064}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005065
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305066/**
5067 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
5068 * @hdd_ctx: HDD context
5069 *
5070 * Deactivates the logging service
5071 *
5072 * Return: 0 on deactivating the logging service
5073 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005074static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305075{
5076 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
5077 return wlan_logging_sock_deactivate_svc();
5078
5079 return 0;
5080}
5081#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005082static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305083{
5084 return 0;
5085}
5086
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005087static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305088{
5089 return 0;
5090}
5091#endif
5092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005093/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005094 * hdd_register_notifiers - Register netdev notifiers.
5095 * @hdd_ctx: HDD context
5096 *
5097 * Register netdev notifiers like IPv4 and IPv6.
5098 *
5099 * Return: 0 on success and errno on failure
5100 */
5101static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
5102{
5103 int ret;
5104
5105 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5106 if (ret) {
5107 hdd_err("register_netdevice_notifier failed: %d", ret);
5108 goto out;
5109 }
5110
5111 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
5112 if (ret)
5113 goto unregister_notifier;
5114
5115 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5116 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5117 if (ret) {
5118 hdd_err("Failed to register IPv4 notifier: %d", ret);
5119 goto unregister_ip6_notifier;
5120 }
5121
5122 return 0;
5123
5124unregister_ip6_notifier:
5125 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5126unregister_notifier:
5127 unregister_netdevice_notifier(&hdd_netdev_notifier);
5128out:
5129 return ret;
5130
5131}
5132
5133/**
5134 * hdd_unregister_notifiers - Unregister netdev notifiers.
5135 * @hdd_ctx: HDD context
5136 *
5137 * Unregister netdev notifiers like IPv4 and IPv6.
5138 *
5139 * Return: None.
5140 */
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305141void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005142{
5143 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5144
5145 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5146
5147 unregister_netdevice_notifier(&hdd_netdev_notifier);
5148}
5149
5150/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005151 * hdd_exit_netlink_services - Exit netlink services
5152 * @hdd_ctx: HDD context
5153 *
5154 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
5155 * nl service.
5156 *
5157 * Return: None.
5158 */
5159static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
5160{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005161 hdd_close_cesium_nl_sock();
Naveen Rawat910726a2017-03-06 11:42:51 -08005162 hdd_deactivate_wifi_pos();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005163 ptt_sock_deactivate_svc();
5164
5165 nl_srv_exit();
5166}
5167
5168/**
5169 * hdd_init_netlink_services- Init netlink services
5170 * @hdd_ctx: HDD context
5171 *
5172 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
5173 * nl service.
5174 *
5175 * Return: 0 on success and errno on failure.
5176 */
5177static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
5178{
5179 int ret;
5180
Ryan Hsuceddceb2016-04-28 10:20:14 -07005181 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005182 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005183 hdd_err("nl_srv_init failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005184 goto out;
5185 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07005186 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005187
Naveen Rawat910726a2017-03-06 11:42:51 -08005188 ret = hdd_activate_wifi_pos(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005189 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005190 hdd_err("hdd_activate_wifi_pos failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005191 goto err_nl_srv;
5192 }
5193
5194 ret = ptt_sock_activate_svc();
5195 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005196 hdd_err("ptt_sock_activate_svc failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005197 goto err_nl_srv;
5198 }
5199
5200 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07005201 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005202 hdd_err("hdd_open_cesium_nl_sock failed ret: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005203
5204 ret = cnss_diag_activate_service();
5205 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005206 hdd_err("cnss_diag_activate_service failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005207 goto err_close_cesium;
5208 }
5209
5210 return 0;
5211
5212err_close_cesium:
5213 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005214 ptt_sock_deactivate_svc();
5215err_nl_srv:
5216 nl_srv_exit();
5217out:
5218 return ret;
5219}
5220
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005221/**
5222 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
5223 * @hdd_ctx: HDD context.
5224 *
5225 * Destroy RX wakelock.
5226 *
5227 * Return: None.
5228 */
5229static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
5230{
5231 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
5232}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005233
5234/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005235 * hdd_rx_wake_lock_create() - Create RX wakelock
5236 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005237 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005238 * Create RX wakelock.
5239 *
5240 * Return: None.
5241 */
5242static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
5243{
5244 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5245}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005246
5247/**
5248 * hdd_roc_context_init() - Init ROC context
5249 * @hdd_ctx: HDD context.
5250 *
5251 * Initialize ROC context.
5252 *
5253 * Return: 0 on success and errno on failure.
5254 */
5255static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
5256{
5257 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
5258 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
5259
5260 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5261
5262 return 0;
5263}
5264
5265/**
5266 * hdd_roc_context_destroy() - Destroy ROC context
5267 * @hdd_ctx: HDD context.
5268 *
5269 * Destroy roc list and flush the pending roc work.
5270 *
5271 * Return: None.
5272 */
5273static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
5274{
5275 flush_delayed_work(&hdd_ctx->roc_req_work);
5276 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08005277 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005278}
5279
5280/**
Houston Hoffman160db392016-10-10 17:37:51 -07005281 * hdd_context_deinit() - Deinitialize HDD context
5282 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005283 *
Houston Hoffman160db392016-10-10 17:37:51 -07005284 * Deinitialize HDD context along with all the feature specific contexts but
5285 * do not free hdd context itself. Caller of this API is supposed to free
5286 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005287 *
Houston Hoffman160db392016-10-10 17:37:51 -07005288 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005289 */
Houston Hoffman160db392016-10-10 17:37:51 -07005290static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005291{
Houston Hoffman160db392016-10-10 17:37:51 -07005292 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005293
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005294 hdd_roc_context_destroy(hdd_ctx);
5295
5296 hdd_sap_context_destroy(hdd_ctx);
5297
5298 hdd_rx_wake_lock_destroy(hdd_ctx);
5299
5300 hdd_tdls_context_destroy(hdd_ctx);
5301
5302 hdd_scan_context_destroy(hdd_ctx);
5303
5304 qdf_list_destroy(&hdd_ctx->hddAdapters);
5305
Houston Hoffman160db392016-10-10 17:37:51 -07005306 return 0;
5307}
5308
5309/**
5310 * hdd_context_destroy() - Destroy HDD context
5311 * @hdd_ctx: HDD context to be destroyed.
5312 *
5313 * Free config and HDD context as well as destroy all the resources.
5314 *
5315 * Return: None
5316 */
5317static void hdd_context_destroy(hdd_context_t *hdd_ctx)
5318{
5319 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
5320 hdd_logging_sock_deactivate_svc(hdd_ctx);
5321
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05305322 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5323
Houston Hoffman160db392016-10-10 17:37:51 -07005324 hdd_context_deinit(hdd_ctx);
5325
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305326 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005327 hdd_ctx->config = NULL;
5328
5329 wiphy_free(hdd_ctx->wiphy);
5330}
5331
5332/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005333 * hdd_wlan_exit() - HDD WLAN exit function
5334 * @hdd_ctx: Pointer to the HDD Context
5335 *
5336 * This is the driver exit point (invoked during rmmod)
5337 *
5338 * Return: None
5339 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005340static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341{
5342 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305343 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05305345 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346
5347 ENTER();
5348
Arun Khandavallifae92942016-08-01 13:31:08 +05305349 if (QDF_TIMER_STATE_RUNNING ==
5350 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005351 hdd_debug("Stop interface change timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05305352 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005353 }
5354
Arun Khandavallifae92942016-08-01 13:31:08 +05305355 if (!QDF_IS_STATUS_SUCCESS
5356 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
5357 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005358
Arun Khandavallifae92942016-08-01 13:31:08 +05305359
5360 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361
Nitesh Shah61c10d92016-10-19 19:29:15 +05305362 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
5363
Prashanth Bhattaab004382016-10-11 16:08:11 -07005364 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005365
5366#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305367 if (QDF_TIMER_STATE_RUNNING ==
5368 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
5369 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005370 }
5371
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305372 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05305373 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005374 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375 }
Liangwei Dongaef84342016-10-21 05:28:00 -04005376 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5377 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5378 hdd_ctx->last_acs_channel_list = NULL;
5379 hdd_ctx->num_of_channels = 0;
5380 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382
Arun Khandavallifae92942016-08-01 13:31:08 +05305383 mutex_lock(&hdd_ctx->iface_change_lock);
5384 driver_status = hdd_ctx->driver_status;
5385 mutex_unlock(&hdd_ctx->iface_change_lock);
5386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 /*
5388 * Powersave Offload Case
5389 * Disable Idle Power Save Mode
5390 */
5391 hdd_set_idle_ps_config(hdd_ctx, false);
5392
Arun Khandavallifae92942016-08-01 13:31:08 +05305393 if (driver_status != DRIVER_MODULES_CLOSED) {
5394 hdd_unregister_wext_all_adapters(hdd_ctx);
5395 /*
5396 * Cancel any outstanding scan requests. We are about to close
5397 * all of our adapters, but an adapter structure is what SME
5398 * passes back to our callback function. Hence if there
5399 * are any outstanding scan requests then there is a
5400 * race condition between when the adapter is closed and
5401 * when the callback is invoked. We try to resolve that
5402 * race condition here by canceling any outstanding scans
5403 * before we close the adapters.
5404 * Note that the scans may be cancelled in an asynchronous
5405 * manner, so ideally there needs to be some kind of
5406 * synchronization. Rather than introduce a new
5407 * synchronization here, we will utilize the fact that we are
5408 * about to Request Full Power, and since that is synchronized,
5409 * the expectation is that by the time Request Full Power has
5410 * completed, all scans will be cancelled
5411 */
Sandeep Puligilla1fcdb772017-02-22 21:14:59 -08005412#ifndef NAPIER_SCAN
Jeff Johnsonf337b0c2017-03-10 10:48:30 -08005413 hdd_cleanup_scan_queue(hdd_ctx);
Sandeep Puligilla1fcdb772017-02-22 21:14:59 -08005414#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05305415 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07005416 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305417 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 }
5419
5420 /*
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305421 * Close the scheduler before calling cds_close to make sure
5422 * no thread is scheduled after the each module close is
5423 * is called i.e after all the data structures are freed.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305425 qdf_status = cds_sched_close(p_cds_context);
5426 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005427 hdd_err("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305428 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07005431 hdd_wlan_stop_modules(hdd_ctx, false);
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05305432
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305433 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
5434 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
5435 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
5436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 /*
5438 * Close CDS
5439 * This frees pMac(HAL) context. There should not be any call
5440 * that requires pMac access after this.
5441 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07005443 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08005444 hdd_request_manager_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445
Komal Seelam8634b772016-09-29 12:12:24 +05305446 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005447 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005448
5449 hdd_ipa_cleanup(hdd_ctx);
5450
5451 /* Free up RoC request queue and flush workqueue */
5452 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005453
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05305454 wlansap_global_deinit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05305455 wlan_hdd_deinit_chan_info(hdd_ctx);
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305456 /*
5457 * If there is re_init failure wiphy would have already de-registered
5458 * check the wiphy status before un-registering again
5459 */
Ashish Kumar Dhanotiyae16feb72017-03-31 19:39:37 +05305460 if (wiphy && wiphy->registered) {
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305461 wiphy_unregister(wiphy);
5462 wlan_hdd_cfg80211_deinit(wiphy);
5463 hdd_lpass_notify_stop(hdd_ctx);
5464 }
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07005465
Arun Khandavallifae92942016-08-01 13:31:08 +05305466 hdd_exit_netlink_services(hdd_ctx);
5467 mutex_destroy(&hdd_ctx->iface_change_lock);
Abhishek Singhe9068f12017-03-31 14:14:52 +05305468
5469 driver_status = hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
5470 if (driver_status)
5471 hdd_err("Pdev delete failed");
5472
5473 driver_status = hdd_objmgr_release_and_destroy_psoc(hdd_ctx);
5474 if (driver_status)
5475 hdd_err("Psoc delete failed");
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005476 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477}
5478
5479void __hdd_wlan_exit(void)
5480{
5481 hdd_context_t *hdd_ctx;
5482
5483 ENTER();
5484
Anurag Chouhan6d760662016-02-20 16:05:43 +05305485 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486 if (!hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005487 hdd_err("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488 EXIT();
5489 return;
5490 }
5491
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005492 /* Check IPA HW Pipe shutdown */
5493 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
5494
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005495 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05305496 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005497
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005498 /* Do all the cleanup before deregistering the driver */
5499 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07005500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501 EXIT();
5502}
5503
5504#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04005505/**
5506 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
5507 * @data: pointer to hdd_context_t
5508 *
5509 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
5510 * Then new ACS request will do a fresh scan without reusing the cached
5511 * scan information.
5512 *
5513 * Return: void
5514 */
Tang Yingying523322d2017-01-17 23:28:43 +08005515static void hdd_skip_acs_scan_timer_handler(void *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516{
5517 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
5518
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005519 hdd_debug("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04005521 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5522 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5523 hdd_ctx->last_acs_channel_list = NULL;
5524 hdd_ctx->num_of_channels = 0;
5525 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526
5527 if (!hdd_ctx->hHal)
5528 return;
5529 sme_scan_flush_result(hdd_ctx->hHal);
5530}
5531#endif
5532
5533#ifdef QCA_HT_2040_COEX
5534/**
5535 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5536 * @adapter: pointer to adapter
5537 * @staId: station id
5538 * @macAddrSTA: station MAC address
5539 * @channel_type: channel type
5540 *
5541 * This function notifies FW with HT20/HT40 mode
5542 *
5543 * Return: 0 if successful, error number otherwise
5544 */
5545int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305546 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005547{
5548 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305549 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 hdd_context_t *hdd_ctx = NULL;
5551
5552 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5553
5554 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305555 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005556 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558 if (!hdd_ctx->hHal)
5559 return -EINVAL;
5560
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305561 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005562 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305563 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005564 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565 return -EINVAL;
5566 }
5567
5568 return 0;
5569}
5570#endif
5571
5572/**
5573 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5574 * @state: state
5575 *
5576 * This function notifies FW with modem power status
5577 *
5578 * Return: 0 if successful, error number otherwise
5579 */
5580int hdd_wlan_notify_modem_power_state(int state)
5581{
5582 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305583 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 hdd_context_t *hdd_ctx;
5585
Anurag Chouhan6d760662016-02-20 16:05:43 +05305586 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005587 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305588 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305590
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005591 if (!hdd_ctx->hHal)
5592 return -EINVAL;
5593
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305594 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5595 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005596 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005597 state);
5598 return -EINVAL;
5599 }
5600 return 0;
5601}
5602
5603/**
5604 *
5605 * hdd_post_cds_enable_config() - HDD post cds start config helper
5606 * @adapter - Pointer to the HDD
5607 *
5608 * Return: None
5609 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305610QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305612 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613
5614 /*
5615 * Send ready indication to the HDD. This will kick off the MAC
5616 * into a 'running' state and should kick off an initial scan.
5617 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305618 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5619 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005620 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5621 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305622 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005623 }
5624
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305625 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005626}
5627
5628/* wake lock APIs for HDD */
5629void hdd_prevent_suspend(uint32_t reason)
5630{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305631 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632}
5633
5634void hdd_allow_suspend(uint32_t reason)
5635{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305636 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005637}
5638
5639void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5640{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305641 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5642 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005643}
5644
5645/**
5646 * hdd_exchange_version_and_caps() - exchange version and capability with target
5647 * @hdd_ctx: Pointer to HDD context
5648 *
5649 * This is the HDD function to exchange version and capability information
5650 * between Host and Target
5651 *
5652 * This function gets reported version of FW.
5653 * It also finds the version of target headers used to compile the host;
5654 * It compares the above two and prints a warning if they are different;
5655 * It gets the SW and HW version string;
5656 * Finally, it exchanges capabilities between host and target i.e. host
5657 * and target exchange a msg indicating the features they support through a
5658 * bitmap
5659 *
5660 * Return: None
5661 */
5662void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5663{
5664
5665 tSirVersionType versionCompiled;
5666 tSirVersionType versionReported;
5667 tSirVersionString versionString;
5668 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305669 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005670
5671 memset(&versionCompiled, 0, sizeof(versionCompiled));
5672 memset(&versionReported, 0, sizeof(versionReported));
5673
5674 /* retrieve and display WCNSS version information */
5675 do {
5676
5677 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5678 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305679 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005680 hdd_err("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005681 break;
5682 }
5683
5684 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5685 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305686 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005687 hdd_err("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005688 break;
5689 }
5690
5691 if ((versionCompiled.major != versionReported.major) ||
5692 (versionCompiled.minor != versionReported.minor) ||
5693 (versionCompiled.version != versionReported.version) ||
5694 (versionCompiled.revision != versionReported.revision)) {
5695 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5696 "Host expected %u.%u.%u.%u\n",
5697 WLAN_MODULE_NAME,
5698 (int)versionReported.major,
5699 (int)versionReported.minor,
5700 (int)versionReported.version,
5701 (int)versionReported.revision,
5702 (int)versionCompiled.major,
5703 (int)versionCompiled.minor,
5704 (int)versionCompiled.version,
5705 (int)versionCompiled.revision);
5706 } else {
5707 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5708 WLAN_MODULE_NAME,
5709 (int)versionReported.major,
5710 (int)versionReported.minor,
5711 (int)versionReported.version,
5712 (int)versionReported.revision);
5713 }
5714
5715 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5716 versionString,
5717 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305718 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005719 hdd_err("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005720 break;
5721 }
5722
5723 pr_info("%s: WCNSS software version %s\n",
5724 WLAN_MODULE_NAME, versionString);
5725
5726 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5727 versionString,
5728 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305729 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005730 hdd_err("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005731 break;
5732 }
5733
5734 pr_info("%s: WCNSS hardware version %s\n",
5735 WLAN_MODULE_NAME, versionString);
5736
5737 /*
5738 * 1.Check if FW version is greater than 0.1.1.0. Only then
5739 * send host-FW capability exchange message
5740 * 2.Host-FW capability exchange message is only present on
5741 * target 1.1 so send the message only if it the target is 1.1
5742 * minor numbers for different target branches:
5743 * 0 -> (1.0)Mainline Build
5744 * 1 -> (1.1)Mainline Build
5745 * 2->(1.04) Stability Build
5746 */
5747 if (((versionReported.major > 0) || (versionReported.minor > 1)
5748 || ((versionReported.minor >= 1)
5749 && (versionReported.version >= 1)))
5750 && ((versionReported.major == 1)
5751 && (versionReported.minor >= 1)))
5752 fwFeatCapsMsgSupported = 1;
5753
5754 if (fwFeatCapsMsgSupported) {
5755 /*
5756 * Indicate if IBSS heartbeat monitoring needs to be
5757 * offloaded
5758 */
5759 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5760 sme_disable_feature_capablity
5761 (IBSS_HEARTBEAT_OFFLOAD);
5762 }
5763
5764 sme_feature_caps_exchange(hdd_ctx->hHal);
5765 }
5766
5767 } while (0);
5768
5769}
5770
5771/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305772QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005773{
5774 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5775 hdd_ctx->reg.cc_src);
5776}
5777
5778/**
5779 * hdd_is_5g_supported() - check if hardware supports 5GHz
5780 * @hdd_ctx: Pointer to the hdd context
5781 *
5782 * HDD function to know if hardware supports 5GHz
5783 *
5784 * Return: true if hardware supports 5GHz
5785 */
5786bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5787{
zdingf54169a2016-10-12 17:08:45 +08005788 if (!hdd_ctx || !hdd_ctx->config)
5789 return true;
5790
5791 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5792 return true;
5793 else
5794 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795}
5796
Amar Singhale4f28ee2015-10-21 14:36:56 -07005797static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798{
5799 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005800 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801
5802 wiphy = hdd_ctx->wiphy;
5803
5804 /*
5805 * The channel information in
5806 * wiphy needs to be initialized before wiphy registration
5807 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005808 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5809 if (ret_val) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005810 hdd_err("regulatory init failed");
Amar Singhale4f28ee2015-10-21 14:36:56 -07005811 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005812 }
5813
5814#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5815 wiphy->wowlan = &wowlan_support_reg_init;
5816#else
5817 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5818 WIPHY_WOWLAN_MAGIC_PKT |
5819 WIPHY_WOWLAN_DISCONNECT |
5820 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5821 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5822 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5823 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5824 WIPHY_WOWLAN_RFKILL_RELEASE;
5825
5826 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5827 WOW_MAX_FILTERS_PER_LIST);
5828 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5829 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5830#endif
5831
5832 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005833 ret_val = wlan_hdd_cfg80211_register(wiphy);
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305834 if (0 > ret_val) {
Amar Singhale4f28ee2015-10-21 14:36:56 -07005835 hdd_err("wiphy registration failed");
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305836 return ret_val;
5837 }
5838
5839 hdd_program_country_code(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840
Amar Singhale4f28ee2015-10-21 14:36:56 -07005841 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842}
5843
Ravi Joshie2331e82015-07-01 18:18:54 -07005844/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005845 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005846 * @hdd_ctx - handle to hdd context
5847 * @tx_packets - transmit packet count
5848 * @rx_packets - receive packet count
5849 *
5850 * The function controls the bus bandwidth and dynamic control of
5851 * tcp delayed ack configuration
5852 *
5853 * Returns: None
5854 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005855#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005856static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5857 const uint64_t tx_packets,
5858 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005859{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005860 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005861 uint64_t temp_rx = 0;
5862 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005863 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannac3da7062017-02-08 21:08:56 -08005864 static enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005865 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005866 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005867 uint16_t index = 0;
5868 bool vote_level_change = false;
5869 bool rx_level_change = false;
5870 bool tx_level_change = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005872 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005873 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005875 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005876 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005877 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005878 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005879 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005881 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005882 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5883 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005884 hdd_ctx->cur_vote_level = next_vote_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005885 vote_level_change = true;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005886 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305887 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305888 if (hdd_ctx->hbw_requested) {
5889 pld_remove_pm_qos(hdd_ctx->parent_dev);
5890 hdd_ctx->hbw_requested = false;
5891 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305892 if (cds_sched_handle_throughput_req(false))
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005893 hdd_warn("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305894 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305895 if (!hdd_ctx->hbw_requested) {
5896 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5897 hdd_ctx->hbw_requested = true;
5898 }
5899
Nirav Shah3bbfa512016-05-12 16:43:49 +05305900 if (cds_sched_handle_throughput_req(true))
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005901 hdd_warn("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305902 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005903 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005904 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005905
5906 /* fine-tuning parameters for RX Flows */
5907 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5908
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909 hdd_ctx->prev_rx = rx_packets;
Mohit Khannab1dd1e82017-02-04 15:14:38 -08005910
Ravi Joshifed83572016-10-07 16:20:37 -07005911 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5912 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5913 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5914 next_rx_level = WLAN_SVC_TP_HIGH;
5915 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005916 } else {
Ravi Joshib89e7f72016-09-07 13:43:15 -07005917 hdd_ctx->rx_high_ind_cnt = 0;
Mohit Khannac3da7062017-02-08 21:08:56 -08005918 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005919 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005922 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005923 next_rx_level, temp_rx);
5924 hdd_ctx->cur_rx_level = next_rx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005925 rx_level_change = true;
Ravi Joshie2331e82015-07-01 18:18:54 -07005926 /* Send throughput indication only if it is enabled.
5927 * Disabling tcp_del_ack will revert the tcp stack behavior
5928 * to default delayed ack. Note that this will disable the
5929 * dynamic delayed ack mechanism across the system
5930 */
5931 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305932 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5933 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934 &next_rx_level,
5935 sizeof(next_rx_level));
5936 }
5937
Mohit Khannae71e2262015-11-10 09:37:24 -08005938 /* fine-tuning parameters for TX Flows */
5939 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5940 hdd_ctx->prev_tx = tx_packets;
5941 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5942 next_tx_level = WLAN_SVC_TP_HIGH;
5943 else
5944 next_tx_level = WLAN_SVC_TP_LOW;
5945
Srinivas Girigowdab841da72017-03-25 18:04:39 -07005946 if (hdd_ctx->cur_tx_level != next_tx_level) {
Mohit Khannae71e2262015-11-10 09:37:24 -08005947 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5948 next_tx_level, temp_tx);
5949 hdd_ctx->cur_tx_level = next_tx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005950 tx_level_change = true;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305951 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5952 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005953 &next_tx_level,
5954 sizeof(next_tx_level));
5955 }
5956
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005957 index = hdd_ctx->hdd_txrx_hist_idx;
5958
5959 if (vote_level_change || tx_level_change || rx_level_change) {
5960 hdd_ctx->hdd_txrx_hist[index].next_tx_level = next_tx_level;
5961 hdd_ctx->hdd_txrx_hist[index].next_rx_level = next_rx_level;
5962 hdd_ctx->hdd_txrx_hist[index].next_vote_level = next_vote_level;
5963 hdd_ctx->hdd_txrx_hist[index].interval_rx = rx_packets;
5964 hdd_ctx->hdd_txrx_hist[index].interval_tx = tx_packets;
5965 hdd_ctx->hdd_txrx_hist[index].qtime = qdf_get_log_timestamp();
5966 hdd_ctx->hdd_txrx_hist_idx++;
5967 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
5968 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005969}
5970
5971#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305972static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005973{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305974 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5975 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005976 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305977 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305978 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5979 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980 uint64_t total_tx = 0, total_rx = 0;
5981 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305982 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305983 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005984 bool connected = false;
5985 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5986
Prashanth Bhattaab004382016-10-11 16:08:11 -07005987 if (wlan_hdd_validate_context(hdd_ctx))
5988 return;
5989
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005990 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305991 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005992 status =
5993 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5994
5995 if (adapterNode->pAdapter == NULL)
5996 continue;
5997 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305998 /*
5999 * Validate magic so we don't end up accessing
6000 * an invalid adapter.
6001 */
6002 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
6003 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006004
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006005 if ((adapter->device_mode == QDF_STA_MODE ||
6006 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
6008 != eConnectionState_Associated) {
6009
6010 continue;
6011 }
6012
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006013 if ((adapter->device_mode == QDF_SAP_MODE ||
6014 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
6016
6017 continue;
6018 }
6019
6020 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
6021 adapter->prev_tx_packets);
6022 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
6023 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306024
6025 if (adapter->device_mode == QDF_SAP_MODE ||
6026 adapter->device_mode == QDF_P2P_GO_MODE ||
6027 adapter->device_mode == QDF_IBSS_MODE) {
6028
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08006029 ret = cdp_get_intra_bss_fwd_pkts_count(
6030 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306031 adapter->sessionId,
6032 &fwd_tx_packets, &fwd_rx_packets);
6033 if (ret == A_OK) {
6034 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
6035 fwd_tx_packets,
6036 adapter->prev_fwd_tx_packets);
6037 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
6038 fwd_tx_packets,
6039 adapter->prev_fwd_rx_packets);
6040 }
6041 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006042
6043 total_rx += adapter->stats.rx_packets;
6044 total_tx += adapter->stats.tx_packets;
6045
6046 spin_lock_bh(&hdd_ctx->bus_bw_lock);
6047 adapter->prev_tx_packets = adapter->stats.tx_packets;
6048 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306049 adapter->prev_fwd_tx_packets = fwd_tx_packets;
6050 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
6052 connected = true;
6053 }
6054
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306055 /* add intra bss forwarded tx and rx packets */
6056 tx_packets += fwd_tx_packets_diff;
6057 rx_packets += fwd_rx_packets_diff;
6058
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
6060 tx_packets += (uint64_t)ipa_tx_packets;
6061 rx_packets += (uint64_t)ipa_rx_packets;
6062
6063 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006064 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006065 return;
6066 }
6067
Yuanyuan Liu13738502016-04-06 17:41:37 -07006068 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006069
6070 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
6071 hdd_ipa_uc_stat_request(adapter, 2);
6072
Dustin Brown2ed60362017-01-18 12:25:50 -08006073 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08006074 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08006075 if (hdd_ctx->bus_bw_timer_running)
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05306076 qdf_timer_mod(&hdd_ctx->bus_bw_timer,
Dustin Brownfce08d12017-01-17 16:29:38 -08006077 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08006078 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006079}
Prashanth Bhattaab004382016-10-11 16:08:11 -07006080
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306081/**
6082 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
6083 * @arg: Argument of timer function
6084 *
6085 * Schedule a workqueue in this function where all the processing is done.
6086 *
6087 * Return: None.
6088 */
6089static void __hdd_bus_bw_cbk(void *arg)
6090{
6091 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
6092
6093 if (wlan_hdd_validate_context(hdd_ctx))
6094 return;
6095
6096 schedule_work(&hdd_ctx->bus_bw_work);
6097}
6098
6099/**
6100 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
6101 * @arg: Argument of timer function
6102 *
6103 * Return: None.
6104 */
6105static void hdd_bus_bw_cbk(void *arg)
6106{
6107 cds_ssr_protect(__func__);
6108 __hdd_bus_bw_cbk(arg);
6109 cds_ssr_unprotect(__func__);
6110}
6111
Prashanth Bhattaab004382016-10-11 16:08:11 -07006112int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
6113{
6114 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306115 INIT_WORK(&hdd_ctx->bus_bw_work,
6116 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08006117 hdd_ctx->bus_bw_timer_running = false;
6118 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306119 qdf_timer_init(NULL,
6120 &hdd_ctx->bus_bw_timer,
6121 hdd_bus_bw_cbk, (void *)hdd_ctx,
6122 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006123
6124 return 0;
6125}
6126
6127void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
6128{
Dustin Brownfce08d12017-01-17 16:29:38 -08006129 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07006130 hdd_reset_tcp_delack(hdd_ctx);
6131
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006132 hdd_debug("wait for bus bw work to flush");
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306133 cancel_work_sync(&hdd_ctx->bus_bw_work);
6134 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08006135 hdd_ctx->bus_bw_timer_running = false;
6136 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006137}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006138#endif
6139
6140/**
Nirav Shahed34b212016-04-25 10:59:16 +05306141 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
6142 * @hdd_ctx: hdd context
6143 *
6144 * Return: 0 for success or error code
6145 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006146static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05306147{
6148 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
6149 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
6150 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006151 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05306152 return -ENOMEM;
6153 }
6154 return 0;
6155}
6156
6157/**
6158 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
6159 * @hdd_ctx: hdd context
6160 *
6161 * Return: none
6162 */
6163void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
6164{
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05306165 if (!hdd_ctx || hdd_ctx->hdd_txrx_hist == NULL)
6166 return;
6167
6168 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
6169 hdd_ctx->hdd_txrx_hist = NULL;
Nirav Shahed34b212016-04-25 10:59:16 +05306170}
6171
Nirav Shahda008342016-05-17 18:50:40 +05306172static uint8_t *convert_level_to_string(uint32_t level)
6173{
6174 switch (level) {
6175 /* initialize the wlan sub system */
6176 case WLAN_SVC_TP_NONE:
6177 return "NONE";
6178 case WLAN_SVC_TP_LOW:
6179 return "LOW";
6180 case WLAN_SVC_TP_MEDIUM:
6181 return "MED";
6182 case WLAN_SVC_TP_HIGH:
6183 return "HIGH";
6184 default:
6185 return "INVAL";
6186 }
6187}
6188
Nirav Shahed34b212016-04-25 10:59:16 +05306189
6190/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006191 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
6192 * @hdd_ctx: hdd context
6193 *
6194 * Return: none
6195 */
6196void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
6197{
6198 int i;
6199
6200#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006201 hdd_debug("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05306202 hdd_ctx->config->busBandwidthComputeInterval);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006203 hdd_debug("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006204 hdd_ctx->config->busBandwidthHighThreshold,
6205 hdd_ctx->config->busBandwidthMediumThreshold,
6206 hdd_ctx->config->busBandwidthLowThreshold);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006207 hdd_debug("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306208 hdd_ctx->config->enable_tcp_delack);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006209 hdd_debug("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006210 hdd_ctx->config->tcpDelackThresholdHigh,
6211 hdd_ctx->config->tcpDelackThresholdLow);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006212 hdd_debug("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05306213 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006214#endif
6215
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006216 hdd_debug("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306217 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
6218
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006219 hdd_debug("[index][timestamp]: interval_rx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006220
6221 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006222 /* using hdd_log to avoid printing function name */
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006223 if (hdd_ctx->hdd_txrx_hist[i].qtime > 0)
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006224 hdd_log(QDF_TRACE_LEVEL_ERROR,
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006225 "[%3d][%15llu]: %6llu, %6llu, %s, %s, %s",
6226 i, hdd_ctx->hdd_txrx_hist[i].qtime,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006227 hdd_ctx->hdd_txrx_hist[i].interval_rx,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006228 hdd_ctx->hdd_txrx_hist[i].interval_tx,
6229 convert_level_to_string(
6230 hdd_ctx->hdd_txrx_hist[i].
6231 next_vote_level),
6232 convert_level_to_string(
6233 hdd_ctx->hdd_txrx_hist[i].
6234 next_rx_level),
6235 convert_level_to_string(
6236 hdd_ctx->hdd_txrx_hist[i].
6237 next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006238 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239}
6240
6241/**
6242 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
6243 * @hdd_ctx: hdd context
6244 *
6245 * Return: none
6246 */
6247void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
6248{
6249 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05306250 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
6251 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252}
6253
6254/**
Srinivas Girigowdab841da72017-03-25 18:04:39 -07006255 * wlan_hdd_display_netif_queue_history() - display netif queue history
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006256 * @pHddCtx: hdd context
6257 *
6258 * Return: none
6259 */
6260void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
6261{
6262
6263 hdd_adapter_t *adapter = NULL;
6264 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306265 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006266 int i;
Nirav Shahda008342016-05-17 18:50:40 +05306267 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006268
6269 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306270 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006271 adapter = adapter_node->pAdapter;
6272
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006273 hdd_debug("Netif queue operation statistics:");
6274 hdd_debug("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05306275 adapter->sessionId, adapter->device_mode);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006276 hdd_debug("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05306277 curr_time = qdf_system_ticks();
6278 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05306279 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05306280 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05306281 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306282 unpause = adapter->total_unpause_time;
6283 } else {
Nirav Shahda008342016-05-17 18:50:40 +05306284 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306285 pause = adapter->total_pause_time;
6286 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006287 hdd_debug("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05306288 qdf_system_ticks_to_msecs(total),
6289 qdf_system_ticks_to_msecs(pause),
6290 qdf_system_ticks_to_msecs(unpause));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006291 hdd_debug("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006292
Nirav Shahda008342016-05-17 18:50:40 +05306293 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
6294 qdf_time_t pause_delta = 0;
6295
6296 if (adapter->pause_map & (1 << i))
6297 pause_delta = delta;
6298
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006299 /* using hdd_log to avoid printing function name */
6300 hdd_log(QDF_TRACE_LEVEL_ERROR,
6301 "%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006302 hdd_reason_type_to_string(i),
6303 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05306304 adapter->queue_oper_stats[i].unpause_count,
6305 qdf_system_ticks_to_msecs(
6306 adapter->queue_oper_stats[i].total_pause_time +
6307 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006308 }
6309
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006310 hdd_debug("Netif queue operation history:");
6311 hdd_debug("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05306312 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
6313
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006314 hdd_debug("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006315
6316 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006317 /* using hdd_log to avoid printing function name */
6318 if (adapter->queue_oper_history[i].time == 0)
6319 continue;
6320 hdd_log(QDF_TRACE_LEVEL_ERROR,
6321 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05306322 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006323 adapter->queue_oper_history[i].time),
6324 hdd_action_type_to_string(
6325 adapter->queue_oper_history[i].netif_action),
6326 hdd_reason_type_to_string(
6327 adapter->queue_oper_history[i].netif_reason),
6328 adapter->queue_oper_history[i].pause_map);
6329 }
6330
6331 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6332 adapter_node = next;
6333 }
6334
6335
6336}
6337
6338/**
6339 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
6340 * @hdd_ctx: hdd context
6341 *
6342 * Return: none
6343 */
6344void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
6345{
6346 hdd_adapter_t *adapter = NULL;
6347 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306348 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006349
6350 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306351 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352 adapter = adapter_node->pAdapter;
6353
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306354 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006355 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306356 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006357 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05306358 adapter->history_index = 0;
6359 adapter->start_time = adapter->last_time = qdf_system_ticks();
6360 adapter->total_pause_time = 0;
6361 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006362 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6363 adapter_node = next;
6364 }
6365}
6366
6367/**
6368 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
6369 * @halHandle: Hal handle
6370 * @pContext: Pointer to the context
6371 * @sessionId: Session ID
6372 * @scanId: Scan ID
6373 * @status: Status
6374 *
6375 * This is the callback to be executed when 11d scan is completed to flush out
6376 * the scan results
6377 *
6378 * 11d scan is done during driver load and is a passive scan on all
6379 * channels supported by the device, 11d scans may find some APs on
6380 * frequencies which are forbidden to be used in the regulatory domain
6381 * the device is operating in. If these APs are notified to the supplicant
6382 * it may try to connect to these APs, thus flush out all the scan results
6383 * which are present in SME after 11d scan is done.
6384 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306385 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006386 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306387static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006388 uint8_t sessionId, uint32_t scanId,
6389 eCsrScanStatus status)
6390{
6391 ENTER();
6392
6393 sme_scan_flush_result(halHandle);
6394
6395 EXIT();
6396
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306397 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006398}
6399
6400#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6401/**
6402 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
6403 * @hdd_ctx: hdd global context
6404 *
6405 * Return: none
6406 */
6407static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6408{
6409 uint8_t i;
6410
6411 mutex_init(&hdd_ctx->op_ctx.op_lock);
6412 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6413 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6414 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
6415 }
6416}
6417#else
6418static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6419{
6420}
6421#endif
6422
Yingying Tang95409972016-10-20 15:16:15 +08006423#ifdef WLAN_FEATURE_WOW_PULSE
6424/**
6425 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
6426 * @phddctx: hdd_context_t structure pointer
6427 * @enable: enable or disable this behaviour
6428 *
6429 * Return: int
6430 */
6431static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6432{
6433 struct hdd_config *pcfg_ini = phddctx->config;
6434 struct wow_pulse_mode wow_pulse_set_info;
6435 QDF_STATUS status;
6436
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006437 hdd_debug("wow pulse enable flag is %d", enable);
Yingying Tang95409972016-10-20 15:16:15 +08006438
6439 if (false == phddctx->config->wow_pulse_support)
6440 return 0;
6441
6442 /* prepare the request to send to SME */
6443 if (enable == true) {
6444 wow_pulse_set_info.wow_pulse_enable = true;
6445 wow_pulse_set_info.wow_pulse_pin =
6446 pcfg_ini->wow_pulse_pin;
6447 wow_pulse_set_info.wow_pulse_interval_low =
6448 pcfg_ini->wow_pulse_interval_low;
6449 wow_pulse_set_info.wow_pulse_interval_high =
6450 pcfg_ini->wow_pulse_interval_high;
6451 } else {
6452 wow_pulse_set_info.wow_pulse_enable = false;
6453 wow_pulse_set_info.wow_pulse_pin = 0;
6454 wow_pulse_set_info.wow_pulse_interval_low = 0;
6455 wow_pulse_set_info.wow_pulse_interval_high = 0;
6456 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006457 hdd_debug("enable %d pin %d low %d high %d",
Yingying Tang95409972016-10-20 15:16:15 +08006458 wow_pulse_set_info.wow_pulse_enable,
6459 wow_pulse_set_info.wow_pulse_pin,
6460 wow_pulse_set_info.wow_pulse_interval_low,
6461 wow_pulse_set_info.wow_pulse_interval_high);
6462
6463 status = sme_set_wow_pulse(&wow_pulse_set_info);
6464 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006465 hdd_debug("sme_set_wow_pulse failure!");
Yingying Tang95409972016-10-20 15:16:15 +08006466 return -EIO;
6467 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006468 hdd_debug("sme_set_wow_pulse success!");
Yingying Tang95409972016-10-20 15:16:15 +08006469 return 0;
6470}
6471#else
6472static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6473{
6474 return 0;
6475}
6476#endif
6477
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006478#ifdef WLAN_FEATURE_FASTPATH
6479/**
6480 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
6481 * @hdd_cfg: hdd config
6482 * @context: lower layer context
6483 *
6484 * Return: none
6485 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306486void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006487 void *context)
6488{
6489 if (hdd_cfg->fastpath_enable)
6490 hif_enable_fastpath(context);
6491}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006492#endif
6493
Yuanyuan Liu13738502016-04-06 17:41:37 -07006494#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006495/**
6496 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006497 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006498 * @level: thermal level
6499 *
6500 * Change IPA data path to SW path when the thermal throttle level greater
6501 * than 0, and restore the original data path when throttle level is 0
6502 *
6503 * Return: none
6504 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006505static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006506{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006507 hdd_context_t *hdd_ctx = context;
6508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006509 /* Change IPA to SW path when throttle level greater than 0 */
6510 if (level > THROTTLE_LEVEL_0)
6511 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
6512 else
6513 /* restore original concurrency mode */
6514 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
6515}
6516
6517/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306518 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
6519 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05306520 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006521 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306522 * Get a safe channel to restart SAP. PCL already takes into account the
6523 * unsafe channels. So, the PCL is validated with the ACS range to provide
6524 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006525 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306526 * Return: Channel number to restart SAP in case of success. In case of any
6527 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006528 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306529static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
6530 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006531{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306532 struct sir_pcl_list pcl;
6533 QDF_STATUS status;
6534 uint32_t i, j;
6535 tHalHandle *hal_handle;
6536 hdd_context_t *hdd_ctx;
6537 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006538
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306539 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6540 if (!hdd_ctx) {
6541 hdd_err("invalid HDD context");
6542 return INVALID_CHANNEL_ID;
6543 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006544
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306545 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6546 if (!hal_handle) {
6547 hdd_err("invalid HAL handle");
6548 return INVALID_CHANNEL_ID;
6549 }
6550
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006551 status = policy_mgr_get_pcl_for_existing_conn(hdd_ctx->hdd_psoc,
6552 PM_SAP_MODE, pcl.pcl_list, &pcl.pcl_len,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306553 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6554 if (QDF_IS_STATUS_ERROR(status)) {
6555 hdd_err("Get PCL failed");
6556 return INVALID_CHANNEL_ID;
6557 }
6558
6559 if (!pcl.pcl_len) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006560 hdd_err("pcl length is zero. this is not expected");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306561 return INVALID_CHANNEL_ID;
6562 }
6563
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006564 hdd_debug("start:%d end:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306565 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6566 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6567
6568 /* PCL already takes unsafe channel into account */
6569 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006570 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306571 if ((pcl.pcl_list[i] >=
6572 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6573 (pcl.pcl_list[i] <=
6574 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006575 hdd_debug("found PCL safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306576 return pcl.pcl_list[i];
6577 }
6578 }
6579
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006580 hdd_debug("no safe channel from PCL found in ACS range");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306581
6582 /* Try for safe channel from all valid channel */
6583 pcl.pcl_len = MAX_NUM_CHAN;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006584 status = sme_get_cfg_valid_channels(pcl.pcl_list,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306585 &pcl.pcl_len);
6586 if (QDF_IS_STATUS_ERROR(status)) {
6587 hdd_err("error in getting valid channel list");
6588 return INVALID_CHANNEL_ID;
6589 }
6590
6591 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006592 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306593 found = false;
6594 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006595 if (pcl.pcl_list[i] ==
6596 hdd_ctx->unsafe_channel_list[j]) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006597 hdd_debug("unsafe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306598 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006599 break;
6600 }
6601 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306602
6603 if (found)
6604 continue;
6605
6606 if ((pcl.pcl_list[i] >=
6607 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6608 (pcl.pcl_list[i] <=
6609 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006610 hdd_debug("found safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306611 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006612 }
6613 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306614
6615 return INVALID_CHANNEL_ID;
6616}
6617
6618/**
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006619 * hdd_switch_sap_channel() - Move SAP to the given channel
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306620 * @adapter: AP adapter
6621 * @channel: Channel
6622 *
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006623 * Moves the SAP interface by invoking the function which
6624 * executes the callback to perform channel switch using (E)CSA.
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306625 *
6626 * Return: None
6627 */
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006628void hdd_switch_sap_channel(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306629{
6630 hdd_ap_ctx_t *hdd_ap_ctx;
6631 tHalHandle *hal_handle;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006632 hdd_context_t *hdd_ctx;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306633
6634 if (!adapter) {
6635 hdd_err("invalid adapter");
6636 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006637 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306638
6639 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6640
6641 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6642 if (!hal_handle) {
6643 hdd_err("invalid HAL handle");
6644 return;
6645 }
6646
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006647 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6648
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306649 hdd_ap_ctx->sapConfig.channel = channel;
6650 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6651 hdd_ap_ctx->sapConfig.ch_width_orig;
6652
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006653 hdd_debug("chan:%d width:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306654 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6655
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006656 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306657 hdd_ap_ctx->sapConfig.sec_ch,
6658 &hdd_ap_ctx->sapConfig.ch_params);
6659
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006660 policy_mgr_change_sap_channel_with_csa(hdd_ctx->hdd_psoc,
6661 adapter->sessionId, channel,
6662 hdd_ap_ctx->sapConfig.ch_width_orig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006663}
Kapil Gupta8878ad92017-02-13 11:56:04 +05306664
6665int hdd_update_acs_timer_reason(hdd_adapter_t *adapter, uint8_t reason)
6666{
6667 struct hdd_external_acs_timer_context *timer_context;
6668
6669 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6670
6671 if (QDF_TIMER_STATE_RUNNING ==
6672 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
6673 ap.vendor_acs_timer)) {
6674 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
6675 }
6676 timer_context = (struct hdd_external_acs_timer_context *)
6677 adapter->sessionCtx.ap.vendor_acs_timer.user_data;
6678 timer_context->reason = reason;
6679 qdf_mc_timer_start(&adapter->sessionCtx.ap.vendor_acs_timer,
6680 WLAN_VENDOR_ACS_WAIT_TIME);
6681 /* Update config to application */
6682 hdd_cfg80211_update_acs_config(adapter, reason);
6683 hdd_notice("Updated ACS config to nl with reason %d", reason);
6684
6685 return 0;
6686}
6687
Agrawal Ashish467dde42016-09-08 18:44:22 +05306688/**
6689 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6690 * @hdd_ctx: hdd context pointer
6691 *
6692 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6693 * and if ACS is enabled, driver will ask userspace to restart the
6694 * sap. User space on LTE coex indication restart driver.
6695 *
6696 * Return - none
6697 */
6698void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6699{
6700 QDF_STATUS status;
6701 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6702 hdd_adapter_t *adapter_temp;
6703 uint32_t i;
6704 bool found = false;
6705 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006706
Agrawal Ashish467dde42016-09-08 18:44:22 +05306707 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6708 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6709 adapter_temp = adapter_node->pAdapter;
6710
6711 if (!adapter_temp) {
6712 hdd_err("adapter is NULL, moving to next one");
6713 goto next_adapater;
6714 }
6715
6716 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6717 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006718 hdd_debug("skip device mode:%d acs:%d",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306719 adapter_temp->device_mode,
6720 adapter_temp->sessionCtx.ap.sapConfig.
6721 acs_cfg.acs_mode);
6722 goto next_adapater;
6723 }
6724
6725 found = false;
6726 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006727 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306728 hdd_ctxt->unsafe_channel_list[i]) {
6729 found = true;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006730 hdd_debug("operating ch:%d is unsafe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306731 adapter_temp->sessionCtx.ap.operatingChannel);
6732 break;
6733 }
6734 }
6735
6736 if (!found) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006737 hdd_debug("ch:%d is safe. no need to change channel",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306738 adapter_temp->sessionCtx.ap.operatingChannel);
6739 goto next_adapater;
6740 }
6741
Kapil Gupta8878ad92017-02-13 11:56:04 +05306742 if (hdd_ctxt->config->vendor_acs_support &&
6743 hdd_ctxt->config->acs_support_for_dfs_ltecoex) {
6744 hdd_update_acs_timer_reason(adapter_temp,
6745 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
6746 goto next_adapater;
6747 } else
6748 restart_chan =
6749 hdd_get_safe_channel_from_pcl_and_acs_range(
Agrawal Ashish467dde42016-09-08 18:44:22 +05306750 adapter_temp);
6751 if (!restart_chan) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006752 hdd_err("fail to restart SAP");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306753 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006754 /*
6755 * SAP restart due to unsafe channel. While
6756 * restarting the SAP, make sure to clear
6757 * acs_channel, channel to reset to
6758 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306759 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006760 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306761 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6762 adapter_temp->sessionCtx.ap.sapConfig.channel =
6763 AUTO_CHANNEL_SELECT;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006764 hdd_debug("sending coex indication");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306765 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6766 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006767 hdd_switch_sap_channel(adapter_temp, restart_chan);
Agrawal Ashish467dde42016-09-08 18:44:22 +05306768 }
6769
6770next_adapater:
6771 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6772 adapter_node = next;
6773 }
6774}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006775/**
6776 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6777 * @adapter: HDD adapter pointer
6778 * @indParam: Channel avoid notification parameter
6779 *
6780 * Avoid channel notification from FW handler.
6781 * FW will send un-safe channel list to avoid over wrapping.
6782 * hostapd should not use notified channel
6783 *
6784 * Return: None
6785 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306786void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006787{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006788 hdd_context_t *hdd_ctxt;
6789 tSirChAvoidIndType *ch_avoid_indi;
6790 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006791 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6792 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006793 uint16_t start_channel;
6794 uint16_t end_channel;
6795 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006796 tHddAvoidFreqList hdd_avoid_freq_list;
6797 uint32_t i;
6798
6799 /* Basic sanity */
6800 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006801 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006802 return;
6803 }
6804
6805 hdd_ctxt = (hdd_context_t *) hdd_context;
6806 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6807 cds_context = hdd_ctxt->pcds_context;
6808
6809 /* Make unsafe channel list */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006810 hdd_debug("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006811 ch_avoid_indi->avoid_range_count);
6812
6813 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306814 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006815 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6816 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6817 ch_avoid_indi->avoid_freq_range[i].start_freq;
6818 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6819 ch_avoid_indi->avoid_freq_range[i].end_freq;
6820 }
6821 hdd_avoid_freq_list.avoidFreqRangeCount =
6822 ch_avoid_indi->avoid_range_count;
6823
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006824 /* clear existing unsafe channel cache */
6825 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306826 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006827 sizeof(hdd_ctxt->unsafe_channel_list));
6828
6829 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6830 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006831 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006832 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006833 break;
6834 }
6835
6836 start_channel = ieee80211_frequency_to_channel(
6837 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6838 end_channel = ieee80211_frequency_to_channel(
6839 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006840 hdd_debug("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006841 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6842 start_channel,
6843 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6844 end_channel);
6845
6846 /* do not process frequency bands that are not mapped to
6847 * predefined channels
6848 */
6849 if (start_channel == 0 || end_channel == 0)
6850 continue;
6851
Amar Singhalb8d4f152016-02-10 10:21:43 -08006852 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6853 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006854 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006855 ch_avoid_indi->avoid_freq_range[
6856 range_loop].start_freq) {
6857 start_channel_idx = channel_loop;
6858 break;
6859 }
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].end_freq) {
6866 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006867 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006868 ch_avoid_indi->avoid_freq_range[
6869 range_loop].end_freq)
6870 end_channel_idx--;
6871 break;
6872 }
6873 }
6874
Amar Singhalb8d4f152016-02-10 10:21:43 -08006875 if (start_channel_idx == INVALID_CHANNEL ||
6876 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006877 continue;
6878
6879 for (channel_loop = start_channel_idx; channel_loop <=
6880 end_channel_idx; channel_loop++) {
6881 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006882 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006883 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006884 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006885 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006886 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006887 break;
6888 }
6889 }
6890 }
6891
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006892 hdd_debug("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006893 hdd_ctxt->unsafe_channel_count);
6894
Yuanyuan Liu13738502016-04-06 17:41:37 -07006895 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6896 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006897 hdd_ctxt->unsafe_channel_count)) {
6898 hdd_err("Failed to set unsafe channel");
6899
6900 /* clear existing unsafe channel cache */
6901 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306902 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006903 sizeof(hdd_ctxt->unsafe_channel_list));
6904
6905 return;
6906 }
6907
6908 for (channel_loop = 0;
6909 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006910 hdd_debug("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006911 hdd_ctxt->unsafe_channel_list[channel_loop]);
6912 }
6913
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306914 /*
6915 * first update the unsafe channel list to the platform driver and
6916 * send the avoid freq event to the application
6917 */
6918 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6919
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306920 if (!hdd_ctxt->unsafe_channel_count) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006921 hdd_debug("no unsafe channels - not restarting SAP");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306922 return;
6923 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306924 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006925}
6926
6927/**
6928 * hdd_init_channel_avoidance() - Initialize channel avoidance
6929 * @hdd_ctx: HDD global context
6930 *
6931 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006932 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006933 * down to the lower layers. Then subscribe to subsequent channel
6934 * avoidance events.
6935 *
6936 * Return: None
6937 */
6938static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6939{
6940 uint16_t unsafe_channel_count;
6941 int index;
6942
Yuanyuan Liu13738502016-04-06 17:41:37 -07006943 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6944 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006945 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006946 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006947
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006948 hdd_debug("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006949 hdd_ctx->unsafe_channel_count);
6950
Anurag Chouhan6d760662016-02-20 16:05:43 +05306951 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006952 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006953
6954 for (index = 0; index < unsafe_channel_count; index++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006955 hdd_debug("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006956 hdd_ctx->unsafe_channel_list[index]);
6957
6958 }
6959
6960 /* Plug in avoid channel notification callback */
6961 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6962}
6963#else
6964static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6965{
6966}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006967static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006968{
6969}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006970#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006971
6972/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006973 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6974 * user space
6975 * @frame_ind: Management frame data to be informed.
6976 *
6977 * This function is used to indicate management frame to
6978 * user space
6979 *
6980 * Return: None
6981 *
6982 */
6983void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6984{
6985 hdd_context_t *hdd_ctx = NULL;
6986 hdd_adapter_t *adapter = NULL;
6987 void *cds_context = NULL;
6988 int i;
6989
6990 /* Get the global VOSS context.*/
6991 cds_context = cds_get_global_context();
6992 if (!cds_context) {
6993 hdd_err("Global CDS context is Null");
6994 return;
6995 }
6996 /* Get the HDD context.*/
6997 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6998
6999 if (0 != wlan_hdd_validate_context(hdd_ctx))
7000 return;
7001
7002 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
7003 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
7004 adapter =
7005 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
7006 if (adapter)
7007 break;
7008 }
7009 } else {
7010 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
7011 frame_ind->sessionId);
7012 }
7013
7014 if ((NULL != adapter) &&
7015 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
7016 __hdd_indicate_mgmt_frame(adapter,
7017 frame_ind->frame_len,
7018 frame_ind->frameBuf,
7019 frame_ind->frameType,
7020 frame_ind->rxChan,
7021 frame_ind->rxRssi);
Rajeev Kumard004abc2016-02-17 12:09:56 -08007022}
7023
Kapil Gupta8878ad92017-02-13 11:56:04 +05307024static void hdd_lte_coex_restart_sap(hdd_adapter_t *adapter,
7025 hdd_context_t *hdd_ctx)
7026{
7027 uint8_t restart_chan = 0;
7028
7029 restart_chan =
7030 hdd_get_safe_channel_from_pcl_and_acs_range(adapter);
7031 if (!restart_chan) {
7032 hdd_alert("fail to restart SAP");
7033 } else {
7034 /* SAP restart due to unsafe channel. While restarting
7035 * the SAP, make sure to clear acs_channel, channel to
7036 * reset to 0. Otherwise these settings will override
7037 * the ACS while restart.
7038 */
7039 hdd_ctx->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
7040 adapter->sessionCtx.ap.sapConfig.channel =
7041 AUTO_CHANNEL_SELECT;
7042 hdd_info("sending coex indication");
7043 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
7044 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08007045 hdd_switch_sap_channel(adapter, restart_chan);
Kapil Gupta8878ad92017-02-13 11:56:04 +05307046 }
7047}
7048
7049void hdd_acs_response_timeout_handler(void *context)
7050{
7051 struct hdd_external_acs_timer_context *timer_context =
7052 (struct hdd_external_acs_timer_context *)context;
7053 hdd_adapter_t *adapter;
7054 hdd_context_t *hdd_ctx;
7055 uint8_t reason;
7056
7057 ENTER();
7058 if (!timer_context) {
7059 hdd_err("invlaid timer context");
7060 return;
7061 }
7062 adapter = timer_context->adapter;
7063 reason = timer_context->reason;
7064
7065
7066 if ((!adapter) ||
7067 (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
7068 hdd_err("invalid adapter or adapter has invalid magic");
7069 return;
7070 }
7071 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7072 if (wlan_hdd_validate_context(hdd_ctx))
7073 return;
7074
7075 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
7076 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
7077 else
7078 return;
7079
7080 hdd_err("ACS timeout happened for %s reason %d",
7081 adapter->dev->name, reason);
7082 switch (reason) {
7083 /* SAP init case */
7084 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
7085 wlan_sap_set_vendor_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7086 false);
7087 wlan_hdd_cfg80211_start_acs(adapter);
7088 break;
7089 /* DFS detected on current channel */
7090 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
7091 wlan_sap_update_next_channel(
7092 WLAN_HDD_GET_SAP_CTX_PTR(adapter), 0, 0);
7093 sme_update_new_channel_event(WLAN_HDD_GET_HAL_CTX(adapter),
7094 adapter->sessionId);
7095 break;
7096 /* LTE coex event on current channel */
7097 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
7098 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
7099 break;
7100 default:
7101 hdd_info("invalid reason for timer invoke");
7102
7103 }
7104}
7105
Rajeev Kumard004abc2016-02-17 12:09:56 -08007106/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007107 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
7108 * @hdd_ctx: HDD context
7109 *
7110 * Disables all the dual mac features like DBS, Agile DFS etc.
7111 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307112 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007113 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307114static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007115{
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007116 struct policy_mgr_dual_mac_config cfg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307117 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007118
7119 if (!hdd_ctx) {
7120 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307121 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007122 }
7123
7124 cfg.scan_config = 0;
7125 cfg.fw_mode_config = 0;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007126 cfg.set_dual_mac_cb = policy_mgr_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007127
7128 hdd_debug("Disabling all dual mac features...");
7129
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007130 status = sme_soc_set_dual_mac_config(cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307131 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007132 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
7133 return status;
7134 }
7135
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307136 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007137}
7138
7139/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007140 * hdd_override_ini_config - Override INI config
7141 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007142 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007143 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007144 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007145 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007146 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007147static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007148{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007149
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007150 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
7151 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007152 hdd_debug("Module enable_dfs_chan_scan set to %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007153 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007154 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007155 if (0 == enable_11d || 1 == enable_11d) {
7156 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007157 hdd_debug("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007158 }
Leo Chang11545d62016-10-17 14:53:50 -07007159
7160 if (!hdd_ipa_is_present(hdd_ctx))
7161 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007162}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007163
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007164/**
7165 * hdd_set_trace_level_for_each - Set trace level for each INI config
7166 * @hdd_ctx - HDD context
7167 *
7168 * Set trace level for each module based on INI config.
7169 *
7170 * Return: None
7171 */
7172static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
7173{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307174 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
7175 hdd_ctx->config->qdf_trace_enable_wdi);
7176 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
7177 hdd_ctx->config->qdf_trace_enable_hdd);
7178 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
7179 hdd_ctx->config->qdf_trace_enable_sme);
7180 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
7181 hdd_ctx->config->qdf_trace_enable_pe);
7182 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
7183 hdd_ctx->config->qdf_trace_enable_wma);
7184 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
7185 hdd_ctx->config->qdf_trace_enable_sys);
7186 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
7187 hdd_ctx->config->qdf_trace_enable_qdf);
7188 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
7189 hdd_ctx->config->qdf_trace_enable_sap);
7190 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
7191 hdd_ctx->config->qdf_trace_enable_hdd_sap);
7192 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
7193 hdd_ctx->config->qdf_trace_enable_bmi);
7194 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
7195 hdd_ctx->config->qdf_trace_enable_cfg);
7196 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
7197 hdd_ctx->config->qdf_trace_enable_epping);
7198 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
7199 hdd_ctx->config->qdf_trace_enable_qdf_devices);
7200 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05307201 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307202 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
7203 hdd_ctx->config->qdf_trace_enable_htc);
7204 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
7205 hdd_ctx->config->qdf_trace_enable_hif);
7206 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
7207 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
7208 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
7209 hdd_ctx->config->qdf_trace_enable_hdd_data);
Naveen Rawat7df31862017-03-01 17:09:30 -08007210 hdd_qdf_trace_enable(QDF_MODULE_ID_WIFIPOS,
7211 hdd_ctx->config->qdf_trace_enable_wifi_pos);
Naveen Rawatf2b0dbd2017-03-27 10:00:15 -07007212 hdd_qdf_trace_enable(QDF_MODULE_ID_NAN,
7213 hdd_ctx->config->qdf_trace_enable_nan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007214 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007215}
7216
7217/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007218 * hdd_context_init() - Initialize HDD context
7219 * @hdd_ctx: HDD context.
7220 *
7221 * Initialize HDD context along with all the feature specific contexts.
7222 *
7223 * return: 0 on success and errno on failure.
7224 */
7225static int hdd_context_init(hdd_context_t *hdd_ctx)
7226{
7227 int ret;
7228
7229 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
7230 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
7231
7232 hdd_init_ll_stats_ctx();
7233
7234 init_completion(&hdd_ctx->mc_sus_event_var);
7235 init_completion(&hdd_ctx->ready_to_suspend);
7236
7237 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307238 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007239 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307240
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007241 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
7242
7243 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
7244
7245 ret = hdd_scan_context_init(hdd_ctx);
7246 if (ret)
7247 goto list_destroy;
7248
Nitesh Shahd1266d72017-01-25 22:07:07 +05307249 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007250
7251 hdd_rx_wake_lock_create(hdd_ctx);
7252
7253 ret = hdd_sap_context_init(hdd_ctx);
7254 if (ret)
7255 goto scan_destroy;
7256
7257 ret = hdd_roc_context_init(hdd_ctx);
7258 if (ret)
7259 goto sap_destroy;
7260
7261 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
7262
7263 hdd_init_offloaded_packets_ctx(hdd_ctx);
7264
7265 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
7266 hdd_ctx->config);
7267 if (ret)
7268 goto roc_destroy;
7269
7270 return 0;
7271
7272roc_destroy:
7273 hdd_roc_context_destroy(hdd_ctx);
7274
7275sap_destroy:
7276 hdd_sap_context_destroy(hdd_ctx);
7277
7278scan_destroy:
7279 hdd_scan_context_destroy(hdd_ctx);
7280 hdd_rx_wake_lock_destroy(hdd_ctx);
7281 hdd_tdls_context_destroy(hdd_ctx);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007282list_destroy:
7283 qdf_list_destroy(&hdd_ctx->hddAdapters);
Sandeep Puligillad0004212017-02-26 18:34:56 -08007284
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007285 return ret;
7286}
7287
7288/**
7289 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05307290 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007291 *
7292 * Allocate and initialize HDD context. HDD context is allocated as part of
7293 * wiphy allocation and then context is initialized.
7294 *
7295 * Return: HDD context on success and ERR_PTR on failure
7296 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007297static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007298{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307299 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007300 int ret = 0;
7301 hdd_context_t *hdd_ctx;
7302 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307303 int qdf_print_idx = -1;
7304
7305 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
7306 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
7307 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
7308 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
7309 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
7310 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
7311 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
7312 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
7313 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
7314 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
7315 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
7316 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
7317 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7318 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7319 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
7320 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
7321 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
7322 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
7323 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
7324 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
7325 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiyaf928edf2017-02-06 14:43:24 +05307326 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
7327 [QDF_MODULE_ID_DP] = {QDF_TRACE_LEVEL_ALL},
7328 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
7329 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
7330 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
7331 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
Mukul Sharma4d7d6b02017-02-13 20:45:22 +05307332 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
Abhishek Singh9679dbf2017-02-15 11:35:41 +05307333 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
Tushnim Bhattacharyya6796d8d2017-03-17 11:06:03 -07007334 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL},
7335 [QDF_MODULE_ID_POLICY_MGR] = {QDF_TRACE_LEVEL_ALL},
Wu Gao9a704f42017-03-10 18:42:11 +08007336 [QDF_MODULE_ID_P2P] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307337 };
7338
7339 status = qdf_print_setup();
7340 if (status != QDF_STATUS_SUCCESS) {
7341 pr_err("QDF print control object setup failed\n");
7342 ret = -EINVAL;
7343 goto err_out;
7344 }
7345 /* Register the module here with QDF */
7346 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
7347 "MCL_WLAN");
7348
7349 /* if qdf_print_idx is negative */
7350 if (qdf_print_idx < 0) {
7351 pr_err("QDF print control can not be registered %d\n",
7352 qdf_print_idx);
7353 ret = -EINVAL;
7354 goto err_out;
7355 }
7356
7357 /* Store the qdf_pidx information into qdf module */
7358 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007359
7360 ENTER();
7361
7362 p_cds_context = cds_get_global_context();
7363 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007364 hdd_err("Failed to get CDS global context");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007365 ret = -EINVAL;
7366 goto err_out;
7367 }
7368
7369 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
7370
7371 if (hdd_ctx == NULL) {
7372 ret = -ENOMEM;
7373 goto err_out;
7374 }
7375
7376 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007377 hdd_ctx->parent_dev = dev;
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05307378 hdd_ctx->last_scan_reject_session_id = 0xFF;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007379
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307380 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007381 if (hdd_ctx->config == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007382 hdd_err("Failed to alloc memory for HDD config!");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007383 ret = -ENOMEM;
7384 goto err_free_hdd_context;
7385 }
7386
7387 /* Read and parse the qcom_cfg.ini file */
7388 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307389 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307390 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007391 WLAN_INI_FILE);
7392 ret = -EINVAL;
7393 goto err_free_config;
7394 }
7395
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007396 hdd_debug("Setting configuredMcastBcastFilter: %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007397 hdd_ctx->config->mcastBcastFilterSetting);
7398
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307399 if (hdd_ctx->config->fhostNSOffload)
7400 hdd_ctx->ns_offload_enable = true;
7401
Abhishek Singh5ea86532016-04-27 14:10:53 +05307402 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
7403
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007404 hdd_override_ini_config(hdd_ctx);
7405
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007406 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007407
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007408 ret = hdd_context_init(hdd_ctx);
7409
7410 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007411 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007412
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007413
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -08007414 pld_set_fw_log_mode(hdd_ctx->parent_dev,
7415 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007416
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007417
7418 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05307419 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007420
Anurag Chouhan6d760662016-02-20 16:05:43 +05307421 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007422 goto skip_multicast_logging;
7423
7424 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
7425
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007426 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
7427 if (ret)
7428 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05307429
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007430 ret = hdd_logging_sock_activate_svc(hdd_ctx);
7431 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05307432 goto err_free_histogram;
7433
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007434skip_multicast_logging:
7435 hdd_set_trace_level_for_each(hdd_ctx);
7436
7437 return hdd_ctx;
7438
Nirav Shahed34b212016-04-25 10:59:16 +05307439err_free_histogram:
7440 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
7441
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007442err_deinit_hdd_context:
7443 hdd_context_deinit(hdd_ctx);
7444
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007445err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307446 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007447
7448err_free_hdd_context:
7449 wiphy_free(hdd_ctx->wiphy);
7450
7451err_out:
7452 return ERR_PTR(ret);
7453}
7454
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007455#ifdef WLAN_OPEN_P2P_INTERFACE
7456/**
7457 * hdd_open_p2p_interface - Open P2P interface
7458 * @hdd_ctx: HDD context
7459 * @rtnl_held: True if RTNL lock held
7460 *
7461 * Open P2P interface during probe. This function called to open the P2P
7462 * interface at probe along with STA interface.
7463 *
7464 * Return: 0 on success and errno on failure
7465 */
7466static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7467{
7468 hdd_adapter_t *adapter;
7469 uint8_t *p2p_dev_addr;
7470
7471 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
7472 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307473 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007474 hdd_ctx->config->intfMacAddr[0].bytes,
7475 sizeof(tSirMacAddr));
7476
7477 /*
7478 * Generate the P2P Device Address. This consists of
7479 * the device's primary MAC address with the locally
7480 * administered bit set.
7481 */
7482 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
7483 } else {
7484 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7485 if (p2p_dev_addr == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007486 hdd_err("Failed to allocate mac_address for p2p_device");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007487 return -ENOSPC;
7488 }
7489
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307490 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307491 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007492 }
7493
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007494 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007495 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08007496 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007497
7498 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007499 hdd_err("Failed to do hdd_open_adapter for P2P Device Interface");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007500 return -ENOSPC;
7501 }
7502
7503 return 0;
7504}
7505#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05307506static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007507 bool rtnl_held)
7508{
7509 return 0;
7510}
7511#endif
7512
Jeff Johnson957bc272017-02-02 08:54:48 -08007513static int hdd_open_ocb_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7514{
7515 hdd_adapter_t *adapter;
7516 int ret = 0;
7517
7518 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
7519 wlan_hdd_get_intf_addr(hdd_ctx),
7520 NET_NAME_UNKNOWN, rtnl_held);
7521 if (adapter == NULL) {
7522 hdd_err("Failed to open 802.11p interface");
7523 ret = -ENOSPC;
7524 }
7525
7526 return ret;
7527}
7528
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007529/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307530 * hdd_start_station_adapter()- Start the Station Adapter
7531 * @adapter: HDD adapter
7532 *
7533 * This function initializes the adapter for the station mode.
7534 *
7535 * Return: 0 on success or errno on failure.
7536 */
7537int hdd_start_station_adapter(hdd_adapter_t *adapter)
7538{
7539 QDF_STATUS status;
7540
7541 ENTER_DEV(adapter->dev);
7542
7543 status = hdd_init_station_mode(adapter);
7544
7545 if (QDF_STATUS_SUCCESS != status) {
7546 hdd_err("Error Initializing station mode: %d", status);
7547 return qdf_status_to_os_return(status);
7548 }
7549
Arun Khandavallifae92942016-08-01 13:31:08 +05307550 hdd_register_tx_flow_control(adapter,
7551 hdd_tx_resume_timer_expired_handler,
7552 hdd_tx_resume_cb);
7553
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307554 EXIT();
7555 return 0;
7556}
7557
7558/**
7559 * hdd_start_ap_adapter()- Start AP Adapter
7560 * @adapter: HDD adapter
7561 *
7562 * This function initializes the adapter for the AP mode.
7563 *
7564 * Return: 0 on success errno on failure.
7565 */
7566int hdd_start_ap_adapter(hdd_adapter_t *adapter)
7567{
7568 QDF_STATUS status;
7569
7570 ENTER();
7571
Arun Khandavallicc544b32017-01-30 19:52:16 +05307572 status = hdd_init_ap_mode(adapter, false);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307573
7574 if (QDF_STATUS_SUCCESS != status) {
7575 hdd_err("Error Initializing the AP mode: %d", status);
7576 return qdf_status_to_os_return(status);
7577 }
7578
Arun Khandavallifae92942016-08-01 13:31:08 +05307579 hdd_register_tx_flow_control(adapter,
7580 hdd_softap_tx_resume_timer_expired_handler,
7581 hdd_softap_tx_resume_cb);
7582
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307583 EXIT();
7584 return 0;
7585}
7586
7587/**
7588 * hdd_start_ftm_adapter()- Start FTM adapter
7589 * @adapter: HDD adapter
7590 *
7591 * This function initializes the adapter for the FTM mode.
7592 *
7593 * Return: 0 on success or errno on failure.
7594 */
7595int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
7596{
7597 QDF_STATUS qdf_status;
7598
7599 ENTER_DEV(adapter->dev);
7600
7601 qdf_status = hdd_init_tx_rx(adapter);
7602
7603 if (QDF_STATUS_SUCCESS != qdf_status) {
7604 hdd_err("Failed to start FTM adapter: %d", qdf_status);
7605 return qdf_status_to_os_return(qdf_status);
7606 }
7607
7608 return 0;
7609 EXIT();
7610}
7611
7612/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007613 * hdd_open_interfaces - Open all required interfaces
7614 * hdd_ctx: HDD context
7615 * rtnl_held: True if RTNL lock is held
7616 *
7617 * Open all the interfaces like STA, P2P and OCB based on the configuration.
7618 *
Jeff Johnson957bc272017-02-02 08:54:48 -08007619 * Return: 0 if all interfaces were created, otherwise negative errno
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007620 */
Jeff Johnson957bc272017-02-02 08:54:48 -08007621static int hdd_open_interfaces(hdd_context_t *hdd_ctx, bool rtnl_held)
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007622{
Jeff Johnson957bc272017-02-02 08:54:48 -08007623 hdd_adapter_t *adapter;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007624 int ret;
7625
Jeff Johnson957bc272017-02-02 08:54:48 -08007626 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
Arun Khandavallifae92942016-08-01 13:31:08 +05307627 /* Create only 802.11p interface */
Jeff Johnson957bc272017-02-02 08:54:48 -08007628 return hdd_open_ocb_interface(hdd_ctx, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007629
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007630 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007631 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08007632 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007633
7634 if (adapter == NULL)
Jeff Johnson957bc272017-02-02 08:54:48 -08007635 return -ENOSPC;
7636
Deepak Dhamdherea2785822016-11-17 01:17:45 -08007637 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
7638 adapter->fast_roaming_allowed = true;
7639
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007640 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
7641 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08007642 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007643
7644 /* Open 802.11p Interface */
7645 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Jeff Johnson957bc272017-02-02 08:54:48 -08007646 ret = hdd_open_ocb_interface(hdd_ctx, rtnl_held);
7647 if (ret)
7648 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007649 }
7650
Jeff Johnson957bc272017-02-02 08:54:48 -08007651 return 0;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007652
Jeff Johnson957bc272017-02-02 08:54:48 -08007653err_close_adapters:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007654 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Jeff Johnson957bc272017-02-02 08:54:48 -08007655 return ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007656}
7657
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007658/**
7659 * hdd_update_country_code - Update country code
7660 * @hdd_ctx: HDD context
7661 * @adapter: Primary adapter context
7662 *
7663 * Update country code based on module parameter country_code at SME and wait
7664 * for the settings to take effect.
7665 *
7666 * Return: 0 on success and errno on failure
7667 */
7668static int hdd_update_country_code(hdd_context_t *hdd_ctx,
7669 hdd_adapter_t *adapter)
7670{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307671 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007672 int ret = 0;
7673 unsigned long rc;
7674
7675 if (country_code == NULL)
7676 return 0;
7677
7678 INIT_COMPLETION(adapter->change_country_code);
7679
7680 status = sme_change_country_code(hdd_ctx->hHal,
7681 wlan_hdd_change_country_code_callback,
7682 country_code, adapter,
7683 hdd_ctx->pcds_context, eSIR_TRUE,
7684 eSIR_TRUE);
7685
7686
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307687 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007688 hdd_err("SME Change Country code from module param fail ret=%d",
7689 ret);
7690 return -EINVAL;
7691 }
7692
7693 rc = wait_for_completion_timeout(&adapter->change_country_code,
7694 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
7695 if (!rc) {
7696 hdd_err("SME while setting country code timed out");
7697 ret = -ETIMEDOUT;
7698 }
7699
7700 return ret;
7701}
7702
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307703#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7704/**
7705 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7706 * @cds_cfg: CDS Configuration
7707 * @hdd_ctx: Pointer to hdd context
7708 *
7709 * Return: none
7710 */
7711static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7712 *cds_cfg,
7713 hdd_context_t *hdd_ctx)
7714{
7715 cds_cfg->tx_flow_stop_queue_th =
7716 hdd_ctx->config->TxFlowStopQueueThreshold;
7717 cds_cfg->tx_flow_start_queue_offset =
7718 hdd_ctx->config->TxFlowStartQueueOffset;
7719}
7720#else
7721static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7722 *cds_cfg,
7723 hdd_context_t *hdd_ctx)
7724{
7725}
7726#endif
7727
7728#ifdef FEATURE_WLAN_RA_FILTERING
7729/**
7730 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7731 * @cds_cfg: CDS Configuration
7732 * @hdd_ctx: Pointer to hdd context
7733 *
7734 * Return: none
7735 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307736static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307737 hdd_context_t *hdd_ctx)
7738{
7739 cds_cfg->ra_ratelimit_interval =
7740 hdd_ctx->config->RArateLimitInterval;
7741 cds_cfg->is_ra_ratelimit_enabled =
7742 hdd_ctx->config->IsRArateLimitEnabled;
7743}
7744#else
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}
7749#endif
7750
7751/**
7752 * hdd_update_cds_config() - API to update cds configuration parameters
7753 * @hdd_ctx: HDD Context
7754 *
7755 * Return: 0 for Success, errno on failure
7756 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007757static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307758{
7759 struct cds_config_info *cds_cfg;
7760
7761 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7762 if (!cds_cfg) {
7763 hdd_err("failed to allocate cds config");
7764 return -ENOMEM;
7765 }
7766
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307767 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08007768 if (!hdd_ctx->config->nMaxPsPoll ||
7769 !hdd_ctx->config->enablePowersaveOffload) {
7770 cds_cfg->powersave_offload_enabled =
7771 hdd_ctx->config->enablePowersaveOffload;
7772 } else {
7773 if ((hdd_ctx->config->enablePowersaveOffload ==
7774 PS_QPOWER_NODEEPSLEEP) ||
7775 (hdd_ctx->config->enablePowersaveOffload ==
7776 PS_LEGACY_NODEEPSLEEP))
7777 cds_cfg->powersave_offload_enabled =
7778 PS_LEGACY_NODEEPSLEEP;
7779 else
7780 cds_cfg->powersave_offload_enabled =
7781 PS_LEGACY_DEEPSLEEP;
7782 hdd_info("Qpower disabled in cds config, %d",
7783 cds_cfg->powersave_offload_enabled);
7784 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307785 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7786 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7787 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7788 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7789 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7790
7791 /* Here ol_ini_info is used to store ini status of arp offload
7792 * ns offload and others. Currently 1st bit is used for arp
7793 * off load and 2nd bit for ns offload currently, rest bits are unused
7794 */
7795 if (hdd_ctx->config->fhostArpOffload)
7796 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7797 if (hdd_ctx->config->fhostNSOffload)
7798 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7799
7800 /*
7801 * Copy the DFS Phyerr Filtering Offload status.
7802 * This parameter reflects the value of the
7803 * dfs_phyerr_filter_offload flag as set in the ini.
7804 */
7805 cds_cfg->dfs_phyerr_filter_offload =
7806 hdd_ctx->config->fDfsPhyerrFilterOffload;
7807 if (hdd_ctx->config->ssdp)
7808 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7809
7810 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7811 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7812
7813 cds_cfg->ap_maxoffload_reorderbuffs =
7814 hdd_ctx->config->apMaxOffloadReorderBuffs;
7815
7816 cds_cfg->ap_disable_intrabss_fwd =
7817 hdd_ctx->config->apDisableIntraBssFwd;
7818
7819 cds_cfg->dfs_pri_multiplier =
7820 hdd_ctx->config->dfsRadarPriMultiplier;
7821 cds_cfg->reorder_offload =
7822 hdd_ctx->config->reorderOffloadSupport;
7823
7824 /* IPA micro controller data path offload resource config item */
7825 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007826 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7827 /* IpaUcTxBufCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007828 hdd_debug("Round down IpaUcTxBufCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007829 hdd_ctx->config->IpaUcTxBufCount);
7830 hdd_ctx->config->IpaUcTxBufCount =
7831 rounddown_pow_of_two(
7832 hdd_ctx->config->IpaUcTxBufCount);
7833 if (!hdd_ctx->config->IpaUcTxBufCount) {
7834 hdd_err("Failed to round down IpaUcTxBufCount");
7835 return -EINVAL;
7836 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007837 hdd_debug("IpaUcTxBufCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007838 hdd_ctx->config->IpaUcTxBufCount);
7839 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307840 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7841 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007842 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7843 /* IpaUcRxIndRingCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007844 hdd_debug("Round down IpaUcRxIndRingCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007845 hdd_ctx->config->IpaUcRxIndRingCount);
7846 hdd_ctx->config->IpaUcRxIndRingCount =
7847 rounddown_pow_of_two(
7848 hdd_ctx->config->IpaUcRxIndRingCount);
7849 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7850 hdd_err("Failed to round down IpaUcRxIndRingCount");
7851 return -EINVAL;
7852 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007853 hdd_debug("IpaUcRxIndRingCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007854 hdd_ctx->config->IpaUcRxIndRingCount);
7855 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307856 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007857 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307858 cds_cfg->uc_tx_partition_base =
7859 hdd_ctx->config->IpaUcTxPartitionBase;
7860 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7861
7862 cds_cfg->ip_tcp_udp_checksum_offload =
7863 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307864 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307865 cds_cfg->ce_classify_enabled =
7866 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007867 cds_cfg->bpf_packet_filter_enable =
7868 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307869 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7870 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7871 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007872 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007873 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007874 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007875 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Dustin Brown13995f02017-01-12 15:38:42 -08007876 cds_cfg->active_bpf_mode = hdd_ctx->config->active_bpf_mode;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307877
7878 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7879 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7880 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007881 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307882 cds_init_ini_config(cds_cfg);
7883 return 0;
7884}
7885
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007886/**
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007887 * hdd_update_user_config() - API to update user configuration
7888 * parameters to obj mgr which are used by multiple components
7889 * @hdd_ctx: HDD Context
7890 *
7891 * Return: 0 for Success, errno on failure
7892 */
7893static int hdd_update_user_config(hdd_context_t *hdd_ctx)
7894{
7895 struct wlan_objmgr_psoc_user_config *user_config;
7896
7897 user_config = qdf_mem_malloc(sizeof(*user_config));
7898 if (user_config == NULL) {
7899 hdd_alert("Failed to alloc memory for user_config!");
7900 return -ENOMEM;
7901 }
7902
7903 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
7904 user_config->dual_mac_feature_disable =
7905 hdd_ctx->config->dual_mac_feature_disable;
7906 user_config->indoor_channel_support =
7907 hdd_ctx->config->indoor_channel_support;
7908 user_config->is_11d_support_enabled =
7909 hdd_ctx->config->Is11dSupportEnabled;
7910 user_config->is_11h_support_enabled =
7911 hdd_ctx->config->Is11hSupportEnabled;
7912 user_config->optimize_chan_avoid_event =
7913 hdd_ctx->config->goptimize_chan_avoid_event;
7914 user_config->skip_dfs_chnl_in_p2p_search =
7915 hdd_ctx->config->skipDfsChnlInP2pSearch;
Naveen Rawat222b2e92017-03-16 09:52:21 -07007916 user_config->band_capability = hdd_ctx->config->nBandCapability;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007917 wlan_objmgr_psoc_set_user_config(hdd_ctx->hdd_psoc, user_config);
7918
7919 qdf_mem_free(user_config);
7920 return 0;
7921}
7922
7923/**
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007924 * hdd_init_thermal_info - Initialize thermal level
7925 * @hdd_ctx: HDD context
7926 *
7927 * Initialize thermal level at SME layer and set the thermal level callback
7928 * which would be called when a configured thermal threshold is hit.
7929 *
7930 * Return: 0 on success and errno on failure
7931 */
7932static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7933{
7934 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307935 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007936
7937 thermal_param.smeThermalMgmtEnabled =
7938 hdd_ctx->config->thermalMitigationEnable;
7939 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7940
Poddar, Siddarth83905022016-04-16 17:56:08 -07007941 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7942 hdd_ctx->config->throttle_dutycycle_level0;
7943 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7944 hdd_ctx->config->throttle_dutycycle_level1;
7945 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7946 hdd_ctx->config->throttle_dutycycle_level2;
7947 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7948 hdd_ctx->config->throttle_dutycycle_level3;
7949
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007950 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7951 hdd_ctx->config->thermalTempMinLevel0;
7952 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7953 hdd_ctx->config->thermalTempMaxLevel0;
7954 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7955 hdd_ctx->config->thermalTempMinLevel1;
7956 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7957 hdd_ctx->config->thermalTempMaxLevel1;
7958 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7959 hdd_ctx->config->thermalTempMinLevel2;
7960 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7961 hdd_ctx->config->thermalTempMaxLevel2;
7962 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7963 hdd_ctx->config->thermalTempMinLevel3;
7964 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7965 hdd_ctx->config->thermalTempMaxLevel3;
7966
7967 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7968
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307969 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307970 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007971
7972 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7973 hdd_set_thermal_level_cb);
7974
7975 return 0;
7976
7977}
7978
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007979#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7980/**
7981 * hdd_hold_rtnl_lock - Hold RTNL lock
7982 *
7983 * Hold RTNL lock
7984 *
7985 * Return: True if held and false otherwise
7986 */
7987static inline bool hdd_hold_rtnl_lock(void)
7988{
7989 rtnl_lock();
7990 return true;
7991}
7992
7993/**
7994 * hdd_release_rtnl_lock - Release RTNL lock
7995 *
7996 * Release RTNL lock
7997 *
7998 * Return: None
7999 */
8000static inline void hdd_release_rtnl_lock(void)
8001{
8002 rtnl_unlock();
8003}
8004#else
8005static inline bool hdd_hold_rtnl_lock(void) { return false; }
8006static inline void hdd_release_rtnl_lock(void) { }
8007#endif
8008
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008009#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008010
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308011/* MAX iwpriv command support */
8012#define PKTLOG_SET_BUFF_SIZE 3
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308013#define PKTLOG_CLEAR_BUFF 4
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308014#define MAX_PKTLOG_SIZE 16
8015
8016/**
8017 * hdd_pktlog_set_buff_size() - set pktlog buffer size
8018 * @hdd_ctx: hdd context
8019 * @set_value2: pktlog buffer size value
8020 *
8021 *
8022 * Return: 0 for success or error.
8023 */
8024static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
8025{
8026 struct sir_wifi_start_log start_log = { 0 };
8027 QDF_STATUS status;
8028
8029 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8030 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
8031 start_log.ini_triggered = cds_is_packet_log_enabled();
8032 start_log.user_triggered = 1;
8033 start_log.size = set_value2;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308034 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308035
8036 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8037 if (!QDF_IS_STATUS_SUCCESS(status)) {
8038 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8039 EXIT();
8040 return -EINVAL;
8041 }
8042
8043 return 0;
8044}
8045
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008046/**
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308047 * hdd_pktlog_clear_buff() - clear pktlog buffer
8048 * @hdd_ctx: hdd context
8049 *
8050 * Return: 0 for success or error.
8051 */
8052static int hdd_pktlog_clear_buff(hdd_context_t *hdd_ctx)
8053{
8054 struct sir_wifi_start_log start_log;
8055 QDF_STATUS status;
8056
8057 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8058 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
8059 start_log.ini_triggered = cds_is_packet_log_enabled();
8060 start_log.user_triggered = 1;
8061 start_log.size = 0;
8062 start_log.is_pktlog_buff_clear = true;
8063
8064 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8065 if (!QDF_IS_STATUS_SUCCESS(status)) {
8066 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8067 EXIT();
8068 return -EINVAL;
8069 }
8070
8071 return 0;
8072}
8073
8074
8075/**
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008076 * hdd_process_pktlog_command() - process pktlog command
8077 * @hdd_ctx: hdd context
8078 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308079 * @set_value2: pktlog buffer size value
8080 *
8081 * This function process pktlog command.
8082 * set_value2 only matters when set_value is 3 (set buff size)
8083 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008084 *
8085 * Return: 0 for success or error.
8086 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308087int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
8088 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008089{
8090 int ret;
8091 bool enable;
8092 uint8_t user_triggered = 0;
8093
8094 ret = wlan_hdd_validate_context(hdd_ctx);
8095 if (0 != ret)
8096 return ret;
8097
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008098 hdd_debug("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008099
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308100 if (set_value > PKTLOG_CLEAR_BUFF) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008101 hdd_err("invalid pktlog value %d", set_value);
8102 return -EINVAL;
8103 }
8104
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308105 if (set_value == PKTLOG_SET_BUFF_SIZE) {
8106 if (set_value2 <= 0) {
8107 hdd_err("invalid pktlog size %d", set_value2);
8108 return -EINVAL;
8109 } else if (set_value2 > MAX_PKTLOG_SIZE) {
8110 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
8111 return -EINVAL;
8112 }
8113 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308114 } else if (set_value == PKTLOG_CLEAR_BUFF) {
8115 return hdd_pktlog_clear_buff(hdd_ctx);
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308116 }
8117
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008118 /*
8119 * set_value = 0 then disable packetlog
8120 * set_value = 1 enable packetlog forcefully
8121 * set_vlaue = 2 then disable packetlog if disabled through ini or
8122 * enable packetlog with AUTO type.
8123 */
8124 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
8125 true : false;
8126
8127 if (1 == set_value) {
8128 enable = true;
8129 user_triggered = 1;
8130 }
8131
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308132 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008133}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008134/**
8135 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
8136 * @hdd_ctx: HDD context
8137 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308138 * @user_triggered: triggered through iwpriv
8139 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008140 *
8141 * Return: 0 on success; error number otherwise
8142 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008143int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308144 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008145{
8146 struct sir_wifi_start_log start_log;
8147 QDF_STATUS status;
8148
8149 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8150 start_log.verbose_level =
8151 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008152 start_log.ini_triggered = cds_is_packet_log_enabled();
8153 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308154 start_log.size = size;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05308155 start_log.is_pktlog_buff_clear = false;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05308156 /*
8157 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
8158 * commands. Host uses this flag to decide whether to send pktlog
8159 * disable command to fw without sending pktlog enable command
8160 * previously. For eg, If vendor sends pktlog disable command without
8161 * sending pktlog enable command, then host discards the packet
8162 * but for iwpriv command, host will send it to fw.
8163 */
8164 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008165 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8166 if (!QDF_IS_STATUS_SUCCESS(status)) {
8167 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8168 EXIT();
8169 return -EINVAL;
8170 }
8171
8172 return 0;
8173}
8174#endif /* REMOVE_PKT_LOG */
8175
Komal Seelam92fff912016-03-24 11:51:41 +05308176/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008177 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
8178 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05308179 * @dev: Device Pointer
8180 * @num: Number of Valid Mac address
8181 *
8182 * Return: Pointer to MAC address buffer
8183 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008184static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
8185 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05308186{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008187 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05308188}
Komal Seelam92fff912016-03-24 11:51:41 +05308189
8190/**
8191 * hdd_populate_random_mac_addr() - API to populate random mac addresses
8192 * @hdd_ctx: HDD Context
8193 * @num: Number of random mac addresses needed
8194 *
8195 * Generate random addresses using bit manipulation on the base mac address
8196 *
8197 * Return: None
8198 */
8199static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
8200{
8201 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
8202 uint32_t iter;
8203 struct hdd_config *ini = hdd_ctx->config;
8204 uint8_t *buf = NULL;
8205 uint8_t macaddr_b3, tmp_br3;
8206 uint8_t *src = ini->intfMacAddr[0].bytes;
8207
8208 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
8209 buf = ini->intfMacAddr[iter].bytes;
8210 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
8211 macaddr_b3 = buf[3];
8212 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
8213 INTF_MACADDR_MASK;
8214 macaddr_b3 += tmp_br3;
8215 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
8216 buf[0] |= 0x02;
8217 buf[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008218 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308219 }
8220}
8221
8222/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008223 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05308224 * @hdd_ctx: HDD Context
8225 *
8226 * API to get mac addresses from platform driver and update the driver
8227 * structures and configure FW with the base mac address.
8228 * Return: int
8229 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008230static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05308231{
8232 uint32_t no_of_mac_addr, iter;
8233 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
8234 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
8235 uint8_t *addr, *buf;
8236 struct device *dev = hdd_ctx->parent_dev;
8237 struct hdd_config *ini = hdd_ctx->config;
8238 tSirMacAddr mac_addr;
8239 QDF_STATUS status;
8240
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008241 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05308242
8243 if (no_of_mac_addr == 0 || !addr) {
8244 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
8245 return -EINVAL;
8246 }
8247
8248 if (no_of_mac_addr > max_mac_addr)
8249 no_of_mac_addr = max_mac_addr;
8250
8251 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
8252
8253 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
8254 buf = ini->intfMacAddr[iter].bytes;
8255 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008256 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308257 }
8258
8259 status = sme_set_custom_mac_addr(mac_addr);
8260
8261 if (!QDF_IS_STATUS_SUCCESS(status))
8262 return -EAGAIN;
Srinivas Girigowdab841da72017-03-25 18:04:39 -07008263
Komal Seelam92fff912016-03-24 11:51:41 +05308264 if (no_of_mac_addr < max_mac_addr)
8265 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
8266 no_of_mac_addr);
8267 return 0;
8268}
8269
8270/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008271 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
8272 * @hdd_ctx: HDD Context
8273 *
8274 * Update MAC address to FW. If MAC address passed by FW is invalid, host
8275 * will generate its own MAC and update it to FW.
8276 *
8277 * Return: 0 for success
8278 * Non-zero error code for failure
8279 */
8280static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
8281{
8282 tSirMacAddr customMacAddr;
8283 QDF_STATUS status;
8284
8285 qdf_mem_copy(&customMacAddr,
8286 &hdd_ctx->config->intfMacAddr[0].bytes[0],
8287 sizeof(tSirMacAddr));
8288 status = sme_set_custom_mac_addr(customMacAddr);
8289 if (!QDF_IS_STATUS_SUCCESS(status))
8290 return -EAGAIN;
8291 return 0;
8292}
8293
8294/**
Komal Seelam92fff912016-03-24 11:51:41 +05308295 * hdd_initialize_mac_address() - API to get wlan mac addresses
8296 * @hdd_ctx: HDD Context
8297 *
8298 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
8299 * is provisioned with mac addresses, driver uses it, else it will use
8300 * wlan_mac.bin to update HW MAC addresses.
8301 *
8302 * Return: None
8303 */
8304static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
8305{
8306 QDF_STATUS status;
8307 int ret;
8308
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008309 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05308310 if (ret == 0)
8311 return;
8312
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008313 hdd_warn("Can't update mac config via platform driver ret: %d", ret);
Komal Seelam92fff912016-03-24 11:51:41 +05308314
8315 status = hdd_update_mac_config(hdd_ctx);
8316
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008317 if (QDF_IS_STATUS_SUCCESS(status))
8318 return;
8319
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008320 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 -07008321
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008322 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008323 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008324 if (ret != 0) {
8325 hdd_err("MAC address out-of-sync, ret:%d", ret);
8326 QDF_ASSERT(ret);
8327 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008328 }
Komal Seelam92fff912016-03-24 11:51:41 +05308329}
8330
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008331/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008332 * hdd_tsf_init() - Initialize the TSF synchronization interface
8333 * @hdd_ctx: HDD global context
8334 *
8335 * When TSF synchronization via GPIO is supported by the driver and
8336 * has been enabled in the configuration file, this function plumbs
8337 * the GPIO value down to firmware via SME.
8338 *
8339 * Return: None
8340 */
8341#ifdef WLAN_FEATURE_TSF
8342static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8343{
8344 QDF_STATUS status;
8345
8346 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
8347 return;
8348
8349 status = sme_set_tsf_gpio(hdd_ctx->hHal,
8350 hdd_ctx->config->tsf_gpio_pin);
8351 if (!QDF_IS_STATUS_SUCCESS(status))
8352 hdd_err("Set tsf GPIO failed, status: %d", status);
8353}
8354#else
8355static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8356{
8357}
8358#endif
8359
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008360static int hdd_set_smart_chainmask_enabled(hdd_context_t *hdd_ctx)
8361{
8362 int vdev_id = 0;
8363 int param_id = WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME;
8364 int value = hdd_ctx->config->smart_chainmask_enabled;
8365 int vpdev = PDEV_CMD;
8366 int ret;
8367
8368 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8369 if (ret)
8370 hdd_err("WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME failed %d", ret);
8371
8372 return ret;
8373}
8374
8375static int hdd_set_alternative_chainmask_enabled(hdd_context_t *hdd_ctx)
8376{
8377 int vdev_id = 0;
8378 int param_id = WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME;
8379 int value = hdd_ctx->config->alternative_chainmask_enabled;
8380 int vpdev = PDEV_CMD;
8381 int ret;
8382
8383 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8384 if (ret)
8385 hdd_err("WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME failed %d",
8386 ret);
8387
8388 return ret;
8389}
8390
Jeff Johnson12a744b2017-04-04 08:19:37 -07008391static int hdd_set_ani_enabled(hdd_context_t *hdd_ctx)
8392{
8393 int vdev_id = 0;
8394 int param_id = WMI_PDEV_PARAM_ANI_ENABLE;
8395 int value = hdd_ctx->config->ani_enabled;
8396 int vpdev = PDEV_CMD;
8397 int ret;
8398
8399 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8400 if (ret)
8401 hdd_err("WMI_PDEV_PARAM_ANI_ENABLE failed %d", ret);
8402
8403 return ret;
8404}
8405
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008406/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07008407 * hdd_pre_enable_configure() - Configurations prior to cds_enable
8408 * @hdd_ctx: HDD context
8409 *
8410 * Pre configurations to be done at lower layer before calling cds enable.
8411 *
8412 * Return: 0 on success and errno on failure.
8413 */
8414static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
8415{
8416 int ret;
8417 QDF_STATUS status;
8418 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07008419 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008420
Leo Changfdb45c32016-10-28 11:09:23 -07008421 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008422 /*
8423 * Set 802.11p config
8424 * TODO-OCB: This has been temporarily added here to ensure this
8425 * parameter is set in CSR when we init the channel list. This should
8426 * be removed once the 5.9 GHz channels are added to the regulatory
8427 * domain.
8428 */
8429 hdd_set_dot11p_config(hdd_ctx);
8430
8431 /*
8432 * Note that the cds_pre_enable() sequence triggers the cfg download.
8433 * The cfg download must occur before we update the SME config
8434 * since the SME config operation must access the cfg database
8435 */
8436 status = hdd_set_sme_config(hdd_ctx);
8437
8438 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008439 hdd_err("Failed hdd_set_sme_config: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008440 ret = qdf_status_to_os_return(status);
8441 goto out;
8442 }
8443
Tushnim Bhattacharyyaba8ee932017-03-23 09:27:40 -07008444 status = hdd_set_policy_mgr_user_cfg(hdd_ctx);
8445 if (QDF_STATUS_SUCCESS != status) {
8446 hdd_alert("Failed hdd_set_policy_mgr_user_cfg: %d", status);
8447 ret = qdf_status_to_os_return(status);
8448 goto out;
8449 }
8450
Prashanth Bhatta07998752016-04-28 12:35:33 -07008451 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
8452 hdd_ctx->config->tx_chain_mask_1ss,
8453 PDEV_CMD);
8454 if (0 != ret) {
8455 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
8456 goto out;
8457 }
8458
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008459 ret = hdd_set_smart_chainmask_enabled(hdd_ctx);
8460 if (ret)
8461 goto out;
8462
8463 ret = hdd_set_alternative_chainmask_enabled(hdd_ctx);
8464 if (ret)
8465 goto out;
8466
Jeff Johnson12a744b2017-04-04 08:19:37 -07008467 ret = hdd_set_ani_enabled(hdd_ctx);
8468 if (ret)
8469 goto out;
8470
Srinivas Girigowda70e169a2017-03-07 23:55:57 -08008471 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
8472 hdd_ctx->config->arp_ac_category,
8473 PDEV_CMD);
8474 if (0 != ret) {
8475 hdd_err("WMI_PDEV_PARAM_ARP_AC_OVERRIDE ac: %d ret: %d",
8476 hdd_ctx->config->arp_ac_category, ret);
8477 goto out;
8478 }
8479
8480
Prashanth Bhatta07998752016-04-28 12:35:33 -07008481 status = hdd_set_sme_chan_list(hdd_ctx);
8482 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008483 hdd_err("Failed to init channel list: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008484 ret = qdf_status_to_os_return(status);
8485 goto out;
8486 }
8487
8488 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07008489 if (!hdd_update_config_cfg(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008490 hdd_err("config update failed");
Prashanth Bhatta07998752016-04-28 12:35:33 -07008491 ret = -EINVAL;
8492 goto out;
8493 }
8494
Prashanth Bhatta07998752016-04-28 12:35:33 -07008495 /*
8496 * Set the MAC Address Currently this is used by HAL to add self sta.
8497 * Remove this once self sta is added as part of session open.
8498 */
8499 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
8500 hdd_ctx->config->intfMacAddr[0].bytes,
8501 sizeof(hdd_ctx->config->intfMacAddr[0]));
8502
8503 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
8504 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
8505 hal_status, hal_status);
8506 ret = -EINVAL;
8507 goto out;
8508 }
8509
8510 hdd_init_channel_avoidance(hdd_ctx);
8511
8512out:
8513 return ret;
8514}
8515
8516/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008517 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
8518 * @context_ptr - hdd context pointer
8519 * @event_ptr - event structure pointer
8520 *
8521 * This is the p2p listen offload stop event handler, it sends vendor
8522 * event back to supplicant to notify the stop reason.
8523 *
8524 * Return: None
8525 */
8526static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
8527 void *event_ptr)
8528{
8529 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
8530 struct sir_p2p_lo_event *evt = event_ptr;
8531 struct sk_buff *vendor_event;
8532
8533 ENTER();
8534
8535 if (hdd_ctx == NULL) {
8536 hdd_err("Invalid HDD context pointer");
8537 return;
8538 }
8539
8540 vendor_event =
8541 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8542 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
8543 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
8544 GFP_KERNEL);
8545
8546 if (!vendor_event) {
8547 hdd_err("cfg80211_vendor_event_alloc failed");
8548 return;
8549 }
8550
8551 if (nla_put_u32(vendor_event,
8552 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
8553 evt->reason_code)) {
8554 hdd_err("nla put failed");
8555 kfree_skb(vendor_event);
8556 return;
8557 }
8558
8559 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8560}
8561
8562/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308563 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
8564 * @hdd_ctx: HDD context
8565 *
8566 * This function sends the adaptive dwell time config configuration to the
8567 * firmware via WMA
8568 *
8569 * Return: 0 - success, < 0 - failure
8570 */
8571static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
8572{
8573 QDF_STATUS status;
8574 struct adaptive_dwelltime_params dwelltime_params;
8575
8576 dwelltime_params.is_enabled =
8577 hdd_ctx->config->adaptive_dwell_mode_enabled;
8578 dwelltime_params.dwelltime_mode =
8579 hdd_ctx->config->global_adapt_dwelltime_mode;
8580 dwelltime_params.lpf_weight =
8581 hdd_ctx->config->adapt_dwell_lpf_weight;
8582 dwelltime_params.passive_mon_intval =
8583 hdd_ctx->config->adapt_dwell_passive_mon_intval;
8584 dwelltime_params.wifi_act_threshold =
8585 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
8586
8587 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
8588 &dwelltime_params);
8589
8590 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
8591 if (!QDF_IS_STATUS_SUCCESS(status)) {
8592 hdd_err("Failed to send Adaptive Dwelltime configuration!");
8593 return -EAGAIN;
8594 }
8595 return 0;
8596}
8597
Arun Khandavallid4349a92016-07-25 11:10:43 +05308598#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8599/**
8600 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
8601 * @hdd_ctx: HDD context
8602 *
8603 * Set auto shutdown callback to get indications from firmware to indicate
8604 * userspace to shutdown WLAN after a configured amount of inactivity.
8605 *
8606 * Return: 0 on success and errno on failure.
8607 */
8608static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8609{
8610 QDF_STATUS status;
8611
8612 if (!hdd_ctx->config->WlanAutoShutdown)
8613 return 0;
8614
8615 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
8616 wlan_hdd_auto_shutdown_cb);
8617 if (status != QDF_STATUS_SUCCESS)
8618 hdd_err("Auto shutdown feature could not be enabled: %d",
8619 status);
8620
8621 return qdf_status_to_os_return(status);
8622}
8623#else
8624static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8625{
8626 return 0;
8627}
8628#endif
8629
8630/**
8631 * hdd_features_init() - Init features
8632 * @hdd_ctx: HDD context
8633 * @adapter: Primary adapter context
8634 *
8635 * Initialize features and their feature context after WLAN firmware is up.
8636 *
8637 * Return: 0 on success and errno on failure.
8638 */
8639static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8640{
8641 tSirTxPowerLimit hddtxlimit;
8642 QDF_STATUS status;
8643 int ret;
8644
8645 ENTER();
8646
8647 ret = hdd_update_country_code(hdd_ctx, adapter);
8648 if (ret) {
8649 hdd_err("Failed to update country code: %d", ret);
8650 goto out;
8651 }
8652
8653 /* FW capabilities received, Set the Dot11 mode */
8654 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07008655 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
8656 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308657
Arun Khandavallid4349a92016-07-25 11:10:43 +05308658
8659 if (hdd_ctx->config->fIsImpsEnabled)
8660 hdd_set_idle_ps_config(hdd_ctx, true);
8661 else
8662 hdd_set_idle_ps_config(hdd_ctx, false);
8663
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308664 if (hdd_ctx->config->enable_go_cts2self_for_sta)
Srinivas Girigowdab841da72017-03-25 18:04:39 -07008665 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308666
Arun Khandavallid4349a92016-07-25 11:10:43 +05308667 if (hdd_lro_init(hdd_ctx))
8668 hdd_err("Unable to initialize LRO in fw");
8669
8670 if (hdd_adaptive_dwelltime_init(hdd_ctx))
8671 hdd_err("Unable to send adaptive dwelltime setting to FW");
8672
8673 ret = hdd_init_thermal_info(hdd_ctx);
8674 if (ret) {
8675 hdd_err("Error while initializing thermal information");
8676 goto deregister_frames;
8677 }
8678
Poddar, Siddarth66a46592017-02-22 11:44:44 +05308679 if (cds_is_packet_log_enabled())
8680 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
8681
Arun Khandavallid4349a92016-07-25 11:10:43 +05308682 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
8683 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
8684 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
8685 if (!QDF_IS_STATUS_SUCCESS(status))
8686 hdd_err("Error setting txlimit in sme: %d", status);
8687
8688 hdd_tsf_init(hdd_ctx);
8689
Arun Khandavallid4349a92016-07-25 11:10:43 +05308690 ret = hdd_register_cb(hdd_ctx);
8691 if (ret) {
8692 hdd_err("Failed to register HDD callbacks!");
8693 goto deregister_frames;
8694 }
8695
8696 if (hdd_ctx->config->dual_mac_feature_disable) {
8697 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
8698 if (status != QDF_STATUS_SUCCESS) {
8699 hdd_err("Failed to disable dual mac features");
8700 goto deregister_cb;
8701 }
8702 }
Selvaraj, Sridhar371f55e2017-02-21 10:36:15 +05308703 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8704 status = sme_enable_disable_chanavoidind_event(
8705 hdd_ctx->hHal, 0);
8706 if (!QDF_IS_STATUS_SUCCESS(status)) {
8707 hdd_err("Failed to disable Chan Avoidance Indication");
8708 goto deregister_cb;
8709 }
8710 }
Arun Khandavallid4349a92016-07-25 11:10:43 +05308711
8712 /* register P2P Listen Offload event callback */
8713 if (wma_is_p2p_lo_capable())
8714 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
8715 wlan_hdd_p2p_lo_event_callback);
8716
8717 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
8718
8719 if (ret)
8720 goto deregister_cb;
8721
8722 EXIT();
8723 return 0;
8724
8725deregister_cb:
8726 hdd_deregister_cb(hdd_ctx);
8727deregister_frames:
8728 wlan_hdd_cfg80211_deregister_frames(adapter);
8729out:
8730 return -EINVAL;
8731
8732}
8733
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308734#ifdef NAPIER_SCAN
8735/**
8736 *
8737 * hdd_post_cds_enable_config() - HDD post cds start config helper
8738 * @adapter - Pointer to the HDD
8739 *
8740 * Return: None
8741 */
8742static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8743{
8744 QDF_STATUS status;
8745
8746 status = ucfg_scan_register_bcn_cb(hdd_ctx->hdd_psoc,
8747 wlan_cfg80211_inform_bss_frame,
8748 SCAN_CB_TYPE_INFORM_BCN);
8749 if (!QDF_IS_STATUS_SUCCESS(status)) {
8750 hdd_err("failed with status code %08d [x%08x]",
8751 status, status);
8752 return status;
8753 }
8754
8755 return QDF_STATUS_SUCCESS;
8756}
8757#else
8758static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8759{
8760 return QDF_STATUS_SUCCESS;
8761}
8762
8763#endif
Arun Khandavallid4349a92016-07-25 11:10:43 +05308764
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308765/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308766 * hdd_configure_cds() - Configure cds modules
8767 * @hdd_ctx: HDD context
8768 * @adapter: Primary adapter context
8769 *
8770 * Enable Cds modules after WLAN firmware is up.
8771 *
8772 * Return: 0 on success and errno on failure.
8773 */
8774int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8775{
8776 int ret;
8777 QDF_STATUS status;
Arun Khandavallifae92942016-08-01 13:31:08 +05308778
8779 ret = hdd_pre_enable_configure(hdd_ctx);
8780 if (ret) {
8781 hdd_err("Failed to pre-configure cds");
8782 goto out;
8783 }
8784
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008785 /* Always get latest IPA resources allocated from cds_open and configure
8786 * IPA module before configuring them to FW. Sequence required as crash
8787 * observed otherwise.
8788 */
8789 if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
8790 if (hdd_ipa_uc_ol_init(hdd_ctx)) {
8791 hdd_err("Failed to setup pipes");
8792 goto out;
8793 }
8794 }
8795
Arun Khandavallifae92942016-08-01 13:31:08 +05308796 /*
8797 * Start CDS which starts up the SME/MAC/HAL modules and everything
8798 * else
8799 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308800 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308801
8802 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008803 hdd_err("cds_enable failed");
Arun Khandavallifae92942016-08-01 13:31:08 +05308804 goto out;
8805 }
8806
8807 status = hdd_post_cds_enable_config(hdd_ctx);
8808 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008809 hdd_err("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008810 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308811 }
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308812 status = hdd_register_bcn_cb(hdd_ctx);
8813 if (!QDF_IS_STATUS_SUCCESS(status)) {
8814 hdd_alert("hdd_post_cds_enable_config failed");
8815 goto cds_disable;
8816 }
Arun Khandavallifae92942016-08-01 13:31:08 +05308817
8818 ret = hdd_features_init(hdd_ctx, adapter);
8819 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008820 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308821
Arun Khandavallifae92942016-08-01 13:31:08 +05308822
8823 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008824
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008825cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308826 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008827
Arun Khandavallifae92942016-08-01 13:31:08 +05308828out:
8829 return -EINVAL;
8830}
8831
8832/**
8833 * hdd_deconfigure_cds() -De-Configure cds
8834 * @hdd_ctx: HDD context
8835 *
8836 * Deconfigure Cds modules before WLAN firmware is down.
8837 *
8838 * Return: 0 on success and errno on failure.
8839 */
Jeff Johnson590e2012016-10-05 16:16:24 -07008840static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308841{
8842 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07008843 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308844
8845 ENTER();
8846 /* De-register the SME callbacks */
8847 hdd_deregister_cb(hdd_ctx);
8848
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308849 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308850 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8851 hdd_err("Failed to Disable the CDS Modules! :%d",
8852 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07008853 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308854 }
8855
8856 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07008857 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308858}
8859
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008860#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
8861static void hdd_deregister_policy_manager_callback(
8862 struct wlan_objmgr_psoc *psoc)
8863{
8864 if (QDF_STATUS_SUCCESS !=
8865 policy_mgr_deregister_hdd_cb(psoc)) {
8866 hdd_err("HDD callback deregister with policy manager failed");
8867 }
8868}
8869#else
8870static void hdd_deregister_policy_manager_callback(
8871 struct wlan_objmgr_psoc *psoc)
8872{
8873}
8874#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05308875
8876/**
8877 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
8878 * @hdd_ctx: HDD context
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008879 * @ftm_mode: ftm mode
Arun Khandavallifae92942016-08-01 13:31:08 +05308880 *
8881 * This function maintains the driver state machine it will be invoked from
8882 * exit, shutdown and con_mode change handler. Depending on the driver state
8883 * shall perform the stopping/closing of the modules.
8884 *
8885 * Return: 0 for success; non-zero for failure
8886 */
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008887int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
Arun Khandavallifae92942016-08-01 13:31:08 +05308888{
8889 void *hif_ctx;
8890 qdf_device_t qdf_ctx;
8891 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308892 int ret = 0;
Dustin Brown70111822017-03-30 15:31:40 -07008893 bool is_idle_stop = !cds_is_driver_unloading() &&
8894 !cds_is_driver_recovering();
8895 int active_threads;
Arun Khandavallifae92942016-08-01 13:31:08 +05308896
8897 ENTER();
8898
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008899 hdd_deregister_policy_manager_callback(hdd_ctx->hdd_psoc);
8900
Arun Khandavallifae92942016-08-01 13:31:08 +05308901 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8902 if (!qdf_ctx) {
8903 hdd_err("QDF device context NULL");
8904 return -EINVAL;
8905 }
8906
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308907 mutex_lock(&hdd_ctx->iface_change_lock);
8908 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05308909
Dustin Brown70111822017-03-30 15:31:40 -07008910 active_threads = cds_return_external_threads_count();
8911 if (active_threads > 0 || hdd_ctx->isWiphySuspended) {
Rajeev Kumar86177c22017-03-16 19:44:39 -07008912 hdd_warn("External threads %d wiphy suspend %d",
Dustin Brown70111822017-03-30 15:31:40 -07008913 active_threads, hdd_ctx->isWiphySuspended);
8914
8915 cds_print_external_threads();
8916
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008917 if (is_idle_stop && !ftm_mode) {
Dustin Brown70111822017-03-30 15:31:40 -07008918 mutex_unlock(&hdd_ctx->iface_change_lock);
8919 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008920 hdd_ctx->config->iface_change_wait_time);
8921 hdd_ctx->stop_modules_in_progress = false;
Dustin Brown70111822017-03-30 15:31:40 -07008922 return 0;
8923 }
Rajeev Kumar86177c22017-03-16 19:44:39 -07008924 }
8925
Arun Khandavallifae92942016-08-01 13:31:08 +05308926 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
8927
8928 switch (hdd_ctx->driver_status) {
8929 case DRIVER_MODULES_UNINITIALIZED:
8930 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308931 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308932 case DRIVER_MODULES_CLOSED:
8933 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308934 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308935 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05308936 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308937 if (hdd_deconfigure_cds(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008938 hdd_err("Failed to de-configure CDS");
Arun Khandavallifae92942016-08-01 13:31:08 +05308939 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308940 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308941 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008942 hdd_debug("successfully Disabled the CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05308943 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8944 break;
8945 case DRIVER_MODULES_OPENED:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008946 hdd_debug("Closing CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05308947 break;
8948 default:
8949 hdd_err("Trying to stop wlan in a wrong state: %d",
8950 hdd_ctx->driver_status);
8951 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308952 ret = -EINVAL;
8953 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308954 }
8955
Govind Singhb048e872016-09-27 22:07:43 +05308956 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8957 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8958 hdd_err("Failed to process post CDS disable Modules! :%d",
8959 qdf_status);
8960 ret = -EINVAL;
8961 QDF_ASSERT(0);
8962 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308963 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308964 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008965 hdd_warn("Failed to stop CDS: %d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308966 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308967 QDF_ASSERT(0);
8968 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008969
Arun Khandavallifae92942016-08-01 13:31:08 +05308970 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8971 if (!hif_ctx) {
8972 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308973 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308974 }
8975
8976 hdd_hif_close(hif_ctx);
8977
8978 ol_cds_free();
8979
Dustin Brown70111822017-03-30 15:31:40 -07008980 if (is_idle_stop) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308981 ret = pld_power_off(qdf_ctx->dev);
8982 if (ret)
8983 hdd_err("CNSS power down failed put device into Low power mode:%d",
8984 ret);
8985 }
8986 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07008987 /*
8988 * Reset total mac phy during module stop such that during
8989 * next module start same psoc is used to populate new service
8990 * ready data
8991 */
8992 hdd_ctx->hdd_psoc->total_mac_phy = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308993
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308994done:
8995 hdd_ctx->stop_modules_in_progress = false;
8996 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308997 EXIT();
8998
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308999 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309000
9001}
9002
9003/**
9004 * hdd_iface_change_callback() - Function invoked when stop modules expires
9005 * @priv: pointer to hdd context
9006 *
9007 * This function is invoked when the timer waiting for the interface change
9008 * expires, it shall cut-down the power to wlan and stop all the modules.
9009 *
9010 * Return: void
9011 */
9012static void hdd_iface_change_callback(void *priv)
9013{
9014 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
9015 int ret;
9016 int status = wlan_hdd_validate_context(hdd_ctx);
9017
9018 if (status)
9019 return;
9020
9021 ENTER();
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009022 hdd_debug("Interface change timer expired close the modules!");
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009023 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309024 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009025 hdd_err("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05309026 EXIT();
9027}
9028
9029/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309030 * hdd_state_info_dump() - prints state information of hdd layer
9031 * @buf: buffer pointer
9032 * @size: size of buffer to be filled
9033 *
9034 * This function is used to dump state information of hdd layer
9035 *
9036 * Return: None
9037 */
9038static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
9039{
9040 hdd_context_t *hdd_ctx;
9041 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
9042 QDF_STATUS status;
9043 hdd_station_ctx_t *hdd_sta_ctx;
9044 hdd_adapter_t *adapter;
9045 uint16_t len = 0;
9046 char *buf = *buf_ptr;
9047
9048 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9049 if (!hdd_ctx) {
9050 hdd_err("Failed to get hdd context ");
9051 return;
9052 }
9053
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009054 hdd_debug("size of buffer: %d", *size);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309055
9056 len += scnprintf(buf + len, *size - len,
9057 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
9058 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08009059 "\n is_scheduler_suspended %d",
9060 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309061
9062 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
9063
9064 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
9065 adapter = adapter_node->pAdapter;
9066 if (adapter->dev)
9067 len += scnprintf(buf + len, *size - len,
9068 "\n device name: %s", adapter->dev->name);
9069 len += scnprintf(buf + len, *size - len,
9070 "\n device_mode: %d", adapter->device_mode);
9071 switch (adapter->device_mode) {
9072 case QDF_STA_MODE:
9073 case QDF_P2P_CLIENT_MODE:
9074 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9075 len += scnprintf(buf + len, *size - len,
9076 "\n connState: %d",
9077 hdd_sta_ctx->conn_info.connState);
9078 break;
9079
9080 default:
9081 break;
9082 }
9083 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
9084 adapter_node = next;
9085 }
9086
9087 *size -= len;
9088 *buf_ptr += len;
9089}
9090
9091/**
9092 * hdd_register_debug_callback() - registration function for hdd layer
9093 * to print hdd state information
9094 *
9095 * Return: None
9096 */
9097static void hdd_register_debug_callback(void)
9098{
9099 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
9100}
9101
9102/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009103 * hdd_wlan_startup() - HDD init function
9104 * @dev: Pointer to the underlying device
9105 *
9106 * This is the driver startup code executed once a WLAN device has been detected
9107 *
9108 * Return: 0 for success, < 0 for failure
9109 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309110int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009111{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309112 QDF_STATUS status;
Jeff Johnson957bc272017-02-02 08:54:48 -08009113 hdd_context_t *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009114 int ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009115 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309116 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009117
9118 ENTER();
9119
Arun Khandavallifae92942016-08-01 13:31:08 +05309120 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009121
9122 if (IS_ERR(hdd_ctx))
9123 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009124
Abhishek Singhe9068f12017-03-31 14:14:52 +05309125 ret = hdd_objmgr_create_and_store_psoc(hdd_ctx,
9126 DEFAULT_PSOC_ID);
9127 if (ret) {
9128 hdd_err("Psoc creation fails!");
9129 QDF_BUG(0);
9130 goto err_hdd_free_context;
9131 }
9132
Arun Khandavallifae92942016-08-01 13:31:08 +05309133 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
9134 hdd_iface_change_callback, (void *)hdd_ctx);
9135
9136 mutex_init(&hdd_ctx->iface_change_lock);
9137
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009138 ret = hdd_init_netlink_services(hdd_ctx);
9139 if (ret)
9140 goto err_hdd_free_context;
9141
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009142 hdd_request_manager_init();
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07009143 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309144
Jeff Johnson957bc272017-02-02 08:54:48 -08009145 ret = hdd_wlan_start_modules(hdd_ctx, NULL, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309146 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009147 hdd_err("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009148 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009149 }
9150
Yingying Tang80e15f32016-09-27 18:23:01 +08009151 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152
Yingying Tang95409972016-10-20 15:16:15 +08009153 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009154 hdd_debug("Failed to set wow pulse");
Yingying Tang95409972016-10-20 15:16:15 +08009155
Anurag Chouhan6d760662016-02-20 16:05:43 +05309156 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009157
9158 if (NULL == hdd_ctx->hHal) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009159 hdd_err("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05309160 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009161 }
9162
Prashanth Bhatta07998752016-04-28 12:35:33 -07009163 ret = hdd_wiphy_init(hdd_ctx);
9164 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009165 hdd_err("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05309166 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009167 }
9168
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05309169 if (hdd_ctx->config->enable_dp_trace)
9170 qdf_dp_trace_init();
9171
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309172 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009173 goto err_wiphy_unregister;
9174
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05309175 wlan_hdd_init_chan_info(hdd_ctx);
9176
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07009177 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08009178
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009179 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009180
Jeff Johnson957bc272017-02-02 08:54:48 -08009181 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
9182 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009183 hdd_err("Failed to open interfaces: %d", ret);
Jeff Johnson46bde382017-02-01 15:31:16 -08009184 goto err_release_rtnl_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009185 }
9186
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009187 hdd_release_rtnl_lock();
9188 rtnl_held = false;
9189
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009190 wlan_hdd_update_11n_mode(hdd_ctx->config);
9191
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009192#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05309193 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309194 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009195 hdd_skip_acs_scan_timer_handler,
9196 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309197 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07009198 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04009199 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009200#endif
9201
Nitesh Shah61c10d92016-10-19 19:29:15 +05309202 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
9203 QDF_TIMER_TYPE_SW,
9204 wlan_hdd_change_tdls_mode,
9205 hdd_ctx);
9206
Prashanth Bhattaab004382016-10-11 16:08:11 -07009207 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009208
Jeff Johnson9afc5012016-09-23 13:56:27 -07009209 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009210
Nirav Shahbd36b062016-07-18 11:12:59 +05309211 if (hdd_ctx->rps)
9212 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07009213
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009214 ret = hdd_register_notifiers(hdd_ctx);
9215 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08009216 goto err_close_adapters;
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05309217
9218 status = wlansap_global_init();
9219 if (QDF_IS_STATUS_ERROR(status))
Jeff Johnson957bc272017-02-02 08:54:48 -08009220 goto err_close_adapters;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009221
Komal Seelam8634b772016-09-29 12:12:24 +05309222 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009223 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309224 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009225
bings612b9c42016-11-07 10:52:03 +08009226 if (hdd_enable_egap(hdd_ctx))
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009227 hdd_debug("enhance green ap is not enabled");
bings612b9c42016-11-07 10:52:03 +08009228
Arun Khandavallifae92942016-08-01 13:31:08 +05309229 if (hdd_ctx->config->fIsImpsEnabled)
9230 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309231
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309232 if (hdd_ctx->config->sifs_burst_duration) {
9233 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
9234 hdd_ctx->config->sifs_burst_duration;
9235
9236 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
9237 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
9238 set_value, PDEV_CMD);
9239 }
9240
Arun Khandavallifae92942016-08-01 13:31:08 +05309241 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
9242 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309243
Selvaraj, Sridhar1ffa0ec2017-03-10 09:52:12 +05309244 complete(&wlan_start_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009245 goto success;
9246
Jeff Johnson957bc272017-02-02 08:54:48 -08009247err_close_adapters:
Jeff Johnson46bde382017-02-01 15:31:16 -08009248 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009249
Jeff Johnson46bde382017-02-01 15:31:16 -08009250err_release_rtnl_lock:
Arun Khandavallid4349a92016-07-25 11:10:43 +05309251 if (rtnl_held)
9252 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009253
Anurag Chouhance6a4052016-09-14 18:20:42 +05309254 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08009255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009256err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009257 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009258
Arun Khandavallifae92942016-08-01 13:31:08 +05309259err_stop_modules:
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009260 hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309261
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05309262err_exit_nl_srv:
Arunk Khandavallifbc1ef02017-03-14 21:25:05 +05309263 if (DRIVER_MODULES_CLOSED == hdd_ctx->driver_status) {
9264 status = cds_sched_close(hdd_ctx->pcds_context);
9265 if (!QDF_IS_STATUS_SUCCESS(status)) {
9266 hdd_err("Failed to close CDS Scheduler");
9267 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
9268 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009269 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009270
Houston Hoffman47a4a052016-11-14 23:22:44 -08009271 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009272 hdd_request_manager_deinit();
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009273 hdd_exit_netlink_services(hdd_ctx);
9274
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309275 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009276err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05309277 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
9278 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07009279 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309280 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009282 return -EIO;
9283
9284success:
9285 EXIT();
9286 return 0;
9287}
9288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009289/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309290 * hdd_wlan_update_target_info() - update target type info
9291 * @hdd_ctx: HDD context
9292 * @context: hif context
9293 *
9294 * Update target info received from firmware in hdd context
9295 * Return:None
9296 */
9297
9298void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
9299{
9300 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
9301
9302 if (!tgt_info) {
9303 hdd_err("Target info is Null");
9304 return;
9305 }
9306
9307 hdd_ctx->target_type = tgt_info->target_type;
9308}
9309
9310/**
9311 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309312 * @hdd_ctx: HDD context
9313 *
9314 * Register the HDD callbacks to CDS/SME.
9315 *
9316 * Return: 0 for success or Error code for failure
9317 */
9318int hdd_register_cb(hdd_context_t *hdd_ctx)
9319{
9320 QDF_STATUS status;
9321 int ret = 0;
9322
9323 ENTER();
9324
9325 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
9326
9327 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
9328 hdd_send_oem_data_rsp_msg);
9329
9330 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
9331 wlan_hdd_cfg80211_fw_mem_dump_cb);
9332 if (!QDF_IS_STATUS_SUCCESS(status)) {
9333 hdd_err("Failed to register memdump callback");
9334 ret = -EINVAL;
9335 return ret;
9336 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05309337 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
9338 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309339 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
9340 sme_nan_register_callback(hdd_ctx->hHal,
9341 wlan_hdd_cfg80211_nan_callback);
9342 sme_stats_ext_register_callback(hdd_ctx->hHal,
9343 wlan_hdd_cfg80211_stats_ext_callback);
9344
9345 sme_ext_scan_register_callback(hdd_ctx->hHal,
9346 wlan_hdd_cfg80211_extscan_callback);
9347
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309348 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
9349 hdd_rssi_threshold_breached);
9350
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309351 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
9352 wlan_hdd_cfg80211_link_layer_stats_callback);
9353
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309354 sme_rso_cmd_status_cb(hdd_ctx->hHal, wlan_hdd_rso_cmd_status_cb);
9355
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05309356 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
9357 hdd_lost_link_info_cb);
9358 /* print error and not block the startup process */
9359 if (!QDF_IS_STATUS_SUCCESS(status))
9360 hdd_err("set lost link info callback failed");
9361
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309362 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
9363
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009364 sme_register_set_connection_info_cb(hdd_ctx->hHal,
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009365 hdd_set_connection_in_progress,
9366 hdd_is_connection_in_progress);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309367 EXIT();
9368
9369 return ret;
9370}
9371
9372/**
9373 * hdd_deregister_cb() - De-Register HDD callbacks.
9374 * @hdd_ctx: HDD context
9375 *
9376 * De-Register the HDD callbacks to CDS/SME.
9377 *
9378 * Return: void
9379 */
9380void hdd_deregister_cb(hdd_context_t *hdd_ctx)
9381{
9382 QDF_STATUS status;
9383
9384 ENTER();
9385
9386 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
9387 if (!QDF_IS_STATUS_SUCCESS(status))
9388 hdd_err("De-register of dcc stats callback failed: %d",
9389 status);
9390
9391 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309392 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
9393
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309394 sme_stats_ext_register_callback(hdd_ctx->hHal,
9395 wlan_hdd_cfg80211_stats_ext_callback);
9396
9397 sme_nan_deregister_callback(hdd_ctx->hHal);
9398 status = sme_reset_tsfcb(hdd_ctx->hHal);
9399 if (!QDF_IS_STATUS_SUCCESS(status))
9400 hdd_err("Failed to de-register tsfcb the callback:%d",
9401 status);
9402 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
9403 if (!QDF_IS_STATUS_SUCCESS(status))
9404 hdd_err("Failed to de-register the fw mem dump callback: %d",
9405 status);
9406
9407 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
9408 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
9409
9410 EXIT();
9411}
9412
9413/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009414 * hdd_softap_sta_deauth() - handle deauth req from HDD
9415 * @adapter: Pointer to the HDD
9416 * @enable: bool value
9417 *
9418 * This to take counter measure to handle deauth req from HDD
9419 *
9420 * Return: None
9421 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309422QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009423 struct tagCsrDelStaParams *pDelStaParams)
9424{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309425 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426
9427 ENTER();
9428
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009429 hdd_debug("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009430 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9431
9432 /* Ignore request to deauth bcmc station */
9433 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309434 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309436 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009437 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9438 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009439
9440 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309441 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009442}
9443
9444/**
9445 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
9446 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309447 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009448 *
9449 * This to take counter measure to handle deauth req from HDD
9450 *
9451 * Return: None
9452 */
9453void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309454 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009455{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009456 ENTER();
9457
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009458 hdd_debug("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009459 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9460
9461 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309462 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009463 return;
9464
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009465 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309466 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009467}
9468
9469void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
9470 bool enable)
9471{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009472 ENTER();
9473
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009474 hdd_debug("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009475 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009477 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9478 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009479}
9480
9481/**
9482 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
9483 * @hdd_ctx: HDD Context
9484 *
9485 * API to find if there is any STA or P2P-Client is connected
9486 *
9487 * Return: true if connected; false otherwise
9488 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309489QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009490{
9491 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
9492}
9493
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009494/**
9495 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
9496 * @adapter: HDD adapter pointer
9497 *
9498 * This function loop through each adapter and disable roaming on each STA
9499 * device mode except the input adapter.
9500 *
9501 * Note: On the input adapter roaming is not enabled yet hence no need to
9502 * disable.
9503 *
9504 * Return: None
9505 */
9506void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
9507{
9508 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9509 hdd_adapter_t *adapterIdx = NULL;
9510 hdd_adapter_list_node_t *adapterNode = NULL;
9511 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309512 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009513
9514 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009515 hdd_ctx->config->isRoamOffloadScanEnabled &&
9516 QDF_STA_MODE == adapter->device_mode &&
9517 policy_mgr_is_sta_active_connection_exists(
9518 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009519 hdd_debug("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009520 adapter->sessionId);
9521 /*
9522 * Loop through adapter and disable roaming for each STA device
9523 * mode except the input adapter.
9524 */
9525 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9526
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309527 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009528 adapterIdx = adapterNode->pAdapter;
9529
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009530 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009531 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009532 hdd_debug("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009533 adapterIdx->sessionId);
9534 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
9535 (adapterIdx),
9536 adapterIdx->sessionId, 0);
9537 }
9538
9539 status = hdd_get_next_adapter(hdd_ctx,
9540 adapterNode,
9541 &pNext);
9542 adapterNode = pNext;
9543 }
9544 }
9545}
9546
9547/**
9548 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
9549 * @adapter: HDD adapter pointer
9550 *
9551 * This function loop through each adapter and enable roaming on each STA
9552 * device mode except the input adapter.
9553 * Note: On the input adapter no need to enable roaming because link got
9554 * disconnected on this.
9555 *
9556 * Return: None
9557 */
9558void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
9559{
9560 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9561 hdd_adapter_t *adapterIdx = NULL;
9562 hdd_adapter_list_node_t *adapterNode = NULL;
9563 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309564 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009565
9566 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009567 hdd_ctx->config->isRoamOffloadScanEnabled &&
9568 QDF_STA_MODE == adapter->device_mode &&
9569 policy_mgr_is_sta_active_connection_exists(
9570 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009571 hdd_debug("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009572 adapter->sessionId);
9573 /*
9574 * Loop through adapter and enable roaming for each STA device
9575 * mode except the input adapter.
9576 */
9577 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9578
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309579 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009580 adapterIdx = adapterNode->pAdapter;
9581
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009582 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009583 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009584 hdd_debug("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009585 adapterIdx->sessionId);
9586 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
9587 (adapterIdx),
9588 adapterIdx->sessionId,
9589 REASON_CONNECT);
9590 }
9591
9592 status = hdd_get_next_adapter(hdd_ctx,
9593 adapterNode,
9594 &pNext);
9595 adapterNode = pNext;
9596 }
9597 }
9598}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009599
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309600/**
9601 * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
9602 * @skb: sk buffer pointer
9603 *
9604 * Sends the bcast message to SVC multicast group with generic nl socket
9605 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
9606 *
9607 * Return: None
9608 */
9609static void nl_srv_bcast_svc(struct sk_buff *skb)
9610{
9611#ifdef CNSS_GENL
9612 nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
9613#else
9614 nl_srv_bcast(skb);
9615#endif
9616}
9617
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309618void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009619{
9620 struct sk_buff *skb;
9621 struct nlmsghdr *nlh;
9622 tAniMsgHdr *ani_hdr;
9623 void *nl_data = NULL;
9624 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309625 struct radio_index_tlv *radio_info;
9626 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009627
9628 if (in_interrupt() || irqs_disabled() || in_atomic())
9629 flags = GFP_ATOMIC;
9630
9631 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
9632
Srinivas Girigowdab841da72017-03-25 18:04:39 -07009633 if (skb == NULL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009635
9636 nlh = (struct nlmsghdr *)skb->data;
9637 nlh->nlmsg_pid = 0; /* from kernel */
9638 nlh->nlmsg_flags = 0;
9639 nlh->nlmsg_seq = 0;
9640 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
9641
9642 ani_hdr = NLMSG_DATA(nlh);
9643 ani_hdr->type = type;
9644
9645 switch (type) {
9646 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05309647 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009648 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009649 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009650 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009651 ani_hdr->length = 0;
9652 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009653 break;
9654 case WLAN_SVC_WLAN_STATUS_IND:
9655 case WLAN_SVC_WLAN_VERSION_IND:
9656 case WLAN_SVC_DFS_CAC_START_IND:
9657 case WLAN_SVC_DFS_CAC_END_IND:
9658 case WLAN_SVC_DFS_RADAR_DETECT_IND:
9659 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
9660 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08009661 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05309662 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009663 ani_hdr->length = len;
9664 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
9665 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
9666 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667 break;
9668
9669 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07009670 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009671 type);
9672 kfree_skb(skb);
9673 return;
9674 }
9675
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309676 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08009677 * Add radio index at the end of the svc event in TLV format
9678 * to maintain the backward compatibility with userspace
9679 * applications.
9680 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309681
9682 tlv_len = 0;
9683
9684 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
9685 < WLAN_NL_MAX_PAYLOAD) {
9686 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
9687 sizeof(*ani_hdr) + len);
9688 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
9689 radio_info->length = (unsigned short) sizeof(radio_info->radio);
9690 radio_info->radio = radio;
9691 tlv_len = sizeof(*radio_info);
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009692 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309693 "Added radio index tlv - radio index %d",
9694 radio_info->radio);
9695 }
9696
9697 nlh->nlmsg_len += tlv_len;
9698 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
9699
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309700 nl_srv_bcast_svc(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701}
9702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009703#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
9704void wlan_hdd_auto_shutdown_cb(void)
9705{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07009706 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309707
9708 if (!hdd_ctx)
9709 return;
9710
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009711 hdd_debug("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309712 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
9713 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009714}
9715
9716void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
9717{
9718 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309719 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009720 hdd_adapter_t *adapter;
9721 bool ap_connected = false, sta_connected = false;
9722 tHalHandle hal_handle;
9723
9724 hal_handle = hdd_ctx->hHal;
9725 if (hal_handle == NULL)
9726 return;
9727
9728 if (hdd_ctx->config->WlanAutoShutdown == 0)
9729 return;
9730
9731 if (enable == false) {
9732 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309733 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009734 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009735 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309736 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009737 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009738 return;
9739 }
9740
9741 /* To enable shutdown timer check conncurrency */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009742 if (policy_mgr_concurrent_open_sessions_running(
9743 hdd_ctx->hdd_psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009744 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309746 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009747 adapter = adapterNode->pAdapter;
9748 if (adapter
9749 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009750 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009751 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9752 conn_info.connState ==
9753 eConnectionState_Associated) {
9754 sta_connected = true;
9755 break;
9756 }
9757 }
9758 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009759 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
9761 bApActive == true) {
9762 ap_connected = true;
9763 break;
9764 }
9765 }
9766 status = hdd_get_next_adapter(hdd_ctx,
9767 adapterNode,
9768 &pNext);
9769 adapterNode = pNext;
9770 }
9771 }
9772
9773 if (ap_connected == true || sta_connected == true) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009774 hdd_debug("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009775 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009776 }
Jeff Johnson68755312017-02-10 11:46:55 -08009777
9778 if (sme_set_auto_shutdown_timer(hal_handle,
9779 hdd_ctx->config->WlanAutoShutdown)
9780 != QDF_STATUS_SUCCESS)
9781 hdd_err("Failed to start wlan auto shutdown timer");
9782 else
9783 hdd_notice("Auto Shutdown timer for %d seconds enabled",
9784 hdd_ctx->config->WlanAutoShutdown);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009785}
9786#endif
9787
9788hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
9789 bool check_start_bss)
9790{
9791 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
9792 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309793 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009794 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
9795
9796 con_sap_adapter = NULL;
9797
9798 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309799 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009800 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009801 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
9802 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009803 adapter != this_sap_adapter) {
9804 if (check_start_bss) {
9805 if (test_bit(SOFTAP_BSS_STARTED,
9806 &adapter->event_flags)) {
9807 con_sap_adapter = adapter;
9808 break;
9809 }
9810 } else {
9811 con_sap_adapter = adapter;
9812 break;
9813 }
9814 }
9815 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
9816 adapterNode = pNext;
9817 }
9818
9819 return con_sap_adapter;
9820}
9821
9822#ifdef MSM_PLATFORM
Dustin Brown5ec6b552017-03-31 12:11:40 -07009823static inline bool hdd_adapter_is_sta(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009824{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009825 return adapter->device_mode == QDF_STA_MODE ||
9826 adapter->device_mode == QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009827}
9828
Dustin Brown5ec6b552017-03-31 12:11:40 -07009829static inline bool hdd_adapter_is_ap(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009830{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009831 return adapter->device_mode == QDF_SAP_MODE ||
9832 adapter->device_mode == QDF_P2P_GO_MODE;
9833}
9834
9835static bool hdd_any_adapter_is_assoc(hdd_context_t *hdd_ctx)
9836{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309837 QDF_STATUS status;
Dustin Brown5ec6b552017-03-31 12:11:40 -07009838 hdd_adapter_list_node_t *node;
9839
9840 status = hdd_get_front_adapter(hdd_ctx, &node);
9841 while (QDF_IS_STATUS_SUCCESS(status) && node) {
9842 hdd_adapter_t *adapter = node->pAdapter;
9843
9844 if (adapter &&
9845 hdd_adapter_is_sta(adapter) &&
9846 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9847 conn_info.connState == eConnectionState_Associated) {
9848 return true;
9849 }
9850
9851 if (adapter &&
9852 hdd_adapter_is_ap(adapter) &&
9853 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive) {
9854 return true;
9855 }
9856
9857 status = hdd_get_next_adapter(hdd_ctx, node, &node);
9858 }
9859
9860 return false;
9861}
9862
9863static bool hdd_bus_bw_compute_timer_is_running(hdd_context_t *hdd_ctx)
9864{
9865 bool is_running;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009866
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309867 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown5ec6b552017-03-31 12:11:40 -07009868 is_running = hdd_ctx->bus_bw_timer_running;
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309869 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009870
Dustin Brown5ec6b552017-03-31 12:11:40 -07009871 return is_running;
9872}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009873
Dustin Brown5ec6b552017-03-31 12:11:40 -07009874static void __hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9875{
9876 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9877 hdd_ctx->bus_bw_timer_running = true;
9878 qdf_timer_start(&hdd_ctx->bus_bw_timer,
9879 hdd_ctx->config->busBandwidthComputeInterval);
9880 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9881}
9882
9883void hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9884{
9885 ENTER();
9886
9887 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9888 hdd_debug("Bandwidth compute timer already started");
9889 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009890 }
9891
Dustin Brown5ec6b552017-03-31 12:11:40 -07009892 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9893
9894 EXIT();
9895}
9896
9897void hdd_bus_bw_compute_timer_try_start(hdd_context_t *hdd_ctx)
9898{
9899 ENTER();
9900
9901 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9902 hdd_debug("Bandwidth compute timer already started");
9903 return;
Ravi Joshib89e7f72016-09-07 13:43:15 -07009904 }
Dustin Brown5ec6b552017-03-31 12:11:40 -07009905
9906 if (hdd_any_adapter_is_assoc(hdd_ctx))
9907 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9908
9909 EXIT();
9910}
9911
9912static void __hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9913{
9914 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
9915
9916 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9917 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
9918 hdd_ctx->bus_bw_timer_running = false;
9919 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9920
9921 hdd_reset_tcp_delack(hdd_ctx);
9922}
9923
9924void hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9925{
9926 ENTER();
9927
9928 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9929 hdd_debug("Bandwidth compute timer already stopped");
9930 return;
9931 }
9932
9933 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9934
9935 EXIT();
9936}
9937
9938void hdd_bus_bw_compute_timer_try_stop(hdd_context_t *hdd_ctx)
9939{
9940 ENTER();
9941
9942 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9943 hdd_debug("Bandwidth compute timer already stopped");
9944 return;
9945 }
9946
9947 if (!hdd_any_adapter_is_assoc(hdd_ctx))
9948 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9949
9950 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009951}
9952#endif
9953
9954/**
9955 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
9956 * and sta's operating channel.
9957 * @sta_adapter: Describe the first argument to foobar.
9958 * @ap_adapter: Describe the second argument to foobar.
9959 * @roam_profile: Roam profile of AP to which STA wants to connect.
9960 * @concurrent_chnl_same: If both SAP and STA channels are same then
9961 * set this flag to true else false.
9962 *
9963 * This function checks the sap's operating channel and sta's operating channel.
9964 * if both are same then it will return false else it will restart the sap in
9965 * sta's channel and return true.
9966 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309967 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009968 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309969QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009970 hdd_adapter_t *ap_adapter,
9971 tCsrRoamProfile *roam_profile,
9972 tScanResultHandle *scan_cache,
9973 bool *concurrent_chnl_same)
9974{
9975 hdd_ap_ctx_t *hdd_ap_ctx;
9976 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309977 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009978 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009979 *concurrent_chnl_same = true;
9980
9981 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9982 status =
Archana Ramachandran2eb7a612017-03-23 22:58:42 -07009983 sme_get_ap_channel_from_scan_cache(roam_profile,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009984 scan_cache,
9985 &channel_id);
Srinivas Girigowdab841da72017-03-25 18:04:39 -07009986 if (QDF_STATUS_SUCCESS == status) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009987 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009988 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9989 if (hdd_ap_ctx->operatingChannel != channel_id) {
9990 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009991 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009993 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
9995 if (hdd_ap_ctx->operatingChannel != channel_id) {
9996 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009997 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009998 }
9999 }
10000 } else {
10001 /*
10002 * Lets handle worst case scenario here, Scan cache lookup is
10003 * failed so we have to stop the SAP to avoid any channel
10004 * discrepancy between SAP's channel and STA's channel.
10005 * Return the status as failure so caller function could know
10006 * that scan look up is failed.
10007 */
Jeff Johnson28f8a772016-08-15 15:30:36 -070010008 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010009 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010010 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010011 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012}
10013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010014/**
10015 * wlan_hdd_stop_sap() - This function stops bss of SAP.
10016 * @ap_adapter: SAP adapter
10017 *
10018 * This function will process the stopping of sap adapter.
10019 *
10020 * Return: None
10021 */
10022void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
10023{
10024 hdd_ap_ctx_t *hdd_ap_ctx;
10025 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010026 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010028
10029 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010030 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010031 return;
10032 }
10033
10034 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10035 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053010036 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010037 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +053010038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010039 mutex_lock(&hdd_ctx->sap_lock);
10040 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010041 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010042 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
10043 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010044 hdd_debug("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010045 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010046 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010047 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +053010048 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -080010049 qdf_stop_bss_event,
10050 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010051 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010052 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -070010053 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010054 return;
10055 }
10056 }
10057 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080010058 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
10059 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010060 ap_adapter->sessionId);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010061 hdd_debug("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010062 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010063 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010064 }
10065 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010066}
10067
10068/**
10069 * wlan_hdd_start_sap() - this function starts bss of SAP.
10070 * @ap_adapter: SAP adapter
10071 *
10072 * This function will process the starting of sap adapter.
10073 *
10074 * Return: None
10075 */
Arun Khandavallicc544b32017-01-30 19:52:16 +053010076void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010077{
10078 hdd_ap_ctx_t *hdd_ap_ctx;
10079 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010080 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010081 hdd_context_t *hdd_ctx;
10082 tsap_Config_t *sap_config;
10083
10084 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010085 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010086 return;
10087 }
10088
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010089 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -070010090 hdd_err("SoftAp role has not been enabled");
10091 return;
10092 }
10093
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010094 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
10095 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10096 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10097 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
10098
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010099 mutex_lock(&hdd_ctx->sap_lock);
10100 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
10101 goto end;
10102
10103 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010104 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010105 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
10106 goto end;
10107 }
10108
Wei Song2f76f642016-11-18 16:32:53 +080010109 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010110 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
10111 &hdd_ap_ctx->sapConfig,
10112 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010113 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010114 goto end;
10115
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010116 hdd_debug("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010117 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -080010118 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010119 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010120 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010121 goto end;
10122 }
Jeff Johnson28f8a772016-08-15 15:30:36 -070010123 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -080010125 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080010126 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
10127 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 ap_adapter->sessionId);
10129 hostapd_state->bCommit = true;
10130
10131end:
10132 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010133}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010134
10135/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010136 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
10137 * mac scan config
10138 * @status: Status of set antenna mode
10139 *
10140 * Callback on setting the dual mac configuration
10141 *
10142 * Return: None
10143 */
10144void wlan_hdd_soc_set_antenna_mode_cb(
10145 enum set_antenna_mode_status status)
10146{
10147 hdd_context_t *hdd_ctx;
10148
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010149 hdd_debug("Status: %d", status);
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010150
10151 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10152 if (0 != wlan_hdd_validate_context(hdd_ctx))
10153 return;
10154
10155 /* Signal the completion of set dual mac config */
10156 complete(&hdd_ctx->set_antenna_mode_cmpl);
10157}
10158
10159/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010160 * hdd_get_fw_version() - Get FW version
10161 * @hdd_ctx: pointer to HDD context.
10162 * @major_spid: FW version - major spid.
10163 * @minor_spid: FW version - minor spid
10164 * @ssid: FW version - ssid
10165 * @crmid: FW version - crmid
10166 *
10167 * This function is called to get the firmware build version stored
10168 * as part of the HDD context
10169 *
10170 * Return: None
10171 */
10172void hdd_get_fw_version(hdd_context_t *hdd_ctx,
10173 uint32_t *major_spid, uint32_t *minor_spid,
10174 uint32_t *siid, uint32_t *crmid)
10175{
10176 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
10177 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
10178 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
10179 *crmid = hdd_ctx->target_fw_version & 0x7fff;
10180}
10181
10182#ifdef QCA_CONFIG_SMP
10183/**
10184 * wlan_hdd_get_cpu() - get cpu_index
10185 *
10186 * Return: cpu_index
10187 */
10188int wlan_hdd_get_cpu(void)
10189{
10190 int cpu_index = get_cpu();
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010191
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010192 put_cpu();
10193 return cpu_index;
10194}
10195#endif
10196
10197/**
10198 * hdd_get_fwpath() - get framework path
10199 *
10200 * This function is used to get the string written by
10201 * userspace to start the wlan driver
10202 *
10203 * Return: string
10204 */
10205const char *hdd_get_fwpath(void)
10206{
10207 return fwpath.string;
10208}
10209
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010210/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010211 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010212 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010213 * This function initilizes CDS global context with the help of cds_init. This
10214 * has to be the first function called after probe to get a valid global
10215 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010216 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010217 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010218 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010219int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010220{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010221 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010222 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010223
Houston Hoffman9e06e542016-12-12 12:06:26 -080010224 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010225#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10226 wlan_logging_sock_init_svc();
10227#endif
10228
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010229 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010230 hdd_err("Failed to allocate CDS context");
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010231 ret = -ENOMEM;
10232 goto err_out;
10233 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010234
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010235 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +053010236 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010237
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010238err_out:
10239 return ret;
10240}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010241
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010242/**
10243 * hdd_deinit() - Deinitialize Driver
10244 *
10245 * This function frees CDS global context with the help of cds_deinit. This
10246 * has to be the last function call in remove callback to free the global
10247 * context.
10248 */
10249void hdd_deinit(void)
10250{
10251 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010252
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010253#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10254 wlan_logging_sock_deinit_svc();
10255#endif
10256}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010257
Yue Ma6e7b1a02017-04-03 14:17:46 -070010258#ifdef QCA_WIFI_NAPIER_EMULATION
10259#define HDD_WLAN_START_WAIT_TIME ((CDS_WMA_TIMEOUT + 5000) * 100)
10260#else
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010261#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
Yue Ma6e7b1a02017-04-03 14:17:46 -070010262#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010263
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010264/**
10265 * __hdd_module_init - Module init helper
10266 *
10267 * Module init helper function used by both module and static driver.
10268 *
10269 * Return: 0 for success, errno on failure
10270 */
10271static int __hdd_module_init(void)
10272{
10273 int ret = 0;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010274 unsigned long rc;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010275
Arun Khandavallifae92942016-08-01 13:31:08 +053010276 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010277 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010278
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010279 pld_init();
10280
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010281 ret = hdd_init();
10282 if (ret) {
10283 pr_err("hdd_init failed %x\n", ret);
10284 goto err_hdd_init;
10285 }
10286
Rajeev Kumar97767a02016-11-30 11:20:40 -080010287 dispatcher_init();
10288
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010289 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010290
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010291 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010292
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010293 init_completion(&wlan_start_comp);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010294 ret = wlan_hdd_register_driver();
10295 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -070010296 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
10297 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010298 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010299 }
10300
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010301 rc = wait_for_completion_timeout(&wlan_start_comp,
10302 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
10303
10304 if (!rc) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010305 hdd_err("Timed-out waiting for wlan_hdd_register_driver");
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010306 QDF_BUG(0);
10307 goto out;
10308 }
10309
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010310 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010311
10312 return 0;
10313out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010314 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -080010315 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010316 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010317
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010318err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010319 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010320
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010321 return ret;
10322}
10323
10324/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010325 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
10326 *
10327 * Block the unloading of the driver until the cds recovery is completed
10328 *
10329 * Return: None
10330 */
10331static void hdd_wait_for_recovery_completion(void)
10332{
10333 int retry = 0;
10334
10335 /* Wait for recovery to complete */
10336 while (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010337 hdd_err("Recovery in progress; wait here!!!");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010338 msleep(1000);
10339 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010340 hdd_err("SSR never completed, error");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010341 QDF_BUG(0);
10342 }
10343 }
10344}
10345
10346/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010347 * __hdd_module_exit - Module exit helper
10348 *
10349 * Module exit helper function used by both module and static driver.
10350 */
10351static void __hdd_module_exit(void)
10352{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010353 int qdf_print_idx = -1;
10354
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010355 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
10356 QWLAN_VERSIONSTR);
10357
bings6028ee82017-03-29 07:51:40 +080010358 cds_set_unload_in_progress(true);
10359
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010360 hdd_wait_for_recovery_completion();
10361
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010362 wlan_hdd_unregister_driver();
10363
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010364 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010365
Rajeev Kumar97767a02016-11-30 11:20:40 -080010366 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010367 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010368 pld_deinit();
10369
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010370 qdf_print_idx = qdf_get_pidx();
10371 qdf_print_ctrl_cleanup(qdf_print_idx);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010372}
10373
Arun Khandavallifae92942016-08-01 13:31:08 +053010374#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010375/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010376 * wlan_boot_cb() - Wlan boot callback
10377 * @kobj: object whose directory we're creating the link in.
10378 * @attr: attribute the user is interacting with
10379 * @buff: the buffer containing the user data
10380 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010381 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010382 * This callback is invoked when the fs is ready to start the
10383 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010384 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010385 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010386 */
Arun Khandavallifae92942016-08-01 13:31:08 +053010387static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010388 struct kobj_attribute *attr,
10389 const char *buf,
10390 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010391{
Arun Khandavallifae92942016-08-01 13:31:08 +053010392
Arun Khandavallifae92942016-08-01 13:31:08 +053010393 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010394 pr_err("%s: wlan driver already initialized\n", __func__);
10395 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +053010396 }
10397
Arun Khandavallifae92942016-08-01 13:31:08 +053010398 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010399 pr_err("%s: wlan driver initialization failed\n", __func__);
10400 return -EIO;
10401 }
10402
10403 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +053010404
10405 return count;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010406}
Arun Khandavallifae92942016-08-01 13:31:08 +053010407
10408/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010409 * hdd_sysfs_cleanup() - cleanup sysfs
10410 *
10411 * Return: None
10412 *
10413 */
10414static void hdd_sysfs_cleanup(void)
10415{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010416 /* remove from group */
10417 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
10418 sysfs_remove_group(wlan_loader->boot_wlan_obj,
10419 wlan_loader->attr_group);
10420
10421 /* unlink the object from parent */
10422 kobject_del(wlan_loader->boot_wlan_obj);
10423
10424 /* free the object */
10425 kobject_put(wlan_loader->boot_wlan_obj);
10426
10427 kfree(wlan_loader->attr_group);
10428 kfree(wlan_loader);
10429
10430 wlan_loader = NULL;
10431}
10432
10433/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010434 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
10435 * ready
10436 *
10437 * This is creates the syfs entry boot_wlan. Which shall be invoked
10438 * when the filesystem is ready.
10439 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010440 * QDF API cannot be used here since this function is called even before
10441 * initializing WLAN driver.
10442 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010443 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +053010444 */
10445static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010446{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010447 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010448
10449 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010450 if (!wlan_loader)
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010451 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010452
10453 wlan_loader->boot_wlan_obj = NULL;
10454 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
10455 GFP_KERNEL);
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010456 if (!wlan_loader->attr_group)
Arun Khandavallifae92942016-08-01 13:31:08 +053010457 goto error_return;
Arun Khandavallifae92942016-08-01 13:31:08 +053010458
10459 wlan_loader->loaded_state = 0;
10460 wlan_loader->attr_group->attrs = attrs;
10461
10462 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
10463 kernel_kobj);
10464 if (!wlan_loader->boot_wlan_obj) {
10465 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010466 goto error_return;
10467 }
10468
10469 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
10470 wlan_loader->attr_group);
10471 if (ret) {
10472 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
10473 goto error_return;
10474 }
10475
10476 return 0;
10477
10478error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010479 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +053010480
10481 return ret;
10482}
10483
10484/**
10485 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
10486 *
10487 * Return: 0 on success or errno on failure
10488 */
10489static int wlan_deinit_sysfs(void)
10490{
Arun Khandavallifae92942016-08-01 13:31:08 +053010491 if (!wlan_loader) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010492 hdd_err("wlan loader context is Null!");
Arun Khandavallifae92942016-08-01 13:31:08 +053010493 return -EINVAL;
10494 }
10495
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010496 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010497 return 0;
10498}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010499
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010500#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +053010501
10502#ifdef MODULE
10503/**
10504 * __hdd_module_init - Module init helper
10505 *
10506 * Module init helper function used by both module and static driver.
10507 *
10508 * Return: 0 for success, errno on failure
10509 */
10510static int hdd_module_init(void)
10511{
10512 int ret = 0;
10513
10514 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
10515 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
10516
10517 if (__hdd_module_init()) {
10518 pr_err("%s: Failed to register handler\n", __func__);
10519 ret = -EINVAL;
10520 }
10521
10522 return ret;
10523}
10524#else
10525static int __init hdd_module_init(void)
10526{
10527 int ret = -EINVAL;
10528
10529 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010530 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +053010531 pr_err("Failed to create sysfs entry for loading wlan");
10532
10533 return ret;
10534}
10535#endif
10536
10537
10538#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010539/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010540 * hdd_module_exit() - Exit function
10541 *
10542 * This is the driver exit point (invoked when module is unloaded using rmmod)
10543 *
10544 * Return: None
10545 */
10546static void __exit hdd_module_exit(void)
10547{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010548 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010549}
Arun Khandavallifae92942016-08-01 13:31:08 +053010550#else
10551static void __exit hdd_module_exit(void)
10552{
10553 __hdd_module_exit();
10554 wlan_deinit_sysfs();
10555}
10556#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010557
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010558static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
10559{
10560 return param_set_copystring(kmessage, kp);
10561}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010562
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010563/**
10564 * is_con_mode_valid() check con mode is valid or not
10565 * @mode: global con mode
10566 *
10567 * Return: TRUE on success FALSE on failure
10568 */
10569static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
10570{
10571 switch (mode) {
10572 case QDF_GLOBAL_MONITOR_MODE:
10573 case QDF_GLOBAL_FTM_MODE:
10574 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010575 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010576 return true;
10577 default:
10578 return false;
10579 }
10580}
10581
10582/**
10583 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
10584 * @mode: global con mode
10585 *
10586 * Return: adapter mode
10587 */
10588static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
10589 enum tQDF_GLOBAL_CON_MODE mode)
10590{
10591
10592 switch (mode) {
10593 case QDF_GLOBAL_MISSION_MODE:
10594 return QDF_STA_MODE;
10595 case QDF_GLOBAL_MONITOR_MODE:
10596 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010597 case QDF_GLOBAL_EPPING_MODE:
10598 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010599 case QDF_GLOBAL_FTM_MODE:
10600 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010601 case QDF_GLOBAL_QVIT_MODE:
10602 return QDF_QVIT_MODE;
10603 default:
10604 return QDF_MAX_NO_OF_MODE;
10605 }
10606}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010607
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010608static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
10609 enum tQDF_GLOBAL_CON_MODE curr_mode)
10610{
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010611 int driver_status;
10612
10613 driver_status = hdd_ctx->driver_status;
10614
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010615 switch (curr_mode) {
10616 case QDF_GLOBAL_MISSION_MODE:
10617 case QDF_GLOBAL_MONITOR_MODE:
10618 case QDF_GLOBAL_FTM_MODE:
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010619 if (driver_status != DRIVER_MODULES_CLOSED) {
10620 hdd_abort_mac_scan_all_adapters(hdd_ctx);
10621 hdd_stop_all_adapters(hdd_ctx);
10622 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010623 hdd_deinit_all_adapters(hdd_ctx, false);
10624 hdd_close_all_adapters(hdd_ctx, false);
10625 break;
10626 case QDF_GLOBAL_EPPING_MODE:
10627 epping_disable();
10628 epping_close();
10629 break;
10630 default:
10631 return;
10632 }
10633}
10634
10635static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
10636 enum tQDF_GLOBAL_CON_MODE mode)
10637{
10638 hdd_adapter_t *adapter;
10639 int ret = 0;
10640 bool rtnl_held;
10641 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
10642 QDF_STATUS status;
10643
10644 if (!qdf_dev) {
10645 hdd_err("qdf device context is Null return!");
10646 return -EINVAL;
10647 }
10648
10649 rtnl_held = hdd_hold_rtnl_lock();
10650 switch (mode) {
10651 case QDF_GLOBAL_MISSION_MODE:
Jeff Johnson957bc272017-02-02 08:54:48 -080010652 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
10653 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010654 hdd_err("Failed to open interfaces: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010655 break;
10656 case QDF_GLOBAL_FTM_MODE:
10657 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
10658 wlan_hdd_get_intf_addr(hdd_ctx),
10659 NET_NAME_UNKNOWN, rtnl_held);
10660 if (adapter == NULL)
10661 ret = -EINVAL;
10662 break;
10663 case QDF_GLOBAL_MONITOR_MODE:
10664 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
10665 wlan_hdd_get_intf_addr(hdd_ctx),
10666 NET_NAME_UNKNOWN, rtnl_held);
10667 if (adapter == NULL)
10668 ret = -EINVAL;
10669 break;
10670 case QDF_GLOBAL_EPPING_MODE:
10671 status = epping_open();
Srinivas Girigowdab841da72017-03-25 18:04:39 -070010672 if (status != QDF_STATUS_SUCCESS) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010673 hdd_err("Failed to open in eeping mode: %d", status);
10674 ret = -EINVAL;
10675 break;
10676 }
10677 ret = epping_enable(qdf_dev->dev);
10678 if (ret) {
10679 hdd_err("Failed to enable in epping mode : %d", ret);
10680 epping_close();
10681 }
10682 break;
10683 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010684 hdd_err("Mode not supported");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010685 ret = -ENOTSUPP;
10686 break;
10687 }
10688 hdd_release_rtnl_lock();
10689 rtnl_held = false;
10690 return ret;
10691}
10692
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010693/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010694 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010695 * @kmessage: con mode name on which driver to be bring up
10696 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010697 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010698 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010699 * This function is invoked when user updates con mode using sys entry,
10700 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010701 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010702 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010703 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010704static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
10705 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010706{
10707 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +053010708 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010709 enum tQDF_GLOBAL_CON_MODE curr_mode;
10710 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010711
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010712 ret = wlan_hdd_validate_context(hdd_ctx);
10713 if (ret)
10714 return ret;
10715
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010716 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010717
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010718 hdd_debug("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010719 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +053010720
Arun Khandavallifae92942016-08-01 13:31:08 +053010721
Arun Khandavallia172c3e2016-08-26 17:33:13 +053010722
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010723 if (!(is_con_mode_valid(con_mode))) {
10724 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010725 ret = -EINVAL;
10726 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010727 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010728
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010729 curr_mode = hdd_get_conparam();
10730 if (curr_mode == con_mode) {
10731 hdd_err("curr mode: %d is same as user triggered mode %d",
10732 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010733 ret = 0;
10734 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010735 }
10736
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010737 /* Cleanup present mode before switching to new mode */
10738 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +053010739
Rajeev Kumar3fef4e82017-03-31 20:25:23 -070010740 ret = hdd_wlan_stop_modules(hdd_ctx, true);
Arun Khandavallifae92942016-08-01 13:31:08 +053010741 if (ret) {
10742 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010743 goto reset_flags;
10744 }
10745
10746 hdd_set_conparam(con_mode);
10747
10748 /* Register for new con_mode & then kick_start modules again */
10749 ret = hdd_register_req_mode(hdd_ctx, con_mode);
10750 if (ret) {
10751 hdd_err("Failed to register for new mode");
10752 goto reset_flags;
10753 }
10754
10755 adapter_mode = hdd_get_adpter_mode(con_mode);
10756 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
10757 hdd_err("invalid adapter");
10758 ret = -EINVAL;
10759 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010760 }
10761
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010762 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +053010763 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010764 hdd_err("Failed to get adapter:%d", adapter_mode);
10765 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010766 }
10767
10768 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
10769 if (ret) {
10770 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010771 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010772 }
10773
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010774 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
10775 con_mode == QDF_GLOBAL_FTM_MODE) {
10776 if (hdd_start_adapter(adapter)) {
10777 hdd_err("Failed to start %s adapter", kmessage);
10778 ret = -EINVAL;
10779 goto reset_flags;
10780 }
Arun Khandavallifae92942016-08-01 13:31:08 +053010781 }
10782
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010783 hdd_info("Mode successfully changed to %s", kmessage);
10784 ret = 0;
10785
10786reset_flags:
10787 cds_set_load_in_progress(false);
10788 return ret;
10789}
10790
10791
10792static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
10793{
10794 int ret;
10795 hdd_context_t *hdd_ctx;
10796
10797 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10798 ret = wlan_hdd_validate_context(hdd_ctx);
10799 if (ret)
10800 return ret;
10801
10802 cds_ssr_protect(__func__);
10803 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
10804 cds_ssr_unprotect(__func__);
10805
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010806 return ret;
10807}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010808
10809/**
10810 * hdd_get_conparam() - driver exit point
10811 *
10812 * This is the driver exit point (invoked when module is unloaded using rmmod)
10813 *
Anurag Chouhan6d760662016-02-20 16:05:43 +053010814 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010815 */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010816enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010817{
Anurag Chouhan6d760662016-02-20 16:05:43 +053010818 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010819}
10820
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010821void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010822{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010823 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010824}
10825
Komal Seelamc11bb222016-01-27 18:57:10 +053010826/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010827 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
10828 * @hdd_ctx: HDD context
10829 *
10830 * Cleans up the pre cac interface, if it exists
10831 *
10832 * Return: None
10833 */
10834void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
10835{
10836 uint8_t session_id;
10837 QDF_STATUS status;
10838 struct hdd_adapter_s *precac_adapter;
10839
10840 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
10841 if (QDF_IS_STATUS_ERROR(status)) {
10842 hdd_err("failed to get pre cac vdev id");
10843 return;
10844 }
10845
10846 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
10847 if (!precac_adapter) {
10848 hdd_err("invalid pre cac adapater");
10849 return;
10850 }
10851
10852 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
10853 wlan_hdd_sap_pre_cac_failure,
10854 (void *)precac_adapter);
10855 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
10856
10857}
10858
10859/**
Komal Seelamec702b02016-02-24 18:42:16 +053010860 * hdd_update_ol_config - API to update ol configuration parameters
10861 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +053010862 *
Komal Seelamc11bb222016-01-27 18:57:10 +053010863 * Return: void
10864 */
Komal Seelamec702b02016-02-24 18:42:16 +053010865static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +053010866{
Komal Seelamec702b02016-02-24 18:42:16 +053010867 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010868 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +053010869
Komal Seelamec702b02016-02-24 18:42:16 +053010870 if (!ol_ctx)
10871 return;
10872
10873 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
10874 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
10875 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
10876 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -070010877 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +053010878
10879 ol_init_ini_config(ol_ctx, &cfg);
10880}
10881
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010882#ifdef FEATURE_RUNTIME_PM
10883/**
10884 * hdd_populate_runtime_cfg() - populate runtime configuration
10885 * @hdd_ctx: hdd context
10886 * @cfg: pointer to the configuration memory being populated
10887 *
10888 * Return: void
10889 */
10890static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10891 struct hif_config_info *cfg)
10892{
10893 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
10894 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
10895}
10896#else
10897static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10898 struct hif_config_info *cfg)
10899{
10900}
10901#endif
10902
Komal Seelamec702b02016-02-24 18:42:16 +053010903/**
10904 * hdd_update_hif_config - API to update HIF configuration parameters
10905 * @hdd_ctx: HDD Context
10906 *
10907 * Return: void
10908 */
10909static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
10910{
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010911 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +053010912 struct hif_config_info cfg;
10913
10914 if (!scn)
10915 return;
10916
10917 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010918 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053010919 hif_init_ini_config(scn, &cfg);
10920}
10921
10922/**
10923 * hdd_update_config() - Initialize driver per module ini parameters
10924 * @hdd_ctx: HDD Context
10925 *
10926 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010927 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053010928 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010929int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053010930{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010931 int ret;
10932
Komal Seelamec702b02016-02-24 18:42:16 +053010933 hdd_update_ol_config(hdd_ctx);
10934 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010935 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
10936 ret = hdd_update_cds_config_ftm(hdd_ctx);
10937 else
10938 ret = hdd_update_cds_config(hdd_ctx);
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -080010939 ret = hdd_update_user_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010940
10941 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053010942}
10943
Mukul Sharma9d797a02017-01-05 20:26:03 +053010944#ifdef FEATURE_WLAN_RA_FILTERING
10945/**
10946 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
10947 * @psoc_cfg: pmo psoc Configuration
10948 * @hdd_ctx: Pointer to hdd context
10949 *
10950 * Return: none
10951 */
10952static inline void hdd_ra_populate_pmo_config(
10953 struct pmo_psoc_cfg *psoc_cfg,
10954 hdd_context_t *hdd_ctx)
10955{
10956 psoc_cfg->ra_ratelimit_interval =
10957 hdd_ctx->config->RArateLimitInterval;
10958 psoc_cfg->ra_ratelimit_enable =
10959 hdd_ctx->config->IsRArateLimitEnabled;
10960}
10961#else
10962static inline void hdd_ra_populate_pmo_config(
10963 struct cds_config_info *cds_cfg,
10964 hdd_context_t *hdd_ctx)
10965{
10966}
10967#endif
10968/**
10969 * hdd_update_pmo_config - API to update pmo configuration parameters
10970 * @hdd_ctx: HDD context
10971 *
10972 * Return: void
10973 */
10974static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
10975{
10976 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10977 struct pmo_psoc_cfg psoc_cfg;
10978 QDF_STATUS status;
10979
10980 /*
10981 * Value of hdd_ctx->wowEnable can be,
10982 * 0 - Disable both magic pattern match and pattern byte match.
10983 * 1 - Enable magic pattern match on all interfaces.
10984 * 2 - Enable pattern byte match on all interfaces.
10985 * 3 - Enable both magic patter and pattern byte match on
10986 * all interfaces.
10987 */
10988 psoc_cfg.magic_ptrn_enable =
10989 (hdd_ctx->config->wowEnable & 0x01) ? true : false;
10990 psoc_cfg.ptrn_match_enable_all_vdev =
10991 (hdd_ctx->config->wowEnable & 0x02) ? true : false;
10992 psoc_cfg.bpf_enable =
10993 hdd_ctx->config->bpf_packet_filter_enable;
10994 psoc_cfg.arp_offload_enable = hdd_ctx->config->fhostArpOffload;
10995 psoc_cfg.ns_offload_enable_static = hdd_ctx->config->fhostNSOffload;
10996 if (hdd_ctx->config->fhostNSOffload)
10997 psoc_cfg.ns_offload_enable_dynamic = true;
10998 psoc_cfg.ssdp = hdd_ctx->config->ssdp;
10999 psoc_cfg.enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
11000 psoc_cfg.active_mode_offload =
11001 hdd_ctx->config->active_mode_offload;
11002 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
11003 psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters;
Mukul Sharma9223f232017-03-08 18:42:27 +053011004 psoc_cfg.sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
11005 psoc_cfg.sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
11006 psoc_cfg.sta_max_li_mod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
11007 psoc_cfg.power_save_mode =
11008 hdd_ctx->config->enablePowersaveOffload;
Mukul Sharma9d797a02017-01-05 20:26:03 +053011009
11010 hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9223f232017-03-08 18:42:27 +053011011 hdd_nan_populate_pmo_config(&psoc_cfg, hdd_ctx);
11012 hdd_lpass_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053011013 status = pmo_ucfg_update_psoc_config(psoc, &psoc_cfg);
11014 if (status != QDF_STATUS_SUCCESS) {
11015 hdd_err("failed pmo psoc configuration");
11016 return -EINVAL;
11017 }
11018
11019 return 0;
11020}
11021
Abhishek Singh257a9482017-03-06 16:52:39 +053011022#ifdef NAPIER_SCAN
Abhishek Singhb20db962017-03-03 21:28:46 +053011023
11024#ifdef FEATURE_WLAN_SCAN_PNO
11025static inline void hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
11026 struct hdd_config *cfg)
11027{
11028 pno_cfg->channel_prediction = cfg->pno_channel_prediction;
11029 pno_cfg->top_k_num_of_channels = cfg->top_k_num_of_channels;
11030 pno_cfg->stationary_thresh = cfg->stationary_thresh;
11031 pno_cfg->adaptive_dwell_mode = cfg->adaptive_dwell_mode_enabled;
11032 pno_cfg->channel_prediction_full_scan =
11033 cfg->channel_prediction_full_scan;
11034}
11035#else
11036static inline void
11037hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
11038 struct hdd_config *cfg)
11039{
11040 return;
11041}
11042#endif
11043
Abhishek Singh257a9482017-03-06 16:52:39 +053011044/**
11045 * hdd_update_scan_config - API to update scan configuration parameters
11046 * @hdd_ctx: HDD context
11047 *
11048 * Return: 0 if success else err
11049 */
11050static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
11051{
11052 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
11053 struct scan_user_cfg scan_cfg;
11054 struct hdd_config *cfg = hdd_ctx->config;
11055 QDF_STATUS status;
11056
11057 scan_cfg.active_dwell = cfg->nActiveMaxChnTime;
11058 scan_cfg.passive_dwell = cfg->nPassiveMaxChnTime;
11059 scan_cfg.conc_active_dwell = cfg->nActiveMaxChnTimeConc;
11060 scan_cfg.conc_passive_dwell = cfg->nPassiveMaxChnTimeConc;
11061 scan_cfg.conc_max_rest_time = cfg->nRestTimeConc;
11062 scan_cfg.conc_min_rest_time = cfg->min_rest_time_conc;
11063 scan_cfg.conc_idle_time = cfg->idle_time_conc;
11064 scan_cfg.scan_cache_aging_time = cfg->scanAgingTimeout;
11065 scan_cfg.scan_dwell_time_mode = cfg->scan_adaptive_dwell_mode;
Kapil Guptafa9a8c62017-04-10 15:25:40 +053011066 scan_cfg.is_snr_monitoring_enabled = cfg->fEnableSNRMonitoring;
Abhishek Singh257a9482017-03-06 16:52:39 +053011067
Abhishek Singhb20db962017-03-03 21:28:46 +053011068 hdd_update_pno_config(&scan_cfg.pno_cfg, cfg);
11069
Abhishek Singh257a9482017-03-06 16:52:39 +053011070 status = ucfg_scan_update_user_config(psoc, &scan_cfg);
11071 if (status != QDF_STATUS_SUCCESS) {
11072 hdd_err("failed pmo psoc configuration");
11073 return -EINVAL;
11074 }
11075
11076 return 0;
11077}
11078#else
11079static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
11080{
11081 return 0;
11082}
11083#endif
11084
Mukul Sharma9d797a02017-01-05 20:26:03 +053011085int hdd_update_components_config(hdd_context_t *hdd_ctx)
11086{
11087 int ret;
11088
11089 ret = hdd_update_pmo_config(hdd_ctx);
Abhishek Singh257a9482017-03-06 16:52:39 +053011090 if (ret)
11091 return ret;
11092 ret = hdd_update_scan_config(hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053011093
11094 return ret;
11095}
11096
Agrawal Ashish65634612016-08-18 13:24:32 +053011097/**
11098 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
11099 * @mode : cfg80211 DFS mode
11100 *
11101 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
11102 */
11103enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
11104{
11105 switch (mode) {
11106 case DFS_MODE_ENABLE:
11107 return ACS_DFS_MODE_ENABLE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011108 case DFS_MODE_DISABLE:
11109 return ACS_DFS_MODE_DISABLE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011110 case DFS_MODE_DEPRIORITIZE:
11111 return ACS_DFS_MODE_DEPRIORITIZE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011112 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011113 hdd_debug("ACS dfs mode is NONE");
11114 return ACS_DFS_MODE_NONE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011115 }
11116}
11117
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011118/**
11119 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
11120 * @hddctx: pointer to hdd context
11121 * @set_value: enable/disable
11122 *
11123 * When Host sends vendor command enable, FW will send *ONE* CA ind to
11124 * Host(even though it is duplicate). When Host send vendor command
11125 * disable,FW doesn't perform any action. Whenever any change in
11126 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
11127 *
11128 * return - 0 on success, appropriate error values on failure.
11129 */
11130int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
11131{
11132 QDF_STATUS status;
11133
Srinivas Girigowdab841da72017-03-25 18:04:39 -070011134 if (0 != wlan_hdd_validate_context(hddctx))
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011135 return -EAGAIN;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011136
11137 if (!hddctx->config->goptimize_chan_avoid_event) {
11138 hdd_warn("goptimize_chan_avoid_event ini param disabled");
11139 return -EINVAL;
11140 }
11141
11142 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
11143 if (!QDF_IS_STATUS_SUCCESS(status)) {
11144 hdd_err("Failed to send chan avoid command to SME");
11145 return -EINVAL;
11146 }
11147 return 0;
11148}
Agrawal Ashish65634612016-08-18 13:24:32 +053011149
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011150/**
11151 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
11152 * @value: value to set
11153 *
11154 * This function will set the passed value to roaming in progress flag.
11155 *
11156 * Return: None
11157 */
11158void hdd_set_roaming_in_progress(bool value)
11159{
11160 hdd_context_t *hdd_ctx;
11161
11162 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11163 if (!hdd_ctx) {
11164 hdd_err("HDD context is NULL");
11165 return;
11166 }
11167
11168 hdd_ctx->roaming_in_progress = value;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011169 hdd_debug("Roaming in Progress set to %d", value);
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011170}
11171
11172/**
11173 * hdd_is_roaming_in_progress() - check if roaming is in progress
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011174 * @adapter - HDD adapter
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011175 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011176 * Return: true if roaming is in progress for STA type, else false
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011177 */
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011178bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter)
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011179{
11180 hdd_context_t *hdd_ctx;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011181 bool ret_status = false;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011182
11183 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11184 if (!hdd_ctx) {
11185 hdd_err("HDD context is NULL");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011186 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011187 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011188 hdd_debug("dev mode = %d, roaming_in_progress = %d",
11189 adapter->device_mode, hdd_ctx->roaming_in_progress);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011190 ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
11191 hdd_ctx->roaming_in_progress);
11192
11193 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011194}
11195
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011196/**
11197 * hdd_is_connection_in_progress() - check if connection is in
11198 * progress
11199 * @session_id: session id
11200 * @reason: scan reject reason
11201 *
11202 * Go through each adapter and check if Connection is in progress
11203 *
11204 * Return: true if connection is in progress else false
11205 */
11206bool hdd_is_connection_in_progress(uint8_t *session_id,
11207 enum scan_reject_states *reason)
11208{
11209 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
11210 hdd_station_ctx_t *hdd_sta_ctx = NULL;
11211 hdd_adapter_t *adapter = NULL;
11212 QDF_STATUS status = 0;
11213 uint8_t sta_id = 0;
11214 uint8_t *sta_mac = NULL;
11215 hdd_context_t *hdd_ctx;
11216
11217 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11218 if (!hdd_ctx) {
11219 hdd_err("HDD context is NULL");
11220 return false;
11221 }
11222
11223 if (true == hdd_ctx->btCoexModeSet) {
11224 hdd_info("BTCoex Mode operation in progress");
11225 return true;
11226 }
11227 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
11228 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
11229 adapter = adapter_node->pAdapter;
11230 if (!adapter)
11231 goto end;
11232
11233 hdd_info("Adapter with device mode %s(%d) exists",
11234 hdd_device_mode_to_string(adapter->device_mode),
11235 adapter->device_mode);
11236 if (((QDF_STA_MODE == adapter->device_mode)
11237 || (QDF_P2P_CLIENT_MODE == adapter->device_mode)
11238 || (QDF_P2P_DEVICE_MODE == adapter->device_mode))
11239 && (eConnectionState_Connecting ==
11240 (WLAN_HDD_GET_STATION_CTX_PTR(adapter))->
11241 conn_info.connState)) {
11242 hdd_err("%p(%d) Connection is in progress",
11243 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11244 adapter->sessionId);
11245 if (session_id && reason) {
11246 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011247 *reason = CONNECTION_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011248 }
11249 return true;
11250 }
Archana Ramachandran62886ce2017-03-24 14:46:32 -070011251 /*
11252 * sme_neighbor_middle_of_roaming is for LFR2
11253 * hdd_is_roaming_in_progress is for LFR3
11254 */
11255 if (((QDF_STA_MODE == adapter->device_mode) &&
11256 sme_neighbor_middle_of_roaming(
11257 WLAN_HDD_GET_HAL_CTX(adapter),
11258 adapter->sessionId)) ||
11259 hdd_is_roaming_in_progress(adapter)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011260 hdd_err("%p(%d) Reassociation in progress",
11261 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11262 adapter->sessionId);
11263 if (session_id && reason) {
11264 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011265 *reason = REASSOC_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011266 }
11267 return true;
11268 }
11269 if ((QDF_STA_MODE == adapter->device_mode) ||
11270 (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
11271 (QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
11272 hdd_sta_ctx =
11273 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
11274 if ((eConnectionState_Associated ==
11275 hdd_sta_ctx->conn_info.connState)
11276 && (false ==
11277 hdd_sta_ctx->conn_info.uIsAuthenticated)) {
11278 sta_mac = (uint8_t *)
11279 &(adapter->macAddressCurrent.bytes[0]);
11280 hdd_err("client " MAC_ADDRESS_STR
11281 " is in middle of WPS/EAPOL exchange.",
11282 MAC_ADDR_ARRAY(sta_mac));
11283 if (session_id && reason) {
11284 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011285 *reason = EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011286 }
11287 return true;
11288 }
11289 } else if ((QDF_SAP_MODE == adapter->device_mode) ||
11290 (QDF_P2P_GO_MODE == adapter->device_mode)) {
11291 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
11292 sta_id++) {
11293 if (!((adapter->aStaInfo[sta_id].isUsed)
11294 && (OL_TXRX_PEER_STATE_CONN ==
11295 adapter->aStaInfo[sta_id].tlSTAState)))
11296 continue;
11297
11298 sta_mac = (uint8_t *)
11299 &(adapter->aStaInfo[sta_id].
11300 macAddrSTA.bytes[0]);
11301 hdd_err("client " MAC_ADDRESS_STR
11302 " of SAP/GO is in middle of WPS/EAPOL exchange",
11303 MAC_ADDR_ARRAY(sta_mac));
11304 if (session_id && reason) {
11305 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011306 *reason = SAP_EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011307 }
11308 return true;
11309 }
11310 if (hdd_ctx->connection_in_progress) {
11311 hdd_err("AP/GO: connection is in progress");
11312 return true;
11313 }
11314 }
11315end:
11316 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
11317 adapter_node = next;
11318 }
11319 return false;
11320}
11321
11322/**
11323 * hdd_restart_sap() - to restart SAP in driver internally
11324 * @ap_adapter: Pointer to SAP hdd_adapter_t structure
11325 *
11326 * Return: None
11327 */
11328void hdd_restart_sap(hdd_adapter_t *ap_adapter)
11329{
11330 hdd_ap_ctx_t *hdd_ap_ctx;
11331 hdd_hostapd_state_t *hostapd_state;
11332 QDF_STATUS qdf_status;
11333 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
11334 tsap_Config_t *sap_config;
11335 void *sap_ctx;
11336
11337 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11338 sap_config = &hdd_ap_ctx->sapConfig;
11339 sap_ctx = hdd_ap_ctx->sapContext;
11340
11341 mutex_lock(&hdd_ctx->sap_lock);
11342 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
11343 wlan_hdd_del_station(ap_adapter);
11344 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
11345 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11346 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
11347 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {
11348 qdf_status =
11349 qdf_wait_single_event(&hostapd_state->
11350 qdf_stop_bss_event,
11351 SME_CMD_TIMEOUT_VALUE);
11352
11353 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11354 cds_err("SAP Stop Failed");
11355 goto end;
11356 }
11357 }
11358 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011359 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011360 ap_adapter->device_mode, ap_adapter->sessionId);
11361 cds_err("SAP Stop Success");
11362
11363 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
11364 cds_err("SAP Not able to set AP IEs");
11365 wlansap_reset_sap_config_add_ie(sap_config,
11366 eUPDATE_IE_ALL);
11367 goto end;
11368 }
11369
11370 qdf_event_reset(&hostapd_state->qdf_event);
11371 if (wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb,
11372 sap_config,
11373 ap_adapter->dev) != QDF_STATUS_SUCCESS) {
11374 cds_err("SAP Start Bss fail");
11375 wlansap_reset_sap_config_add_ie(sap_config,
11376 eUPDATE_IE_ALL);
11377 goto end;
11378 }
11379
11380 cds_info("Waiting for SAP to start");
11381 qdf_status =
11382 qdf_wait_single_event(&hostapd_state->qdf_event,
11383 SME_CMD_TIMEOUT_VALUE);
11384 wlansap_reset_sap_config_add_ie(sap_config,
11385 eUPDATE_IE_ALL);
11386 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11387 cds_err("SAP Start failed");
11388 goto end;
11389 }
11390 cds_err("SAP Start Success");
11391 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
11392 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011393 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
11394 ap_adapter->device_mode,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011395 ap_adapter->sessionId);
11396 hostapd_state->bCommit = true;
11397 }
11398end:
11399 mutex_unlock(&hdd_ctx->sap_lock);
11400 return;
11401}
11402
11403/**
11404 * hdd_check_and_restart_sap_with_non_dfs_acs() - Restart SAP
11405 * with non dfs acs
11406 *
11407 * Restarts SAP in non-DFS ACS mode when STA-AP mode DFS is not supported
11408 *
11409 * Return: None
11410 */
11411void hdd_check_and_restart_sap_with_non_dfs_acs(void)
11412{
11413 hdd_adapter_t *ap_adapter;
11414 hdd_context_t *hdd_ctx;
11415 cds_context_type *cds_ctx;
11416
11417 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11418 if (!hdd_ctx) {
11419 cds_err("HDD context is NULL");
11420 return;
11421 }
11422
11423 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
11424 if (!cds_ctx) {
11425 cds_err("Invalid CDS Context");
11426 return;
11427 }
11428
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011429 if (policy_mgr_get_concurrency_mode(hdd_ctx->hdd_psoc)
11430 != (QDF_STA_MASK | QDF_SAP_MASK)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011431 cds_info("Concurrency mode is not SAP");
11432 return;
11433 }
11434
11435 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11436 if (ap_adapter != NULL &&
11437 test_bit(SOFTAP_BSS_STARTED,
11438 &ap_adapter->event_flags)
11439 && CDS_IS_DFS_CH(ap_adapter->sessionCtx.ap.
11440 operatingChannel)) {
11441
11442 cds_warn("STA-AP Mode DFS not supported. Restart SAP with Non DFS ACS");
11443 ap_adapter->sessionCtx.ap.sapConfig.channel =
11444 AUTO_CHANNEL_SELECT;
11445 ap_adapter->sessionCtx.ap.sapConfig.
11446 acs_cfg.acs_mode = true;
11447
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011448 hdd_restart_sap(ap_adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011449 }
11450}
11451
11452/**
11453 * hdd_set_connection_in_progress() - to set the connection in
11454 * progress flag
11455 * @value: value to set
11456 *
11457 * This function will set the passed value to connection in progress flag.
11458 * If value is previously being set to true then no need to set it again.
11459 *
11460 * Return: true if value is being set correctly and false otherwise.
11461 */
11462bool hdd_set_connection_in_progress(bool value)
11463{
11464 bool status = true;
11465 hdd_context_t *hdd_ctx;
11466
11467 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11468 if (!hdd_ctx) {
11469 cds_err("HDD context is NULL");
11470 return false;
11471 }
11472
11473 qdf_spin_lock(&hdd_ctx->connection_status_lock);
11474 /*
11475 * if the value is set to true previously and if someone is
11476 * trying to make it true again then it could be some race
11477 * condition being triggered. Avoid this situation by returning
11478 * false
11479 */
11480 if (hdd_ctx->connection_in_progress && value)
11481 status = false;
11482 else
11483 hdd_ctx->connection_in_progress = value;
11484 qdf_spin_unlock(&hdd_ctx->connection_status_lock);
11485 return status;
11486}
11487
Archana Ramachandranb8c04f92017-03-17 20:05:47 -070011488int wlan_hdd_send_p2p_quota(hdd_adapter_t *adapter, int set_value)
11489{
11490 if (!adapter) {
11491 hdd_err("Invalid adapter");
11492 return -EINVAL;
11493 }
11494 hdd_info("Send MCC P2P QUOTA to WMA: %d", set_value);
11495 wma_cli_set_command(adapter->sessionId,
11496 WMA_VDEV_MCC_SET_TIME_QUOTA,
11497 set_value, VDEV_CMD);
11498 return 0;
11499
11500}
11501
11502int wlan_hdd_send_mcc_latency(hdd_adapter_t *adapter, int set_value)
11503{
11504 if (!adapter) {
11505 hdd_err("Invalid adapter");
11506 return -EINVAL;
11507 }
11508
11509 hdd_info("Send MCC latency WMA: %d", set_value);
11510 wma_cli_set_command(adapter->sessionId,
11511 WMA_VDEV_MCC_SET_TIME_LATENCY,
11512 set_value, VDEV_CMD);
11513 return 0;
11514}
11515
Archana Ramachandranea34c4f2017-03-19 18:56:18 -070011516hdd_adapter_t *wlan_hdd_get_adapter_from_vdev(struct wlan_objmgr_psoc
11517 *psoc, uint8_t vdev_id)
11518{
11519 hdd_adapter_t *adapter = NULL;
11520 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11521
11522 /*
11523 * Currently PSOC is not being used. But this logic will
11524 * change once we have the converged implementation of
11525 * HDD context per PSOC in place. This would break if
11526 * multiple vdev objects reuse the vdev id.
11527 */
11528 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
11529 if (!adapter)
11530 hdd_err("Get adapter by vdev id failed");
11531
11532 return adapter;
11533}
11534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535/* Register the module init/exit functions */
11536module_init(hdd_module_init);
11537module_exit(hdd_module_exit);
11538
11539MODULE_LICENSE("Dual BSD/GPL");
11540MODULE_AUTHOR("Qualcomm Atheros, Inc.");
11541MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
11542
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
11544 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545
11546module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
11547 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
11548
11549module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
11550
11551module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
11552
11553module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);