blob: 9960bdd647ba620e31675965a6be68c5eed71783 [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"
Krishna Kumaar Natarajaned1efd92016-09-24 18:05:47 -070096#include "wlan_hdd_he.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097
98#include <wlan_hdd_ipa.h>
99#include "hif.h"
100#include "wma.h"
101#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700102#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530104#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700105#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700106#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530107#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700108#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530109#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800110#include <dispatcher_init_deinit.h>
Rajeev Kumar699debf2017-01-06 14:17:00 -0800111#include "wlan_hdd_object_manager.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530112#include "cds_utils.h"
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -0800113#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800114#include <qca_vendor.h>
Mukul Sharma9d797a02017-01-05 20:26:03 +0530115#include "wlan_pmo_ucfg_api.h"
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +0530116#include "sir_api.h"
Naveen Rawat910726a2017-03-06 11:42:51 -0800117#include "os_if_wifi_pos.h"
118#include "wifi_pos_api.h"
119#include "wlan_hdd_oemdata.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +0530121#ifdef CNSS_GENL
122#include <net/cnss_nl.h>
123#endif
124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800125#ifdef MODULE
126#define WLAN_MODULE_NAME module_name(THIS_MODULE)
127#else
128#define WLAN_MODULE_NAME "wlan"
129#endif
130
131#ifdef TIMER_MANAGER
132#define TIMER_MANAGER_STR " +TIMER_MANAGER"
133#else
134#define TIMER_MANAGER_STR ""
135#endif
136
137#ifdef MEMORY_DEBUG
138#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
139#else
140#define MEMORY_DEBUG_STR ""
141#endif
142
Arun Khandavallifae92942016-08-01 13:31:08 +0530143#ifndef MODULE
144static struct gwlan_loader *wlan_loader;
145static ssize_t wlan_boot_cb(struct kobject *kobj,
146 struct kobj_attribute *attr,
147 const char *buf, size_t count);
148struct gwlan_loader {
149 bool loaded_state;
150 struct kobject *boot_wlan_obj;
151 struct attribute_group *attr_group;
152};
153
154static struct kobj_attribute wlan_boot_attribute =
155 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
156
157static struct attribute *attrs[] = {
158 &wlan_boot_attribute.attr,
159 NULL,
160};
161
162#define MODULE_INITIALIZED 1
163#endif
164
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165/* the Android framework expects this param even though we don't use it */
166#define BUF_LEN 20
167static char fwpath_buffer[BUF_LEN];
168static struct kparam_string fwpath = {
169 .string = fwpath_buffer,
170 .maxlen = BUF_LEN,
171};
172
173static char *country_code;
174static int enable_11d = -1;
175static int enable_dfs_chan_scan = -1;
176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177/*
178 * spinlock for synchronizing asynchronous request/response
179 * (full description of use in wlan_hdd_main.h)
180 */
181DEFINE_SPINLOCK(hdd_context_lock);
182
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800183#define WLAN_NLINK_CESIUM 30
184
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530185static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186
187#define WOW_MAX_FILTER_LISTS 1
188#define WOW_MAX_FILTERS_PER_LIST 4
189#define WOW_MIN_PATTERN_SIZE 6
190#define WOW_MAX_PATTERN_SIZE 64
191
192#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
193static const struct wiphy_wowlan_support wowlan_support_reg_init = {
194 .flags = WIPHY_WOWLAN_ANY |
195 WIPHY_WOWLAN_MAGIC_PKT |
196 WIPHY_WOWLAN_DISCONNECT |
197 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
198 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
199 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
200 WIPHY_WOWLAN_4WAY_HANDSHAKE |
201 WIPHY_WOWLAN_RFKILL_RELEASE,
202 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
203 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
204 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
205};
206#endif
207
208/* internal function declaration */
209
210struct sock *cesium_nl_srv_sock;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +0530211struct completion wlan_start_comp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
213void wlan_hdd_auto_shutdown_cb(void);
214#endif
215
216/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530217 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
218 * @hdd_ctx: pointer to hdd_context_t
219 *
220 * Return: none
221 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700222static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530223{
224 hdd_adapter_t *adapter;
225 hdd_adapter_list_node_t *adapter_node, *next;
226 QDF_STATUS status = QDF_STATUS_SUCCESS;
227
228 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
229 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
230 adapter = adapter_node->pAdapter;
231 if (NULL != adapter)
232 hdd_send_rps_ind(adapter);
233 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
234 adapter_node = next;
235 }
236}
237
238/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
240 * @vdev_id: vdev_id
241 * @action: action type
242 * @reason: reason type
243 *
244 * Return: none
245 */
246void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
247 enum netif_action_type action, enum netif_reason_type reason)
248{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530249 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250 hdd_adapter_t *adapter;
251
252 if (!hdd_ctx) {
253 hdd_err("hdd ctx is NULL");
254 return;
255 }
256 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
257
258 wlan_hdd_netif_queue_control(adapter, action, reason);
259 return;
260}
261
262/*
263 * Store WLAN driver version info in a global variable such that crash debugger
264 * can extract it from driver debug symbol and crashdump for post processing
265 */
266uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
267
268/**
269 * hdd_device_mode_to_string() - return string conversion of device mode
270 * @device_mode: device mode
271 *
272 * This utility function helps log string conversion of device mode.
273 *
274 * Return: string conversion of device mode, if match found;
275 * "Unknown" otherwise.
276 */
277const char *hdd_device_mode_to_string(uint8_t device_mode)
278{
279 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800280 CASE_RETURN_STRING(QDF_STA_MODE);
281 CASE_RETURN_STRING(QDF_SAP_MODE);
282 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
283 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
284 CASE_RETURN_STRING(QDF_FTM_MODE);
285 CASE_RETURN_STRING(QDF_IBSS_MODE);
286 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
287 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700288 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 default:
290 return "Unknown";
291 }
292}
293
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530294/**
295 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
296 * @adapter: HDD adapter
297 * @chan_number: Channel number
298 * @chan_bw: Bandwidth
299 *
300 * Checks if the given bandwidth is valid for the given channel number.
301 *
302 * Return: 0 for success, non-zero for failure
303 */
304int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
305 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800306 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530307{
308 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
309 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
310 bool found = false;
311 tHalHandle hal;
312
313 hal = WLAN_HDD_GET_HAL_CTX(adapter);
314 if (!hal) {
315 hdd_err("Invalid HAL context");
316 return -EINVAL;
317 }
318
319 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
320 hdd_err("No valid channel list");
321 return -EOPNOTSUPP;
322 }
323
324 for (i = 0; i < len; i++) {
325 if (chan[i] == chan_number) {
326 found = true;
327 break;
328 }
329 }
330
331 if (found == false) {
332 hdd_err("Channel not in driver's valid channel list");
333 return -EOPNOTSUPP;
334 }
335
336 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
337 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
338 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
339 return -EINVAL;
340 }
341
342 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
343 if (chan_bw == CH_WIDTH_80MHZ) {
344 hdd_err("BW80 not possible in 2.4GHz band");
345 return -EINVAL;
346 }
347 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
348 (chan_bw != CH_WIDTH_MAX)) {
349 hdd_err("Only BW20 possible on channel 14");
350 return -EINVAL;
351 }
352 }
353
354 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
355 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
356 (chan_bw != CH_WIDTH_MAX)) {
357 hdd_err("Only BW20 possible on channel 165");
358 return -EINVAL;
359 }
360 }
361
362 return 0;
363}
364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365static int __hdd_netdev_notifier_call(struct notifier_block *nb,
366 unsigned long state, void *data)
367{
368#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
369 struct netdev_notifier_info *dev_notif_info = data;
370 struct net_device *dev = dev_notif_info->dev;
371#else
372 struct net_device *dev = data;
373#endif
374 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
375 hdd_context_t *hdd_ctx;
376
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800377 ENTER_DEV(dev);
378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379 /* Make sure that this callback corresponds to our device. */
380 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
381 return NOTIFY_DONE;
382
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530383 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700385 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 return NOTIFY_DONE;
387 }
388
389 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700390 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 return NOTIFY_DONE;
392 }
393
394 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
395 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700396 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530397 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 return NOTIFY_DONE;
399 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800400 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 return NOTIFY_DONE;
402
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700403 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800404 dev->name, state);
405
406 switch (state) {
407 case NETDEV_REGISTER:
408 break;
409
410 case NETDEV_UNREGISTER:
411 break;
412
413 case NETDEV_UP:
414 sme_ch_avoid_update_req(hdd_ctx->hHal);
415 break;
416
417 case NETDEV_DOWN:
418 break;
419
420 case NETDEV_CHANGE:
421 if (true == adapter->isLinkUpSvcNeeded)
422 complete(&adapter->linkup_event_var);
423 break;
424
425 case NETDEV_GOING_DOWN:
426 if (adapter->scan_info.mScanPending != false) {
427 unsigned long rc;
428 INIT_COMPLETION(adapter->scan_info.
429 abortscan_event_var);
430 hdd_abort_mac_scan(adapter->pHddCtx,
431 adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530432 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 eCSR_SCAN_ABORT_DEFAULT);
434 rc = wait_for_completion_timeout(
435 &adapter->scan_info.abortscan_event_var,
436 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
437 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700438 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439 }
440 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700441 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 }
443 break;
444
445 default:
446 break;
447 }
448
449 return NOTIFY_DONE;
450}
451
452/**
453 * hdd_netdev_notifier_call() - netdev notifier callback function
454 * @nb: pointer to notifier block
455 * @state: state
456 * @ndev: ndev pointer
457 *
458 * Return: 0 on success, error number otherwise.
459 */
460static int hdd_netdev_notifier_call(struct notifier_block *nb,
461 unsigned long state,
462 void *ndev)
463{
464 int ret;
465
466 cds_ssr_protect(__func__);
467 ret = __hdd_netdev_notifier_call(nb, state, ndev);
468 cds_ssr_unprotect(__func__);
469
470 return ret;
471}
472
473struct notifier_block hdd_netdev_notifier = {
474 .notifier_call = hdd_netdev_notifier_call,
475};
476
477/* variable to hold the insmod parameters */
478static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800479
480/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530483/**
484 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
485 * @ch_width: NL channel width
486 *
487 * Converts the NL channel width to the driver's internal representation
488 *
489 * Return: Converted channel width. In case of non matching NL channel width,
490 * CH_WIDTH_MAX will be returned.
491 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800492enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530493{
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800494 uint8_t fw_ch_bw;
495 fw_ch_bw = wma_get_vht_ch_width();
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530496 switch (ch_width) {
497 case NL80211_CHAN_WIDTH_20_NOHT:
498 case NL80211_CHAN_WIDTH_20:
499 return CH_WIDTH_20MHZ;
500 case NL80211_CHAN_WIDTH_40:
501 return CH_WIDTH_40MHZ;
502 break;
503 case NL80211_CHAN_WIDTH_80:
504 return CH_WIDTH_80MHZ;
505 case NL80211_CHAN_WIDTH_80P80:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800506 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
507 return CH_WIDTH_80P80MHZ;
508 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
509 return CH_WIDTH_160MHZ;
510 else
511 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530512 case NL80211_CHAN_WIDTH_160:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800513 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
514 return CH_WIDTH_160MHZ;
515 else
516 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530517 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800518 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530519 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800520 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530521 default:
522 hdd_err("Invalid channel width %d, setting to default",
523 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800524 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530525 }
526}
527
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530528/* wlan_hdd_find_opclass() - Find operating class for a channel
529 * @hal: handler to HAL
530 * @channel: channel id
531 * @bw_offset: bandwidth offset
532 *
533 * Function invokes sme api to find the operating class
534 *
535 * Return: operating class
536 */
537uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
538 uint8_t bw_offset)
539{
540 uint8_t opclass = 0;
541
542 sme_get_opclass(hal, channel, bw_offset, &opclass);
543 return opclass;
544}
545
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530547 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530548 * @module_id: Module whose trace level is being configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 * @bitmask: Bitmask of log levels to be enabled
550 *
551 * Called immediately after the cfg.ini is read in order to configure
552 * the desired trace levels.
553 *
554 * Return: None
555 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530556int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530558 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530559 int qdf_print_idx = -1;
560 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 /*
562 * if the bitmask is the default value, then a bitmask was not
563 * specified in cfg.ini, so leave the logging level alone (it
564 * will remain at the "compiled in" default value)
565 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530566 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530567 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 }
569
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 }
587 level++;
588 bitmask >>= 1;
589 }
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530590 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591}
592
593/**
594 * wlan_hdd_validate_context() - check the HDD context
595 * @hdd_ctx: HDD context pointer
596 *
597 * Return: 0 if the context is valid. Error code otherwise
598 */
599int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
600{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530602 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 return -ENODEV;
604 }
605
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800606 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530607 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
608 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609 return -EAGAIN;
610 }
611
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800612 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530613 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
614 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 return -EAGAIN;
616 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530617
618 if (hdd_ctx->start_modules_in_progress ||
619 hdd_ctx->stop_modules_in_progress) {
620 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
621 (void *)_RET_IP_);
622 return -EAGAIN;
623 }
624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625 return 0;
626}
627
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628/**
629 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
630 * @hdd_adapter_t Hdd adapter.
631 *
632 * This function sets the IBSS power save config parameters to WMA
633 * which will send it to firmware if FW supports IBSS power save
634 * before vdev start.
635 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530636 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637 * on failure.
638 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530639QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640{
641 int ret;
642 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
643
644 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700645 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530646 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647 }
648
649 ret = wma_cli_set_command(adapter->sessionId,
650 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
651 hdd_ctx->config->ibssATIMWinSize,
652 VDEV_CMD);
653 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700654 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530655 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 }
657
658 ret = wma_cli_set_command(adapter->sessionId,
659 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
660 hdd_ctx->config->isIbssPowerSaveAllowed,
661 VDEV_CMD);
662 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700663 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
664 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530665 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800666 }
667
668 ret = wma_cli_set_command(adapter->sessionId,
669 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
670 hdd_ctx->config->
671 isIbssPowerCollapseAllowed, VDEV_CMD);
672 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700673 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
674 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530675 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 }
677
678 ret = wma_cli_set_command(adapter->sessionId,
679 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
680 hdd_ctx->config->isIbssAwakeOnTxRx,
681 VDEV_CMD);
682 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700683 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530684 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 }
686
687 ret = wma_cli_set_command(adapter->sessionId,
688 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
689 hdd_ctx->config->ibssInactivityCount,
690 VDEV_CMD);
691 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700692 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530693 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 }
695
696 ret = wma_cli_set_command(adapter->sessionId,
697 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
698 hdd_ctx->config->ibssTxSpEndInactivityTime,
699 VDEV_CMD);
700 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700701 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
702 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530703 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 }
705
706 ret = wma_cli_set_command(adapter->sessionId,
707 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
708 hdd_ctx->config->ibssPsWarmupTime,
709 VDEV_CMD);
710 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700711 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
712 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530713 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 }
715
716 ret = wma_cli_set_command(adapter->sessionId,
717 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
718 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
719 VDEV_CMD);
720 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700721 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
722 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530723 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 }
725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530726 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727}
728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729#define INTF_MACADDR_MASK 0x7
730
731/**
732 * hdd_update_macaddr() - update mac address
733 * @config: hdd configuration
734 * @hw_macaddr: mac address
735 *
736 * Mac address for multiple virtual interface is found as following
737 * i) The mac address of the first interface is just the actual hw mac address.
738 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
739 * define the mac address for the remaining interfaces and locally
740 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
741 * supported virtual interfaces, right now this is 0x07 (meaning 8
742 * interface).
743 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
744 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
745 *
746 * Return: None
747 */
748void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530749 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800750{
751 int8_t i;
752 uint8_t macaddr_b3, tmp_br3;
753
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530754 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530755 QDF_MAC_ADDR_SIZE);
756 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530757 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530758 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 macaddr_b3 = config->intfMacAddr[i].bytes[3];
760 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
761 INTF_MACADDR_MASK;
762 macaddr_b3 += tmp_br3;
763
764 /* XOR-ing bit-24 of the mac address. This will give enough
765 * mac address range before collision
766 */
767 macaddr_b3 ^= (1 << 7);
768
769 /* Set locally administered bit */
770 config->intfMacAddr[i].bytes[0] |= 0x02;
771 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700772 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 MAC_ADDRESS_STR, i,
774 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
775 }
776}
777
778static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
779 struct wma_tgt_services *cfg)
780{
781 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782
783 /* Set up UAPSD */
784 config->apUapsdEnabled &= cfg->uapsd;
785
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786 /* 11AC mode support */
787 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
788 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
789 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790
791 /* ARP offload: override user setting if invalid */
792 config->fhostArpOffload &= cfg->arp_offload;
793
794#ifdef FEATURE_WLAN_SCAN_PNO
795 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700796 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800797 if (cfg->pno_offload)
798 config->PnoOffload = true;
799#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800#ifdef FEATURE_WLAN_TDLS
801 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530802 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
803 cfg->en_tdls_offchan;
804 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
805 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
807 config->fEnableTDLSSleepSta = true;
808 } else {
809 config->fEnableTDLSSleepSta = false;
810 }
811#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812#ifdef WLAN_FEATURE_ROAM_OFFLOAD
813 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
814#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700815 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816
817}
818
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700819/**
820 * hdd_update_vdev_nss() - sets the vdev nss
821 * @hdd_ctx: HDD context
822 *
823 * Sets the Nss per vdev type based on INI
824 *
825 * Return: None
826 */
827static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
828{
829 struct hdd_config *cfg_ini = hdd_ctx->config;
830 uint8_t max_supp_nss = 1;
831
Naveen Rawat10b1c152017-01-18 11:16:06 -0800832 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700833 max_supp_nss = 2;
834
835 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
836 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
837
838 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
839 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
840}
841
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
843 struct wma_tgt_ht_cap *cfg)
844{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530845 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 uint32_t value, val32;
847 uint16_t val16;
848 struct hdd_config *pconfig = hdd_ctx->config;
849 tSirMacHTCapabilityInfo *phtCapInfo;
850 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
851 uint8_t enable_tx_stbc;
852
853 /* check and update RX STBC */
854 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
855 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
856
857 /* get the MPDU density */
858 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
859
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530860 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700861 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862 value = 0;
863 }
864
865 /*
866 * MPDU density:
867 * override user's setting if value is larger
868 * than the one supported by target
869 */
870 if (value > cfg->mpdu_density) {
871 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
872 cfg->mpdu_density);
873
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530874 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700875 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876 }
877
878 /* get the HT capability info */
879 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530880 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700881 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 return;
883 }
884 val16 = (uint16_t) val32;
885 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
886
887 /* Set the LDPC capability */
888 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
889
890 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
891 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
892
893 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
894 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
895
896 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
897 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
898
899 enable_tx_stbc = pconfig->enableTxSTBC;
900
901 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
902 pconfig->enable2x2 = 1;
903 } else {
904 pconfig->enable2x2 = 0;
905 enable_tx_stbc = 0;
906
907 /* 1x1 */
908 /* Update Rx Highest Long GI data Rate */
909 if (sme_cfg_set_int(hdd_ctx->hHal,
910 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700911 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530912 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700913 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 }
915
916 /* Update Tx Highest Long GI data Rate */
917 if (sme_cfg_set_int
918 (hdd_ctx->hHal,
919 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700920 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530921 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700922 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 }
924 }
925 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
926 enable_tx_stbc = 0;
927 phtCapInfo->txSTBC = enable_tx_stbc;
928
929 val32 = val16;
930 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530931 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700932 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800933#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
934 value = SIZE_OF_SUPPORTED_MCS_SET;
935 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530936 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700937 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800938
939 if (pconfig->enable2x2) {
940 for (value = 0; value < cfg->num_rf_chains; value++)
941 mcs_set[value] =
942 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
943
944 status =
945 sme_cfg_set_str(hdd_ctx->hHal,
946 WNI_CFG_SUPPORTED_MCS_SET,
947 mcs_set,
948 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530949 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700950 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800951 }
952 }
953#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
954}
955
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800956static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
957 struct wma_tgt_vht_cap *cfg)
958{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530959 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800960 uint32_t value = 0;
961 struct hdd_config *pconfig = hdd_ctx->config;
962 struct wiphy *wiphy = hdd_ctx->wiphy;
963 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700964 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700965 uint32_t temp = 0;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800966 uint32_t ch_width = eHT_CHANNEL_WIDTH_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967
Dustin Brown5e06bd32016-10-04 12:49:10 -0700968 if (!band_5g) {
969 hdd_info("5GHz band disabled, skipping capability population");
970 return;
971 }
972
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800973 /* Get the current MPDU length */
974 status =
975 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
976 &value);
977
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530978 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700979 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800980 value = 0;
981 }
982
983 /*
984 * VHT max MPDU length:
985 * override if user configured value is too high
986 * that the target cannot support
987 */
988 if (value > cfg->vht_max_mpdu) {
989 status = sme_cfg_set_int(hdd_ctx->hHal,
990 WNI_CFG_VHT_MAX_MPDU_LENGTH,
991 cfg->vht_max_mpdu);
992
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530993 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700994 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995 }
996 }
997
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700998 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
999 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1000
1001 if (pconfig->enable2x2)
1002 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1003
1004 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1005 QDF_STATUS_E_FAILURE) {
1006 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1007 }
1008
1009 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1010 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1011 if (pconfig->enable2x2)
1012 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1013
1014 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1015 QDF_STATUS_E_FAILURE) {
1016 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1017 }
1018
1019 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1020 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1021 if (pconfig->enable2x2)
1022 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1023
1024 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1025 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1026
1027 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1028 QDF_STATUS_E_FAILURE) {
1029 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1030 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001032 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001033 &value);
1034
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301035 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001036 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001037 value = 0;
1038 }
1039
1040 /* Set the LDPC capability */
1041 if (value && !cfg->vht_rx_ldpc) {
1042 status = sme_cfg_set_int(hdd_ctx->hHal,
1043 WNI_CFG_VHT_LDPC_CODING_CAP,
1044 cfg->vht_rx_ldpc);
1045
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301046 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001047 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048 }
1049 }
1050
1051 /* Get current GI 80 value */
1052 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1053 &value);
1054
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301055 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001056 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001057 value = 0;
1058 }
1059
1060 /* set the Guard interval 80MHz */
1061 if (value && !cfg->vht_short_gi_80) {
1062 status = sme_cfg_set_int(hdd_ctx->hHal,
1063 WNI_CFG_VHT_SHORT_GI_80MHZ,
1064 cfg->vht_short_gi_80);
1065
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301066 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001067 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068 }
1069 }
1070
1071 /* Get current GI 160 value */
1072 status = sme_cfg_get_int(hdd_ctx->hHal,
1073 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1074 &value);
1075
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301076 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001077 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 value = 0;
1079 }
1080
1081 /* Get VHT TX STBC cap */
1082 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1083
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301084 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001085 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001086 value = 0;
1087 }
1088
1089 /* VHT TX STBC cap */
1090 if (value && !cfg->vht_tx_stbc) {
1091 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1092 cfg->vht_tx_stbc);
1093
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301094 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001095 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001096 }
1097 }
1098
1099 /* Get VHT RX STBC cap */
1100 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1101
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301102 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001103 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001104 value = 0;
1105 }
1106
1107 /* VHT RX STBC cap */
1108 if (value && !cfg->vht_rx_stbc) {
1109 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1110 cfg->vht_rx_stbc);
1111
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301112 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001113 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 }
1115 }
1116
1117 /* Get VHT SU Beamformer cap */
1118 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1119 &value);
1120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301121 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001122 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001123 value = 0;
1124 }
1125
1126 /* set VHT SU Beamformer cap */
1127 if (value && !cfg->vht_su_bformer) {
1128 status = sme_cfg_set_int(hdd_ctx->hHal,
1129 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1130 cfg->vht_su_bformer);
1131
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301132 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001133 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 }
1135 }
1136
1137 /* check and update SU BEAMFORMEE capabality */
1138 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1139 pconfig->enableTxBF = cfg->vht_su_bformee;
1140
1141 status = sme_cfg_set_int(hdd_ctx->hHal,
1142 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1143 pconfig->enableTxBF);
1144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301145 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001146 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147 }
1148
1149 /* Get VHT MU Beamformer cap */
1150 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1151 &value);
1152
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301153 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001154 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 value = 0;
1156 }
1157
1158 /* set VHT MU Beamformer cap */
1159 if (value && !cfg->vht_mu_bformer) {
1160 status = sme_cfg_set_int(hdd_ctx->hHal,
1161 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1162 cfg->vht_mu_bformer);
1163
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301164 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001165 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166 }
1167 }
1168
1169 /* Get VHT MU Beamformee cap */
1170 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1171 &value);
1172
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301173 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001174 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001175 value = 0;
1176 }
1177
1178 /* set VHT MU Beamformee cap */
1179 if (value && !cfg->vht_mu_bformee) {
1180 status = sme_cfg_set_int(hdd_ctx->hHal,
1181 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1182 cfg->vht_mu_bformee);
1183
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301184 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001185 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186 }
1187 }
1188
1189 /* Get VHT MAX AMPDU Len exp */
1190 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1191 &value);
1192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301193 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001194 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 value = 0;
1196 }
1197
1198 /*
1199 * VHT max AMPDU len exp:
1200 * override if user configured value is too high
1201 * that the target cannot support.
1202 * Even though Rome publish ampdu_len=7, it can
1203 * only support 4 because of some h/w bug.
1204 */
1205
1206 if (value > cfg->vht_max_ampdu_len_exp) {
1207 status = sme_cfg_set_int(hdd_ctx->hHal,
1208 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1209 cfg->vht_max_ampdu_len_exp);
1210
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301211 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001212 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 }
1214 }
1215
1216 /* Get VHT TXOP PS CAP */
1217 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1218
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301219 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001220 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 value = 0;
1222 }
1223
1224 /* set VHT TXOP PS cap */
1225 if (value && !cfg->vht_txop_ps) {
1226 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1227 cfg->vht_txop_ps);
1228
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301229 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001230 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 }
1232 }
1233
1234 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1235 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1236 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1237 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1238 else
1239 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1240
1241
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001242 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1243 status = sme_cfg_set_int(hdd_ctx->hHal,
1244 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1245 VHT_CAP_160_AND_80P80_SUPP);
1246 if (status == QDF_STATUS_E_FAILURE)
1247 hdd_alert("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 band_5g->vht_cap.cap |=
1249 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001250 ch_width = eHT_CHANNEL_WIDTH_80P80MHZ;
1251 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1252 status = sme_cfg_set_int(hdd_ctx->hHal,
1253 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1254 VHT_CAP_160_SUPP);
1255 if (status == QDF_STATUS_E_FAILURE)
1256 hdd_alert("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 band_5g->vht_cap.cap |=
1258 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001259 ch_width = eHT_CHANNEL_WIDTH_160MHZ;
1260 }
1261 pconfig->vhtChannelWidth = QDF_MIN(pconfig->vhtChannelWidth,
1262 ch_width);
1263 /* Get the current supported chan width */
1264 status = sme_cfg_get_int(hdd_ctx->hHal,
1265 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1266 &value);
1267 if (status != QDF_STATUS_SUCCESS) {
1268 hdd_err("could not get CH BW");
1269 value = 0;
1270 }
1271 /* set the Guard interval 80MHz */
1272 if (value) {
1273 status = sme_cfg_set_int(hdd_ctx->hHal,
1274 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1275 cfg->vht_short_gi_160);
1276
1277 if (status == QDF_STATUS_E_FAILURE)
1278 hdd_alert("failed to set SHORT GI 80MHZ");
1279 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001280
1281 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1282 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1283
1284 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1285 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1286 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1287 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1288
1289 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1290 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1291
1292 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1293 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1294 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1295 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1296 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1297 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1298
1299 band_5g->vht_cap.cap |=
1300 (cfg->vht_max_ampdu_len_exp <<
1301 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1302
1303 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1304 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1305 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1306 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1307 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1308 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1309 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1310 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1311
1312 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1313 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1314
1315}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001317/**
1318 * hdd_generate_macaddr_auto() - Auto-generate mac address
1319 * @hdd_ctx: Pointer to the HDD context
1320 *
1321 * Auto-generate mac address using device serial number.
1322 * Keep the first 3 bytes of OUI as before and replace
1323 * the last 3 bytes with the lower 3 bytes of serial number.
1324 *
1325 * Return: 0 for success
1326 * Non zero failure code for errors
1327 */
1328static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1329{
1330 unsigned int serialno = 0;
1331 struct qdf_mac_addr mac_addr = {
1332 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1333 };
1334
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001335 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001336 if (serialno == 0)
1337 return -EINVAL;
1338
1339 serialno &= 0x00ffffff;
1340
1341 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1342 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1343 mac_addr.bytes[5] = serialno & 0xff;
1344
1345 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1346 return 0;
1347}
1348
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301349/**
1350 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1351 * configuration to cfg_ini in HDD
1352 * @hdd_ctx: Pointer to hdd_ctx
1353 * @cfg: target configuration
1354 *
1355 * Return: None
1356 */
1357#ifdef FEATURE_WLAN_RA_FILTERING
1358static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1359 struct wma_tgt_cfg *cfg)
1360{
1361 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1362}
1363#else
1364static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1365 struct wma_tgt_cfg *cfg)
1366{
1367}
1368#endif
1369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370void hdd_update_tgt_cfg(void *context, void *param)
1371{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001372 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1374 struct wma_tgt_cfg *cfg = param;
1375 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001376 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301377
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001378 ret = hdd_create_and_store_pdev(hdd_ctx);
1379 if (ret) {
1380 hdd_err("pdev creation fails!");
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301381 QDF_BUG(0);
1382 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001383
1384 if (cds_cfg) {
1385 if (hdd_ctx->config->enable_sub_20_channel_width !=
1386 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1387 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1388 cds_cfg->sub_20_channel_width =
1389 WLAN_SUB_20_CH_WIDTH_NONE;
1390 } else {
1391 cds_cfg->sub_20_channel_width =
1392 hdd_ctx->config->enable_sub_20_channel_width;
1393 }
1394 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395
1396 /* first store the INI band capability */
1397 temp_band_cap = hdd_ctx->config->nBandCapability;
1398
1399 hdd_ctx->config->nBandCapability = cfg->band_cap;
1400
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001401 /*
1402 * now overwrite the target band capability with INI
1403 * setting if INI setting is a subset
1404 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405
1406 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1407 (temp_band_cap != eCSR_BAND_ALL))
1408 hdd_ctx->config->nBandCapability = temp_band_cap;
1409 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1410 (temp_band_cap != eCSR_BAND_ALL) &&
1411 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001412 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001413 }
1414
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001415 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001416 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1417 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1418 }
1419
1420 /* This can be extended to other configurations like ht, vht cap... */
1421
Anurag Chouhanc5548422016-02-24 18:33:27 +05301422 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001423 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001424 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001425 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001426 static struct qdf_mac_addr default_mac_addr = {
1427 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1428 };
1429 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1430 &default_mac_addr)) {
1431 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1432 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1433 MAC_ADDRESS_STR,
1434 MAC_ADDR_ARRAY(hdd_ctx->config->
1435 intfMacAddr[0].bytes));
1436 } else {
1437 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1438 MAC_ADDRESS_STR,
1439 MAC_ADDR_ARRAY(hdd_ctx->config->
1440 intfMacAddr[0].bytes));
1441 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001442 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 }
1444
1445 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001446 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447
1448 hdd_ctx->max_intf_count = cfg->max_intf_count;
1449
Jeff Johnsonc875e242016-09-23 18:12:34 -07001450 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001451 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001453 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1454 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1455
1456 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1457
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajaned1efd92016-09-24 18:05:47 -07001459 if (cfg->services.en_11ax) {
1460 hdd_info("11AX: 11ax is enabled - update HDD config");
1461 hdd_update_tgt_he_cap(hdd_ctx, cfg);
1462 }
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001463
1464 hdd_update_vdev_nss(hdd_ctx);
1465
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001466 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001467 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001468 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001469 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001470
1471 hdd_ctx->current_antenna_mode =
1472 (hdd_ctx->config->enable2x2 == 0x01) ?
1473 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1474 hdd_info("Init current antenna mode: %d",
1475 hdd_ctx->current_antenna_mode);
1476
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001477 hdd_info("Target BPF %d Host BPF %d",
1478 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1479 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1480 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301481 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301482
Arun Khandavallid454d422016-08-17 12:47:05 +05301483 /*
1484 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1485 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1486 * configure the STA mode wow pattern.
1487 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301488 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301489 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301490
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301491 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1492
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001493 /* Configure NAN datapath features */
1494 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495}
1496
1497/**
1498 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1499 * @context: HDD context pointer
1500 * @param: HDD radar indication pointer
1501 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001502 * This function is invoked in atomic context when a radar
1503 * is found on the SAP current operating channel and Data Tx
1504 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505 * Actions: Stop the netif Tx queues,Indicate Radar present
1506 * in HDD context for future usage.
1507 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301508 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001509 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301510bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511{
1512 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1513 struct wma_dfs_radar_ind *hdd_radar_event =
1514 (struct wma_dfs_radar_ind *)param;
1515 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1516 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301517 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301518 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301520 if (!hdd_ctx || !hdd_radar_event ||
1521 hdd_ctx->config->disableDFSChSwitch)
1522 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523
1524 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001525 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301526 /*
1527 * Application already triggered channel switch
1528 * on current channel, so return here.
1529 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301530 return false;
1531 }
1532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301534 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301536 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1537 if ((QDF_SAP_MODE == adapter->device_mode ||
1538 QDF_P2P_GO_MODE == adapter->device_mode) &&
1539 (CHANNEL_STATE_DFS ==
1540 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1542 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301543 hdd_info("tx blocked for session:%d",
1544 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 }
1546
1547 status = hdd_get_next_adapter(hdd_ctx,
1548 adapterNode,
1549 &pNext);
1550 adapterNode = pNext;
1551 }
1552 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301553
1554 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556
1557/**
1558 * hdd_is_valid_mac_address() - validate MAC address
1559 * @pMacAddr: Pointer to the input MAC address
1560 *
1561 * This function validates whether the given MAC address is valid or not
1562 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1563 * where X is the hexa decimal digit character and separated by ':'
1564 * This algorithm works even if MAC address is not separated by ':'
1565 *
1566 * This code checks given input string mac contains exactly 12 hexadecimal
1567 * digits and a separator colon : appears in the input string only after
1568 * an even number of hex digits.
1569 *
1570 * Return: 1 for valid and 0 for invalid
1571 */
1572bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1573{
1574 int xdigit = 0;
1575 int separator = 0;
1576 while (*pMacAddr) {
1577 if (isxdigit(*pMacAddr)) {
1578 xdigit++;
1579 } else if (':' == *pMacAddr) {
1580 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1581 break;
1582
1583 ++separator;
1584 } else {
1585 /* Invalid MAC found */
1586 return 0;
1587 }
1588 ++pMacAddr;
1589 }
1590 return xdigit == 12 && (separator == 5 || separator == 0);
1591}
1592
1593/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301594 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1595 * @dev: Handle to struct net_device to be updated.
1596 *
1597 * Return: None
1598 */
1599static void hdd_mon_mode_ether_setup(struct net_device *dev)
1600{
1601 dev->header_ops = NULL;
1602 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1603 dev->hard_header_len = ETH_HLEN;
1604 dev->mtu = ETH_DATA_LEN;
1605 dev->addr_len = ETH_ALEN;
1606 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1607 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1608 dev->priv_flags |= IFF_TX_SKB_SHARING;
1609
1610 memset(dev->broadcast, 0xFF, ETH_ALEN);
1611}
1612
1613/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001614 * __hdd__mon_open() - HDD Open function
1615 * @dev: Pointer to net_device structure
1616 *
1617 * This is called in response to ifconfig up
1618 *
1619 * Return: 0 for success; non-zero for failure
1620 */
1621static int __hdd_mon_open(struct net_device *dev)
1622{
1623 int ret;
1624
1625 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301626 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001627 ret = hdd_set_mon_rx_cb(dev);
1628 return ret;
1629}
1630
1631/**
1632 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1633 * @dev: Pointer to net_device structure
1634 *
1635 * This is called in response to ifconfig up
1636 *
1637 * Return: 0 for success; non-zero for failure
1638 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001639static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001640{
1641 int ret;
1642
1643 cds_ssr_protect(__func__);
1644 ret = __hdd_mon_open(dev);
1645 cds_ssr_unprotect(__func__);
1646
1647 return ret;
1648}
1649
1650/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301651 * hdd_start_adapter() - Wrapper function for device specific adapter
1652 * @adapter: pointer to HDD adapter
1653 *
1654 * This function is called to start the device specific adapter for
1655 * the mode passed in the adapter's device_mode.
1656 *
1657 * Return: 0 for success; non-zero for failure
1658 */
1659int hdd_start_adapter(hdd_adapter_t *adapter)
1660{
1661
1662 int ret;
1663 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1664
1665 ENTER_DEV(adapter->dev);
1666 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1667
1668 switch (device_mode) {
1669 case QDF_P2P_CLIENT_MODE:
1670 case QDF_P2P_DEVICE_MODE:
1671 case QDF_OCB_MODE:
1672 case QDF_STA_MODE:
1673 case QDF_MONITOR_MODE:
1674 ret = hdd_start_station_adapter(adapter);
1675 if (ret)
1676 goto err_start_adapter;
1677 break;
1678 case QDF_P2P_GO_MODE:
1679 case QDF_SAP_MODE:
1680 ret = hdd_start_ap_adapter(adapter);
1681 if (ret)
1682 goto err_start_adapter;
1683 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301684 case QDF_IBSS_MODE:
1685 /*
1686 * For IBSS interface is initialized as part of
1687 * hdd_init_station_mode()
1688 */
1689 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301690 case QDF_FTM_MODE:
1691 ret = hdd_start_ftm_adapter(adapter);
1692 if (ret)
1693 goto err_start_adapter;
1694 break;
1695 default:
1696 hdd_err("Invalid session type %d", device_mode);
1697 QDF_ASSERT(0);
1698 goto err_start_adapter;
1699 }
1700 if (hdd_set_fw_params(adapter))
1701 hdd_err("Failed to set the FW params for the adapter!");
1702
1703 /*
1704 * Action frame registered in one adapter which will
1705 * applicable to all interfaces
1706 */
1707 wlan_hdd_cfg80211_register_frames(adapter);
1708 EXIT();
1709 return 0;
1710err_start_adapter:
1711 return -EINVAL;
1712}
1713
1714/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301715 * hdd_enable_power_management() - API to Enable Power Management
1716 *
1717 * API invokes Bus Interface Layer power management functionality
1718 *
1719 * Return: None
1720 */
1721static void hdd_enable_power_management(void)
1722{
1723 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1724
1725 if (!hif_ctx) {
1726 hdd_err("Bus Interface Context is Invalid");
1727 return;
1728 }
1729
1730 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1731}
1732
1733/**
1734 * hdd_disable_power_management() - API to disable Power Management
1735 *
1736 * API disable Bus Interface Layer Power management functionality
1737 *
1738 * Return: None
1739 */
1740static void hdd_disable_power_management(void)
1741{
1742 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1743
1744 if (!hif_ctx) {
1745 hdd_err("Bus Interface Context is Invalid");
1746 return;
1747 }
1748
1749 hif_disable_power_management(hif_ctx);
1750}
1751
1752/**
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301753 * hdd_update_hw_sw_info() - API to update the HW/SW information
1754 *
1755 * API to update the HW and SW information in the driver
1756 *
1757 * Return: None
1758 */
1759static void hdd_update_hw_sw_info(hdd_context_t *hdd_ctx)
1760{
1761 void *hif_sc;
1762
1763 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
1764 if (!hif_sc) {
1765 hdd_err("HIF context is NULL");
1766 return;
1767 }
1768
1769 /*
1770 * target hw version/revision would only be retrieved after firmware
1771 * download
1772 */
1773 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
1774 &hdd_ctx->target_hw_revision,
1775 &hdd_ctx->target_hw_name);
1776
1777 /* Get the wlan hw/fw version */
1778 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
1779
1780 return;
1781}
1782
1783/**
gbian62edd7e2017-03-07 13:12:13 +08001784 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
1785 * @hdd_ctx: Pointer to hdd context
1786 *
1787 * Return: none
1788 */
1789static void
1790hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
1791{
1792 uint8_t num_entries = 0;
1793 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
1794 uint8_t *tx_sched_wrr_ac;
1795 int i;
1796 cds_context_type *cds_ctx;
1797
1798 if (NULL == hdd_ctx)
1799 return;
1800
1801 if (NULL == hdd_ctx->config) {
1802 /* Do nothing if hdd_ctx is invalid */
1803 hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
1804 return;
1805 }
1806
1807 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1808
1809 if (!cds_ctx) {
1810 hdd_err("Invalid CDS Context");
1811 return;
1812 }
1813
1814 for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
1815 switch (i) {
1816 case OL_TX_WMM_AC_BE:
1817 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
1818 break;
1819 case OL_TX_WMM_AC_BK:
1820 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
1821 break;
1822 case OL_TX_WMM_AC_VI:
1823 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
1824 break;
1825 case OL_TX_WMM_AC_VO:
1826 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
1827 break;
1828 default:
1829 tx_sched_wrr_ac = NULL;
1830 break;
1831 }
1832
1833 hdd_string_to_u8_array(tx_sched_wrr_ac,
1834 tx_sched_wrr_param,
1835 &num_entries,
1836 sizeof(tx_sched_wrr_param));
1837
1838 if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
1839 cds_ctx->ac_specs[i].wrr_skip_weight =
1840 tx_sched_wrr_param[0];
1841 cds_ctx->ac_specs[i].credit_threshold =
1842 tx_sched_wrr_param[1];
1843 cds_ctx->ac_specs[i].send_limit =
1844 tx_sched_wrr_param[2];
1845 cds_ctx->ac_specs[i].credit_reserve =
1846 tx_sched_wrr_param[3];
1847 cds_ctx->ac_specs[i].discard_weight =
1848 tx_sched_wrr_param[4];
1849 }
1850
1851 num_entries = 0;
1852 }
1853}
1854
1855/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301856 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1857 * @hdd_ctx: HDD context
1858 * @adapter: HDD adapter
1859 * @reinit: flag to indicate from SSR or normal path
1860 *
1861 * This function maintains the driver state machine it will be invoked from
1862 * startup, reinit and change interface. Depending on the driver state shall
1863 * perform the opening of the modules.
1864 *
1865 * Return: 0 for success; non-zero for failure
1866 */
1867int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1868 bool reinit)
1869{
1870 int ret;
1871 qdf_device_t qdf_dev;
1872 QDF_STATUS status;
1873 p_cds_contextType p_cds_context;
1874 bool unint = false;
1875 void *hif_ctx;
1876
1877 ENTER();
1878
1879 p_cds_context = cds_get_global_context();
1880 if (!p_cds_context) {
1881 hdd_err("Global Context is NULL");
1882 QDF_ASSERT(0);
1883 return -EINVAL;
1884 }
1885
1886 hdd_info("start modules called in state! :%d reinit: %d",
1887 hdd_ctx->driver_status, reinit);
1888
1889 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1890 if (!qdf_dev) {
1891 hdd_err("QDF Device Context is Invalid return");
1892 return -EINVAL;
1893 }
1894
1895 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301896 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301897
1898 if (QDF_TIMER_STATE_RUNNING ==
1899 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1900
1901 hdd_set_idle_ps_config(hdd_ctx, false);
1902 hdd_info("Interface change Timer running Stop timer");
1903 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1904 }
1905
1906 switch (hdd_ctx->driver_status) {
1907 case DRIVER_MODULES_UNINITIALIZED:
1908 unint = true;
1909 /* Fall through dont add break here */
1910 case DRIVER_MODULES_CLOSED:
1911 if (!reinit && !unint) {
1912 ret = pld_power_on(qdf_dev->dev);
1913 if (ret) {
1914 hdd_err("Failed to Powerup the device: %d", ret);
1915 goto release_lock;
1916 }
1917 }
1918 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1919 qdf_dev->bus_type,
1920 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1921 HIF_ENABLE_TYPE_PROBE);
1922 if (ret) {
1923 hdd_err("Failed to open hif: %d", ret);
1924 goto power_down;
1925 }
1926
1927 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301928 if (!hif_ctx) {
1929 hdd_err("hif context is null!!");
1930 goto power_down;
1931 }
1932
Arun Khandavallifae92942016-08-01 13:31:08 +05301933 status = ol_cds_init(qdf_dev, hif_ctx);
1934 if (status != QDF_STATUS_SUCCESS) {
1935 hdd_err("No Memory to Create BMI Context :%d", status);
1936 goto hif_close;
1937 }
1938
Rajeev Kumar138ef912017-01-13 15:19:48 -08001939 ret = hdd_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID);
1940 if (ret) {
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301941 hdd_err("Psoc creation fails!");
1942 goto ol_cds_free;
1943 }
1944
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08001945 ret = hdd_update_config(hdd_ctx);
1946 if (ret) {
1947 hdd_err("Failed to update configuration :%d", ret);
1948 goto destroy_psoc_object;
1949 }
1950
gbian62edd7e2017-03-07 13:12:13 +08001951 hdd_update_cds_ac_specs_params(hdd_ctx);
1952
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301953 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05301954 if (!QDF_IS_STATUS_SUCCESS(status)) {
1955 hdd_err("Failed to Open CDS: %d", status);
Selvaraj, Sridhara7dc2382017-01-27 18:29:39 +05301956 goto destroy_psoc_object;
Arun Khandavallifae92942016-08-01 13:31:08 +05301957 }
1958
Mukul Sharma9d797a02017-01-05 20:26:03 +05301959 /* initalize components configurations after psoc open */
1960 ret = hdd_update_components_config(hdd_ctx);
1961 if (ret) {
1962 hdd_err("Failed to update components configs :%d",
1963 ret);
1964 goto close;
1965 }
1966
Arun Khandavallifae92942016-08-01 13:31:08 +05301967 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1968
1969 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1970
1971 status = cds_pre_enable(hdd_ctx->pcds_context);
1972 if (!QDF_IS_STATUS_SUCCESS(status)) {
1973 hdd_err("Failed to pre-enable CDS: %d", status);
1974 goto close;
1975 }
1976
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301977 hdd_update_hw_sw_info(hdd_ctx);
1978
Arun Khandavallifae92942016-08-01 13:31:08 +05301979 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1980 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1981 hdd_ftm_mc_process_msg);
1982 break;
1983 }
1984 if (unint) {
1985 hdd_info("In phase-1 initialization don't enable modules");
1986 break;
1987 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301988
1989 if (reinit) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08001990 if (hdd_ipa_uc_ssr_reinit(hdd_ctx)) {
1991 hdd_err("HDD IPA UC reinit failed");
1992 goto close;
1993 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301994 }
1995
Arun Khandavallifae92942016-08-01 13:31:08 +05301996 /* Fall through dont add break here */
1997 case DRIVER_MODULES_OPENED:
1998 if (!adapter) {
1999 hdd_alert("adapter is Null");
2000 goto close;
2001 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05302002 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2003 hdd_err("in ftm mode, no need to configure cds modules");
2004 break;
2005 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302006 if (hdd_configure_cds(hdd_ctx, adapter)) {
2007 hdd_err("Failed to Enable cds modules");
2008 goto close;
2009 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05302010 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05302011 hdd_info("Driver Modules Successfully Enabled");
2012 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
2013 break;
2014 case DRIVER_MODULES_ENABLED:
2015 hdd_info("Driver modules already Enabled");
2016 break;
2017 default:
2018 hdd_err("WLAN start invoked in wrong state! :%d\n",
2019 hdd_ctx->driver_status);
2020 goto release_lock;
2021 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302022 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302023 mutex_unlock(&hdd_ctx->iface_change_lock);
2024 EXIT();
2025 return 0;
2026
2027close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302028 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05302029
Selvaraj, Sridhara7dc2382017-01-27 18:29:39 +05302030destroy_psoc_object:
2031 hdd_release_and_destroy_psoc(hdd_ctx);
2032
Arun Khandavallifae92942016-08-01 13:31:08 +05302033ol_cds_free:
2034 ol_cds_free();
2035
2036hif_close:
2037 hdd_hif_close(p_cds_context->pHIFContext);
2038power_down:
2039 if (!reinit && !unint)
2040 pld_power_off(qdf_dev->dev);
2041release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302042 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302043 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302044 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05302045 return -EINVAL;
2046}
2047
Naveen Rawat910726a2017-03-06 11:42:51 -08002048#ifdef WIFI_POS_CONVERGED
2049static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2050{
2051 int ret = os_if_wifi_pos_register_nl();
2052
2053 if (ret)
2054 hdd_err("os_if_wifi_pos_register_nl failed");
2055
2056 return ret;
2057}
2058
2059static int hdd_deactivate_wifi_pos(void)
2060{
2061 int ret = os_if_wifi_pos_deregister_nl();
2062
2063 if (ret)
2064 hdd_err("os_if_wifi_pos_deregister_nl failed");
2065
2066 return ret;
2067}
2068
2069/**
2070 * hdd_populate_wifi_pos_cfg - populates wifi_pos parameters
2071 * @hdd_ctx: hdd context
2072 *
2073 * Return: status of operation
2074 */
2075static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2076{
2077 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2078 struct hdd_config *cfg = hdd_ctx->config;
2079
2080 wifi_pos_set_oem_target_type(psoc, hdd_ctx->target_type);
2081 wifi_pos_set_oem_fw_version(psoc, hdd_ctx->target_fw_version);
2082 wifi_pos_set_drv_ver_major(psoc, QWLAN_VERSION_MAJOR);
2083 wifi_pos_set_drv_ver_minor(psoc, QWLAN_VERSION_MINOR);
2084 wifi_pos_set_drv_ver_patch(psoc, QWLAN_VERSION_PATCH);
2085 wifi_pos_set_drv_ver_build(psoc, QWLAN_VERSION_BUILD);
2086 wifi_pos_set_dwell_time_min(psoc, cfg->nNeighborScanMinChanTime);
2087 wifi_pos_set_dwell_time_max(psoc, cfg->nNeighborScanMaxChanTime);
2088}
2089#else
2090static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2091{
2092 return oem_activate_service(hdd_ctx);
2093}
2094
2095static int hdd_deactivate_wifi_pos(void)
2096{
2097 return 0;
2098}
2099
2100static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2101{
2102}
2103#endif
2104
Arun Khandavallifae92942016-08-01 13:31:08 +05302105/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106 * __hdd_open() - HDD Open function
2107 * @dev: Pointer to net_device structure
2108 *
2109 * This is called in response to ifconfig up
2110 *
2111 * Return: 0 for success; non-zero for failure
2112 */
2113static int __hdd_open(struct net_device *dev)
2114{
2115 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2116 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2117 int ret;
2118
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002119 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302120 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05302121 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122
2123 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302124 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002125 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127
Arun Khandavallifae92942016-08-01 13:31:08 +05302128 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
2129 if (ret) {
2130 hdd_err("Failed to start WLAN modules return");
2131 return -ret;
2132 }
2133
2134
2135 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2136 ret = hdd_start_adapter(adapter);
2137 if (ret) {
2138 hdd_err("Failed to start adapter :%d",
2139 adapter->device_mode);
2140 return ret;
2141 }
2142 }
2143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2145 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302146 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002147 /* Enable TX queues only when we are connected */
2148 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05302149 WLAN_START_ALL_NETIF_QUEUE,
2150 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002151 }
2152
Naveen Rawat286def52016-09-23 15:38:02 -07002153 /* Enable carrier and transmit queues for NDI */
2154 if (WLAN_HDD_IS_NDI(adapter)) {
2155 hdd_notice("Enabling Tx Queues");
2156 wlan_hdd_netif_queue_control(adapter,
2157 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
2158 WLAN_CONTROL_PATH);
2159 }
2160
Naveen Rawat910726a2017-03-06 11:42:51 -08002161 hdd_populate_wifi_pos_cfg(hdd_ctx);
2162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002163 return ret;
2164}
2165
Arun Khandavallifae92942016-08-01 13:31:08 +05302166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167/**
2168 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
2169 * @dev: Pointer to net_device structure
2170 *
2171 * This is called in response to ifconfig up
2172 *
2173 * Return: 0 for success; non-zero for failure
2174 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002175static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176{
2177 int ret;
2178
2179 cds_ssr_protect(__func__);
2180 ret = __hdd_open(dev);
2181 cds_ssr_unprotect(__func__);
2182
2183 return ret;
2184}
2185
2186/**
2187 * __hdd_stop() - HDD stop function
2188 * @dev: Pointer to net_device structure
2189 *
2190 * This is called in response to ifconfig down
2191 *
2192 * Return: 0 for success; non-zero for failure
2193 */
2194static int __hdd_stop(struct net_device *dev)
2195{
2196 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2197 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2198 int ret;
2199
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002200 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302202 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 adapter->sessionId, adapter->device_mode));
2204
2205 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302206 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208
2209 /* Nothing to be done if the interface is not opened */
2210 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002211 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 return -ENODEV;
2213 }
2214
2215 /* Make sure the interface is marked as closed */
2216 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002217 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218
2219 /*
2220 * Disable TX on the interface, after this hard_start_xmit() will not
2221 * be called on that interface
2222 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002223 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2225 WLAN_CONTROL_PATH);
2226
2227 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002228 * NAN data interface is different in some sense. The traffic on NDI is
2229 * bursty in nature and depends on the need to transfer. The service
2230 * layer may down the interface after the usage and up again when
2231 * required. In some sense, the NDI is expected to be available
2232 * (like SAP) iface until NDI delete request is issued by the service
2233 * layer. Skip BSS termination and adapter deletion for NAN Data
2234 * interface (NDI).
2235 */
2236 if (WLAN_HDD_IS_NDI(adapter))
2237 return 0;
2238
2239 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240 * The interface is marked as down for outside world (aka kernel)
2241 * But the driver is pretty much alive inside. The driver needs to
2242 * tear down the existing connection on the netdev (session)
2243 * cleanup the data pipes and wait until the control plane is stabilized
2244 * for this interface. The call also needs to wait until the above
2245 * mentioned actions are completed before returning to the caller.
2246 * Notice that the hdd_stop_adapter is requested not to close the session
2247 * That is intentional to be able to scan if it is a STA/P2P interface
2248 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302249 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002250
2251 /* DeInit the adapter. This ensures datapath cleanup as well */
2252 hdd_deinit_adapter(hdd_ctx, adapter, true);
2253
Arun Khandavallifae92942016-08-01 13:31:08 +05302254
2255 /*
2256 * Find if any iface is up. If any iface is up then can't put device to
2257 * sleep/power save mode
2258 */
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05302259 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302260 hdd_info("Closing all modules from the hdd_stop");
2261 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2262 hdd_ctx->config->iface_change_wait_time
2263 * 50000);
2264 }
2265
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002266 EXIT();
2267 return 0;
2268}
2269
2270/**
2271 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2272 * @dev: pointer to net_device structure
2273 *
2274 * This is called in response to ifconfig down
2275 *
2276 * Return: 0 for success and error number for failure
2277 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002278static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279{
2280 int ret;
2281
2282 cds_ssr_protect(__func__);
2283 ret = __hdd_stop(dev);
2284 cds_ssr_unprotect(__func__);
2285
2286 return ret;
2287}
2288
2289/**
2290 * __hdd_uninit() - HDD uninit function
2291 * @dev: Pointer to net_device structure
2292 *
2293 * This is called during the netdev unregister to uninitialize all data
2294 * associated with the device
2295 *
2296 * Return: None
2297 */
2298static void __hdd_uninit(struct net_device *dev)
2299{
2300 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2301
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002302 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303
2304 do {
2305 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002306 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002307 break;
2308 }
2309
2310 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002311 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 break;
2313 }
2314
2315 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002316 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 /*
2318 * we haven't validated all cases so let this go for
2319 * now
2320 */
2321 }
2322
2323 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2324
2325 /* after uninit our adapter structure will no longer be valid */
2326 adapter->dev = NULL;
2327 adapter->magic = 0;
2328 } while (0);
2329
2330 EXIT();
2331}
2332
2333/**
2334 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2335 * @dev: pointer to net_device structure
2336 *
2337 * This is called during the netdev unregister to uninitialize all data
2338 * associated with the device
2339 *
2340 * Return: none
2341 */
2342static void hdd_uninit(struct net_device *dev)
2343{
2344 cds_ssr_protect(__func__);
2345 __hdd_uninit(dev);
2346 cds_ssr_unprotect(__func__);
2347}
2348
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002349static int hdd_open_cesium_nl_sock(void)
2350{
2351#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2352 struct netlink_kernel_cfg cfg = {
2353 .groups = WLAN_NLINK_MCAST_GRP_ID,
2354 .input = NULL
2355 };
2356#endif
2357 int ret = 0;
2358
2359#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2360 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2361#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2362 THIS_MODULE,
2363#endif
2364 &cfg);
2365#else
2366 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2367 WLAN_NLINK_MCAST_GRP_ID,
2368 NULL, NULL, THIS_MODULE);
2369#endif
2370
2371 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002372 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002373 ret = -ECONNREFUSED;
2374 }
2375
2376 return ret;
2377}
2378
2379static void hdd_close_cesium_nl_sock(void)
2380{
2381 if (NULL != cesium_nl_srv_sock) {
2382 netlink_kernel_release(cesium_nl_srv_sock);
2383 cesium_nl_srv_sock = NULL;
2384 }
2385}
2386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387/**
2388 * __hdd_set_mac_address() - set the user specified mac address
2389 * @dev: Pointer to the net device.
2390 * @addr: Pointer to the sockaddr.
2391 *
2392 * This function sets the user specified mac address using
2393 * the command ifconfig wlanX hw ether <mac adress>.
2394 *
2395 * Return: 0 for success, non zero for failure
2396 */
2397static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2398{
2399 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2400 hdd_context_t *hdd_ctx;
2401 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302402 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002403 int ret;
2404
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002405 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002406
2407 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2408 ret = wlan_hdd_validate_context(hdd_ctx);
2409 if (0 != ret)
2410 return ret;
2411
2412 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2413 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2414
2415 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302416 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002417}
2418
2419/**
2420 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2421 * function from SSR
2422 * @dev: pointer to net_device structure
2423 * @addr: Pointer to the sockaddr
2424 *
2425 * This function sets the user specified mac address using
2426 * the command ifconfig wlanX hw ether <mac adress>.
2427 *
2428 * Return: 0 for success.
2429 */
2430static int hdd_set_mac_address(struct net_device *dev, void *addr)
2431{
2432 int ret;
2433
2434 cds_ssr_protect(__func__);
2435 ret = __hdd_set_mac_address(dev, addr);
2436 cds_ssr_unprotect(__func__);
2437
2438 return ret;
2439}
2440
2441uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2442{
2443 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302444 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2446 break;
2447 }
2448
Anurag Chouhan6d760662016-02-20 16:05:43 +05302449 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 return NULL;
2451
2452 hdd_ctx->config->intfAddrMask |= (1 << i);
2453 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2454}
2455
2456void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2457{
2458 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302459 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 if (!memcmp(releaseAddr,
2461 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2462 6)) {
2463 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2464 break;
2465 }
2466 }
2467 return;
2468}
2469
2470#ifdef WLAN_FEATURE_PACKET_FILTERING
2471/**
2472 * __hdd_set_multicast_list() - set the multicast address list
2473 * @dev: Pointer to the WLAN device.
2474 * @skb: Pointer to OS packet (sk_buff).
2475 *
2476 * This funciton sets the multicast address list.
2477 *
2478 * Return: None
2479 */
2480static void __hdd_set_multicast_list(struct net_device *dev)
2481{
2482 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483 int i = 0, status;
2484 struct netdev_hw_addr *ha;
2485 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302486 struct pmo_mc_addr_list_params *mc_list_request = NULL;
2487 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2488 int mc_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002490 ENTER_DEV(dev);
Anurag Chouhan6d760662016-02-20 16:05:43 +05302491 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302492 goto out;
Mukul Sharma51c44942015-10-30 19:30:19 +05302493
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302495 if (0 != status)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302496 goto out;
2497
2498 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
2499 if (!mc_list_request) {
2500 hdd_notice("Cannot allocate mc_list_request");
2501 goto out;
2502 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503
2504 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002505 hdd_notice("allow all multicast frames");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302506 hdd_disable_and_flush_mc_addr_list(adapter,
2507 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508 } else {
2509 mc_count = netdev_mc_count(dev);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302510 if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
Dustin Brown61269462016-09-19 13:25:45 -07002511 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302512 pmo_ucfg_max_mc_addr_supported(psoc));
2513 hdd_disable_and_flush_mc_addr_list(adapter,
2514 pmo_mc_list_change_notify);
2515 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302518 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2519 i, MAC_ADDR_ARRAY(ha->addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 if (i == mc_count)
2521 break;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302522 memset(&(mc_list_request->mc_addr[i].bytes),
2523 0, ETH_ALEN);
2524 memcpy(&(mc_list_request->mc_addr[i].bytes),
2525 ha->addr, ETH_ALEN);
2526 hdd_info("mlist[%d] = %pM", i,
2527 mc_list_request->mc_addr[i].bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528 i++;
2529 }
2530 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302531
2532 mc_list_request->psoc = psoc;
2533 mc_list_request->vdev_id = adapter->sessionId;
2534 mc_list_request->count = mc_count;
2535 status = hdd_cache_mc_addr_list(mc_list_request);
2536 if (status == 0) {
2537 hdd_enable_mc_addr_filtering(adapter,
2538 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 } else {
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302540 hdd_err("error while caching mc list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302542out:
2543 if (mc_list_request)
2544 qdf_mem_free(mc_list_request);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302545 EXIT();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547}
2548
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550/**
2551 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2552 * @dev: pointer to net_device
2553 *
2554 * Return: none
2555 */
2556static void hdd_set_multicast_list(struct net_device *dev)
2557{
2558 cds_ssr_protect(__func__);
2559 __hdd_set_multicast_list(dev);
2560 cds_ssr_unprotect(__func__);
2561}
2562#endif
2563
2564/**
2565 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2566 * @dev: Pointer to the WLAN device.
2567 * @skb: Pointer to OS packet (sk_buff).
2568 *
2569 * This function is registered with the Linux OS for network
2570 * core to decide which queue to use first.
2571 *
2572 * Return: ac, Queue Index/access category corresponding to UP in IP header
2573 */
2574static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2576 , void *accel_priv
2577#endif
2578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2579 , select_queue_fallback_t fallback
2580#endif
2581)
2582{
2583 return hdd_wmm_select_queue(dev, skb);
2584}
2585
2586static struct net_device_ops wlan_drv_ops = {
2587 .ndo_open = hdd_open,
2588 .ndo_stop = hdd_stop,
2589 .ndo_uninit = hdd_uninit,
2590 .ndo_start_xmit = hdd_hard_start_xmit,
2591 .ndo_tx_timeout = hdd_tx_timeout,
2592 .ndo_get_stats = hdd_get_stats,
2593 .ndo_do_ioctl = hdd_ioctl,
2594 .ndo_set_mac_address = hdd_set_mac_address,
2595 .ndo_select_queue = hdd_select_queue,
2596#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002598#endif
2599};
2600
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002601/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2602static struct net_device_ops wlan_mon_drv_ops = {
2603 .ndo_open = hdd_mon_open,
2604 .ndo_stop = hdd_stop,
2605 .ndo_get_stats = hdd_get_stats,
2606};
2607
2608/**
2609 * hdd_set_station_ops() - update net_device ops for monitor mode
2610 * @pWlanDev: Handle to struct net_device to be updated.
2611 * Return: None
2612 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613void hdd_set_station_ops(struct net_device *pWlanDev)
2614{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002615 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2616 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2617 else
2618 pWlanDev->netdev_ops = &wlan_drv_ops;
2619}
2620
Komal Seelama89be8d2016-09-29 11:09:26 +05302621#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302622/**
2623 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2624 * @hdd_ctx: HDD context
2625 *
2626 * Return: None
2627 */
2628static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2629{
2630 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2631
2632 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302633 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302634 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302635}
2636
2637/**
2638 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2639 * @hdd_ctx: HDD Context
2640 *
2641 * Return: None
2642 */
2643static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2644{
2645 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2646
2647 qdf_runtime_lock_deinit(ctx->scan);
2648 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302649 qdf_runtime_lock_deinit(ctx->roc);
2650 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302651 qdf_runtime_lock_deinit(ctx->dfs);
2652 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302653}
2654
Komal Seelama89be8d2016-09-29 11:09:26 +05302655static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2656{
2657 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2658
2659 ctx->connect = qdf_runtime_lock_init("connect");
2660}
2661
2662static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2663{
2664 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2665
2666 qdf_runtime_lock_deinit(ctx->connect);
2667 ctx->connect = NULL;
2668}
2669#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302670static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2671static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302672static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2673static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2674#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002675/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002676 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2677 * @hdd_ctx: global hdd context
2678 * @macAddr: mac address to assign to the interface
2679 * @name: User-visible name of the interface
2680 *
2681 * hdd adapter pointer would point to the netdev->priv space, this function
2682 * would retrive the pointer, and setup the hdd adapter configuration.
2683 *
2684 * Return: the pointer to hdd adapter, otherwise NULL
2685 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002686static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2687 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002688 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 const char *name)
2690{
2691 struct net_device *pWlanDev = NULL;
2692 hdd_adapter_t *adapter = NULL;
2693 /*
2694 * cfg80211 initialization and registration....
2695 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002696 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2697#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2698 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002700 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2701 hdd_mon_mode_ether_setup : ether_setup),
2702 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703
2704 if (pWlanDev != NULL) {
2705
2706 /* Save the pointer to the net_device in the HDD adapter */
2707 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2708
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302709 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710
2711 adapter->dev = pWlanDev;
2712 adapter->pHddCtx = hdd_ctx;
2713 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302714 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715
2716 init_completion(&adapter->session_open_comp_var);
2717 init_completion(&adapter->session_close_comp_var);
2718 init_completion(&adapter->disconnect_comp_var);
2719 init_completion(&adapter->linkup_event_var);
2720 init_completion(&adapter->cancel_rem_on_chan_var);
2721 init_completion(&adapter->rem_on_chan_ready_event);
2722 init_completion(&adapter->sta_authorized_event);
2723 init_completion(&adapter->offchannel_tx_event);
2724 init_completion(&adapter->tx_action_cnf_event);
2725#ifdef FEATURE_WLAN_TDLS
2726 init_completion(&adapter->tdls_add_station_comp);
2727 init_completion(&adapter->tdls_del_station_comp);
2728 init_completion(&adapter->tdls_mgmt_comp);
2729 init_completion(&adapter->tdls_link_establish_req_comp);
2730#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002731 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002732 init_completion(&adapter->change_country_code);
2733
2734
2735 init_completion(&adapter->scan_info.abortscan_event_var);
2736
2737 adapter->offloads_configured = false;
2738 adapter->isLinkUpSvcNeeded = false;
2739 adapter->higherDtimTransition = true;
2740 /* Init the net_device structure */
2741 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2742
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302743 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002744 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302745 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002746 sizeof(tSirMacAddr));
2747 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748
2749 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2750 pWlanDev->features |=
2751 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2752 pWlanDev->features |= NETIF_F_RXCSUM;
2753
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002754 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2755
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 hdd_set_station_ops(adapter->dev);
2757
2758 pWlanDev->destructor = free_netdev;
2759 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002760 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 adapter->wdev.wiphy = hdd_ctx->wiphy;
2762 adapter->wdev.netdev = pWlanDev;
2763 /* set pWlanDev's parent to underlying device */
2764 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2765 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302766 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302768 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 }
2770
2771 return adapter;
2772}
2773
Jeff Johnson590e2012016-10-05 16:16:24 -07002774static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2775 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776{
2777 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002778
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002779 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2781 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002782 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302783 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 }
2785 }
2786 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002787 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302788 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002789 }
2790 } else {
2791 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002792 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302793 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002794 }
2795 }
2796 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2797
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302798 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002799}
2800
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002801QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002802{
2803 hdd_adapter_t *adapter = pContext;
2804
2805 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002806 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302807 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808 }
2809
2810 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002811 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302812 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 }
2814
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002815 /*
2816 * For NAN Data interface, the close session results in the final
2817 * indication to the userspace
2818 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002819 if (adapter->device_mode == QDF_NDI_MODE)
2820 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002821
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2823
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824 /*
2825 * We can be blocked while waiting for scheduled work to be
2826 * flushed, and the adapter structure can potentially be freed, in
2827 * which case the magic will have been reset. So make sure the
2828 * magic is still good, and hence the adapter structure is still
2829 * valid, before signaling completion
2830 */
2831 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2832 complete(&adapter->session_close_comp_var);
2833
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302834 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835}
2836
Krunal Soni8c37e322016-02-03 16:08:37 -08002837/**
2838 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2839 * @adapter: pointer to device adapter
2840 * @type: type of interface
2841 *
2842 * This routine will check the mode of adapter and if it is required then it
2843 * will initialize the TDLS operations
2844 *
2845 * Return: QDF_STATUS
2846 */
2847#ifdef FEATURE_WLAN_TDLS
2848static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2849{
2850 if (QDF_IBSS_MODE != type) {
2851 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002852 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002853 return QDF_STATUS_E_FAILURE;
2854 }
2855 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2856 }
2857 return QDF_STATUS_SUCCESS;
2858}
2859#else
2860static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2861{
2862 return QDF_STATUS_SUCCESS;
2863}
2864#endif
2865
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302866QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867{
2868 struct net_device *pWlanDev = adapter->dev;
2869 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2870 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302871 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302872 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002873 uint32_t type, subType;
2874 unsigned long rc;
2875 int ret_val;
2876
2877 INIT_COMPLETION(adapter->session_open_comp_var);
2878 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002879 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302881 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002882 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 goto error_sme_open;
2884 }
2885 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302886 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2888 (uint8_t *) &adapter->macAddressCurrent,
2889 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302890 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002891 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302892 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302893 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894 goto error_sme_open;
2895 }
2896 /* Block on a completion variable. Can't wait forever though. */
2897 rc = wait_for_completion_timeout(
2898 &adapter->session_open_comp_var,
2899 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2900 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002901 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902 rc);
Sandeep Puligillae8065992016-11-14 00:23:43 -08002903 adapter->sessionId = HDD_SESSION_ID_INVALID;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302904 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 }
2906
Rajeev Kumardeabf3e2017-01-13 15:55:05 -08002907 ret_val = hdd_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
2908 if (ret_val)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302909 goto error_vdev_create;
2910
Naveen Rawata410c5a2016-09-19 14:22:33 -07002911 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302913 qdf_ret_status = hdd_register_wext(pWlanDev);
2914 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002915 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302916 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302917 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918 goto error_register_wext;
2919 }
2920 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002921 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2923
Deepak Dhamdherea2785822016-11-17 01:17:45 -08002924 /* set fast roaming capability in sme session */
2925 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
2926 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 /* Set the default operation channel */
2928 pHddStaCtx->conn_info.operationChannel =
2929 hdd_ctx->config->OperatingChannel;
2930
2931 /* Make the default Auth Type as OPEN */
2932 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2933
2934 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302935 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002936 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 status, status);
2938 goto error_init_txrx;
2939 }
2940
2941 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2942
2943 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302944 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002945 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002946 status, status);
2947 goto error_wmm_init;
2948 }
2949
2950 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2951
2952 ret_val = wma_cli_set_command(adapter->sessionId,
2953 WMI_PDEV_PARAM_BURST_ENABLE,
2954 hdd_ctx->config->enableSifsBurst,
2955 PDEV_CMD);
2956
2957 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002958 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002959 ret_val);
2960 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002961 status = hdd_check_and_init_tdls(adapter, type);
2962 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002964
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302965 status = hdd_lro_enable(hdd_ctx, adapter);
2966 if (status != QDF_STATUS_SUCCESS)
2967 goto error_lro_enable;
2968
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302969 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002970
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302971error_lro_enable:
2972 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973error_tdls_init:
2974 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2975 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976error_wmm_init:
2977 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2978 hdd_deinit_tx_rx(adapter);
2979error_init_txrx:
2980 hdd_unregister_wext(pWlanDev);
2981error_register_wext:
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08002982 ret_val = hdd_release_and_destroy_vdev(adapter);
2983 if (ret_val)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302984 hdd_err("vdev delete failed");
2985error_vdev_create:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002986 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2987 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302988 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 adapter->sessionId,
2990 hdd_sme_close_session_callback,
2991 adapter)) {
2992 unsigned long rc;
2993
2994 /*
2995 * Block on a completion variable.
2996 * Can't wait forever though.
2997 */
2998 rc = wait_for_completion_timeout(
2999 &adapter->session_close_comp_var,
3000 msecs_to_jiffies
3001 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3002 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07003003 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003004 rc);
3005 }
3006 }
3007error_sme_open:
3008 return status;
3009}
3010
3011void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
3012{
3013 hdd_cfg80211_state_t *cfgState;
3014
3015 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3016
3017 if (NULL != cfgState->buf) {
3018 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019 rc = wait_for_completion_timeout(
3020 &adapter->tx_action_cnf_event,
3021 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3022 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003023 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05303024 /*
3025 * Inform tx status as FAILURE to upper layer and free
3026 * cfgState->buf
3027 */
3028 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 }
3030 }
3031 return;
3032}
3033
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303034/**
3035 * hdd_station_adapter_deinit() - De-initialize the station adapter
3036 * @hdd_ctx: global hdd context
3037 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07003038 * @rtnl_held: Used to indicate whether or not the caller is holding
3039 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303040 *
3041 * This function De-initializes the STA/P2P/OCB adapter.
3042 *
3043 * Return: None.
3044 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003045static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
3046 hdd_adapter_t *adapter,
3047 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303048{
3049 ENTER_DEV(adapter->dev);
3050
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303051 if (adapter->dev) {
3052 if (rtnl_held)
3053 adapter->dev->wireless_handlers = NULL;
3054 else {
3055 rtnl_lock();
3056 adapter->dev->wireless_handlers = NULL;
3057 rtnl_unlock();
3058 }
3059 }
3060
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303061 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
3062 hdd_deinit_tx_rx(adapter);
3063 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3064 }
3065
3066 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3067 hdd_wmm_adapter_close(adapter);
3068 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3069 }
3070
3071 hdd_cleanup_actionframe(hdd_ctx, adapter);
3072 wlan_hdd_tdls_exit(adapter);
3073
3074 EXIT();
3075}
3076
3077/**
3078 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
3079 * @hdd_ctx: global hdd context
3080 * @adapter: HDD adapter
3081 * @rtnl_held: the rtnl lock hold flag
3082 * This function De-initializes the AP/P2PGo adapter.
3083 *
3084 * Return: None.
3085 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003086static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
3087 hdd_adapter_t *adapter,
3088 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303089{
3090 ENTER_DEV(adapter->dev);
3091
3092 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3093 hdd_wmm_adapter_close(adapter);
3094 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3095 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003096 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303097
3098 hdd_cleanup_actionframe(hdd_ctx, adapter);
3099
3100 hdd_unregister_hostapd(adapter, rtnl_held);
3101
3102 EXIT();
3103}
3104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3106 bool rtnl_held)
3107{
3108 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303109
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003110 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003111 case QDF_STA_MODE:
3112 case QDF_P2P_CLIENT_MODE:
3113 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303115 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116 break;
3117 }
3118
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003119 case QDF_SAP_MODE:
3120 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003121 {
3122
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303123 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 break;
3125 }
3126
3127 default:
3128 break;
3129 }
3130
3131 EXIT();
3132}
3133
Jeff Johnson590e2012016-10-05 16:16:24 -07003134static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3135 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136{
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003137 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 struct net_device *pWlanDev = NULL;
3139
3140 if (adapter)
3141 pWlanDev = adapter->dev;
3142 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003143 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144 return;
3145 }
3146
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003147 ret = hdd_release_and_destroy_vdev(adapter);
3148 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303149 hdd_err("vdev delete failed");
3150
Rajeev Kumardca5f812016-02-04 17:28:06 -08003151 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303152
3153 if (adapter->scan_info.default_scan_ies) {
3154 qdf_mem_free(adapter->scan_info.default_scan_ies);
3155 adapter->scan_info.default_scan_ies = NULL;
3156 }
3157
Komal Seelama89be8d2016-09-29 11:09:26 +05303158 hdd_adapter_runtime_suspend_denit(adapter);
3159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 /*
3161 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
3162 * the driver is almost closed and cannot handle either control
3163 * messages or data. However, unregister_netdevice() call above will
3164 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
3165 * to close the active connections (basically excites control path) which
3166 * is not right. Setting this flag helps hdd_stop() to recognize that
3167 * the interface is closed and restricts any operations on that
3168 */
3169 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3170
3171 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
3172 if (rtnl_held) {
3173 unregister_netdevice(pWlanDev);
3174 } else {
3175 unregister_netdev(pWlanDev);
3176 }
3177 /*
3178 * Note that the adapter is no longer valid at this point
3179 * since the memory has been reclaimed
3180 */
3181 }
3182}
3183
Jeff Johnson590e2012016-10-05 16:16:24 -07003184static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
3185 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186{
3187 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3188 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303189 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303191 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 adapter = adapterNode->pAdapter;
3193 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303194 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303196 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 }
3198 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3199 adapterNode = pNext;
3200 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303201 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202}
Ryan Hsu07495ea2016-01-21 15:25:39 -08003203
Arun Khandavalli2358d522016-05-16 18:05:37 +05303204#ifdef CONFIG_FW_LOGS_BASED_ON_INI
3205/**
3206 * hdd_set_fw_log_params() - Set log parameters to FW
3207 * @hdd_ctx: HDD Context
3208 * @adapter: HDD Adapter
3209 *
3210 * This function set the FW Debug log level based on the INI.
3211 *
3212 * Return: None
3213 */
3214static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3215 hdd_adapter_t *adapter)
3216{
3217 uint8_t count = 0, numentries = 0,
3218 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3219 uint32_t value = 0;
3220 int ret;
3221
Arun Khandavallifae92942016-08-01 13:31:08 +05303222 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3223 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303224 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
3225 return;
3226 }
3227
Arun Khandavallifae92942016-08-01 13:31:08 +05303228 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303229 hdd_ctx->fw_log_settings.dl_type =
3230 hdd_ctx->config->enableFwLogType;
3231 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303232 WMI_DBGLOG_TYPE,
3233 hdd_ctx->config->enableFwLogType,
3234 DBG_CMD);
3235 if (ret != 0)
3236 hdd_err("Failed to enable FW log type ret %d",
3237 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303238
3239 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303240 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303241 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303242 WMI_DBGLOG_LOG_LEVEL,
3243 hdd_ctx->config->enableFwLogLevel,
3244 DBG_CMD);
3245 if (ret != 0)
3246 hdd_err("Failed to enable FW log level ret %d",
3247 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303248
3249 hdd_string_to_u8_array(
3250 hdd_ctx->config->enableFwModuleLogLevel,
3251 moduleloglevel,
3252 &numentries,
3253 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3254
3255 while (count < numentries) {
3256 /*
3257 * FW module log level input string looks like
3258 * below:
3259 * gFwDebugModuleLoglevel=<FW Module ID>,
3260 * <Log Level>,...
3261 * For example:
3262 * gFwDebugModuleLoglevel=
3263 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3264 * Above input string means :
3265 * For FW module ID 1 enable log level 0
3266 * For FW module ID 2 enable log level 1
3267 * For FW module ID 3 enable log level 2
3268 * For FW module ID 4 enable log level 3
3269 * For FW module ID 5 enable log level 4
3270 * For FW module ID 6 enable log level 5
3271 * For FW module ID 7 enable log level 6
3272 */
3273
Nishank Aggarwale239d962017-03-03 12:26:02 +05303274 if ((moduleloglevel[count] > WLAN_MODULE_ID_MAX)
3275 || (moduleloglevel[count + 1] > DBGLOG_LVL_MAX)) {
3276 hdd_err("Module id %d and dbglog level %d input length is more than max",
3277 moduleloglevel[count],
3278 moduleloglevel[count + 1]);
3279 return;
3280 }
3281
3282 value = moduleloglevel[count] << 16;
3283 value |= moduleloglevel[count + 1];
Arun Khandavalli2358d522016-05-16 18:05:37 +05303284 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303285 WMI_DBGLOG_MOD_LOG_LEVEL,
3286 value, DBG_CMD);
3287 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303288 hdd_err("Failed to enable FW module log level %d ret %d",
3289 value, ret);
3290
3291 count += 2;
3292 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303293
Arun Khandavalli2358d522016-05-16 18:05:37 +05303294}
3295#else
3296static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3297 hdd_adapter_t *adapter)
3298{
3299}
3300
3301#endif
3302
3303/**
3304 * hdd_set_fw_params() - Set parameters to firmware
3305 * @adapter: HDD adapter
3306 *
3307 * This function Sets various parameters to fw once the
3308 * adapter is started.
3309 *
3310 * Return: 0 on success or errno on failure
3311 */
3312int hdd_set_fw_params(hdd_adapter_t *adapter)
3313{
3314 int ret;
3315 hdd_context_t *hdd_ctx;
3316
3317 ENTER_DEV(adapter->dev);
3318
3319 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3320 if (!hdd_ctx)
3321 return -EINVAL;
3322
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003323 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303324 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303325#define HDD_DTIM_1CHAIN_RX_ID 0x5
3326#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003327 /*
3328 * Disable DTIM 1 chain Rx when in 1x1,
3329 * we are passing two value
3330 * as param_id << 29 | param_value.
3331 * Below param_value = 0(disable)
3332 */
3333 ret = wma_cli_set_command(adapter->sessionId,
3334 WMI_STA_SMPS_PARAM_CMDID,
3335 HDD_DTIM_1CHAIN_RX_ID <<
3336 HDD_SMPS_PARAM_VALUE_S,
3337 VDEV_CMD);
3338 if (ret) {
3339 hdd_err("DTIM 1 chain set failed %d", ret);
3340 goto error;
3341 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303342
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003343 ret = wma_cli_set_command(adapter->sessionId,
3344 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3345 hdd_ctx->config->txchainmask1x1,
3346 PDEV_CMD);
3347 if (ret) {
3348 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3349 ret);
3350 goto error;
3351 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303352
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003353 ret = wma_cli_set_command(adapter->sessionId,
3354 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3355 hdd_ctx->config->rxchainmask1x1,
3356 PDEV_CMD);
3357 if (ret) {
3358 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3359 ret);
3360 goto error;
3361 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303362#undef HDD_DTIM_1CHAIN_RX_ID
3363#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003364 } else {
3365 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3366 }
3367
Arun Khandavallifae92942016-08-01 13:31:08 +05303368 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3369 ret = wma_cli_set_command(adapter->sessionId,
3370 WMI_PDEV_PARAM_HYST_EN,
3371 hdd_ctx->config->enableMemDeepSleep,
3372 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303373
Arun Khandavallifae92942016-08-01 13:31:08 +05303374 if (ret) {
3375 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3376 ret);
3377 goto error;
3378 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303379
3380 ret = wma_cli_set_command(adapter->sessionId,
3381 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3382 hdd_ctx->config->rts_profile,
3383 VDEV_CMD);
3384 if (ret) {
3385 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3386 goto error;
3387 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303388 }
3389
3390 hdd_set_fw_log_params(hdd_ctx, adapter);
3391
3392 EXIT();
3393 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303394
Arun Khandavalli2358d522016-05-16 18:05:37 +05303395error:
3396 return -EINVAL;
3397}
3398
Ryan Hsu07495ea2016-01-21 15:25:39 -08003399/**
3400 * hdd_open_adapter() - open and setup the hdd adatper
3401 * @hdd_ctx: global hdd context
3402 * @session_type: type of the interface to be created
3403 * @iface_name: User-visible name of the interface
3404 * @macAddr: MAC address to assign to the interface
3405 * @name_assign_type: the name of assign type of the netdev
3406 * @rtnl_held: the rtnl lock hold flag
3407 *
3408 * This function open and setup the hdd adpater according to the device
3409 * type request, assign the name, the mac address assigned, and then prepared
3410 * the hdd related parameters, queue, lock and ready to start.
3411 *
3412 * Return: the pointer of hdd adapter, otherwise NULL.
3413 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3415 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003416 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003417 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418{
3419 hdd_adapter_t *adapter = NULL;
3420 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303421 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423
Arun Khandavallifae92942016-08-01 13:31:08 +05303424 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425
3426 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3427 /*
3428 * Max limit reached on the number of vdevs configured by the
3429 * host. Return error
3430 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303431 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3432 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003433 return NULL;
3434 }
3435
3436 if (macAddr == NULL) {
3437 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303438 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003439 return NULL;
3440 }
3441 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303442 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303443 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3444 " already exists",
3445 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003446 return NULL;
3447 }
3448
3449 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003450 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451 /* Reset locally administered bit if the device mode is STA */
3452 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3453 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003454 case QDF_P2P_CLIENT_MODE:
3455 case QDF_P2P_DEVICE_MODE:
3456 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003457 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303458 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003459 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3460 name_assign_type,
3461 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462
3463 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303464 hdd_err("failed to allocate adapter for session %d",
3465 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003466 return NULL;
3467 }
3468
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003469 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003471 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303473 else if (QDF_MONITOR_MODE == session_type)
3474 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475 else
3476 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3477
3478 adapter->device_mode = session_type;
3479
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303480 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003481 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303482 if (QDF_STATUS_SUCCESS != status)
3483 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303484 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486 /*
3487 * Workqueue which gets scheduled in IPv4 notification
3488 * callback
3489 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3491 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492
3493#ifdef WLAN_NS_OFFLOAD
3494 /*
3495 * Workqueue which gets scheduled in IPv6
3496 * notification callback.
3497 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3499 hdd_ipv6_notifier_work_queue);
3500#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003501 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303502 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303504 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 }
3506
3507 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303508 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003509 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303510 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3511 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303513
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003515 case QDF_P2P_GO_MODE:
3516 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003517 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3518 name_assign_type,
3519 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303521 hdd_alert("failed to allocate adapter for session %d",
3522 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523 return NULL;
3524 }
3525
3526 adapter->wdev.iftype =
3527 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003528 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 NL80211_IFTYPE_P2P_GO;
3530 adapter->device_mode = session_type;
3531
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303533 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3535 goto err_free_netdev;
3536 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303537 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303539 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3540 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303542 case QDF_FTM_MODE:
3543 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3544 name_assign_type,
3545 "wlan0");
3546 if (NULL == adapter) {
3547 hdd_err("Failed to allocate adapter for FTM mode");
3548 return NULL;
3549 }
3550 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3551 adapter->device_mode = session_type;
3552 status = hdd_register_interface(adapter, rtnl_held);
3553 if (QDF_STATUS_SUCCESS != status) {
3554 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3555 goto err_free_netdev;
3556 }
3557 /* Stop the Interface TX queue. */
3558 hdd_info("Disabling queues");
3559 wlan_hdd_netif_queue_control(adapter,
3560 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3561 WLAN_CONTROL_PATH);
3562 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003563 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303564 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303565 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 return NULL;
3567 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003568
3569 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3570 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3571
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303572 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573 /* Add it to the hdd's session list. */
3574 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303575 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303577 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 } else {
3579 pHddAdapterNode->pAdapter = adapter;
3580 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3581 }
3582 }
3583
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303584 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 if (NULL != adapter) {
3586 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3587 adapter = NULL;
3588 }
3589 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303590 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003591 }
3592 return NULL;
3593 }
3594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303595 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003596 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003597
3598 /* Initialize the WoWL service */
3599 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003600 hdd_alert("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303601 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602 }
3603
3604 /* Adapter successfully added. Increment the vdev count */
3605 hdd_ctx->current_intf_count++;
3606
Jeff Johnson5880d792016-08-15 13:32:30 -07003607 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608 hdd_ctx->current_intf_count);
3609
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003610 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 }
3612
Rajeev Kumardca5f812016-02-04 17:28:06 -08003613 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3614 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003615
3616 return adapter;
3617
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303618err_close_adapter:
3619 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303622 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003623
3624 return NULL;
3625}
3626
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303627QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003628 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629{
3630 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303631 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632
3633 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303634 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003635 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 status);
3637 return status;
3638 }
3639
3640 while (pCurrent->pAdapter != adapter) {
3641 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303642 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003643 break;
3644
3645 pCurrent = pNext;
3646 }
3647 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303648 if (QDF_STATUS_SUCCESS == status) {
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303649 hdd_info("wait for bus bw work to flush");
3650 cancel_work_sync(&hdd_ctx->bus_bw_work);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003651 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003652 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3653
3654 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303655 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 adapterNode = NULL;
3657
3658 /* Adapter removed. Decrement vdev count */
3659 if (hdd_ctx->current_intf_count != 0)
3660 hdd_ctx->current_intf_count--;
3661
3662 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303663 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303665
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303666 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667}
3668
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003669/**
3670 * hdd_close_all_adapters - Close all open adapters
3671 * @hdd_ctx: Hdd context
3672 * rtnl_held: True if RTNL lock held
3673 *
3674 * Close all open adapters.
3675 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303676 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003677 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303678QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679{
3680 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303681 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682
3683 ENTER();
3684
3685 do {
3686 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303687 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303688 wlan_hdd_release_intf_addr(hdd_ctx,
3689 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003691 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303692 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303693 /* Adapter removed. Decrement vdev count */
3694 if (hdd_ctx->current_intf_count != 0)
3695 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303697 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698
3699 EXIT();
3700
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303701 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702}
3703
3704void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3705{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303706 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 tSirUpdateIE updateIE;
3708 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003709 case QDF_STA_MODE:
3710 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003711 {
3712 hdd_station_ctx_t *pHddStaCtx =
3713 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003714 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 break;
3716 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003717 case QDF_SAP_MODE:
3718 case QDF_P2P_GO_MODE:
3719 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003720 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003721 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003722 break;
3723 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003724 case QDF_FTM_MODE:
3725 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 default:
3727 /*
3728 * wlan_hdd_reset_prob_rspies should not have been called
3729 * for these kind of devices
3730 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003731 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 pHostapdAdapter->device_mode);
3733 return;
3734 }
3735
Anurag Chouhanc5548422016-02-24 18:33:27 +05303736 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3738 updateIE.ieBufferlength = 0;
3739 updateIE.pAdditionIEBuffer = NULL;
3740 updateIE.append = true;
3741 updateIE.notify = false;
3742 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3743 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303744 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003745 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003746 }
3747}
3748
Peng Xu66162de2016-02-11 17:01:20 -08003749/**
3750 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3751 * @hdd_ctx: HDD context which is already NULL validated
3752 * @adapter: HDD adapter which is already NULL validated
3753 *
3754 * Close the SME session and wait for its completion, if needed.
3755 *
3756 * Return: None
3757 */
3758static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3759 hdd_adapter_t *adapter)
3760{
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003761 int ret;
Peng Xu66162de2016-02-11 17:01:20 -08003762 unsigned long rc;
3763
3764 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3765 hdd_err("session is not opened:%d", adapter->sessionId);
3766 return;
3767 }
3768
3769 INIT_COMPLETION(adapter->session_close_comp_var);
3770 if (QDF_STATUS_SUCCESS ==
3771 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3772 hdd_sme_close_session_callback,
3773 adapter)) {
3774 /*
3775 * Block on a completion variable. Can't wait
3776 * forever though.
3777 */
3778 rc = wait_for_completion_timeout(
3779 &adapter->session_close_comp_var,
3780 msecs_to_jiffies
3781 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003782 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003783 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003784 if (adapter->device_mode == QDF_NDI_MODE)
3785 hdd_ndp_session_end_handler(adapter);
3786 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303787 return;
Sandeep Puligillaada72922016-09-29 19:31:21 -07003788 }
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003789 ret = hdd_release_and_destroy_vdev(adapter);
3790 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303791 hdd_err("vdev delete failed");
3792
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303793 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003794 }
3795}
3796
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303797QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 const bool bCloseSession)
3799{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303800 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3802 union iwreq_data wrqu;
3803 tSirUpdateIE updateIE;
3804 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303805 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806
3807 ENTER();
3808
Sachin Ahuja988fd102016-09-15 17:16:25 +05303809 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003810 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3812 WLAN_CONTROL_PATH);
3813 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003814 case QDF_STA_MODE:
3815 case QDF_P2P_CLIENT_MODE:
3816 case QDF_IBSS_MODE:
3817 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003818 case QDF_NDI_MODE:
3819 if ((QDF_NDI_MODE == adapter->device_mode) ||
3820 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3822 hdd_is_connecting(
3823 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003824 INIT_COMPLETION(adapter->disconnect_comp_var);
3825 /*
3826 * For NDI do not use pWextState from sta_ctx, if needed
3827 * extract from ndi_ctx.
3828 */
3829 if (QDF_NDI_MODE == adapter->device_mode)
3830 qdf_ret_status = sme_roam_disconnect(
3831 hdd_ctx->hHal,
3832 adapter->sessionId,
3833 eCSR_DISCONNECT_REASON_NDI_DELETE);
3834 else if (pWextState->roamProfile.BSSType ==
3835 eCSR_BSS_TYPE_START_IBSS)
3836 qdf_ret_status = sme_roam_disconnect(
3837 hdd_ctx->hHal,
3838 adapter->sessionId,
3839 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003841 qdf_ret_status = sme_roam_disconnect(
3842 hdd_ctx->hHal,
3843 adapter->sessionId,
3844 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303846 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 rc = wait_for_completion_timeout(
3848 &adapter->disconnect_comp_var,
3849 msecs_to_jiffies
3850 (WLAN_WAIT_TIME_DISCONNECT));
3851 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003852 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853 }
3854 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003855 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856 }
3857 memset(&wrqu, '\0', sizeof(wrqu));
3858 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3859 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3860 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3861 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303862 }
3863 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303864 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303866 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303867 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868
3869#ifdef WLAN_OPEN_SOURCE
3870 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3871#endif
3872
3873 hdd_deregister_tx_flow_control(adapter);
3874
3875#ifdef WLAN_NS_OFFLOAD
3876#ifdef WLAN_OPEN_SOURCE
3877 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3878#endif
3879#endif
3880
3881 /*
3882 * It is possible that the caller of this function does not
3883 * wish to close the session
3884 */
Krunal Soni985b8132017-02-10 18:49:08 -08003885 if (true == bCloseSession) {
3886 if (0 != wlan_hdd_try_disconnect(adapter)) {
3887 hdd_err("Error: Can't disconnect adapter");
3888 return QDF_STATUS_E_FAILURE;
3889 }
Peng Xu66162de2016-02-11 17:01:20 -08003890 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Krunal Soni985b8132017-02-10 18:49:08 -08003891 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892 break;
3893
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003894 case QDF_SAP_MODE:
3895 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003897 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 /*
3899 * Before stopping the sap adapter, lets make sure there
3900 * is no sap restart work pending.
3901 */
3902 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003903 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003904 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 }
3906 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003907 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3909
3910 hdd_deregister_tx_flow_control(adapter);
3911
3912 mutex_lock(&hdd_ctx->sap_lock);
3913 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303914 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303915 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916
3917 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003918 status = wlansap_stop_bss(
3919 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303921 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003922 hdd_hostapd_state_t *hostapd_state =
3923 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303924 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303925 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303926 qdf_status =
3927 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08003928 qdf_stop_bss_event,
3929 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930
Anurag Chouhance0dc992016-02-16 18:18:03 +05303931 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003932 hdd_err("failure waiting for wlansap_stop_bss %d",
3933 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 }
3935 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003936 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003937 }
3938 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003939 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003940 adapter->device_mode,
3941 adapter->sessionId);
3942
Anurag Chouhanc5548422016-02-24 18:33:27 +05303943 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003944 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945 updateIE.smeSessionId = adapter->sessionId;
3946 updateIE.ieBufferlength = 0;
3947 updateIE.pAdditionIEBuffer = NULL;
3948 updateIE.append = false;
3949 updateIE.notify = false;
3950 /* Probe bcn reset */
3951 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3952 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303953 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003954 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955 }
3956 /* Assoc resp reset */
3957 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3958 &updateIE,
3959 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303960 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003961 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962 }
3963 /* Reset WNI_CFG_PROBE_RSP Flags */
3964 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303965 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966 adapter->sessionCtx.ap.beacon = NULL;
3967 }
3968 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003969 if (true == bCloseSession)
3970 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003972 case QDF_OCB_MODE:
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -08003973 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003974 (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
Leo Changfdb45c32016-10-28 11:09:23 -07003975 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003976 break;
3977 default:
3978 break;
3979 }
3980
3981 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303982 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003983}
3984
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05303985/**
3986 * hdd_deinit_all_adapters - deinit all adapters
3987 * @hdd_ctx: HDD context
3988 * @rtnl_held: True if RTNL lock held
3989 *
3990 */
3991void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
3992{
3993 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3994 QDF_STATUS status;
3995 hdd_adapter_t *adapter;
3996
3997 ENTER();
3998
3999 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4000
4001 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4002 adapter = adapter_node->pAdapter;
4003 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
4004 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4005 adapter_node = next;
4006 }
4007
4008 EXIT();
4009}
4010
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304011QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004012{
4013 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304014 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015 hdd_adapter_t *adapter;
4016
4017 ENTER();
4018
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304019 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4022
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304023 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 adapter = adapterNode->pAdapter;
4025 hdd_stop_adapter(hdd_ctx, adapter, true);
4026 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4027 adapterNode = pNext;
4028 }
4029
4030 EXIT();
4031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304032 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033}
4034
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304035QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036{
4037 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304038 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039 hdd_adapter_t *adapter;
4040
4041 ENTER();
4042
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304043 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4044
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4046
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304047 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07004049 hdd_notice("Disabling queues");
Arun Khandavallicc544b32017-01-30 19:52:16 +05304050 if (hdd_ctx->config->sap_internal_restart &&
4051 adapter->device_mode == QDF_SAP_MODE) {
4052 wlan_hdd_netif_queue_control(adapter,
4053 WLAN_NETIF_TX_DISABLE,
4054 WLAN_CONTROL_PATH);
4055 hdd_sap_indicate_disconnect_for_sta(adapter);
4056 hdd_cleanup_actionframe(hdd_ctx, adapter);
4057 hdd_sap_destroy_events(adapter);
4058 } else
4059 wlan_hdd_netif_queue_control(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004060 WLAN_NETIF_TX_DISABLE_N_CARRIER,
4061 WLAN_CONTROL_PATH);
4062
4063 adapter->sessionCtx.station.hdd_ReassocScenario = false;
4064
4065 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08004066 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 adapter->sessionId);
4068 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
4069 hdd_wmm_adapter_close(adapter);
4070 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
4071 }
4072
Wu Gao36717432016-11-21 15:09:48 +08004073 /*
4074 * If adapter is SAP, set session ID to invalid since SAP
4075 * session will be cleanup during SSR.
4076 */
4077 if (adapter->device_mode == QDF_SAP_MODE)
4078 wlansap_set_invalid_session(
4079 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
4080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4082 adapterNode = pNext;
4083 }
4084
4085 EXIT();
4086
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304087 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004088}
4089
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304090bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
4091{
4092 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4093 QDF_STATUS status;
4094 bool close_modules = true;
4095
4096 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4097 while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
4098 if (test_bit(DEVICE_IFACE_OPENED,
4099 &adapter_node->pAdapter->event_flags)) {
4100 hdd_info("Still other ifaces are up cannot close modules");
4101 close_modules = false;
4102 break;
4103 }
4104 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4105 adapter_node = next;
4106 }
4107
4108 return close_modules;
4109}
4110
Arun Khandavallifae92942016-08-01 13:31:08 +05304111/**
4112 * hdd_is_interface_up()- Checkfor interface up before ssr
4113 * @hdd_ctx: HDD context
4114 *
4115 * check if there are any wlan interfaces before SSR accordingly start
4116 * the interface.
4117 *
4118 * Return: 0 if interface was opened else false
4119 */
4120static bool hdd_is_interface_up(hdd_adapter_t *adapter)
4121{
4122 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
4123 return true;
4124 else
4125 return false;
4126}
4127
Anurag Chouhanc4092922016-09-08 15:56:11 +05304128#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05304129 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304130struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4131 struct ieee80211_channel *channel,
4132 const u8 *bssid, const u8 *ssid,
4133 size_t ssid_len)
4134{
4135 return cfg80211_get_bss(wiphy, channel, bssid,
4136 ssid, ssid_len,
4137 WLAN_CAPABILITY_ESS,
4138 WLAN_CAPABILITY_ESS);
4139}
4140#else
4141struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4142 struct ieee80211_channel *channel,
4143 const u8 *bssid, const u8 *ssid,
4144 size_t ssid_len)
4145{
4146 return cfg80211_get_bss(wiphy, channel, bssid,
4147 ssid, ssid_len,
4148 IEEE80211_BSS_TYPE_ESS,
4149 IEEE80211_PRIVACY_ANY);
4150}
4151#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304152
Abhishek Singha84d3952016-09-13 13:45:05 +05304153#if defined CFG80211_CONNECT_BSS
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304154#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
4155 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
4156/**
4157 * hdd_convert_timeout_reason() - Convert to kernel specific enum
4158 * @timeout_reason: reason for connect timeout
4159 *
4160 * This function is used to convert host timeout
4161 * reason enum to kernel specific enum.
4162 *
4163 * Return: nl timeout enum
4164 */
4165static enum nl80211_timeout_reason hdd_convert_timeout_reason(
4166 tSirResultCodes timeout_reason)
4167{
4168 switch (timeout_reason) {
4169 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
4170 return NL80211_TIMEOUT_SCAN;
4171 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
4172 return NL80211_TIMEOUT_AUTH;
4173 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
4174 return NL80211_TIMEOUT_ASSOC;
4175 default:
4176 return NL80211_TIMEOUT_UNSPECIFIED;
4177 }
4178}
4179
4180/**
4181 * hdd_cfg80211_connect_timeout() - API to send connection timeout reason
4182 * @dev: network device
4183 * @bssid: bssid to which we want to associate
4184 * @timeout_reason: reason for connect timeout
4185 *
4186 * This API is used to send connection timeout reason to supplicant
4187 *
4188 * Return: void
4189 */
4190static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4191 const u8 *bssid,
4192 tSirResultCodes timeout_reason)
4193{
4194 enum nl80211_timeout_reason nl_timeout_reason;
4195 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4196
4197 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
4198 nl_timeout_reason);
4199}
4200
4201/**
4202 * __hdd_connect_bss() - API to send connection status to supplicant
4203 * @dev: network device
4204 * @bssid: bssid to which we want to associate
4205 * @req_ie: Request Information Element
4206 * @req_ie_len: len of the req IE
4207 * @resp_ie: Response IE
4208 * @resp_ie_len: len of ht response IE
4209 * @status: status
4210 * @gfp: Kernel Flag
4211 * @timeout_reason: reason for connect timeout
4212 *
4213 * Return: void
4214 */
4215static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4216 struct cfg80211_bss *bss, const u8 *req_ie,
4217 size_t req_ie_len, const u8 *resp_ie,
4218 size_t resp_ie_len, int status, gfp_t gfp,
4219 tSirResultCodes timeout_reason)
4220{
4221 enum nl80211_timeout_reason nl_timeout_reason;
4222 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4223
4224 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4225 resp_ie, resp_ie_len, status, gfp,
4226 nl_timeout_reason);
4227}
4228#else
4229#if defined CFG80211_CONNECT_TIMEOUT
4230static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4231 const u8 *bssid,
4232 tSirResultCodes timeout_reason)
4233{
4234 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
4235}
4236#endif
4237
4238static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4239 struct cfg80211_bss *bss, const u8 *req_ie,
4240 size_t req_ie_len, const u8 *resp_ie,
4241 size_t resp_ie_len, int status, gfp_t gfp,
4242 tSirResultCodes timeout_reason)
4243{
4244 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4245 resp_ie, resp_ie_len, status, gfp);
4246}
4247#endif
4248
Abhishek Singha84d3952016-09-13 13:45:05 +05304249/**
4250 * hdd_connect_bss() - API to send connection status to supplicant
4251 * @dev: network device
4252 * @bssid: bssid to which we want to associate
4253 * @req_ie: Request Information Element
4254 * @req_ie_len: len of the req IE
4255 * @resp_ie: Response IE
4256 * @resp_ie_len: len of ht response IE
4257 * @status: status
4258 * @gfp: Kernel Flag
4259 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304260 * @timeout_reason: reason for connect timeout
Abhishek Singha84d3952016-09-13 13:45:05 +05304261 *
4262 * The API is a wrapper to send connection status to supplicant
4263 *
4264 * Return: Void
4265 */
4266#if defined CFG80211_CONNECT_TIMEOUT
4267static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4268 struct cfg80211_bss *bss, const u8 *req_ie,
4269 size_t req_ie_len, const u8 *resp_ie,
4270 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304271 bool connect_timeout,
4272 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304273{
4274 if (connect_timeout)
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304275 hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304276 else
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304277 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4278 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304279}
4280#else
4281static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4282 struct cfg80211_bss *bss, const u8 *req_ie,
4283 size_t req_ie_len, const u8 *resp_ie,
4284 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304285 bool connect_timeout,
4286 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304287{
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304288 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4289 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304290}
4291#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304292
4293/**
4294 * hdd_connect_result() - API to send connection status to supplicant
4295 * @dev: network device
4296 * @bssid: bssid to which we want to associate
4297 * @roam_info: information about connected bss
4298 * @req_ie: Request Information Element
4299 * @req_ie_len: len of the req IE
4300 * @resp_ie: Response IE
4301 * @resp_ie_len: len of ht response IE
4302 * @status: status
4303 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05304304 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304305 * @timeout_reason: reason for connect timeout
Anurag Chouhanc4092922016-09-08 15:56:11 +05304306 *
4307 * The API is a wrapper to send connection status to supplicant
4308 * and allow runtime suspend
4309 *
4310 * Return: Void
4311 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304312void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4313 tCsrRoamInfo *roam_info, const u8 *req_ie,
4314 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304315 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304316 bool connect_timeout,
4317 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304318{
4319 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4320 struct cfg80211_bss *bss = NULL;
4321
4322 if (WLAN_STATUS_SUCCESS == status) {
4323 struct ieee80211_channel *chan;
4324 int freq;
4325 int chan_no = roam_info->pBssDesc->channelId;
4326
4327 if (chan_no <= 14)
4328 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004329 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304330 else
4331 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004332 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304333
4334 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
4335 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
4336 roam_info->u.pConnectedProfile->SSID.ssId,
4337 roam_info->u.pConnectedProfile->SSID.length);
4338 }
Komal Seelama89be8d2016-09-29 11:09:26 +05304339
Abhishek Singha84d3952016-09-13 13:45:05 +05304340 hdd_connect_bss(dev, bssid, bss, req_ie,
4341 req_ie_len, resp_ie, resp_ie_len,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304342 status, gfp, connect_timeout, timeout_reason);
Komal Seelama89be8d2016-09-29 11:09:26 +05304343
4344 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304345}
4346#else
4347void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4348 tCsrRoamInfo *roam_info, const u8 *req_ie,
4349 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304350 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304351 bool connect_timeout,
4352 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304353{
Komal Seelama89be8d2016-09-29 11:09:26 +05304354 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4355
Anurag Chouhanc4092922016-09-08 15:56:11 +05304356 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4357 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304358 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304359}
4360#endif
4361
4362
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304363QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364{
4365 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304366 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 hdd_adapter_t *adapter;
4368#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304369 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370#endif
4371 eConnectionState connState;
4372
4373 ENTER();
4374
4375 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304376 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377 adapter = adapterNode->pAdapter;
4378
Arun Khandavallifae92942016-08-01 13:31:08 +05304379 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304380 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 hdd_wmm_init(adapter);
4383
4384 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004385 case QDF_STA_MODE:
4386 case QDF_P2P_CLIENT_MODE:
4387 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388
4389 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4390 ->conn_info.connState;
4391
4392 hdd_init_station_mode(adapter);
4393 /* Open the gates for HDD to receive Wext commands */
4394 adapter->isLinkUpSvcNeeded = false;
4395 adapter->scan_info.mScanPending = false;
4396
4397 /* Indicate disconnect event to supplicant if associated previously */
4398 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004399 eConnectionState_IbssConnected == connState ||
4400 eConnectionState_NotConnected == connState ||
4401 eConnectionState_IbssDisconnected == connState ||
4402 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403 union iwreq_data wrqu;
4404 memset(&wrqu, '\0', sizeof(wrqu));
4405 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4406 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4407 wireless_send_event(adapter->dev, SIOCGIWAP,
4408 &wrqu, NULL);
4409 adapter->sessionCtx.station.
4410 hdd_ReassocScenario = false;
4411
4412 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304413 wlan_hdd_cfg80211_indicate_disconnect(
4414 adapter->dev, false,
4415 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004416 } else if (eConnectionState_Connecting == connState) {
4417 /*
4418 * Indicate connect failure to supplicant if we were in the
4419 * process of connecting
4420 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304421 hdd_connect_result(adapter->dev, NULL, NULL,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304422 NULL, 0, NULL, 0,
4423 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4424 GFP_KERNEL, false,
4425 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 }
4427
4428 hdd_register_tx_flow_control(adapter,
4429 hdd_tx_resume_timer_expired_handler,
4430 hdd_tx_resume_cb);
4431
4432 break;
4433
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004434 case QDF_SAP_MODE:
Arun Khandavallicc544b32017-01-30 19:52:16 +05304435 if (hdd_ctx->config->sap_internal_restart)
4436 hdd_init_ap_mode(adapter, true);
4437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004438 break;
4439
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004440 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004441#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07004442 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4444#else
Jeff Johnson5880d792016-08-15 13:32:30 -07004445 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446 /* event supplicant to restart */
4447 cfg80211_del_sta(adapter->dev,
4448 (const u8 *)&bcastMac.bytes[0],
4449 GFP_KERNEL);
4450#endif
4451 break;
4452
4453 default:
4454 break;
4455 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304456get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4458 adapterNode = pNext;
4459 }
4460
4461 EXIT();
4462
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304463 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004464}
4465
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304466QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004467 hdd_adapter_list_node_t **padapterNode)
4468{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304469 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004470 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304471 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4472 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004473 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 return status;
4475}
4476
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304477QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004478 hdd_adapter_list_node_t *adapterNode,
4479 hdd_adapter_list_node_t **pNextAdapterNode)
4480{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304481 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004482 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304483 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4484 (qdf_list_node_t *) adapterNode,
4485 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004486
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004487 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004488 return status;
4489}
4490
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304491QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492 hdd_adapter_list_node_t *adapterNode)
4493{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304494 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004495 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304496 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004498 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 return status;
4500}
4501
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304502QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 hdd_adapter_list_node_t **padapterNode)
4504{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304505 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004506 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304507 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4508 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004509 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510 return status;
4511}
4512
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304513QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514 hdd_adapter_list_node_t *adapterNode)
4515{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304516 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004517 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304518 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4519 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004520 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 return status;
4522}
4523
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304524QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525 hdd_adapter_list_node_t *adapterNode)
4526{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304527 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004528 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304529 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4530 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004531 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004532 return status;
4533}
4534
4535hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4536 tSirMacAddr macAddr)
4537{
4538 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4539 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304540 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004541
4542 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4543
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304544 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004545 adapter = adapterNode->pAdapter;
4546
4547 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304548 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004549 macAddr, sizeof(tSirMacAddr))) {
4550 return adapter;
4551 }
4552 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4553 adapterNode = pNext;
4554 }
4555
4556 return NULL;
4557
4558}
4559
4560hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4561 uint32_t vdev_id)
4562{
4563 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4564 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304565 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004566
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304567 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304569 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004570 adapter = adapterNode->pAdapter;
4571
4572 if (adapter->sessionId == vdev_id)
4573 return adapter;
4574
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304575 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4577 adapterNode = pNext;
4578 }
4579
Jeff Johnson5880d792016-08-15 13:32:30 -07004580 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581
4582 return NULL;
4583}
4584
Abhishek Singh7996eb72015-12-30 17:24:02 +05304585/**
4586 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4587 * the sessionid
4588 * @hdd_ctx: hdd context.
4589 * @sme_session_id: sme session is for the adapter to get.
4590 *
4591 * This function is used to get the adapter with provided session id
4592 *
4593 * Return: adapter pointer if found
4594 *
4595 */
4596hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4597 uint32_t sme_session_id)
4598{
4599 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4600 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304601 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304602
4603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304604 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304605
4606 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304607 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304608 adapter = adapter_node->pAdapter;
4609
4610 if (adapter &&
4611 adapter->sessionId == sme_session_id)
4612 return adapter;
4613
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304614 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304615 hdd_get_next_adapter(hdd_ctx,
4616 adapter_node, &next);
4617 adapter_node = next;
4618 }
4619 return NULL;
4620}
4621
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004622/**
4623 * hdd_get_adapter() - to get adapter matching the mode
4624 * @hdd_ctx: hdd context
4625 * @mode: adapter mode
4626 *
4627 * This routine will return the pointer to adapter matching
4628 * with the passed mode.
4629 *
4630 * Return: pointer to adapter or null
4631 */
4632hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4633 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004634{
4635 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4636 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304637 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638
4639 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304641 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004642 adapter = adapterNode->pAdapter;
4643
4644 if (adapter && (mode == adapter->device_mode))
4645 return adapter;
4646
4647 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4648 adapterNode = pNext;
4649 }
4650
4651 return NULL;
4652
4653}
4654
4655/**
4656 * hdd_get_operating_channel() - return operating channel of the device mode
4657 * @hdd_ctx: Pointer to the HDD context.
4658 * @mode: Device mode for which operating channel is required.
4659 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004660 * QDF_STA_MODE,
4661 * QDF_P2P_CLIENT_MODE,
4662 * QDF_SAP_MODE,
4663 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 *
4665 * This API returns the operating channel of the requested device mode
4666 *
4667 * Return: channel number. "0" id the requested device is not found OR it is
4668 * not connected.
4669 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004670uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4671 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672{
4673 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304674 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675 hdd_adapter_t *adapter;
4676 uint8_t operatingChannel = 0;
4677
4678 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4679
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304680 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 adapter = adapterNode->pAdapter;
4682
4683 if (mode == adapter->device_mode) {
4684 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004685 case QDF_STA_MODE:
4686 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004687 if (hdd_conn_is_connected
4688 (WLAN_HDD_GET_STATION_CTX_PTR
4689 (adapter))) {
4690 operatingChannel =
4691 (WLAN_HDD_GET_STATION_CTX_PTR
4692 (adapter))->conn_info.
4693 operationChannel;
4694 }
4695 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004696 case QDF_SAP_MODE:
4697 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004698 /* softap connection info */
4699 if (test_bit
4700 (SOFTAP_BSS_STARTED,
4701 &adapter->event_flags))
4702 operatingChannel =
4703 (WLAN_HDD_GET_AP_CTX_PTR
4704 (adapter))->operatingChannel;
4705 break;
4706 default:
4707 break;
4708 }
4709
4710 break; /* Found the device of interest. break the loop */
4711 }
4712
4713 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4714 adapterNode = pNext;
4715 }
4716 return operatingChannel;
4717}
4718
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304719static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 hdd_ctx)
4721{
4722 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304723 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724 hdd_adapter_t *adapter;
4725
4726 ENTER();
4727
4728 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4729
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304730 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004731 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004732 if ((adapter->device_mode == QDF_STA_MODE) ||
4733 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4734 (adapter->device_mode == QDF_IBSS_MODE) ||
4735 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4736 (adapter->device_mode == QDF_SAP_MODE) ||
4737 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738 wlan_hdd_cfg80211_deregister_frames(adapter);
4739 hdd_unregister_wext(adapter->dev);
4740 }
4741 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4742 adapterNode = pNext;
4743 }
4744
4745 EXIT();
4746
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304747 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004748}
4749
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304750QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004751{
4752 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304753 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 hdd_adapter_t *adapter;
4755
4756 ENTER();
4757
4758 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4759
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304760 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004761 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004762 if ((adapter->device_mode == QDF_STA_MODE) ||
4763 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4764 (adapter->device_mode == QDF_IBSS_MODE) ||
4765 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4766 (adapter->device_mode == QDF_SAP_MODE) ||
4767 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004768 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05304769 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 eCSR_SCAN_ABORT_DEFAULT);
4771 }
4772 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4773 adapterNode = pNext;
4774 }
4775
4776 EXIT();
4777
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304778 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779}
4780
Dustin Brownf27bce82016-11-03 12:52:27 -07004781/**
4782 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4783 * adapters
4784 * @hdd_ctx: The HDD context containing the adapters to operate on
4785 *
4786 * return: QDF_STATUS_SUCCESS
4787 */
4788static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4789{
4790 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4791 QDF_STATUS status;
4792 hdd_adapter_t *adapter;
4793 int err;
4794
4795 ENTER();
4796
4797 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4798
4799 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4800 adapter = adapter_node->pAdapter;
4801 if ((adapter->device_mode == QDF_STA_MODE) ||
4802 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4803 (adapter->device_mode == QDF_IBSS_MODE) ||
4804 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4805 (adapter->device_mode == QDF_SAP_MODE) ||
4806 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4807 err = wlan_hdd_sched_scan_stop(adapter->dev);
4808 if (err)
4809 hdd_err("Unable to stop scheduled scan");
4810 }
4811 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node);
4812 adapter_node = next_node;
4813 }
4814
4815 EXIT();
4816
4817 return QDF_STATUS_SUCCESS;
4818}
4819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820#ifdef WLAN_NS_OFFLOAD
4821/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004822 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 * @hdd_ctx: Pointer to hdd context
4824 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004825 * Unregister for IPv6 address change notifications.
4826 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004827 * Return: None
4828 */
4829static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4830{
4831 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4832
4833 return;
4834}
4835
4836/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004837 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 * @hdd_ctx: Pointer to hdd context
4839 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004840 * Register for IPv6 address change notifications.
4841 *
4842 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004844static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004845{
4846 int ret;
4847
4848 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4849 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004850 if (ret) {
4851 hdd_err("Failed to register IPv6 notifier: %d", ret);
4852 goto out;
4853 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004855 hdd_info("Registered IPv6 notifier");
4856out:
4857 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858}
4859#else
4860/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004861 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 * @hdd_ctx: Pointer to hdd context
4863 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004864 * Unregister for IPv6 address change notifications.
4865 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 * Return: None
4867 */
4868static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4869{
4870}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004873 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874 * @hdd_ctx: Pointer to hdd context
4875 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004876 * Register for IPv6 address change notifications.
4877 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878 * Return: None
4879 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004880static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004882 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004883}
4884#endif
4885
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304886#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4887/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004888 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304889 * @hdd_ctx: HDD context
4890 *
4891 * Activates the logging service
4892 *
4893 * Return: Zero in case of success, negative value otherwise
4894 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004895static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304896{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004897 int ret;
4898 struct hdd_config *config = hdd_ctx->config;
4899
4900 if (!config->wlanLoggingEnable)
4901 return 0;
4902
4903 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4904 config->wlanLoggingNumBuf);
4905 if (ret)
4906 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4907 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304908}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004909
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304910/**
4911 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4912 * @hdd_ctx: HDD context
4913 *
4914 * Deactivates the logging service
4915 *
4916 * Return: 0 on deactivating the logging service
4917 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004918static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304919{
4920 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4921 return wlan_logging_sock_deactivate_svc();
4922
4923 return 0;
4924}
4925#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004926static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304927{
4928 return 0;
4929}
4930
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004931static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304932{
4933 return 0;
4934}
4935#endif
4936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004937/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004938 * hdd_register_notifiers - Register netdev notifiers.
4939 * @hdd_ctx: HDD context
4940 *
4941 * Register netdev notifiers like IPv4 and IPv6.
4942 *
4943 * Return: 0 on success and errno on failure
4944 */
4945static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4946{
4947 int ret;
4948
4949 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4950 if (ret) {
4951 hdd_err("register_netdevice_notifier failed: %d", ret);
4952 goto out;
4953 }
4954
4955 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4956 if (ret)
4957 goto unregister_notifier;
4958
4959 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4960 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4961 if (ret) {
4962 hdd_err("Failed to register IPv4 notifier: %d", ret);
4963 goto unregister_ip6_notifier;
4964 }
4965
4966 return 0;
4967
4968unregister_ip6_notifier:
4969 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4970unregister_notifier:
4971 unregister_netdevice_notifier(&hdd_netdev_notifier);
4972out:
4973 return ret;
4974
4975}
4976
4977/**
4978 * hdd_unregister_notifiers - Unregister netdev notifiers.
4979 * @hdd_ctx: HDD context
4980 *
4981 * Unregister netdev notifiers like IPv4 and IPv6.
4982 *
4983 * Return: None.
4984 */
4985static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4986{
4987 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4988
4989 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4990
4991 unregister_netdevice_notifier(&hdd_netdev_notifier);
4992}
4993
4994/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004995 * hdd_exit_netlink_services - Exit netlink services
4996 * @hdd_ctx: HDD context
4997 *
4998 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4999 * nl service.
5000 *
5001 * Return: None.
5002 */
5003static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
5004{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005005 hdd_close_cesium_nl_sock();
Naveen Rawat910726a2017-03-06 11:42:51 -08005006 hdd_deactivate_wifi_pos();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005007 ptt_sock_deactivate_svc();
5008
5009 nl_srv_exit();
5010}
5011
5012/**
5013 * hdd_init_netlink_services- Init netlink services
5014 * @hdd_ctx: HDD context
5015 *
5016 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
5017 * nl service.
5018 *
5019 * Return: 0 on success and errno on failure.
5020 */
5021static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
5022{
5023 int ret;
5024
Ryan Hsuceddceb2016-04-28 10:20:14 -07005025 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005026 if (ret) {
5027 hdd_alert("nl_srv_init failed: %d", ret);
5028 goto out;
5029 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07005030 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005031
Naveen Rawat910726a2017-03-06 11:42:51 -08005032 ret = hdd_activate_wifi_pos(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005033 if (ret) {
Naveen Rawat910726a2017-03-06 11:42:51 -08005034 hdd_alert("hdd_activate_wifi_pos failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005035 goto err_nl_srv;
5036 }
5037
5038 ret = ptt_sock_activate_svc();
5039 if (ret) {
5040 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
5041 goto err_nl_srv;
5042 }
5043
5044 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07005045 if (ret)
5046 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005047
5048 ret = cnss_diag_activate_service();
5049 if (ret) {
5050 hdd_alert("cnss_diag_activate_service failed: %d", ret);
5051 goto err_close_cesium;
5052 }
5053
5054 return 0;
5055
5056err_close_cesium:
5057 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005058 ptt_sock_deactivate_svc();
5059err_nl_srv:
5060 nl_srv_exit();
5061out:
5062 return ret;
5063}
5064
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005065/**
5066 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
5067 * @hdd_ctx: HDD context.
5068 *
5069 * Destroy RX wakelock.
5070 *
5071 * Return: None.
5072 */
5073static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
5074{
5075 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
5076}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005077
5078/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005079 * hdd_rx_wake_lock_create() - Create RX wakelock
5080 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005081 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005082 * Create RX wakelock.
5083 *
5084 * Return: None.
5085 */
5086static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
5087{
5088 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5089}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005090
5091/**
5092 * hdd_roc_context_init() - Init ROC context
5093 * @hdd_ctx: HDD context.
5094 *
5095 * Initialize ROC context.
5096 *
5097 * Return: 0 on success and errno on failure.
5098 */
5099static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
5100{
5101 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
5102 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
5103
5104 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5105
5106 return 0;
5107}
5108
5109/**
5110 * hdd_roc_context_destroy() - Destroy ROC context
5111 * @hdd_ctx: HDD context.
5112 *
5113 * Destroy roc list and flush the pending roc work.
5114 *
5115 * Return: None.
5116 */
5117static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
5118{
5119 flush_delayed_work(&hdd_ctx->roc_req_work);
5120 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08005121 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005122}
5123
5124/**
Houston Hoffman160db392016-10-10 17:37:51 -07005125 * hdd_context_deinit() - Deinitialize HDD context
5126 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005127 *
Houston Hoffman160db392016-10-10 17:37:51 -07005128 * Deinitialize HDD context along with all the feature specific contexts but
5129 * do not free hdd context itself. Caller of this API is supposed to free
5130 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005131 *
Houston Hoffman160db392016-10-10 17:37:51 -07005132 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005133 */
Houston Hoffman160db392016-10-10 17:37:51 -07005134static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005135{
Houston Hoffman160db392016-10-10 17:37:51 -07005136 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005137
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005138 hdd_roc_context_destroy(hdd_ctx);
5139
5140 hdd_sap_context_destroy(hdd_ctx);
5141
5142 hdd_rx_wake_lock_destroy(hdd_ctx);
5143
5144 hdd_tdls_context_destroy(hdd_ctx);
5145
5146 hdd_scan_context_destroy(hdd_ctx);
5147
5148 qdf_list_destroy(&hdd_ctx->hddAdapters);
5149
Houston Hoffman160db392016-10-10 17:37:51 -07005150 return 0;
5151}
5152
5153/**
5154 * hdd_context_destroy() - Destroy HDD context
5155 * @hdd_ctx: HDD context to be destroyed.
5156 *
5157 * Free config and HDD context as well as destroy all the resources.
5158 *
5159 * Return: None
5160 */
5161static void hdd_context_destroy(hdd_context_t *hdd_ctx)
5162{
5163 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
5164 hdd_logging_sock_deactivate_svc(hdd_ctx);
5165
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05305166 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5167
Houston Hoffman160db392016-10-10 17:37:51 -07005168 hdd_context_deinit(hdd_ctx);
5169
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305170 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005171 hdd_ctx->config = NULL;
5172
5173 wiphy_free(hdd_ctx->wiphy);
5174}
5175
5176/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177 * hdd_wlan_exit() - HDD WLAN exit function
5178 * @hdd_ctx: Pointer to the HDD Context
5179 *
5180 * This is the driver exit point (invoked during rmmod)
5181 *
5182 * Return: None
5183 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005184static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185{
5186 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305187 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005188 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05305189 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005190
5191 ENTER();
5192
Arun Khandavallifae92942016-08-01 13:31:08 +05305193 if (QDF_TIMER_STATE_RUNNING ==
5194 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
5195 hdd_info("Stpp interface change timer");
5196 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005197 }
5198
Arun Khandavallifae92942016-08-01 13:31:08 +05305199 if (!QDF_IS_STATUS_SUCCESS
5200 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
5201 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005202
Arun Khandavallifae92942016-08-01 13:31:08 +05305203
5204 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205
Nitesh Shah61c10d92016-10-19 19:29:15 +05305206 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
5207
Prashanth Bhattaab004382016-10-11 16:08:11 -07005208 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209
5210#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305211 if (QDF_TIMER_STATE_RUNNING ==
5212 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
5213 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214 }
5215
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305216 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05305217 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005218 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219 }
Liangwei Dongaef84342016-10-21 05:28:00 -04005220 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5221 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5222 hdd_ctx->last_acs_channel_list = NULL;
5223 hdd_ctx->num_of_channels = 0;
5224 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226
Arun Khandavallifae92942016-08-01 13:31:08 +05305227 mutex_lock(&hdd_ctx->iface_change_lock);
5228 driver_status = hdd_ctx->driver_status;
5229 mutex_unlock(&hdd_ctx->iface_change_lock);
5230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 /*
5232 * Powersave Offload Case
5233 * Disable Idle Power Save Mode
5234 */
5235 hdd_set_idle_ps_config(hdd_ctx, false);
5236
Arun Khandavallifae92942016-08-01 13:31:08 +05305237 if (driver_status != DRIVER_MODULES_CLOSED) {
5238 hdd_unregister_wext_all_adapters(hdd_ctx);
5239 /*
5240 * Cancel any outstanding scan requests. We are about to close
5241 * all of our adapters, but an adapter structure is what SME
5242 * passes back to our callback function. Hence if there
5243 * are any outstanding scan requests then there is a
5244 * race condition between when the adapter is closed and
5245 * when the callback is invoked. We try to resolve that
5246 * race condition here by canceling any outstanding scans
5247 * before we close the adapters.
5248 * Note that the scans may be cancelled in an asynchronous
5249 * manner, so ideally there needs to be some kind of
5250 * synchronization. Rather than introduce a new
5251 * synchronization here, we will utilize the fact that we are
5252 * about to Request Full Power, and since that is synchronized,
5253 * the expectation is that by the time Request Full Power has
5254 * completed, all scans will be cancelled
5255 */
Jeff Johnsonf337b0c2017-03-10 10:48:30 -08005256 hdd_cleanup_scan_queue(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305257 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07005258 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305259 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 }
5261
5262 /*
5263 * Close the scheduler before calling cds_close to make sure no thread
5264 * is scheduled after the each module close is called i.e after all the
5265 * data structures are freed.
5266 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305267 qdf_status = cds_sched_close(p_cds_context);
5268 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005269 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305270 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005271 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05305273 hdd_wlan_stop_modules(hdd_ctx);
5274
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305275 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
5276 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
5277 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
5278
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005279 /*
5280 * Close CDS
5281 * This frees pMac(HAL) context. There should not be any call
5282 * that requires pMac access after this.
5283 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005284
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07005285 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08005286 hdd_request_manager_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287
Komal Seelam8634b772016-09-29 12:12:24 +05305288 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005289 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005290
5291 hdd_ipa_cleanup(hdd_ctx);
5292
5293 /* Free up RoC request queue and flush workqueue */
5294 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05305296 wlansap_global_deinit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05305297 wlan_hdd_deinit_chan_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005298 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05305299 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005300
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07005301 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07005302
Arun Khandavallifae92942016-08-01 13:31:08 +05305303 hdd_exit_netlink_services(hdd_ctx);
5304 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005305 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306}
5307
5308void __hdd_wlan_exit(void)
5309{
5310 hdd_context_t *hdd_ctx;
5311
5312 ENTER();
5313
Anurag Chouhan6d760662016-02-20 16:05:43 +05305314 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005315 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005316 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 EXIT();
5318 return;
5319 }
5320
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005321 /* Check IPA HW Pipe shutdown */
5322 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
5323
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005324 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05305325 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005327 /* Do all the cleanup before deregistering the driver */
5328 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07005329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 EXIT();
5331}
5332
5333#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04005334/**
5335 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
5336 * @data: pointer to hdd_context_t
5337 *
5338 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
5339 * Then new ACS request will do a fresh scan without reusing the cached
5340 * scan information.
5341 *
5342 * Return: void
5343 */
Tang Yingying523322d2017-01-17 23:28:43 +08005344static void hdd_skip_acs_scan_timer_handler(void *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005345{
5346 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
5347
Jeff Johnson760350b2016-08-15 14:01:52 -07005348 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04005350 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5351 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5352 hdd_ctx->last_acs_channel_list = NULL;
5353 hdd_ctx->num_of_channels = 0;
5354 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355
5356 if (!hdd_ctx->hHal)
5357 return;
5358 sme_scan_flush_result(hdd_ctx->hHal);
5359}
5360#endif
5361
5362#ifdef QCA_HT_2040_COEX
5363/**
5364 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5365 * @adapter: pointer to adapter
5366 * @staId: station id
5367 * @macAddrSTA: station MAC address
5368 * @channel_type: channel type
5369 *
5370 * This function notifies FW with HT20/HT40 mode
5371 *
5372 * Return: 0 if successful, error number otherwise
5373 */
5374int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305375 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376{
5377 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305378 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379 hdd_context_t *hdd_ctx = NULL;
5380
5381 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5382
5383 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305384 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305386
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 if (!hdd_ctx->hHal)
5388 return -EINVAL;
5389
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305390 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305392 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005393 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005394 return -EINVAL;
5395 }
5396
5397 return 0;
5398}
5399#endif
5400
5401/**
5402 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5403 * @state: state
5404 *
5405 * This function notifies FW with modem power status
5406 *
5407 * Return: 0 if successful, error number otherwise
5408 */
5409int hdd_wlan_notify_modem_power_state(int state)
5410{
5411 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305412 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 hdd_context_t *hdd_ctx;
5414
Anurag Chouhan6d760662016-02-20 16:05:43 +05305415 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305417 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 if (!hdd_ctx->hHal)
5421 return -EINVAL;
5422
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305423 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5424 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005425 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 state);
5427 return -EINVAL;
5428 }
5429 return 0;
5430}
5431
5432/**
5433 *
5434 * hdd_post_cds_enable_config() - HDD post cds start config helper
5435 * @adapter - Pointer to the HDD
5436 *
5437 * Return: None
5438 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305439QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305441 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442
5443 /*
5444 * Send ready indication to the HDD. This will kick off the MAC
5445 * into a 'running' state and should kick off an initial scan.
5446 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305447 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5448 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005449 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5450 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305451 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 }
5453
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305454 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455}
5456
5457/* wake lock APIs for HDD */
5458void hdd_prevent_suspend(uint32_t reason)
5459{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305460 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461}
5462
5463void hdd_allow_suspend(uint32_t reason)
5464{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305465 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005466}
5467
5468void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5469{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305470 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5471 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005472}
5473
5474/**
5475 * hdd_exchange_version_and_caps() - exchange version and capability with target
5476 * @hdd_ctx: Pointer to HDD context
5477 *
5478 * This is the HDD function to exchange version and capability information
5479 * between Host and Target
5480 *
5481 * This function gets reported version of FW.
5482 * It also finds the version of target headers used to compile the host;
5483 * It compares the above two and prints a warning if they are different;
5484 * It gets the SW and HW version string;
5485 * Finally, it exchanges capabilities between host and target i.e. host
5486 * and target exchange a msg indicating the features they support through a
5487 * bitmap
5488 *
5489 * Return: None
5490 */
5491void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5492{
5493
5494 tSirVersionType versionCompiled;
5495 tSirVersionType versionReported;
5496 tSirVersionString versionString;
5497 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305498 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005499
5500 memset(&versionCompiled, 0, sizeof(versionCompiled));
5501 memset(&versionReported, 0, sizeof(versionReported));
5502
5503 /* retrieve and display WCNSS version information */
5504 do {
5505
5506 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5507 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305508 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005509 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005510 break;
5511 }
5512
5513 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5514 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305515 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005516 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517 break;
5518 }
5519
5520 if ((versionCompiled.major != versionReported.major) ||
5521 (versionCompiled.minor != versionReported.minor) ||
5522 (versionCompiled.version != versionReported.version) ||
5523 (versionCompiled.revision != versionReported.revision)) {
5524 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5525 "Host expected %u.%u.%u.%u\n",
5526 WLAN_MODULE_NAME,
5527 (int)versionReported.major,
5528 (int)versionReported.minor,
5529 (int)versionReported.version,
5530 (int)versionReported.revision,
5531 (int)versionCompiled.major,
5532 (int)versionCompiled.minor,
5533 (int)versionCompiled.version,
5534 (int)versionCompiled.revision);
5535 } else {
5536 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5537 WLAN_MODULE_NAME,
5538 (int)versionReported.major,
5539 (int)versionReported.minor,
5540 (int)versionReported.version,
5541 (int)versionReported.revision);
5542 }
5543
5544 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5545 versionString,
5546 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305547 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005548 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 break;
5550 }
5551
5552 pr_info("%s: WCNSS software version %s\n",
5553 WLAN_MODULE_NAME, versionString);
5554
5555 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5556 versionString,
5557 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305558 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005559 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560 break;
5561 }
5562
5563 pr_info("%s: WCNSS hardware version %s\n",
5564 WLAN_MODULE_NAME, versionString);
5565
5566 /*
5567 * 1.Check if FW version is greater than 0.1.1.0. Only then
5568 * send host-FW capability exchange message
5569 * 2.Host-FW capability exchange message is only present on
5570 * target 1.1 so send the message only if it the target is 1.1
5571 * minor numbers for different target branches:
5572 * 0 -> (1.0)Mainline Build
5573 * 1 -> (1.1)Mainline Build
5574 * 2->(1.04) Stability Build
5575 */
5576 if (((versionReported.major > 0) || (versionReported.minor > 1)
5577 || ((versionReported.minor >= 1)
5578 && (versionReported.version >= 1)))
5579 && ((versionReported.major == 1)
5580 && (versionReported.minor >= 1)))
5581 fwFeatCapsMsgSupported = 1;
5582
5583 if (fwFeatCapsMsgSupported) {
5584 /*
5585 * Indicate if IBSS heartbeat monitoring needs to be
5586 * offloaded
5587 */
5588 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5589 sme_disable_feature_capablity
5590 (IBSS_HEARTBEAT_OFFLOAD);
5591 }
5592
5593 sme_feature_caps_exchange(hdd_ctx->hHal);
5594 }
5595
5596 } while (0);
5597
5598}
5599
5600/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305601QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602{
5603 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5604 hdd_ctx->reg.cc_src);
5605}
5606
5607/**
5608 * hdd_is_5g_supported() - check if hardware supports 5GHz
5609 * @hdd_ctx: Pointer to the hdd context
5610 *
5611 * HDD function to know if hardware supports 5GHz
5612 *
5613 * Return: true if hardware supports 5GHz
5614 */
5615bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5616{
zdingf54169a2016-10-12 17:08:45 +08005617 if (!hdd_ctx || !hdd_ctx->config)
5618 return true;
5619
5620 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5621 return true;
5622 else
5623 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624}
5625
Amar Singhale4f28ee2015-10-21 14:36:56 -07005626static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627{
5628 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005629 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630
5631 wiphy = hdd_ctx->wiphy;
5632
5633 /*
5634 * The channel information in
5635 * wiphy needs to be initialized before wiphy registration
5636 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005637 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5638 if (ret_val) {
5639 hdd_alert("regulatory init failed");
5640 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 }
5642
5643#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5644 wiphy->wowlan = &wowlan_support_reg_init;
5645#else
5646 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5647 WIPHY_WOWLAN_MAGIC_PKT |
5648 WIPHY_WOWLAN_DISCONNECT |
5649 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5650 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5651 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5652 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5653 WIPHY_WOWLAN_RFKILL_RELEASE;
5654
5655 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5656 WOW_MAX_FILTERS_PER_LIST);
5657 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5658 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5659#endif
5660
5661 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005662 ret_val = wlan_hdd_cfg80211_register(wiphy);
5663 if (0 > ret_val)
5664 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665
Amar Singhale4f28ee2015-10-21 14:36:56 -07005666 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667}
5668
Ravi Joshie2331e82015-07-01 18:18:54 -07005669/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005670 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005671 * @hdd_ctx - handle to hdd context
5672 * @tx_packets - transmit packet count
5673 * @rx_packets - receive packet count
5674 *
5675 * The function controls the bus bandwidth and dynamic control of
5676 * tcp delayed ack configuration
5677 *
5678 * Returns: None
5679 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005681static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5682 const uint64_t tx_packets,
5683 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005685 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005686 uint64_t temp_rx = 0;
5687 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005688 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005689 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5690 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005691 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005693 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005694 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005695 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005696 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005697 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005698 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005699 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005700 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005701
Mohit Khannae71e2262015-11-10 09:37:24 -08005702 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5703 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704
5705 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005706 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5707 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005708 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005709 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305710 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305711 if (hdd_ctx->hbw_requested) {
5712 pld_remove_pm_qos(hdd_ctx->parent_dev);
5713 hdd_ctx->hbw_requested = false;
5714 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305715 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005716 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305717 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305718 if (!hdd_ctx->hbw_requested) {
5719 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5720 hdd_ctx->hbw_requested = true;
5721 }
5722
Nirav Shah3bbfa512016-05-12 16:43:49 +05305723 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005724 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305725 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005726 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005728
5729 /* fine-tuning parameters for RX Flows */
5730 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005732 hdd_ctx->prev_rx = rx_packets;
Ravi Joshifed83572016-10-07 16:20:37 -07005733 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5734 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5735 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5736 next_rx_level = WLAN_SVC_TP_HIGH;
5737 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005738 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005739 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005740 hdd_ctx->rx_high_ind_cnt = 0;
5741 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742
Mohit Khannae71e2262015-11-10 09:37:24 -08005743 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5744 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005745
5746 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005747 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005748 next_rx_level, temp_rx);
5749 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005750 /* Send throughput indication only if it is enabled.
5751 * Disabling tcp_del_ack will revert the tcp stack behavior
5752 * to default delayed ack. Note that this will disable the
5753 * dynamic delayed ack mechanism across the system
5754 */
5755 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305756 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5757 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005758 &next_rx_level,
5759 sizeof(next_rx_level));
5760 }
5761
Mohit Khannae71e2262015-11-10 09:37:24 -08005762 /* fine-tuning parameters for TX Flows */
5763 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5764 hdd_ctx->prev_tx = tx_packets;
5765 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5766 next_tx_level = WLAN_SVC_TP_HIGH;
5767 else
5768 next_tx_level = WLAN_SVC_TP_LOW;
5769
5770 if (hdd_ctx->cur_tx_level != next_tx_level) {
5771 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5772 next_tx_level, temp_tx);
5773 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305774 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5775 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005776 &next_tx_level,
5777 sizeof(next_tx_level));
5778 }
5779
5780 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5781 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005782 hdd_ctx->hdd_txrx_hist_idx++;
5783 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784}
5785
5786#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305787static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305789 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5790 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305792 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305793 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5794 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 uint64_t total_tx = 0, total_rx = 0;
5796 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305797 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305798 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 bool connected = false;
5800 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5801
Prashanth Bhattaab004382016-10-11 16:08:11 -07005802 if (wlan_hdd_validate_context(hdd_ctx))
5803 return;
5804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005805 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305806 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005807 status =
5808 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5809
5810 if (adapterNode->pAdapter == NULL)
5811 continue;
5812 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305813 /*
5814 * Validate magic so we don't end up accessing
5815 * an invalid adapter.
5816 */
5817 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5818 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005820 if ((adapter->device_mode == QDF_STA_MODE ||
5821 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5823 != eConnectionState_Associated) {
5824
5825 continue;
5826 }
5827
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005828 if ((adapter->device_mode == QDF_SAP_MODE ||
5829 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5831
5832 continue;
5833 }
5834
5835 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5836 adapter->prev_tx_packets);
5837 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5838 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305839
5840 if (adapter->device_mode == QDF_SAP_MODE ||
5841 adapter->device_mode == QDF_P2P_GO_MODE ||
5842 adapter->device_mode == QDF_IBSS_MODE) {
5843
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08005844 ret = cdp_get_intra_bss_fwd_pkts_count(
5845 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305846 adapter->sessionId,
5847 &fwd_tx_packets, &fwd_rx_packets);
5848 if (ret == A_OK) {
5849 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5850 fwd_tx_packets,
5851 adapter->prev_fwd_tx_packets);
5852 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5853 fwd_tx_packets,
5854 adapter->prev_fwd_rx_packets);
5855 }
5856 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005857
5858 total_rx += adapter->stats.rx_packets;
5859 total_tx += adapter->stats.tx_packets;
5860
5861 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5862 adapter->prev_tx_packets = adapter->stats.tx_packets;
5863 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305864 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5865 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005866 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5867 connected = true;
5868 }
5869
5870 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5871 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5872 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5873 rx_packets;
5874 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5875 tx_packets;
5876
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305877 /* add intra bss forwarded tx and rx packets */
5878 tx_packets += fwd_tx_packets_diff;
5879 rx_packets += fwd_rx_packets_diff;
5880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005881 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5882 tx_packets += (uint64_t)ipa_tx_packets;
5883 rx_packets += (uint64_t)ipa_rx_packets;
5884
5885 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005886 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005887 return;
5888 }
5889
Yuanyuan Liu13738502016-04-06 17:41:37 -07005890 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005891
5892 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5893 hdd_ipa_uc_stat_request(adapter, 2);
5894
Dustin Brown2ed60362017-01-18 12:25:50 -08005895 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08005896 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08005897 if (hdd_ctx->bus_bw_timer_running)
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05305898 qdf_timer_mod(&hdd_ctx->bus_bw_timer,
Dustin Brownfce08d12017-01-17 16:29:38 -08005899 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08005900 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005901}
Prashanth Bhattaab004382016-10-11 16:08:11 -07005902
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305903/**
5904 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
5905 * @arg: Argument of timer function
5906 *
5907 * Schedule a workqueue in this function where all the processing is done.
5908 *
5909 * Return: None.
5910 */
5911static void __hdd_bus_bw_cbk(void *arg)
5912{
5913 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
5914
5915 if (wlan_hdd_validate_context(hdd_ctx))
5916 return;
5917
5918 schedule_work(&hdd_ctx->bus_bw_work);
5919}
5920
5921/**
5922 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
5923 * @arg: Argument of timer function
5924 *
5925 * Return: None.
5926 */
5927static void hdd_bus_bw_cbk(void *arg)
5928{
5929 cds_ssr_protect(__func__);
5930 __hdd_bus_bw_cbk(arg);
5931 cds_ssr_unprotect(__func__);
5932}
5933
Prashanth Bhattaab004382016-10-11 16:08:11 -07005934int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
5935{
5936 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305937 INIT_WORK(&hdd_ctx->bus_bw_work,
5938 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08005939 hdd_ctx->bus_bw_timer_running = false;
5940 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305941 qdf_timer_init(NULL,
5942 &hdd_ctx->bus_bw_timer,
5943 hdd_bus_bw_cbk, (void *)hdd_ctx,
5944 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005945
5946 return 0;
5947}
5948
5949void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
5950{
Dustin Brownfce08d12017-01-17 16:29:38 -08005951 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07005952 hdd_reset_tcp_delack(hdd_ctx);
5953
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305954 hdd_info("wait for bus bw work to flush");
5955 cancel_work_sync(&hdd_ctx->bus_bw_work);
5956 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08005957 hdd_ctx->bus_bw_timer_running = false;
5958 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005959}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960#endif
5961
5962/**
Nirav Shahed34b212016-04-25 10:59:16 +05305963 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5964 * @hdd_ctx: hdd context
5965 *
5966 * Return: 0 for success or error code
5967 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005968static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305969{
5970 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5971 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5972 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005973 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305974 return -ENOMEM;
5975 }
5976 return 0;
5977}
5978
5979/**
5980 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5981 * @hdd_ctx: hdd context
5982 *
5983 * Return: none
5984 */
5985void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5986{
5987 if (hdd_ctx->hdd_txrx_hist) {
5988 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5989 hdd_ctx->hdd_txrx_hist = NULL;
5990 }
5991}
5992
Nirav Shahda008342016-05-17 18:50:40 +05305993static uint8_t *convert_level_to_string(uint32_t level)
5994{
5995 switch (level) {
5996 /* initialize the wlan sub system */
5997 case WLAN_SVC_TP_NONE:
5998 return "NONE";
5999 case WLAN_SVC_TP_LOW:
6000 return "LOW";
6001 case WLAN_SVC_TP_MEDIUM:
6002 return "MED";
6003 case WLAN_SVC_TP_HIGH:
6004 return "HIGH";
6005 default:
6006 return "INVAL";
6007 }
6008}
6009
Nirav Shahed34b212016-04-25 10:59:16 +05306010
6011/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
6013 * @hdd_ctx: hdd context
6014 *
6015 * Return: none
6016 */
6017void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
6018{
6019 int i;
6020
6021#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07006022 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05306023 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07006024 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006025 hdd_ctx->config->busBandwidthHighThreshold,
6026 hdd_ctx->config->busBandwidthMediumThreshold,
6027 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07006028 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306029 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07006030 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006031 hdd_ctx->config->tcpDelackThresholdHigh,
6032 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07006033 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05306034 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006035#endif
6036
Jeff Johnson760350b2016-08-15 14:01:52 -07006037 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306038 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
6039
Jeff Johnson760350b2016-08-15 14:01:52 -07006040 hdd_err("index, total_rx, interval_rx, total_tx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041
6042 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006043 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006044 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
6045 hdd_ctx->hdd_txrx_hist[i].interval_rx,
6046 hdd_ctx->hdd_txrx_hist[i].total_tx,
6047 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05306048 convert_level_to_string(
6049 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
6050 convert_level_to_string(
6051 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
6052 convert_level_to_string(
6053 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006054 }
6055 return;
6056}
6057
6058/**
6059 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
6060 * @hdd_ctx: hdd context
6061 *
6062 * Return: none
6063 */
6064void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
6065{
6066 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05306067 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
6068 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006069}
6070
6071/**
6072 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
6073 * @pHddCtx: hdd context
6074 *
6075 * Return: none
6076 */
6077void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
6078{
6079
6080 hdd_adapter_t *adapter = NULL;
6081 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306082 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006083 int i;
Nirav Shahda008342016-05-17 18:50:40 +05306084 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006085
6086 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306087 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006088 adapter = adapter_node->pAdapter;
6089
Jeff Johnson760350b2016-08-15 14:01:52 -07006090 hdd_err("\nNetif queue operation statistics:");
6091 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05306092 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07006093 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05306094 curr_time = qdf_system_ticks();
6095 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05306096 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05306097 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05306098 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306099 unpause = adapter->total_unpause_time;
6100 } else {
Nirav Shahda008342016-05-17 18:50:40 +05306101 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306102 pause = adapter->total_pause_time;
6103 }
Jeff Johnson760350b2016-08-15 14:01:52 -07006104 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05306105 qdf_system_ticks_to_msecs(total),
6106 qdf_system_ticks_to_msecs(pause),
6107 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07006108 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006109
Nirav Shahda008342016-05-17 18:50:40 +05306110 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
6111 qdf_time_t pause_delta = 0;
6112
6113 if (adapter->pause_map & (1 << i))
6114 pause_delta = delta;
6115
Jeff Johnson760350b2016-08-15 14:01:52 -07006116 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006117 hdd_reason_type_to_string(i),
6118 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05306119 adapter->queue_oper_stats[i].unpause_count,
6120 qdf_system_ticks_to_msecs(
6121 adapter->queue_oper_stats[i].total_pause_time +
6122 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006123 }
6124
Jeff Johnson760350b2016-08-15 14:01:52 -07006125 hdd_err("\nNetif queue operation history:");
6126 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05306127 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
6128
Jeff Johnson760350b2016-08-15 14:01:52 -07006129 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006130
6131 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006132 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05306133 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006134 adapter->queue_oper_history[i].time),
6135 hdd_action_type_to_string(
6136 adapter->queue_oper_history[i].netif_action),
6137 hdd_reason_type_to_string(
6138 adapter->queue_oper_history[i].netif_reason),
6139 adapter->queue_oper_history[i].pause_map);
6140 }
6141
6142 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6143 adapter_node = next;
6144 }
6145
6146
6147}
6148
6149/**
6150 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
6151 * @hdd_ctx: hdd context
6152 *
6153 * Return: none
6154 */
6155void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
6156{
6157 hdd_adapter_t *adapter = NULL;
6158 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306159 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006160
6161 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306162 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006163 adapter = adapter_node->pAdapter;
6164
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306165 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006166 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306167 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006168 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05306169 adapter->history_index = 0;
6170 adapter->start_time = adapter->last_time = qdf_system_ticks();
6171 adapter->total_pause_time = 0;
6172 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006173 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6174 adapter_node = next;
6175 }
6176}
6177
6178/**
6179 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
6180 * @halHandle: Hal handle
6181 * @pContext: Pointer to the context
6182 * @sessionId: Session ID
6183 * @scanId: Scan ID
6184 * @status: Status
6185 *
6186 * This is the callback to be executed when 11d scan is completed to flush out
6187 * the scan results
6188 *
6189 * 11d scan is done during driver load and is a passive scan on all
6190 * channels supported by the device, 11d scans may find some APs on
6191 * frequencies which are forbidden to be used in the regulatory domain
6192 * the device is operating in. If these APs are notified to the supplicant
6193 * it may try to connect to these APs, thus flush out all the scan results
6194 * which are present in SME after 11d scan is done.
6195 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306196 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006197 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306198static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006199 uint8_t sessionId, uint32_t scanId,
6200 eCsrScanStatus status)
6201{
6202 ENTER();
6203
6204 sme_scan_flush_result(halHandle);
6205
6206 EXIT();
6207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306208 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006209}
6210
6211#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6212/**
6213 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
6214 * @hdd_ctx: hdd global context
6215 *
6216 * Return: none
6217 */
6218static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6219{
6220 uint8_t i;
6221
6222 mutex_init(&hdd_ctx->op_ctx.op_lock);
6223 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6224 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6225 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
6226 }
6227}
6228#else
6229static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6230{
6231}
6232#endif
6233
Yingying Tang95409972016-10-20 15:16:15 +08006234#ifdef WLAN_FEATURE_WOW_PULSE
6235/**
6236 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
6237 * @phddctx: hdd_context_t structure pointer
6238 * @enable: enable or disable this behaviour
6239 *
6240 * Return: int
6241 */
6242static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6243{
6244 struct hdd_config *pcfg_ini = phddctx->config;
6245 struct wow_pulse_mode wow_pulse_set_info;
6246 QDF_STATUS status;
6247
6248 hdd_notice("wow pulse enable flag is %d", enable);
6249
6250 if (false == phddctx->config->wow_pulse_support)
6251 return 0;
6252
6253 /* prepare the request to send to SME */
6254 if (enable == true) {
6255 wow_pulse_set_info.wow_pulse_enable = true;
6256 wow_pulse_set_info.wow_pulse_pin =
6257 pcfg_ini->wow_pulse_pin;
6258 wow_pulse_set_info.wow_pulse_interval_low =
6259 pcfg_ini->wow_pulse_interval_low;
6260 wow_pulse_set_info.wow_pulse_interval_high =
6261 pcfg_ini->wow_pulse_interval_high;
6262 } else {
6263 wow_pulse_set_info.wow_pulse_enable = false;
6264 wow_pulse_set_info.wow_pulse_pin = 0;
6265 wow_pulse_set_info.wow_pulse_interval_low = 0;
6266 wow_pulse_set_info.wow_pulse_interval_high = 0;
6267 }
6268 hdd_notice("enable %d pin %d low %d high %d",
6269 wow_pulse_set_info.wow_pulse_enable,
6270 wow_pulse_set_info.wow_pulse_pin,
6271 wow_pulse_set_info.wow_pulse_interval_low,
6272 wow_pulse_set_info.wow_pulse_interval_high);
6273
6274 status = sme_set_wow_pulse(&wow_pulse_set_info);
6275 if (QDF_STATUS_E_FAILURE == status) {
6276 hdd_notice("sme_set_wow_pulse failure!");
6277 return -EIO;
6278 }
6279 hdd_notice("sme_set_wow_pulse success!");
6280 return 0;
6281}
6282#else
6283static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6284{
6285 return 0;
6286}
6287#endif
6288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006289#ifdef WLAN_FEATURE_FASTPATH
6290/**
6291 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
6292 * @hdd_cfg: hdd config
6293 * @context: lower layer context
6294 *
6295 * Return: none
6296 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306297void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006298 void *context)
6299{
6300 if (hdd_cfg->fastpath_enable)
6301 hif_enable_fastpath(context);
6302}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006303#endif
6304
Yuanyuan Liu13738502016-04-06 17:41:37 -07006305#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006306/**
6307 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006308 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006309 * @level: thermal level
6310 *
6311 * Change IPA data path to SW path when the thermal throttle level greater
6312 * than 0, and restore the original data path when throttle level is 0
6313 *
6314 * Return: none
6315 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006316static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006317{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006318 hdd_context_t *hdd_ctx = context;
6319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006320 /* Change IPA to SW path when throttle level greater than 0 */
6321 if (level > THROTTLE_LEVEL_0)
6322 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
6323 else
6324 /* restore original concurrency mode */
6325 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
6326}
6327
6328/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306329 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
6330 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05306331 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006332 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306333 * Get a safe channel to restart SAP. PCL already takes into account the
6334 * unsafe channels. So, the PCL is validated with the ACS range to provide
6335 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006336 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306337 * Return: Channel number to restart SAP in case of success. In case of any
6338 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306340static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
6341 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006342{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306343 struct sir_pcl_list pcl;
6344 QDF_STATUS status;
6345 uint32_t i, j;
6346 tHalHandle *hal_handle;
6347 hdd_context_t *hdd_ctx;
6348 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006349
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306350 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6351 if (!hdd_ctx) {
6352 hdd_err("invalid HDD context");
6353 return INVALID_CHANNEL_ID;
6354 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006355
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306356 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6357 if (!hal_handle) {
6358 hdd_err("invalid HAL handle");
6359 return INVALID_CHANNEL_ID;
6360 }
6361
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306362 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
6363 pcl.pcl_list, &pcl.pcl_len,
6364 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6365 if (QDF_IS_STATUS_ERROR(status)) {
6366 hdd_err("Get PCL failed");
6367 return INVALID_CHANNEL_ID;
6368 }
6369
6370 if (!pcl.pcl_len) {
6371 hdd_alert("pcl length is zero. this is not expected");
6372 return INVALID_CHANNEL_ID;
6373 }
6374
6375 hdd_info("start:%d end:%d",
6376 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6377 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6378
6379 /* PCL already takes unsafe channel into account */
6380 for (i = 0; i < pcl.pcl_len; i++) {
6381 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6382 if ((pcl.pcl_list[i] >=
6383 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6384 (pcl.pcl_list[i] <=
6385 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6386 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
6387 return pcl.pcl_list[i];
6388 }
6389 }
6390
6391 hdd_info("no safe channel from PCL found in ACS range");
6392
6393 /* Try for safe channel from all valid channel */
6394 pcl.pcl_len = MAX_NUM_CHAN;
6395 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
6396 &pcl.pcl_len);
6397 if (QDF_IS_STATUS_ERROR(status)) {
6398 hdd_err("error in getting valid channel list");
6399 return INVALID_CHANNEL_ID;
6400 }
6401
6402 for (i = 0; i < pcl.pcl_len; i++) {
6403 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6404 found = false;
6405 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006406 if (pcl.pcl_list[i] ==
6407 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306408 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
6409 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006410 break;
6411 }
6412 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306413
6414 if (found)
6415 continue;
6416
6417 if ((pcl.pcl_list[i] >=
6418 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6419 (pcl.pcl_list[i] <=
6420 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6421 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
6422 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006423 }
6424 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306425
6426 return INVALID_CHANNEL_ID;
6427}
6428
6429/**
6430 * hdd_restart_sap() - Restarts SAP on the given channel
6431 * @adapter: AP adapter
6432 * @channel: Channel
6433 *
6434 * Restarts the SAP interface by invoking the function which executes the
6435 * callback to perform channel switch using (E)CSA.
6436 *
6437 * Return: None
6438 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05306439void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306440{
6441 hdd_ap_ctx_t *hdd_ap_ctx;
6442 tHalHandle *hal_handle;
6443
6444 if (!adapter) {
6445 hdd_err("invalid adapter");
6446 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006447 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306448
6449 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6450
6451 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6452 if (!hal_handle) {
6453 hdd_err("invalid HAL handle");
6454 return;
6455 }
6456
6457 hdd_ap_ctx->sapConfig.channel = channel;
6458 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6459 hdd_ap_ctx->sapConfig.ch_width_orig;
6460
6461 hdd_info("chan:%d width:%d",
6462 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6463
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006464 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306465 hdd_ap_ctx->sapConfig.sec_ch,
6466 &hdd_ap_ctx->sapConfig.ch_params);
6467
6468 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006469}
Kapil Gupta8878ad92017-02-13 11:56:04 +05306470
6471int hdd_update_acs_timer_reason(hdd_adapter_t *adapter, uint8_t reason)
6472{
6473 struct hdd_external_acs_timer_context *timer_context;
6474
6475 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6476
6477 if (QDF_TIMER_STATE_RUNNING ==
6478 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
6479 ap.vendor_acs_timer)) {
6480 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
6481 }
6482 timer_context = (struct hdd_external_acs_timer_context *)
6483 adapter->sessionCtx.ap.vendor_acs_timer.user_data;
6484 timer_context->reason = reason;
6485 qdf_mc_timer_start(&adapter->sessionCtx.ap.vendor_acs_timer,
6486 WLAN_VENDOR_ACS_WAIT_TIME);
6487 /* Update config to application */
6488 hdd_cfg80211_update_acs_config(adapter, reason);
6489 hdd_notice("Updated ACS config to nl with reason %d", reason);
6490
6491 return 0;
6492}
6493
Agrawal Ashish467dde42016-09-08 18:44:22 +05306494/**
6495 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6496 * @hdd_ctx: hdd context pointer
6497 *
6498 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6499 * and if ACS is enabled, driver will ask userspace to restart the
6500 * sap. User space on LTE coex indication restart driver.
6501 *
6502 * Return - none
6503 */
6504void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6505{
6506 QDF_STATUS status;
6507 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6508 hdd_adapter_t *adapter_temp;
6509 uint32_t i;
6510 bool found = false;
6511 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006512
Agrawal Ashish467dde42016-09-08 18:44:22 +05306513 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6514 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6515 adapter_temp = adapter_node->pAdapter;
6516
6517 if (!adapter_temp) {
6518 hdd_err("adapter is NULL, moving to next one");
6519 goto next_adapater;
6520 }
6521
6522 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6523 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
6524 hdd_info("skip device mode:%d acs:%d",
6525 adapter_temp->device_mode,
6526 adapter_temp->sessionCtx.ap.sapConfig.
6527 acs_cfg.acs_mode);
6528 goto next_adapater;
6529 }
6530
6531 found = false;
6532 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006533 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306534 hdd_ctxt->unsafe_channel_list[i]) {
6535 found = true;
6536 hdd_info("operating ch:%d is unsafe",
6537 adapter_temp->sessionCtx.ap.operatingChannel);
6538 break;
6539 }
6540 }
6541
6542 if (!found) {
6543 hdd_info("ch:%d is safe. no need to change channel",
6544 adapter_temp->sessionCtx.ap.operatingChannel);
6545 goto next_adapater;
6546 }
6547
Kapil Gupta8878ad92017-02-13 11:56:04 +05306548 if (hdd_ctxt->config->vendor_acs_support &&
6549 hdd_ctxt->config->acs_support_for_dfs_ltecoex) {
6550 hdd_update_acs_timer_reason(adapter_temp,
6551 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
6552 goto next_adapater;
6553 } else
6554 restart_chan =
6555 hdd_get_safe_channel_from_pcl_and_acs_range(
Agrawal Ashish467dde42016-09-08 18:44:22 +05306556 adapter_temp);
6557 if (!restart_chan) {
6558 hdd_alert("fail to restart SAP");
6559 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006560 /*
6561 * SAP restart due to unsafe channel. While
6562 * restarting the SAP, make sure to clear
6563 * acs_channel, channel to reset to
6564 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306565 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006566 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306567 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6568 adapter_temp->sessionCtx.ap.sapConfig.channel =
6569 AUTO_CHANNEL_SELECT;
Agrawal Ashish467dde42016-09-08 18:44:22 +05306570 hdd_info("sending coex indication");
6571 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6572 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6573 hdd_restart_sap(adapter_temp, restart_chan);
6574 }
6575
6576next_adapater:
6577 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6578 adapter_node = next;
6579 }
6580}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006581/**
6582 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6583 * @adapter: HDD adapter pointer
6584 * @indParam: Channel avoid notification parameter
6585 *
6586 * Avoid channel notification from FW handler.
6587 * FW will send un-safe channel list to avoid over wrapping.
6588 * hostapd should not use notified channel
6589 *
6590 * Return: None
6591 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306592void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006593{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006594 hdd_context_t *hdd_ctxt;
6595 tSirChAvoidIndType *ch_avoid_indi;
6596 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006597 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6598 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006599 uint16_t start_channel;
6600 uint16_t end_channel;
6601 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602 tHddAvoidFreqList hdd_avoid_freq_list;
6603 uint32_t i;
6604
6605 /* Basic sanity */
6606 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006607 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608 return;
6609 }
6610
6611 hdd_ctxt = (hdd_context_t *) hdd_context;
6612 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6613 cds_context = hdd_ctxt->pcds_context;
6614
6615 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006616 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006617 ch_avoid_indi->avoid_range_count);
6618
6619 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306620 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006621 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6622 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6623 ch_avoid_indi->avoid_freq_range[i].start_freq;
6624 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6625 ch_avoid_indi->avoid_freq_range[i].end_freq;
6626 }
6627 hdd_avoid_freq_list.avoidFreqRangeCount =
6628 ch_avoid_indi->avoid_range_count;
6629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006630 /* clear existing unsafe channel cache */
6631 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306632 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006633 sizeof(hdd_ctxt->unsafe_channel_list));
6634
6635 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6636 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006637 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006638 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006639 break;
6640 }
6641
6642 start_channel = ieee80211_frequency_to_channel(
6643 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6644 end_channel = ieee80211_frequency_to_channel(
6645 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006646 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006647 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6648 start_channel,
6649 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6650 end_channel);
6651
6652 /* do not process frequency bands that are not mapped to
6653 * predefined channels
6654 */
6655 if (start_channel == 0 || end_channel == 0)
6656 continue;
6657
Amar Singhalb8d4f152016-02-10 10:21:43 -08006658 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6659 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006660 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006661 ch_avoid_indi->avoid_freq_range[
6662 range_loop].start_freq) {
6663 start_channel_idx = channel_loop;
6664 break;
6665 }
6666 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006667 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6668 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006669 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006670 ch_avoid_indi->avoid_freq_range[
6671 range_loop].end_freq) {
6672 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006673 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006674 ch_avoid_indi->avoid_freq_range[
6675 range_loop].end_freq)
6676 end_channel_idx--;
6677 break;
6678 }
6679 }
6680
Amar Singhalb8d4f152016-02-10 10:21:43 -08006681 if (start_channel_idx == INVALID_CHANNEL ||
6682 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006683 continue;
6684
6685 for (channel_loop = start_channel_idx; channel_loop <=
6686 end_channel_idx; channel_loop++) {
6687 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006688 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006689 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006690 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006691 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006692 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006693 break;
6694 }
6695 }
6696 }
6697
Jeff Johnson34c88b72016-08-15 14:27:11 -07006698 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006699 hdd_ctxt->unsafe_channel_count);
6700
Yuanyuan Liu13738502016-04-06 17:41:37 -07006701 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6702 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703 hdd_ctxt->unsafe_channel_count)) {
6704 hdd_err("Failed to set unsafe channel");
6705
6706 /* clear existing unsafe channel cache */
6707 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306708 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006709 sizeof(hdd_ctxt->unsafe_channel_list));
6710
6711 return;
6712 }
6713
6714 for (channel_loop = 0;
6715 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006716 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006717 hdd_ctxt->unsafe_channel_list[channel_loop]);
6718 }
6719
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306720 /*
6721 * first update the unsafe channel list to the platform driver and
6722 * send the avoid freq event to the application
6723 */
6724 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6725
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306726 if (!hdd_ctxt->unsafe_channel_count) {
6727 hdd_info("no unsafe channels - not restarting SAP");
6728 return;
6729 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306730 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006731 return;
6732}
6733
6734/**
6735 * hdd_init_channel_avoidance() - Initialize channel avoidance
6736 * @hdd_ctx: HDD global context
6737 *
6738 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006739 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740 * down to the lower layers. Then subscribe to subsequent channel
6741 * avoidance events.
6742 *
6743 * Return: None
6744 */
6745static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6746{
6747 uint16_t unsafe_channel_count;
6748 int index;
6749
Yuanyuan Liu13738502016-04-06 17:41:37 -07006750 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6751 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006752 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006753 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006754
Jeff Johnson34c88b72016-08-15 14:27:11 -07006755 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006756 hdd_ctx->unsafe_channel_count);
6757
Anurag Chouhan6d760662016-02-20 16:05:43 +05306758 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006759 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006760
6761 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006762 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006763 hdd_ctx->unsafe_channel_list[index]);
6764
6765 }
6766
6767 /* Plug in avoid channel notification callback */
6768 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6769}
6770#else
6771static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6772{
6773}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006774static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006775{
6776}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006777#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006778
6779/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006780 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6781 * user space
6782 * @frame_ind: Management frame data to be informed.
6783 *
6784 * This function is used to indicate management frame to
6785 * user space
6786 *
6787 * Return: None
6788 *
6789 */
6790void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6791{
6792 hdd_context_t *hdd_ctx = NULL;
6793 hdd_adapter_t *adapter = NULL;
6794 void *cds_context = NULL;
6795 int i;
6796
6797 /* Get the global VOSS context.*/
6798 cds_context = cds_get_global_context();
6799 if (!cds_context) {
6800 hdd_err("Global CDS context is Null");
6801 return;
6802 }
6803 /* Get the HDD context.*/
6804 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6805
6806 if (0 != wlan_hdd_validate_context(hdd_ctx))
6807 return;
6808
6809 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6810 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6811 adapter =
6812 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6813 if (adapter)
6814 break;
6815 }
6816 } else {
6817 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6818 frame_ind->sessionId);
6819 }
6820
6821 if ((NULL != adapter) &&
6822 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6823 __hdd_indicate_mgmt_frame(adapter,
6824 frame_ind->frame_len,
6825 frame_ind->frameBuf,
6826 frame_ind->frameType,
6827 frame_ind->rxChan,
6828 frame_ind->rxRssi);
6829 return;
6830}
6831
Kapil Gupta8878ad92017-02-13 11:56:04 +05306832static void hdd_lte_coex_restart_sap(hdd_adapter_t *adapter,
6833 hdd_context_t *hdd_ctx)
6834{
6835 uint8_t restart_chan = 0;
6836
6837 restart_chan =
6838 hdd_get_safe_channel_from_pcl_and_acs_range(adapter);
6839 if (!restart_chan) {
6840 hdd_alert("fail to restart SAP");
6841 } else {
6842 /* SAP restart due to unsafe channel. While restarting
6843 * the SAP, make sure to clear acs_channel, channel to
6844 * reset to 0. Otherwise these settings will override
6845 * the ACS while restart.
6846 */
6847 hdd_ctx->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6848 adapter->sessionCtx.ap.sapConfig.channel =
6849 AUTO_CHANNEL_SELECT;
6850 hdd_info("sending coex indication");
6851 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
6852 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6853 hdd_restart_sap(adapter, restart_chan);
6854 }
6855}
6856
6857void hdd_acs_response_timeout_handler(void *context)
6858{
6859 struct hdd_external_acs_timer_context *timer_context =
6860 (struct hdd_external_acs_timer_context *)context;
6861 hdd_adapter_t *adapter;
6862 hdd_context_t *hdd_ctx;
6863 uint8_t reason;
6864
6865 ENTER();
6866 if (!timer_context) {
6867 hdd_err("invlaid timer context");
6868 return;
6869 }
6870 adapter = timer_context->adapter;
6871 reason = timer_context->reason;
6872
6873
6874 if ((!adapter) ||
6875 (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
6876 hdd_err("invalid adapter or adapter has invalid magic");
6877 return;
6878 }
6879 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6880 if (wlan_hdd_validate_context(hdd_ctx))
6881 return;
6882
6883 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
6884 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6885 else
6886 return;
6887
6888 hdd_err("ACS timeout happened for %s reason %d",
6889 adapter->dev->name, reason);
6890 switch (reason) {
6891 /* SAP init case */
6892 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
6893 wlan_sap_set_vendor_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6894 false);
6895 wlan_hdd_cfg80211_start_acs(adapter);
6896 break;
6897 /* DFS detected on current channel */
6898 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
6899 wlan_sap_update_next_channel(
6900 WLAN_HDD_GET_SAP_CTX_PTR(adapter), 0, 0);
6901 sme_update_new_channel_event(WLAN_HDD_GET_HAL_CTX(adapter),
6902 adapter->sessionId);
6903 break;
6904 /* LTE coex event on current channel */
6905 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
6906 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
6907 break;
6908 default:
6909 hdd_info("invalid reason for timer invoke");
6910
6911 }
6912}
6913
Rajeev Kumard004abc2016-02-17 12:09:56 -08006914/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006915 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6916 * @hdd_ctx: HDD context
6917 *
6918 * Disables all the dual mac features like DBS, Agile DFS etc.
6919 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306920 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006921 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306922static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006923{
6924 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306925 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006926
6927 if (!hdd_ctx) {
6928 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306929 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006930 }
6931
6932 cfg.scan_config = 0;
6933 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306934 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006935
6936 hdd_debug("Disabling all dual mac features...");
6937
6938 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306939 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006940 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6941 return status;
6942 }
6943
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306944 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006945}
6946
6947/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006948 * hdd_override_ini_config - Override INI config
6949 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006950 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006951 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006952 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006953 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006954 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006955static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006956{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006957
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006958 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6959 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6960 hdd_notice("Module enable_dfs_chan_scan set to %d",
6961 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006962 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006963 if (0 == enable_11d || 1 == enable_11d) {
6964 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6965 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006966 }
Leo Chang11545d62016-10-17 14:53:50 -07006967
6968 if (!hdd_ipa_is_present(hdd_ctx))
6969 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006970}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006971
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006972/**
6973 * hdd_set_trace_level_for_each - Set trace level for each INI config
6974 * @hdd_ctx - HDD context
6975 *
6976 * Set trace level for each module based on INI config.
6977 *
6978 * Return: None
6979 */
6980static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6981{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306982 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6983 hdd_ctx->config->qdf_trace_enable_wdi);
6984 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6985 hdd_ctx->config->qdf_trace_enable_hdd);
6986 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6987 hdd_ctx->config->qdf_trace_enable_sme);
6988 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6989 hdd_ctx->config->qdf_trace_enable_pe);
6990 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6991 hdd_ctx->config->qdf_trace_enable_wma);
6992 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6993 hdd_ctx->config->qdf_trace_enable_sys);
6994 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6995 hdd_ctx->config->qdf_trace_enable_qdf);
6996 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6997 hdd_ctx->config->qdf_trace_enable_sap);
6998 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6999 hdd_ctx->config->qdf_trace_enable_hdd_sap);
7000 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
7001 hdd_ctx->config->qdf_trace_enable_bmi);
7002 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
7003 hdd_ctx->config->qdf_trace_enable_cfg);
7004 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
7005 hdd_ctx->config->qdf_trace_enable_epping);
7006 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
7007 hdd_ctx->config->qdf_trace_enable_qdf_devices);
7008 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05307009 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307010 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
7011 hdd_ctx->config->qdf_trace_enable_htc);
7012 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
7013 hdd_ctx->config->qdf_trace_enable_hif);
7014 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
7015 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
7016 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
7017 hdd_ctx->config->qdf_trace_enable_hdd_data);
Naveen Rawat7df31862017-03-01 17:09:30 -08007018 hdd_qdf_trace_enable(QDF_MODULE_ID_WIFIPOS,
7019 hdd_ctx->config->qdf_trace_enable_wifi_pos);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007020 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007021}
7022
7023/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007024 * hdd_context_init() - Initialize HDD context
7025 * @hdd_ctx: HDD context.
7026 *
7027 * Initialize HDD context along with all the feature specific contexts.
7028 *
7029 * return: 0 on success and errno on failure.
7030 */
7031static int hdd_context_init(hdd_context_t *hdd_ctx)
7032{
7033 int ret;
7034
7035 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
7036 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
7037
7038 hdd_init_ll_stats_ctx();
7039
7040 init_completion(&hdd_ctx->mc_sus_event_var);
7041 init_completion(&hdd_ctx->ready_to_suspend);
7042
7043 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307044 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007045 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307046
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007047 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
7048
7049 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
7050
7051 ret = hdd_scan_context_init(hdd_ctx);
7052 if (ret)
7053 goto list_destroy;
7054
Nitesh Shahd1266d72017-01-25 22:07:07 +05307055 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007056
7057 hdd_rx_wake_lock_create(hdd_ctx);
7058
7059 ret = hdd_sap_context_init(hdd_ctx);
7060 if (ret)
7061 goto scan_destroy;
7062
7063 ret = hdd_roc_context_init(hdd_ctx);
7064 if (ret)
7065 goto sap_destroy;
7066
7067 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
7068
7069 hdd_init_offloaded_packets_ctx(hdd_ctx);
7070
7071 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
7072 hdd_ctx->config);
7073 if (ret)
7074 goto roc_destroy;
7075
7076 return 0;
7077
7078roc_destroy:
7079 hdd_roc_context_destroy(hdd_ctx);
7080
7081sap_destroy:
7082 hdd_sap_context_destroy(hdd_ctx);
7083
7084scan_destroy:
7085 hdd_scan_context_destroy(hdd_ctx);
7086 hdd_rx_wake_lock_destroy(hdd_ctx);
7087 hdd_tdls_context_destroy(hdd_ctx);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007088list_destroy:
7089 qdf_list_destroy(&hdd_ctx->hddAdapters);
Sandeep Puligillad0004212017-02-26 18:34:56 -08007090
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007091 return ret;
7092}
7093
7094/**
7095 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05307096 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007097 *
7098 * Allocate and initialize HDD context. HDD context is allocated as part of
7099 * wiphy allocation and then context is initialized.
7100 *
7101 * Return: HDD context on success and ERR_PTR on failure
7102 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007103static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007104{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307105 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007106 int ret = 0;
7107 hdd_context_t *hdd_ctx;
7108 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307109 int qdf_print_idx = -1;
7110
7111 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
7112 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
7113 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
7114 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
7115 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
7116 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
7117 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
7118 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
7119 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
7120 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
7121 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
7122 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
7123 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7124 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7125 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
7126 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
7127 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
7128 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
7129 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
7130 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
7131 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiyaf928edf2017-02-06 14:43:24 +05307132 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
7133 [QDF_MODULE_ID_DP] = {QDF_TRACE_LEVEL_ALL},
7134 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
7135 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
7136 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
7137 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
Mukul Sharma4d7d6b02017-02-13 20:45:22 +05307138 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
Abhishek Singh9679dbf2017-02-15 11:35:41 +05307139 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
Tushnim Bhattacharyya6796d8d2017-03-17 11:06:03 -07007140 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL},
7141 [QDF_MODULE_ID_POLICY_MGR] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307142 };
7143
7144 status = qdf_print_setup();
7145 if (status != QDF_STATUS_SUCCESS) {
7146 pr_err("QDF print control object setup failed\n");
7147 ret = -EINVAL;
7148 goto err_out;
7149 }
7150 /* Register the module here with QDF */
7151 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
7152 "MCL_WLAN");
7153
7154 /* if qdf_print_idx is negative */
7155 if (qdf_print_idx < 0) {
7156 pr_err("QDF print control can not be registered %d\n",
7157 qdf_print_idx);
7158 ret = -EINVAL;
7159 goto err_out;
7160 }
7161
7162 /* Store the qdf_pidx information into qdf module */
7163 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007164
7165 ENTER();
7166
7167 p_cds_context = cds_get_global_context();
7168 if (p_cds_context == NULL) {
7169 hdd_alert("Failed to get CDS global context");
7170 ret = -EINVAL;
7171 goto err_out;
7172 }
7173
7174 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
7175
7176 if (hdd_ctx == NULL) {
7177 ret = -ENOMEM;
7178 goto err_out;
7179 }
7180
7181 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007182 hdd_ctx->parent_dev = dev;
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05307183 hdd_ctx->last_scan_reject_session_id = 0xFF;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007184
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307185 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007186 if (hdd_ctx->config == NULL) {
7187 hdd_alert("Failed to alloc memory for HDD config!");
7188 ret = -ENOMEM;
7189 goto err_free_hdd_context;
7190 }
7191
7192 /* Read and parse the qcom_cfg.ini file */
7193 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307194 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307195 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007196 WLAN_INI_FILE);
7197 ret = -EINVAL;
7198 goto err_free_config;
7199 }
7200
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007201 hdd_notice("Setting configuredMcastBcastFilter: %d",
7202 hdd_ctx->config->mcastBcastFilterSetting);
7203
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307204 if (hdd_ctx->config->fhostNSOffload)
7205 hdd_ctx->ns_offload_enable = true;
7206
Abhishek Singh5ea86532016-04-27 14:10:53 +05307207 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
7208
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007209 hdd_override_ini_config(hdd_ctx);
7210
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007211 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007212
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007213 ret = hdd_context_init(hdd_ctx);
7214
7215 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007216 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007217
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007218
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -08007219 pld_set_fw_log_mode(hdd_ctx->parent_dev,
7220 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007221
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007222
7223 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05307224 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007225
Anurag Chouhan6d760662016-02-20 16:05:43 +05307226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007227 goto skip_multicast_logging;
7228
7229 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
7230
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007231 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
7232 if (ret)
7233 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05307234
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007235 ret = hdd_logging_sock_activate_svc(hdd_ctx);
7236 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05307237 goto err_free_histogram;
7238
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007239skip_multicast_logging:
7240 hdd_set_trace_level_for_each(hdd_ctx);
7241
7242 return hdd_ctx;
7243
Nirav Shahed34b212016-04-25 10:59:16 +05307244err_free_histogram:
7245 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
7246
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007247err_deinit_hdd_context:
7248 hdd_context_deinit(hdd_ctx);
7249
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007250err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307251 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007252
7253err_free_hdd_context:
7254 wiphy_free(hdd_ctx->wiphy);
7255
7256err_out:
7257 return ERR_PTR(ret);
7258}
7259
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007260#ifdef WLAN_OPEN_P2P_INTERFACE
7261/**
7262 * hdd_open_p2p_interface - Open P2P interface
7263 * @hdd_ctx: HDD context
7264 * @rtnl_held: True if RTNL lock held
7265 *
7266 * Open P2P interface during probe. This function called to open the P2P
7267 * interface at probe along with STA interface.
7268 *
7269 * Return: 0 on success and errno on failure
7270 */
7271static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7272{
7273 hdd_adapter_t *adapter;
7274 uint8_t *p2p_dev_addr;
7275
7276 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
7277 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307278 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007279 hdd_ctx->config->intfMacAddr[0].bytes,
7280 sizeof(tSirMacAddr));
7281
7282 /*
7283 * Generate the P2P Device Address. This consists of
7284 * the device's primary MAC address with the locally
7285 * administered bit set.
7286 */
7287 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
7288 } else {
7289 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7290 if (p2p_dev_addr == NULL) {
7291 hdd_alert("Failed to allocate mac_address for p2p_device");
7292 return -ENOSPC;
7293 }
7294
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307295 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307296 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007297 }
7298
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007299 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007300 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08007301 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007302
7303 if (NULL == adapter) {
7304 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
7305 return -ENOSPC;
7306 }
7307
7308 return 0;
7309}
7310#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05307311static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007312 bool rtnl_held)
7313{
7314 return 0;
7315}
7316#endif
7317
Jeff Johnson957bc272017-02-02 08:54:48 -08007318static int hdd_open_ocb_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7319{
7320 hdd_adapter_t *adapter;
7321 int ret = 0;
7322
7323 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
7324 wlan_hdd_get_intf_addr(hdd_ctx),
7325 NET_NAME_UNKNOWN, rtnl_held);
7326 if (adapter == NULL) {
7327 hdd_err("Failed to open 802.11p interface");
7328 ret = -ENOSPC;
7329 }
7330
7331 return ret;
7332}
7333
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007334/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307335 * hdd_start_station_adapter()- Start the Station Adapter
7336 * @adapter: HDD adapter
7337 *
7338 * This function initializes the adapter for the station mode.
7339 *
7340 * Return: 0 on success or errno on failure.
7341 */
7342int hdd_start_station_adapter(hdd_adapter_t *adapter)
7343{
7344 QDF_STATUS status;
7345
7346 ENTER_DEV(adapter->dev);
7347
7348 status = hdd_init_station_mode(adapter);
7349
7350 if (QDF_STATUS_SUCCESS != status) {
7351 hdd_err("Error Initializing station mode: %d", status);
7352 return qdf_status_to_os_return(status);
7353 }
7354
Arun Khandavallifae92942016-08-01 13:31:08 +05307355 hdd_register_tx_flow_control(adapter,
7356 hdd_tx_resume_timer_expired_handler,
7357 hdd_tx_resume_cb);
7358
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307359 EXIT();
7360 return 0;
7361}
7362
7363/**
7364 * hdd_start_ap_adapter()- Start AP Adapter
7365 * @adapter: HDD adapter
7366 *
7367 * This function initializes the adapter for the AP mode.
7368 *
7369 * Return: 0 on success errno on failure.
7370 */
7371int hdd_start_ap_adapter(hdd_adapter_t *adapter)
7372{
7373 QDF_STATUS status;
7374
7375 ENTER();
7376
Arun Khandavallicc544b32017-01-30 19:52:16 +05307377 status = hdd_init_ap_mode(adapter, false);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307378
7379 if (QDF_STATUS_SUCCESS != status) {
7380 hdd_err("Error Initializing the AP mode: %d", status);
7381 return qdf_status_to_os_return(status);
7382 }
7383
Arun Khandavallifae92942016-08-01 13:31:08 +05307384 hdd_register_tx_flow_control(adapter,
7385 hdd_softap_tx_resume_timer_expired_handler,
7386 hdd_softap_tx_resume_cb);
7387
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307388 EXIT();
7389 return 0;
7390}
7391
7392/**
7393 * hdd_start_ftm_adapter()- Start FTM adapter
7394 * @adapter: HDD adapter
7395 *
7396 * This function initializes the adapter for the FTM mode.
7397 *
7398 * Return: 0 on success or errno on failure.
7399 */
7400int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
7401{
7402 QDF_STATUS qdf_status;
7403
7404 ENTER_DEV(adapter->dev);
7405
7406 qdf_status = hdd_init_tx_rx(adapter);
7407
7408 if (QDF_STATUS_SUCCESS != qdf_status) {
7409 hdd_err("Failed to start FTM adapter: %d", qdf_status);
7410 return qdf_status_to_os_return(qdf_status);
7411 }
7412
7413 return 0;
7414 EXIT();
7415}
7416
7417/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007418 * hdd_open_interfaces - Open all required interfaces
7419 * hdd_ctx: HDD context
7420 * rtnl_held: True if RTNL lock is held
7421 *
7422 * Open all the interfaces like STA, P2P and OCB based on the configuration.
7423 *
Jeff Johnson957bc272017-02-02 08:54:48 -08007424 * Return: 0 if all interfaces were created, otherwise negative errno
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007425 */
Jeff Johnson957bc272017-02-02 08:54:48 -08007426static int hdd_open_interfaces(hdd_context_t *hdd_ctx, bool rtnl_held)
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007427{
Jeff Johnson957bc272017-02-02 08:54:48 -08007428 hdd_adapter_t *adapter;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007429 int ret;
7430
Jeff Johnson957bc272017-02-02 08:54:48 -08007431 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
Arun Khandavallifae92942016-08-01 13:31:08 +05307432 /* Create only 802.11p interface */
Jeff Johnson957bc272017-02-02 08:54:48 -08007433 return hdd_open_ocb_interface(hdd_ctx, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007434
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007435 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007436 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08007437 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007438
7439 if (adapter == NULL)
Jeff Johnson957bc272017-02-02 08:54:48 -08007440 return -ENOSPC;
7441
Deepak Dhamdherea2785822016-11-17 01:17:45 -08007442 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
7443 adapter->fast_roaming_allowed = true;
7444
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007445 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
7446 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08007447 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007448
7449 /* Open 802.11p Interface */
7450 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Jeff Johnson957bc272017-02-02 08:54:48 -08007451 ret = hdd_open_ocb_interface(hdd_ctx, rtnl_held);
7452 if (ret)
7453 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007454 }
7455
Jeff Johnson957bc272017-02-02 08:54:48 -08007456 return 0;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007457
Jeff Johnson957bc272017-02-02 08:54:48 -08007458err_close_adapters:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007459 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Jeff Johnson957bc272017-02-02 08:54:48 -08007460 return ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007461}
7462
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007463/**
7464 * hdd_update_country_code - Update country code
7465 * @hdd_ctx: HDD context
7466 * @adapter: Primary adapter context
7467 *
7468 * Update country code based on module parameter country_code at SME and wait
7469 * for the settings to take effect.
7470 *
7471 * Return: 0 on success and errno on failure
7472 */
7473static int hdd_update_country_code(hdd_context_t *hdd_ctx,
7474 hdd_adapter_t *adapter)
7475{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307476 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007477 int ret = 0;
7478 unsigned long rc;
7479
7480 if (country_code == NULL)
7481 return 0;
7482
7483 INIT_COMPLETION(adapter->change_country_code);
7484
7485 status = sme_change_country_code(hdd_ctx->hHal,
7486 wlan_hdd_change_country_code_callback,
7487 country_code, adapter,
7488 hdd_ctx->pcds_context, eSIR_TRUE,
7489 eSIR_TRUE);
7490
7491
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307492 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007493 hdd_err("SME Change Country code from module param fail ret=%d",
7494 ret);
7495 return -EINVAL;
7496 }
7497
7498 rc = wait_for_completion_timeout(&adapter->change_country_code,
7499 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
7500 if (!rc) {
7501 hdd_err("SME while setting country code timed out");
7502 ret = -ETIMEDOUT;
7503 }
7504
7505 return ret;
7506}
7507
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307508#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7509/**
7510 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7511 * @cds_cfg: CDS Configuration
7512 * @hdd_ctx: Pointer to hdd context
7513 *
7514 * Return: none
7515 */
7516static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7517 *cds_cfg,
7518 hdd_context_t *hdd_ctx)
7519{
7520 cds_cfg->tx_flow_stop_queue_th =
7521 hdd_ctx->config->TxFlowStopQueueThreshold;
7522 cds_cfg->tx_flow_start_queue_offset =
7523 hdd_ctx->config->TxFlowStartQueueOffset;
7524}
7525#else
7526static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7527 *cds_cfg,
7528 hdd_context_t *hdd_ctx)
7529{
7530}
7531#endif
7532
7533#ifdef FEATURE_WLAN_RA_FILTERING
7534/**
7535 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7536 * @cds_cfg: CDS Configuration
7537 * @hdd_ctx: Pointer to hdd context
7538 *
7539 * Return: none
7540 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307541static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307542 hdd_context_t *hdd_ctx)
7543{
7544 cds_cfg->ra_ratelimit_interval =
7545 hdd_ctx->config->RArateLimitInterval;
7546 cds_cfg->is_ra_ratelimit_enabled =
7547 hdd_ctx->config->IsRArateLimitEnabled;
7548}
7549#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307550static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307551 hdd_context_t *hdd_ctx)
7552{
7553}
7554#endif
7555
7556/**
7557 * hdd_update_cds_config() - API to update cds configuration parameters
7558 * @hdd_ctx: HDD Context
7559 *
7560 * Return: 0 for Success, errno on failure
7561 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007562static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307563{
7564 struct cds_config_info *cds_cfg;
7565
7566 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7567 if (!cds_cfg) {
7568 hdd_err("failed to allocate cds config");
7569 return -ENOMEM;
7570 }
7571
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307572 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08007573 if (!hdd_ctx->config->nMaxPsPoll ||
7574 !hdd_ctx->config->enablePowersaveOffload) {
7575 cds_cfg->powersave_offload_enabled =
7576 hdd_ctx->config->enablePowersaveOffload;
7577 } else {
7578 if ((hdd_ctx->config->enablePowersaveOffload ==
7579 PS_QPOWER_NODEEPSLEEP) ||
7580 (hdd_ctx->config->enablePowersaveOffload ==
7581 PS_LEGACY_NODEEPSLEEP))
7582 cds_cfg->powersave_offload_enabled =
7583 PS_LEGACY_NODEEPSLEEP;
7584 else
7585 cds_cfg->powersave_offload_enabled =
7586 PS_LEGACY_DEEPSLEEP;
7587 hdd_info("Qpower disabled in cds config, %d",
7588 cds_cfg->powersave_offload_enabled);
7589 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307590 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7591 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7592 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7593 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7594 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7595
7596 /* Here ol_ini_info is used to store ini status of arp offload
7597 * ns offload and others. Currently 1st bit is used for arp
7598 * off load and 2nd bit for ns offload currently, rest bits are unused
7599 */
7600 if (hdd_ctx->config->fhostArpOffload)
7601 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7602 if (hdd_ctx->config->fhostNSOffload)
7603 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7604
7605 /*
7606 * Copy the DFS Phyerr Filtering Offload status.
7607 * This parameter reflects the value of the
7608 * dfs_phyerr_filter_offload flag as set in the ini.
7609 */
7610 cds_cfg->dfs_phyerr_filter_offload =
7611 hdd_ctx->config->fDfsPhyerrFilterOffload;
7612 if (hdd_ctx->config->ssdp)
7613 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7614
7615 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7616 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7617
7618 cds_cfg->ap_maxoffload_reorderbuffs =
7619 hdd_ctx->config->apMaxOffloadReorderBuffs;
7620
7621 cds_cfg->ap_disable_intrabss_fwd =
7622 hdd_ctx->config->apDisableIntraBssFwd;
7623
7624 cds_cfg->dfs_pri_multiplier =
7625 hdd_ctx->config->dfsRadarPriMultiplier;
7626 cds_cfg->reorder_offload =
7627 hdd_ctx->config->reorderOffloadSupport;
7628
7629 /* IPA micro controller data path offload resource config item */
7630 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007631 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7632 /* IpaUcTxBufCount should be power of 2 */
7633 hdd_err("Round down IpaUcTxBufCount %d to nearest power of 2",
7634 hdd_ctx->config->IpaUcTxBufCount);
7635 hdd_ctx->config->IpaUcTxBufCount =
7636 rounddown_pow_of_two(
7637 hdd_ctx->config->IpaUcTxBufCount);
7638 if (!hdd_ctx->config->IpaUcTxBufCount) {
7639 hdd_err("Failed to round down IpaUcTxBufCount");
7640 return -EINVAL;
7641 }
7642 hdd_err("IpaUcTxBufCount rounded down to %d",
7643 hdd_ctx->config->IpaUcTxBufCount);
7644 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307645 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7646 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007647 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7648 /* IpaUcRxIndRingCount should be power of 2 */
7649 hdd_err("Round down IpaUcRxIndRingCount %d to nearest power of 2",
7650 hdd_ctx->config->IpaUcRxIndRingCount);
7651 hdd_ctx->config->IpaUcRxIndRingCount =
7652 rounddown_pow_of_two(
7653 hdd_ctx->config->IpaUcRxIndRingCount);
7654 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7655 hdd_err("Failed to round down IpaUcRxIndRingCount");
7656 return -EINVAL;
7657 }
7658 hdd_err("IpaUcRxIndRingCount rounded down to %d",
7659 hdd_ctx->config->IpaUcRxIndRingCount);
7660 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307661 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007662 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307663 cds_cfg->uc_tx_partition_base =
7664 hdd_ctx->config->IpaUcTxPartitionBase;
7665 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7666
7667 cds_cfg->ip_tcp_udp_checksum_offload =
7668 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307669 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307670 cds_cfg->ce_classify_enabled =
7671 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007672 cds_cfg->bpf_packet_filter_enable =
7673 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307674 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7675 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7676 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007677 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007678 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007679 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007680 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Dustin Brown13995f02017-01-12 15:38:42 -08007681 cds_cfg->active_bpf_mode = hdd_ctx->config->active_bpf_mode;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307682
7683 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7684 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7685 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007686 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307687 cds_init_ini_config(cds_cfg);
7688 return 0;
7689}
7690
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007691/**
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007692 * hdd_update_user_config() - API to update user configuration
7693 * parameters to obj mgr which are used by multiple components
7694 * @hdd_ctx: HDD Context
7695 *
7696 * Return: 0 for Success, errno on failure
7697 */
7698static int hdd_update_user_config(hdd_context_t *hdd_ctx)
7699{
7700 struct wlan_objmgr_psoc_user_config *user_config;
7701
7702 user_config = qdf_mem_malloc(sizeof(*user_config));
7703 if (user_config == NULL) {
7704 hdd_alert("Failed to alloc memory for user_config!");
7705 return -ENOMEM;
7706 }
7707
7708 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
7709 user_config->dual_mac_feature_disable =
7710 hdd_ctx->config->dual_mac_feature_disable;
7711 user_config->indoor_channel_support =
7712 hdd_ctx->config->indoor_channel_support;
7713 user_config->is_11d_support_enabled =
7714 hdd_ctx->config->Is11dSupportEnabled;
7715 user_config->is_11h_support_enabled =
7716 hdd_ctx->config->Is11hSupportEnabled;
7717 user_config->optimize_chan_avoid_event =
7718 hdd_ctx->config->goptimize_chan_avoid_event;
7719 user_config->skip_dfs_chnl_in_p2p_search =
7720 hdd_ctx->config->skipDfsChnlInP2pSearch;
Naveen Rawat222b2e92017-03-16 09:52:21 -07007721 user_config->band_capability = hdd_ctx->config->nBandCapability;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007722 wlan_objmgr_psoc_set_user_config(hdd_ctx->hdd_psoc, user_config);
7723
7724 qdf_mem_free(user_config);
7725 return 0;
7726}
7727
7728/**
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007729 * hdd_init_thermal_info - Initialize thermal level
7730 * @hdd_ctx: HDD context
7731 *
7732 * Initialize thermal level at SME layer and set the thermal level callback
7733 * which would be called when a configured thermal threshold is hit.
7734 *
7735 * Return: 0 on success and errno on failure
7736 */
7737static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7738{
7739 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307740 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007741
7742 thermal_param.smeThermalMgmtEnabled =
7743 hdd_ctx->config->thermalMitigationEnable;
7744 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7745
Poddar, Siddarth83905022016-04-16 17:56:08 -07007746 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7747 hdd_ctx->config->throttle_dutycycle_level0;
7748 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7749 hdd_ctx->config->throttle_dutycycle_level1;
7750 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7751 hdd_ctx->config->throttle_dutycycle_level2;
7752 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7753 hdd_ctx->config->throttle_dutycycle_level3;
7754
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007755 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7756 hdd_ctx->config->thermalTempMinLevel0;
7757 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7758 hdd_ctx->config->thermalTempMaxLevel0;
7759 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7760 hdd_ctx->config->thermalTempMinLevel1;
7761 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7762 hdd_ctx->config->thermalTempMaxLevel1;
7763 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7764 hdd_ctx->config->thermalTempMinLevel2;
7765 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7766 hdd_ctx->config->thermalTempMaxLevel2;
7767 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7768 hdd_ctx->config->thermalTempMinLevel3;
7769 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7770 hdd_ctx->config->thermalTempMaxLevel3;
7771
7772 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7773
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307774 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307775 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007776
7777 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7778 hdd_set_thermal_level_cb);
7779
7780 return 0;
7781
7782}
7783
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007784#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7785/**
7786 * hdd_hold_rtnl_lock - Hold RTNL lock
7787 *
7788 * Hold RTNL lock
7789 *
7790 * Return: True if held and false otherwise
7791 */
7792static inline bool hdd_hold_rtnl_lock(void)
7793{
7794 rtnl_lock();
7795 return true;
7796}
7797
7798/**
7799 * hdd_release_rtnl_lock - Release RTNL lock
7800 *
7801 * Release RTNL lock
7802 *
7803 * Return: None
7804 */
7805static inline void hdd_release_rtnl_lock(void)
7806{
7807 rtnl_unlock();
7808}
7809#else
7810static inline bool hdd_hold_rtnl_lock(void) { return false; }
7811static inline void hdd_release_rtnl_lock(void) { }
7812#endif
7813
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007814#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007815
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307816/* MAX iwpriv command support */
7817#define PKTLOG_SET_BUFF_SIZE 3
7818#define MAX_PKTLOG_SIZE 16
7819
7820/**
7821 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7822 * @hdd_ctx: hdd context
7823 * @set_value2: pktlog buffer size value
7824 *
7825 *
7826 * Return: 0 for success or error.
7827 */
7828static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7829{
7830 struct sir_wifi_start_log start_log = { 0 };
7831 QDF_STATUS status;
7832
7833 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7834 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7835 start_log.ini_triggered = cds_is_packet_log_enabled();
7836 start_log.user_triggered = 1;
7837 start_log.size = set_value2;
7838
7839 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7840 if (!QDF_IS_STATUS_SUCCESS(status)) {
7841 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7842 EXIT();
7843 return -EINVAL;
7844 }
7845
7846 return 0;
7847}
7848
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007849/**
7850 * hdd_process_pktlog_command() - process pktlog command
7851 * @hdd_ctx: hdd context
7852 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307853 * @set_value2: pktlog buffer size value
7854 *
7855 * This function process pktlog command.
7856 * set_value2 only matters when set_value is 3 (set buff size)
7857 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007858 *
7859 * Return: 0 for success or error.
7860 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307861int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
7862 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007863{
7864 int ret;
7865 bool enable;
7866 uint8_t user_triggered = 0;
7867
7868 ret = wlan_hdd_validate_context(hdd_ctx);
7869 if (0 != ret)
7870 return ret;
7871
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307872 hdd_info("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007873
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307874 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007875 hdd_err("invalid pktlog value %d", set_value);
7876 return -EINVAL;
7877 }
7878
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307879 if (set_value == PKTLOG_SET_BUFF_SIZE) {
7880 if (set_value2 <= 0) {
7881 hdd_err("invalid pktlog size %d", set_value2);
7882 return -EINVAL;
7883 } else if (set_value2 > MAX_PKTLOG_SIZE) {
7884 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
7885 return -EINVAL;
7886 }
7887 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
7888 }
7889
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007890 /*
7891 * set_value = 0 then disable packetlog
7892 * set_value = 1 enable packetlog forcefully
7893 * set_vlaue = 2 then disable packetlog if disabled through ini or
7894 * enable packetlog with AUTO type.
7895 */
7896 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
7897 true : false;
7898
7899 if (1 == set_value) {
7900 enable = true;
7901 user_triggered = 1;
7902 }
7903
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307904 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007905}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007906/**
7907 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
7908 * @hdd_ctx: HDD context
7909 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307910 * @user_triggered: triggered through iwpriv
7911 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007912 *
7913 * Return: 0 on success; error number otherwise
7914 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007915int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307916 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007917{
7918 struct sir_wifi_start_log start_log;
7919 QDF_STATUS status;
7920
7921 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7922 start_log.verbose_level =
7923 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007924 start_log.ini_triggered = cds_is_packet_log_enabled();
7925 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307926 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307927 /*
7928 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7929 * commands. Host uses this flag to decide whether to send pktlog
7930 * disable command to fw without sending pktlog enable command
7931 * previously. For eg, If vendor sends pktlog disable command without
7932 * sending pktlog enable command, then host discards the packet
7933 * but for iwpriv command, host will send it to fw.
7934 */
7935 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007936 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7937 if (!QDF_IS_STATUS_SUCCESS(status)) {
7938 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7939 EXIT();
7940 return -EINVAL;
7941 }
7942
7943 return 0;
7944}
7945#endif /* REMOVE_PKT_LOG */
7946
7947
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307948#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7949/**
7950 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7951 * switch without restart
7952 *
7953 * Registers callback function to change the operating channel of SAP by using
7954 * channel switch announcements instead of restarting SAP.
7955 *
7956 * Return: QDF_STATUS
7957 */
7958QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7959{
7960 QDF_STATUS status;
7961
7962 status = cds_register_sap_restart_channel_switch_cb(
7963 (void *)hdd_sap_restart_with_channel_switch);
7964 if (!QDF_IS_STATUS_SUCCESS(status))
7965 hdd_err("restart cb registration failed");
7966
7967 return status;
7968}
7969#endif
7970
Komal Seelam92fff912016-03-24 11:51:41 +05307971/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007972 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
7973 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05307974 * @dev: Device Pointer
7975 * @num: Number of Valid Mac address
7976 *
7977 * Return: Pointer to MAC address buffer
7978 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007979static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
7980 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05307981{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007982 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05307983}
Komal Seelam92fff912016-03-24 11:51:41 +05307984
7985/**
7986 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7987 * @hdd_ctx: HDD Context
7988 * @num: Number of random mac addresses needed
7989 *
7990 * Generate random addresses using bit manipulation on the base mac address
7991 *
7992 * Return: None
7993 */
7994static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7995{
7996 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7997 uint32_t iter;
7998 struct hdd_config *ini = hdd_ctx->config;
7999 uint8_t *buf = NULL;
8000 uint8_t macaddr_b3, tmp_br3;
8001 uint8_t *src = ini->intfMacAddr[0].bytes;
8002
8003 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
8004 buf = ini->intfMacAddr[iter].bytes;
8005 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
8006 macaddr_b3 = buf[3];
8007 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
8008 INTF_MACADDR_MASK;
8009 macaddr_b3 += tmp_br3;
8010 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
8011 buf[0] |= 0x02;
8012 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07008013 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308014 }
8015}
8016
8017/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008018 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05308019 * @hdd_ctx: HDD Context
8020 *
8021 * API to get mac addresses from platform driver and update the driver
8022 * structures and configure FW with the base mac address.
8023 * Return: int
8024 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008025static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05308026{
8027 uint32_t no_of_mac_addr, iter;
8028 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
8029 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
8030 uint8_t *addr, *buf;
8031 struct device *dev = hdd_ctx->parent_dev;
8032 struct hdd_config *ini = hdd_ctx->config;
8033 tSirMacAddr mac_addr;
8034 QDF_STATUS status;
8035
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008036 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05308037
8038 if (no_of_mac_addr == 0 || !addr) {
8039 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
8040 return -EINVAL;
8041 }
8042
8043 if (no_of_mac_addr > max_mac_addr)
8044 no_of_mac_addr = max_mac_addr;
8045
8046 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
8047
8048 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
8049 buf = ini->intfMacAddr[iter].bytes;
8050 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07008051 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308052 }
8053
8054 status = sme_set_custom_mac_addr(mac_addr);
8055
8056 if (!QDF_IS_STATUS_SUCCESS(status))
8057 return -EAGAIN;
8058 if (no_of_mac_addr < max_mac_addr)
8059 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
8060 no_of_mac_addr);
8061 return 0;
8062}
8063
8064/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008065 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
8066 * @hdd_ctx: HDD Context
8067 *
8068 * Update MAC address to FW. If MAC address passed by FW is invalid, host
8069 * will generate its own MAC and update it to FW.
8070 *
8071 * Return: 0 for success
8072 * Non-zero error code for failure
8073 */
8074static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
8075{
8076 tSirMacAddr customMacAddr;
8077 QDF_STATUS status;
8078
8079 qdf_mem_copy(&customMacAddr,
8080 &hdd_ctx->config->intfMacAddr[0].bytes[0],
8081 sizeof(tSirMacAddr));
8082 status = sme_set_custom_mac_addr(customMacAddr);
8083 if (!QDF_IS_STATUS_SUCCESS(status))
8084 return -EAGAIN;
8085 return 0;
8086}
8087
8088/**
Komal Seelam92fff912016-03-24 11:51:41 +05308089 * hdd_initialize_mac_address() - API to get wlan mac addresses
8090 * @hdd_ctx: HDD Context
8091 *
8092 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
8093 * is provisioned with mac addresses, driver uses it, else it will use
8094 * wlan_mac.bin to update HW MAC addresses.
8095 *
8096 * Return: None
8097 */
8098static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
8099{
8100 QDF_STATUS status;
8101 int ret;
8102
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008103 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05308104 if (ret == 0)
8105 return;
8106
8107 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
8108
8109 status = hdd_update_mac_config(hdd_ctx);
8110
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008111 if (QDF_IS_STATUS_SUCCESS(status))
8112 return;
8113
8114 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
8115
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008116 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008117 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008118 if (ret != 0) {
8119 hdd_err("MAC address out-of-sync, ret:%d", ret);
8120 QDF_ASSERT(ret);
8121 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008122 }
Komal Seelam92fff912016-03-24 11:51:41 +05308123}
8124
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008125/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008126 * hdd_tsf_init() - Initialize the TSF synchronization interface
8127 * @hdd_ctx: HDD global context
8128 *
8129 * When TSF synchronization via GPIO is supported by the driver and
8130 * has been enabled in the configuration file, this function plumbs
8131 * the GPIO value down to firmware via SME.
8132 *
8133 * Return: None
8134 */
8135#ifdef WLAN_FEATURE_TSF
8136static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8137{
8138 QDF_STATUS status;
8139
8140 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
8141 return;
8142
8143 status = sme_set_tsf_gpio(hdd_ctx->hHal,
8144 hdd_ctx->config->tsf_gpio_pin);
8145 if (!QDF_IS_STATUS_SUCCESS(status))
8146 hdd_err("Set tsf GPIO failed, status: %d", status);
8147}
8148#else
8149static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8150{
8151}
8152#endif
8153
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008154static int hdd_set_smart_chainmask_enabled(hdd_context_t *hdd_ctx)
8155{
8156 int vdev_id = 0;
8157 int param_id = WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME;
8158 int value = hdd_ctx->config->smart_chainmask_enabled;
8159 int vpdev = PDEV_CMD;
8160 int ret;
8161
8162 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8163 if (ret)
8164 hdd_err("WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME failed %d", ret);
8165
8166 return ret;
8167}
8168
8169static int hdd_set_alternative_chainmask_enabled(hdd_context_t *hdd_ctx)
8170{
8171 int vdev_id = 0;
8172 int param_id = WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME;
8173 int value = hdd_ctx->config->alternative_chainmask_enabled;
8174 int vpdev = PDEV_CMD;
8175 int ret;
8176
8177 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8178 if (ret)
8179 hdd_err("WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME failed %d",
8180 ret);
8181
8182 return ret;
8183}
8184
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008185/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07008186 * hdd_pre_enable_configure() - Configurations prior to cds_enable
8187 * @hdd_ctx: HDD context
8188 *
8189 * Pre configurations to be done at lower layer before calling cds enable.
8190 *
8191 * Return: 0 on success and errno on failure.
8192 */
8193static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
8194{
8195 int ret;
8196 QDF_STATUS status;
8197 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07008198 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008199
Leo Changfdb45c32016-10-28 11:09:23 -07008200 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008201 /*
8202 * Set 802.11p config
8203 * TODO-OCB: This has been temporarily added here to ensure this
8204 * parameter is set in CSR when we init the channel list. This should
8205 * be removed once the 5.9 GHz channels are added to the regulatory
8206 * domain.
8207 */
8208 hdd_set_dot11p_config(hdd_ctx);
8209
8210 /*
8211 * Note that the cds_pre_enable() sequence triggers the cfg download.
8212 * The cfg download must occur before we update the SME config
8213 * since the SME config operation must access the cfg database
8214 */
8215 status = hdd_set_sme_config(hdd_ctx);
8216
8217 if (QDF_STATUS_SUCCESS != status) {
8218 hdd_alert("Failed hdd_set_sme_config: %d", status);
8219 ret = qdf_status_to_os_return(status);
8220 goto out;
8221 }
8222
8223 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
8224 hdd_ctx->config->tx_chain_mask_1ss,
8225 PDEV_CMD);
8226 if (0 != ret) {
8227 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
8228 goto out;
8229 }
8230
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008231 ret = hdd_set_smart_chainmask_enabled(hdd_ctx);
8232 if (ret)
8233 goto out;
8234
8235 ret = hdd_set_alternative_chainmask_enabled(hdd_ctx);
8236 if (ret)
8237 goto out;
8238
Prashanth Bhatta07998752016-04-28 12:35:33 -07008239 hdd_program_country_code(hdd_ctx);
8240
8241 status = hdd_set_sme_chan_list(hdd_ctx);
8242 if (status != QDF_STATUS_SUCCESS) {
8243 hdd_alert("Failed to init channel list: %d", status);
8244 ret = qdf_status_to_os_return(status);
8245 goto out;
8246 }
8247
8248 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07008249 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07008250 hdd_alert("config update failed");
8251 ret = -EINVAL;
8252 goto out;
8253 }
8254
Prashanth Bhatta07998752016-04-28 12:35:33 -07008255 /*
8256 * Set the MAC Address Currently this is used by HAL to add self sta.
8257 * Remove this once self sta is added as part of session open.
8258 */
8259 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
8260 hdd_ctx->config->intfMacAddr[0].bytes,
8261 sizeof(hdd_ctx->config->intfMacAddr[0]));
8262
8263 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
8264 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
8265 hal_status, hal_status);
8266 ret = -EINVAL;
8267 goto out;
8268 }
8269
8270 hdd_init_channel_avoidance(hdd_ctx);
8271
8272out:
8273 return ret;
8274}
8275
8276/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008277 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
8278 * @context_ptr - hdd context pointer
8279 * @event_ptr - event structure pointer
8280 *
8281 * This is the p2p listen offload stop event handler, it sends vendor
8282 * event back to supplicant to notify the stop reason.
8283 *
8284 * Return: None
8285 */
8286static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
8287 void *event_ptr)
8288{
8289 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
8290 struct sir_p2p_lo_event *evt = event_ptr;
8291 struct sk_buff *vendor_event;
8292
8293 ENTER();
8294
8295 if (hdd_ctx == NULL) {
8296 hdd_err("Invalid HDD context pointer");
8297 return;
8298 }
8299
8300 vendor_event =
8301 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8302 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
8303 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
8304 GFP_KERNEL);
8305
8306 if (!vendor_event) {
8307 hdd_err("cfg80211_vendor_event_alloc failed");
8308 return;
8309 }
8310
8311 if (nla_put_u32(vendor_event,
8312 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
8313 evt->reason_code)) {
8314 hdd_err("nla put failed");
8315 kfree_skb(vendor_event);
8316 return;
8317 }
8318
8319 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8320}
8321
8322/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308323 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
8324 * @hdd_ctx: HDD context
8325 *
8326 * This function sends the adaptive dwell time config configuration to the
8327 * firmware via WMA
8328 *
8329 * Return: 0 - success, < 0 - failure
8330 */
8331static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
8332{
8333 QDF_STATUS status;
8334 struct adaptive_dwelltime_params dwelltime_params;
8335
8336 dwelltime_params.is_enabled =
8337 hdd_ctx->config->adaptive_dwell_mode_enabled;
8338 dwelltime_params.dwelltime_mode =
8339 hdd_ctx->config->global_adapt_dwelltime_mode;
8340 dwelltime_params.lpf_weight =
8341 hdd_ctx->config->adapt_dwell_lpf_weight;
8342 dwelltime_params.passive_mon_intval =
8343 hdd_ctx->config->adapt_dwell_passive_mon_intval;
8344 dwelltime_params.wifi_act_threshold =
8345 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
8346
8347 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
8348 &dwelltime_params);
8349
8350 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
8351 if (!QDF_IS_STATUS_SUCCESS(status)) {
8352 hdd_err("Failed to send Adaptive Dwelltime configuration!");
8353 return -EAGAIN;
8354 }
8355 return 0;
8356}
8357
Arun Khandavallid4349a92016-07-25 11:10:43 +05308358#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8359/**
8360 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
8361 * @hdd_ctx: HDD context
8362 *
8363 * Set auto shutdown callback to get indications from firmware to indicate
8364 * userspace to shutdown WLAN after a configured amount of inactivity.
8365 *
8366 * Return: 0 on success and errno on failure.
8367 */
8368static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8369{
8370 QDF_STATUS status;
8371
8372 if (!hdd_ctx->config->WlanAutoShutdown)
8373 return 0;
8374
8375 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
8376 wlan_hdd_auto_shutdown_cb);
8377 if (status != QDF_STATUS_SUCCESS)
8378 hdd_err("Auto shutdown feature could not be enabled: %d",
8379 status);
8380
8381 return qdf_status_to_os_return(status);
8382}
8383#else
8384static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8385{
8386 return 0;
8387}
8388#endif
8389
8390/**
8391 * hdd_features_init() - Init features
8392 * @hdd_ctx: HDD context
8393 * @adapter: Primary adapter context
8394 *
8395 * Initialize features and their feature context after WLAN firmware is up.
8396 *
8397 * Return: 0 on success and errno on failure.
8398 */
8399static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8400{
8401 tSirTxPowerLimit hddtxlimit;
8402 QDF_STATUS status;
8403 int ret;
8404
8405 ENTER();
8406
8407 ret = hdd_update_country_code(hdd_ctx, adapter);
8408 if (ret) {
8409 hdd_err("Failed to update country code: %d", ret);
8410 goto out;
8411 }
8412
8413 /* FW capabilities received, Set the Dot11 mode */
8414 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07008415 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
8416 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308417
Arun Khandavallid4349a92016-07-25 11:10:43 +05308418
8419 if (hdd_ctx->config->fIsImpsEnabled)
8420 hdd_set_idle_ps_config(hdd_ctx, true);
8421 else
8422 hdd_set_idle_ps_config(hdd_ctx, false);
8423
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308424 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8425 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
8426
Arun Khandavallid4349a92016-07-25 11:10:43 +05308427 if (hdd_lro_init(hdd_ctx))
8428 hdd_err("Unable to initialize LRO in fw");
8429
8430 if (hdd_adaptive_dwelltime_init(hdd_ctx))
8431 hdd_err("Unable to send adaptive dwelltime setting to FW");
8432
8433 ret = hdd_init_thermal_info(hdd_ctx);
8434 if (ret) {
8435 hdd_err("Error while initializing thermal information");
8436 goto deregister_frames;
8437 }
8438
Poddar, Siddarth66a46592017-02-22 11:44:44 +05308439 if (cds_is_packet_log_enabled())
8440 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
8441
Arun Khandavallid4349a92016-07-25 11:10:43 +05308442 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
8443 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
8444 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
8445 if (!QDF_IS_STATUS_SUCCESS(status))
8446 hdd_err("Error setting txlimit in sme: %d", status);
8447
8448 hdd_tsf_init(hdd_ctx);
8449
Arun Khandavallid4349a92016-07-25 11:10:43 +05308450 ret = hdd_register_cb(hdd_ctx);
8451 if (ret) {
8452 hdd_err("Failed to register HDD callbacks!");
8453 goto deregister_frames;
8454 }
8455
8456 if (hdd_ctx->config->dual_mac_feature_disable) {
8457 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
8458 if (status != QDF_STATUS_SUCCESS) {
8459 hdd_err("Failed to disable dual mac features");
8460 goto deregister_cb;
8461 }
8462 }
Selvaraj, Sridhar371f55e2017-02-21 10:36:15 +05308463 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8464 status = sme_enable_disable_chanavoidind_event(
8465 hdd_ctx->hHal, 0);
8466 if (!QDF_IS_STATUS_SUCCESS(status)) {
8467 hdd_err("Failed to disable Chan Avoidance Indication");
8468 goto deregister_cb;
8469 }
8470 }
Arun Khandavallid4349a92016-07-25 11:10:43 +05308471
8472 /* register P2P Listen Offload event callback */
8473 if (wma_is_p2p_lo_capable())
8474 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
8475 wlan_hdd_p2p_lo_event_callback);
8476
8477 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
8478
8479 if (ret)
8480 goto deregister_cb;
8481
8482 EXIT();
8483 return 0;
8484
8485deregister_cb:
8486 hdd_deregister_cb(hdd_ctx);
8487deregister_frames:
8488 wlan_hdd_cfg80211_deregister_frames(adapter);
8489out:
8490 return -EINVAL;
8491
8492}
8493
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308494#ifdef NAPIER_SCAN
8495/**
8496 *
8497 * hdd_post_cds_enable_config() - HDD post cds start config helper
8498 * @adapter - Pointer to the HDD
8499 *
8500 * Return: None
8501 */
8502static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8503{
8504 QDF_STATUS status;
8505
8506 status = ucfg_scan_register_bcn_cb(hdd_ctx->hdd_psoc,
8507 wlan_cfg80211_inform_bss_frame,
8508 SCAN_CB_TYPE_INFORM_BCN);
8509 if (!QDF_IS_STATUS_SUCCESS(status)) {
8510 hdd_err("failed with status code %08d [x%08x]",
8511 status, status);
8512 return status;
8513 }
8514
8515 return QDF_STATUS_SUCCESS;
8516}
8517#else
8518static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8519{
8520 return QDF_STATUS_SUCCESS;
8521}
8522
8523#endif
Arun Khandavallid4349a92016-07-25 11:10:43 +05308524
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308525/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308526 * hdd_configure_cds() - Configure cds modules
8527 * @hdd_ctx: HDD context
8528 * @adapter: Primary adapter context
8529 *
8530 * Enable Cds modules after WLAN firmware is up.
8531 *
8532 * Return: 0 on success and errno on failure.
8533 */
8534int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8535{
8536 int ret;
8537 QDF_STATUS status;
8538 /* structure of function pointers to be used by CDS */
8539 struct cds_sme_cbacks sme_cbacks;
8540
8541 ret = hdd_pre_enable_configure(hdd_ctx);
8542 if (ret) {
8543 hdd_err("Failed to pre-configure cds");
8544 goto out;
8545 }
8546
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008547 /* Always get latest IPA resources allocated from cds_open and configure
8548 * IPA module before configuring them to FW. Sequence required as crash
8549 * observed otherwise.
8550 */
8551 if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
8552 if (hdd_ipa_uc_ol_init(hdd_ctx)) {
8553 hdd_err("Failed to setup pipes");
8554 goto out;
8555 }
8556 }
8557
Arun Khandavallifae92942016-08-01 13:31:08 +05308558 /*
8559 * Start CDS which starts up the SME/MAC/HAL modules and everything
8560 * else
8561 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308562 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308563
8564 if (!QDF_IS_STATUS_SUCCESS(status)) {
8565 hdd_alert("cds_enable failed");
8566 goto out;
8567 }
8568
8569 status = hdd_post_cds_enable_config(hdd_ctx);
8570 if (!QDF_IS_STATUS_SUCCESS(status)) {
8571 hdd_alert("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008572 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308573 }
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308574 status = hdd_register_bcn_cb(hdd_ctx);
8575 if (!QDF_IS_STATUS_SUCCESS(status)) {
8576 hdd_alert("hdd_post_cds_enable_config failed");
8577 goto cds_disable;
8578 }
Arun Khandavallifae92942016-08-01 13:31:08 +05308579
8580 ret = hdd_features_init(hdd_ctx, adapter);
8581 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008582 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308583
8584 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
8585 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
8586 status = cds_init_policy_mgr(&sme_cbacks);
8587 if (!QDF_IS_STATUS_SUCCESS(status)) {
8588 hdd_err("Policy manager initialization failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008589 goto hdd_features_deinit;
Arun Khandavallifae92942016-08-01 13:31:08 +05308590 }
8591
8592 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008593
8594hdd_features_deinit:
8595 hdd_deregister_cb(hdd_ctx);
8596 wlan_hdd_cfg80211_deregister_frames(adapter);
8597cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308598 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008599
Arun Khandavallifae92942016-08-01 13:31:08 +05308600out:
8601 return -EINVAL;
8602}
8603
8604/**
8605 * hdd_deconfigure_cds() -De-Configure cds
8606 * @hdd_ctx: HDD context
8607 *
8608 * Deconfigure Cds modules before WLAN firmware is down.
8609 *
8610 * Return: 0 on success and errno on failure.
8611 */
Jeff Johnson590e2012016-10-05 16:16:24 -07008612static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308613{
8614 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07008615 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308616
8617 ENTER();
8618 /* De-register the SME callbacks */
8619 hdd_deregister_cb(hdd_ctx);
8620
8621 /* De-init Policy Manager */
8622 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
8623 hdd_err("Failed to deinit policy manager");
8624 /* Proceed and complete the clean up */
Houston Hoffman6640cf32016-10-10 16:44:29 -07008625 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308626 }
8627
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308628 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308629 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8630 hdd_err("Failed to Disable the CDS Modules! :%d",
8631 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07008632 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308633 }
8634
8635 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07008636 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308637}
8638
8639
8640/**
8641 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
8642 * @hdd_ctx: HDD context
Arun Khandavallifae92942016-08-01 13:31:08 +05308643 *
8644 * This function maintains the driver state machine it will be invoked from
8645 * exit, shutdown and con_mode change handler. Depending on the driver state
8646 * shall perform the stopping/closing of the modules.
8647 *
8648 * Return: 0 for success; non-zero for failure
8649 */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008650int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308651{
8652 void *hif_ctx;
8653 qdf_device_t qdf_ctx;
8654 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308655 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308656 p_cds_sched_context cds_sched_context = NULL;
8657
8658 ENTER();
8659
8660 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8661 if (!qdf_ctx) {
8662 hdd_err("QDF device context NULL");
8663 return -EINVAL;
8664 }
8665
8666 cds_sched_context = get_cds_sched_ctxt();
8667 if (!cds_sched_context) {
8668 hdd_err("cds scheduler context NULL");
8669 return -EINVAL;
8670 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308671 mutex_lock(&hdd_ctx->iface_change_lock);
8672 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05308673
8674 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
8675
8676 switch (hdd_ctx->driver_status) {
8677 case DRIVER_MODULES_UNINITIALIZED:
8678 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308679 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308680 case DRIVER_MODULES_CLOSED:
8681 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308682 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308683 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05308684 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308685 if (hdd_deconfigure_cds(hdd_ctx)) {
8686 hdd_alert("Failed to de-configure CDS");
8687 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308688 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308689 }
8690 hdd_info("successfully Disabled the CDS modules!");
8691 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8692 break;
8693 case DRIVER_MODULES_OPENED:
8694 hdd_info("Closing CDS modules!");
8695 break;
8696 default:
8697 hdd_err("Trying to stop wlan in a wrong state: %d",
8698 hdd_ctx->driver_status);
8699 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308700 ret = -EINVAL;
8701 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308702 }
8703
Govind Singhb048e872016-09-27 22:07:43 +05308704 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8705 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8706 hdd_err("Failed to process post CDS disable Modules! :%d",
8707 qdf_status);
8708 ret = -EINVAL;
8709 QDF_ASSERT(0);
8710 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308711 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308712 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8713 hdd_warn("Failed to stop CDS:%d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308714 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308715 QDF_ASSERT(0);
8716 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008717
Rajeev Kumarecf87ff2017-01-13 15:46:07 -08008718 ret = hdd_release_and_destroy_pdev(hdd_ctx);
8719 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308720 hdd_err("Pdev delete failed");
8721
Rajeev Kumar99e4cf62017-01-13 15:31:19 -08008722 ret = hdd_release_and_destroy_psoc(hdd_ctx);
8723 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308724 hdd_err("Psoc delete failed");
8725
Arun Khandavallifae92942016-08-01 13:31:08 +05308726 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8727 if (!hif_ctx) {
8728 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308729 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308730 }
8731
8732 hdd_hif_close(hif_ctx);
8733
8734 ol_cds_free();
8735
Arunk Khandavalli649c0092016-11-22 21:20:43 +05308736 if (!cds_is_driver_recovering() && !cds_is_driver_unloading()) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308737 ret = pld_power_off(qdf_ctx->dev);
8738 if (ret)
8739 hdd_err("CNSS power down failed put device into Low power mode:%d",
8740 ret);
8741 }
8742 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
8743
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308744done:
8745 hdd_ctx->stop_modules_in_progress = false;
8746 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308747 EXIT();
8748
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308749 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308750
8751}
8752
8753/**
8754 * hdd_iface_change_callback() - Function invoked when stop modules expires
8755 * @priv: pointer to hdd context
8756 *
8757 * This function is invoked when the timer waiting for the interface change
8758 * expires, it shall cut-down the power to wlan and stop all the modules.
8759 *
8760 * Return: void
8761 */
8762static void hdd_iface_change_callback(void *priv)
8763{
8764 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
8765 int ret;
8766 int status = wlan_hdd_validate_context(hdd_ctx);
8767
8768 if (status)
8769 return;
8770
8771 ENTER();
8772 hdd_info("Interface change timer expired close the modules!");
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008773 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308774 if (ret)
8775 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05308776 EXIT();
8777}
8778
8779/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308780 * hdd_state_info_dump() - prints state information of hdd layer
8781 * @buf: buffer pointer
8782 * @size: size of buffer to be filled
8783 *
8784 * This function is used to dump state information of hdd layer
8785 *
8786 * Return: None
8787 */
8788static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
8789{
8790 hdd_context_t *hdd_ctx;
8791 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8792 QDF_STATUS status;
8793 hdd_station_ctx_t *hdd_sta_ctx;
8794 hdd_adapter_t *adapter;
8795 uint16_t len = 0;
8796 char *buf = *buf_ptr;
8797
8798 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8799 if (!hdd_ctx) {
8800 hdd_err("Failed to get hdd context ");
8801 return;
8802 }
8803
8804 hdd_notice("size of buffer: %d", *size);
8805
8806 len += scnprintf(buf + len, *size - len,
8807 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8808 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008809 "\n is_scheduler_suspended %d",
8810 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308811
8812 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8813
8814 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8815 adapter = adapter_node->pAdapter;
8816 if (adapter->dev)
8817 len += scnprintf(buf + len, *size - len,
8818 "\n device name: %s", adapter->dev->name);
8819 len += scnprintf(buf + len, *size - len,
8820 "\n device_mode: %d", adapter->device_mode);
8821 switch (adapter->device_mode) {
8822 case QDF_STA_MODE:
8823 case QDF_P2P_CLIENT_MODE:
8824 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8825 len += scnprintf(buf + len, *size - len,
8826 "\n connState: %d",
8827 hdd_sta_ctx->conn_info.connState);
8828 break;
8829
8830 default:
8831 break;
8832 }
8833 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
8834 adapter_node = next;
8835 }
8836
8837 *size -= len;
8838 *buf_ptr += len;
8839}
8840
8841/**
8842 * hdd_register_debug_callback() - registration function for hdd layer
8843 * to print hdd state information
8844 *
8845 * Return: None
8846 */
8847static void hdd_register_debug_callback(void)
8848{
8849 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
8850}
8851
8852/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008853 * hdd_wlan_startup() - HDD init function
8854 * @dev: Pointer to the underlying device
8855 *
8856 * This is the driver startup code executed once a WLAN device has been detected
8857 *
8858 * Return: 0 for success, < 0 for failure
8859 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308860int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008861{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308862 QDF_STATUS status;
Jeff Johnson957bc272017-02-02 08:54:48 -08008863 hdd_context_t *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008864 int ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008865 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308866 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008867
8868 ENTER();
8869
Arun Khandavallifae92942016-08-01 13:31:08 +05308870 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008871
8872 if (IS_ERR(hdd_ctx))
8873 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008874
Arun Khandavallifae92942016-08-01 13:31:08 +05308875 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
8876 hdd_iface_change_callback, (void *)hdd_ctx);
8877
8878 mutex_init(&hdd_ctx->iface_change_lock);
8879
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008880 ret = hdd_init_netlink_services(hdd_ctx);
8881 if (ret)
8882 goto err_hdd_free_context;
8883
Jeff Johnsonce0032c2017-01-20 07:18:27 -08008884 hdd_request_manager_init();
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07008885 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308886
Jeff Johnson957bc272017-02-02 08:54:48 -08008887 ret = hdd_wlan_start_modules(hdd_ctx, NULL, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05308888 if (ret) {
8889 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008890 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008891 }
8892
Yingying Tang80e15f32016-09-27 18:23:01 +08008893 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008894
Yingying Tang95409972016-10-20 15:16:15 +08008895 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
8896 hdd_notice("Failed to set wow pulse");
8897
Anurag Chouhan6d760662016-02-20 16:05:43 +05308898 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008899
8900 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008901 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05308902 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008903 }
8904
Prashanth Bhatta07998752016-04-28 12:35:33 -07008905 ret = hdd_wiphy_init(hdd_ctx);
8906 if (ret) {
8907 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05308908 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008909 }
8910
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05308911 if (hdd_ctx->config->enable_dp_trace)
8912 qdf_dp_trace_init();
8913
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308914 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008915 goto err_wiphy_unregister;
8916
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05308917 wlan_hdd_init_chan_info(hdd_ctx);
8918
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07008919 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08008920
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008921 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008922
Jeff Johnson957bc272017-02-02 08:54:48 -08008923 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
8924 if (ret) {
8925 hdd_alert("Failed to open interfaces: %d", ret);
Jeff Johnson46bde382017-02-01 15:31:16 -08008926 goto err_release_rtnl_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008927 }
8928
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008929 hdd_release_rtnl_lock();
8930 rtnl_held = false;
8931
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08008932 wlan_hdd_update_11n_mode(hdd_ctx->config);
8933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008934#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05308935 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308936 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008937 hdd_skip_acs_scan_timer_handler,
8938 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308939 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07008940 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04008941 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008942#endif
8943
Nitesh Shah61c10d92016-10-19 19:29:15 +05308944 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
8945 QDF_TIMER_TYPE_SW,
8946 wlan_hdd_change_tdls_mode,
8947 hdd_ctx);
8948
Prashanth Bhattaab004382016-10-11 16:08:11 -07008949 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008950
Jeff Johnson9afc5012016-09-23 13:56:27 -07008951 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008952
Nirav Shahbd36b062016-07-18 11:12:59 +05308953 if (hdd_ctx->rps)
8954 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07008955
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008956 ret = hdd_register_notifiers(hdd_ctx);
8957 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08008958 goto err_close_adapters;
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05308959
8960 status = wlansap_global_init();
8961 if (QDF_IS_STATUS_ERROR(status))
Jeff Johnson957bc272017-02-02 08:54:48 -08008962 goto err_close_adapters;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008963
Komal Seelam8634b772016-09-29 12:12:24 +05308964 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008965 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308966 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008967
bings612b9c42016-11-07 10:52:03 +08008968 if (hdd_enable_egap(hdd_ctx))
8969 hdd_err("enhance green ap is not enabled");
8970
Arun Khandavallifae92942016-08-01 13:31:08 +05308971 if (hdd_ctx->config->fIsImpsEnabled)
8972 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308973
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308974 if (hdd_ctx->config->sifs_burst_duration) {
8975 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
8976 hdd_ctx->config->sifs_burst_duration;
8977
8978 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
8979 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
8980 set_value, PDEV_CMD);
8981 }
8982
Arun Khandavallifae92942016-08-01 13:31:08 +05308983 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
8984 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308985
Selvaraj, Sridhar1ffa0ec2017-03-10 09:52:12 +05308986 complete(&wlan_start_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008987 goto success;
8988
Jeff Johnson957bc272017-02-02 08:54:48 -08008989err_close_adapters:
Jeff Johnson46bde382017-02-01 15:31:16 -08008990 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008991
Jeff Johnson46bde382017-02-01 15:31:16 -08008992err_release_rtnl_lock:
Arun Khandavallid4349a92016-07-25 11:10:43 +05308993 if (rtnl_held)
8994 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008995
Anurag Chouhance6a4052016-09-14 18:20:42 +05308996 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08008997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008998err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008999 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009000
Arun Khandavallifae92942016-08-01 13:31:08 +05309001err_stop_modules:
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07009002 hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309003
9004
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009005 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309006 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009007 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309008 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009009 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009010
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009011err_exit_nl_srv:
Houston Hoffman47a4a052016-11-14 23:22:44 -08009012 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009013 hdd_request_manager_deinit();
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009014 hdd_exit_netlink_services(hdd_ctx);
9015
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309016 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009017err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05309018 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
9019 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07009020 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309021 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009023 return -EIO;
9024
9025success:
9026 EXIT();
9027 return 0;
9028}
9029
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009030/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309031 * hdd_wlan_update_target_info() - update target type info
9032 * @hdd_ctx: HDD context
9033 * @context: hif context
9034 *
9035 * Update target info received from firmware in hdd context
9036 * Return:None
9037 */
9038
9039void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
9040{
9041 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
9042
9043 if (!tgt_info) {
9044 hdd_err("Target info is Null");
9045 return;
9046 }
9047
9048 hdd_ctx->target_type = tgt_info->target_type;
9049}
9050
9051/**
9052 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309053 * @hdd_ctx: HDD context
9054 *
9055 * Register the HDD callbacks to CDS/SME.
9056 *
9057 * Return: 0 for success or Error code for failure
9058 */
9059int hdd_register_cb(hdd_context_t *hdd_ctx)
9060{
9061 QDF_STATUS status;
9062 int ret = 0;
9063
9064 ENTER();
9065
9066 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
9067
9068 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
9069 hdd_send_oem_data_rsp_msg);
9070
9071 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
9072 wlan_hdd_cfg80211_fw_mem_dump_cb);
9073 if (!QDF_IS_STATUS_SUCCESS(status)) {
9074 hdd_err("Failed to register memdump callback");
9075 ret = -EINVAL;
9076 return ret;
9077 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05309078 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
9079 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309080 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
9081 sme_nan_register_callback(hdd_ctx->hHal,
9082 wlan_hdd_cfg80211_nan_callback);
9083 sme_stats_ext_register_callback(hdd_ctx->hHal,
9084 wlan_hdd_cfg80211_stats_ext_callback);
9085
9086 sme_ext_scan_register_callback(hdd_ctx->hHal,
9087 wlan_hdd_cfg80211_extscan_callback);
9088
9089 status = cds_register_sap_restart_channel_switch_cb(
9090 (void *)hdd_sap_restart_with_channel_switch);
9091 if (!QDF_IS_STATUS_SUCCESS(status)) {
9092 hdd_err("restart cb registration failed");
9093 ret = -EINVAL;
9094 return ret;
9095 }
9096
9097 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
9098 hdd_rssi_threshold_breached);
9099
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309100 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
9101 wlan_hdd_cfg80211_link_layer_stats_callback);
9102
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05309103 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
9104 hdd_lost_link_info_cb);
9105 /* print error and not block the startup process */
9106 if (!QDF_IS_STATUS_SUCCESS(status))
9107 hdd_err("set lost link info callback failed");
9108
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309109 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
9110
9111 EXIT();
9112
9113 return ret;
9114}
9115
9116/**
9117 * hdd_deregister_cb() - De-Register HDD callbacks.
9118 * @hdd_ctx: HDD context
9119 *
9120 * De-Register the HDD callbacks to CDS/SME.
9121 *
9122 * Return: void
9123 */
9124void hdd_deregister_cb(hdd_context_t *hdd_ctx)
9125{
9126 QDF_STATUS status;
9127
9128 ENTER();
9129
9130 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
9131 if (!QDF_IS_STATUS_SUCCESS(status))
9132 hdd_err("De-register of dcc stats callback failed: %d",
9133 status);
9134
9135 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309136 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
9137
9138 status = cds_deregister_sap_restart_channel_switch_cb();
9139 if (!QDF_IS_STATUS_SUCCESS(status))
9140 hdd_err("De-register restart cb registration failed: %d",
9141 status);
9142
9143 sme_stats_ext_register_callback(hdd_ctx->hHal,
9144 wlan_hdd_cfg80211_stats_ext_callback);
9145
9146 sme_nan_deregister_callback(hdd_ctx->hHal);
9147 status = sme_reset_tsfcb(hdd_ctx->hHal);
9148 if (!QDF_IS_STATUS_SUCCESS(status))
9149 hdd_err("Failed to de-register tsfcb the callback:%d",
9150 status);
9151 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
9152 if (!QDF_IS_STATUS_SUCCESS(status))
9153 hdd_err("Failed to de-register the fw mem dump callback: %d",
9154 status);
9155
9156 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
9157 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
9158
9159 EXIT();
9160}
9161
9162/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009163 * hdd_softap_sta_deauth() - handle deauth req from HDD
9164 * @adapter: Pointer to the HDD
9165 * @enable: bool value
9166 *
9167 * This to take counter measure to handle deauth req from HDD
9168 *
9169 * Return: None
9170 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309171QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009172 struct tagCsrDelStaParams *pDelStaParams)
9173{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309174 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009175
9176 ENTER();
9177
Jeff Johnson34c88b72016-08-15 14:27:11 -07009178 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009179 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9180
9181 /* Ignore request to deauth bcmc station */
9182 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309183 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009184
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309185 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009186 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9187 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009188
9189 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309190 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009191}
9192
9193/**
9194 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
9195 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309196 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009197 *
9198 * This to take counter measure to handle deauth req from HDD
9199 *
9200 * Return: None
9201 */
9202void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309203 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009204{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009205 ENTER();
9206
Jeff Johnson34c88b72016-08-15 14:27:11 -07009207 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009208 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9209
9210 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309211 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009212 return;
9213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009214 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309215 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009216}
9217
9218void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
9219 bool enable)
9220{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009221 ENTER();
9222
Jeff Johnson34c88b72016-08-15 14:27:11 -07009223 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009224 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9225
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009226 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9227 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009228}
9229
9230/**
9231 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
9232 * @hdd_ctx: HDD Context
9233 *
9234 * API to find if there is any STA or P2P-Client is connected
9235 *
9236 * Return: true if connected; false otherwise
9237 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309238QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009239{
9240 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
9241}
9242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009243/**
9244 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
9245 * @adapter: HDD adapter pointer
9246 *
9247 * This function loop through each adapter and disable roaming on each STA
9248 * device mode except the input adapter.
9249 *
9250 * Note: On the input adapter roaming is not enabled yet hence no need to
9251 * disable.
9252 *
9253 * Return: None
9254 */
9255void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
9256{
9257 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9258 hdd_adapter_t *adapterIdx = NULL;
9259 hdd_adapter_list_node_t *adapterNode = NULL;
9260 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309261 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009262
9263 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
9264 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009265 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009266 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009267 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009268 adapter->sessionId);
9269 /*
9270 * Loop through adapter and disable roaming for each STA device
9271 * mode except the input adapter.
9272 */
9273 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9274
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309275 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009276 adapterIdx = adapterNode->pAdapter;
9277
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009278 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009279 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009280 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009281 adapterIdx->sessionId);
9282 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
9283 (adapterIdx),
9284 adapterIdx->sessionId, 0);
9285 }
9286
9287 status = hdd_get_next_adapter(hdd_ctx,
9288 adapterNode,
9289 &pNext);
9290 adapterNode = pNext;
9291 }
9292 }
9293}
9294
9295/**
9296 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
9297 * @adapter: HDD adapter pointer
9298 *
9299 * This function loop through each adapter and enable roaming on each STA
9300 * device mode except the input adapter.
9301 * Note: On the input adapter no need to enable roaming because link got
9302 * disconnected on this.
9303 *
9304 * Return: None
9305 */
9306void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
9307{
9308 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9309 hdd_adapter_t *adapterIdx = NULL;
9310 hdd_adapter_list_node_t *adapterNode = NULL;
9311 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309312 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009313
9314 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
9315 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009316 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009317 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009318 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009319 adapter->sessionId);
9320 /*
9321 * Loop through adapter and enable roaming for each STA device
9322 * mode except the input adapter.
9323 */
9324 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9325
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309326 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009327 adapterIdx = adapterNode->pAdapter;
9328
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009329 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009330 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009331 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009332 adapterIdx->sessionId);
9333 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
9334 (adapterIdx),
9335 adapterIdx->sessionId,
9336 REASON_CONNECT);
9337 }
9338
9339 status = hdd_get_next_adapter(hdd_ctx,
9340 adapterNode,
9341 &pNext);
9342 adapterNode = pNext;
9343 }
9344 }
9345}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009346
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309347/**
9348 * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
9349 * @skb: sk buffer pointer
9350 *
9351 * Sends the bcast message to SVC multicast group with generic nl socket
9352 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
9353 *
9354 * Return: None
9355 */
9356static void nl_srv_bcast_svc(struct sk_buff *skb)
9357{
9358#ifdef CNSS_GENL
9359 nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
9360#else
9361 nl_srv_bcast(skb);
9362#endif
9363}
9364
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309365void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009366{
9367 struct sk_buff *skb;
9368 struct nlmsghdr *nlh;
9369 tAniMsgHdr *ani_hdr;
9370 void *nl_data = NULL;
9371 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309372 struct radio_index_tlv *radio_info;
9373 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009374
9375 if (in_interrupt() || irqs_disabled() || in_atomic())
9376 flags = GFP_ATOMIC;
9377
9378 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
9379
9380 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009381 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009382 return;
9383 }
9384
9385 nlh = (struct nlmsghdr *)skb->data;
9386 nlh->nlmsg_pid = 0; /* from kernel */
9387 nlh->nlmsg_flags = 0;
9388 nlh->nlmsg_seq = 0;
9389 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
9390
9391 ani_hdr = NLMSG_DATA(nlh);
9392 ani_hdr->type = type;
9393
9394 switch (type) {
9395 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05309396 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009397 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009399 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009400 ani_hdr->length = 0;
9401 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009402 break;
9403 case WLAN_SVC_WLAN_STATUS_IND:
9404 case WLAN_SVC_WLAN_VERSION_IND:
9405 case WLAN_SVC_DFS_CAC_START_IND:
9406 case WLAN_SVC_DFS_CAC_END_IND:
9407 case WLAN_SVC_DFS_RADAR_DETECT_IND:
9408 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
9409 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08009410 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05309411 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009412 ani_hdr->length = len;
9413 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
9414 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
9415 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009416 break;
9417
9418 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07009419 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009420 type);
9421 kfree_skb(skb);
9422 return;
9423 }
9424
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309425 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08009426 * Add radio index at the end of the svc event in TLV format
9427 * to maintain the backward compatibility with userspace
9428 * applications.
9429 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309430
9431 tlv_len = 0;
9432
9433 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
9434 < WLAN_NL_MAX_PAYLOAD) {
9435 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
9436 sizeof(*ani_hdr) + len);
9437 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
9438 radio_info->length = (unsigned short) sizeof(radio_info->radio);
9439 radio_info->radio = radio;
9440 tlv_len = sizeof(*radio_info);
9441 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
9442 "Added radio index tlv - radio index %d",
9443 radio_info->radio);
9444 }
9445
9446 nlh->nlmsg_len += tlv_len;
9447 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
9448
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309449 nl_srv_bcast_svc(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009450
9451 return;
9452}
9453
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009454#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
9455void wlan_hdd_auto_shutdown_cb(void)
9456{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07009457 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309458
9459 if (!hdd_ctx)
9460 return;
9461
Jeff Johnson28f8a772016-08-15 15:30:36 -07009462 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309463 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
9464 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009465}
9466
9467void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
9468{
9469 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309470 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009471 hdd_adapter_t *adapter;
9472 bool ap_connected = false, sta_connected = false;
9473 tHalHandle hal_handle;
9474
9475 hal_handle = hdd_ctx->hHal;
9476 if (hal_handle == NULL)
9477 return;
9478
9479 if (hdd_ctx->config->WlanAutoShutdown == 0)
9480 return;
9481
9482 if (enable == false) {
9483 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309484 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009485 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009486 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309487 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009488 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009489 return;
9490 }
9491
9492 /* To enable shutdown timer check conncurrency */
9493 if (cds_concurrent_open_sessions_running()) {
9494 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9495
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309496 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009497 adapter = adapterNode->pAdapter;
9498 if (adapter
9499 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009500 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009501 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9502 conn_info.connState ==
9503 eConnectionState_Associated) {
9504 sta_connected = true;
9505 break;
9506 }
9507 }
9508 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009509 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
9511 bApActive == true) {
9512 ap_connected = true;
9513 break;
9514 }
9515 }
9516 status = hdd_get_next_adapter(hdd_ctx,
9517 adapterNode,
9518 &pNext);
9519 adapterNode = pNext;
9520 }
9521 }
9522
9523 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009524 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009525 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009526 }
Jeff Johnson68755312017-02-10 11:46:55 -08009527
9528 if (sme_set_auto_shutdown_timer(hal_handle,
9529 hdd_ctx->config->WlanAutoShutdown)
9530 != QDF_STATUS_SUCCESS)
9531 hdd_err("Failed to start wlan auto shutdown timer");
9532 else
9533 hdd_notice("Auto Shutdown timer for %d seconds enabled",
9534 hdd_ctx->config->WlanAutoShutdown);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009535}
9536#endif
9537
9538hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
9539 bool check_start_bss)
9540{
9541 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
9542 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309543 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009544 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
9545
9546 con_sap_adapter = NULL;
9547
9548 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309549 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009550 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009551 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
9552 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553 adapter != this_sap_adapter) {
9554 if (check_start_bss) {
9555 if (test_bit(SOFTAP_BSS_STARTED,
9556 &adapter->event_flags)) {
9557 con_sap_adapter = adapter;
9558 break;
9559 }
9560 } else {
9561 con_sap_adapter = adapter;
9562 break;
9563 }
9564 }
9565 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
9566 adapterNode = pNext;
9567 }
9568
9569 return con_sap_adapter;
9570}
9571
9572#ifdef MSM_PLATFORM
9573void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
9574{
9575 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9576
Dustin Brownfce08d12017-01-17 16:29:38 -08009577 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9578 if (!hdd_ctx->bus_bw_timer_running) {
9579 hdd_ctx->bus_bw_timer_running = true;
9580 qdf_timer_start(&hdd_ctx->bus_bw_timer,
9581 hdd_ctx->config->busBandwidthComputeInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009582
Dustin Brownfce08d12017-01-17 16:29:38 -08009583 }
9584 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009586}
9587
9588void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
9589{
9590 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309591 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009592 bool can_stop = true;
9593 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9594
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309595 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brownfce08d12017-01-17 16:29:38 -08009596 if (!hdd_ctx->bus_bw_timer_running) {
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309597 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009598 /* trying to stop timer, when not running is not good */
Srinivas Girigowda0ee96442016-08-17 19:10:56 -07009599 hdd_info("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009600 return;
9601 }
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309602 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603
9604 if (cds_concurrent_open_sessions_running()) {
9605 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9606
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309607 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009608 adapter = adapterNode->pAdapter;
9609 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009610 && (adapter->device_mode == QDF_STA_MODE
9611 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009612 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9613 conn_info.connState ==
9614 eConnectionState_Associated) {
9615 can_stop = false;
9616 break;
9617 }
9618 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009619 && (adapter->device_mode == QDF_SAP_MODE
9620 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009621 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
9622 true) {
9623 can_stop = false;
9624 break;
9625 }
9626 status = hdd_get_next_adapter(hdd_ctx,
9627 adapterNode,
9628 &pNext);
9629 adapterNode = pNext;
9630 }
9631 }
9632
Ravi Joshib89e7f72016-09-07 13:43:15 -07009633 if (can_stop == true) {
Chris Guoc0c95bf2016-11-10 14:28:25 +08009634 /* reset the ipa perf level */
9635 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
Dustin Brownfce08d12017-01-17 16:29:38 -08009636 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05309637 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08009638 hdd_ctx->bus_bw_timer_running = false;
9639 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Ravi Joshib89e7f72016-09-07 13:43:15 -07009640 hdd_reset_tcp_delack(hdd_ctx);
9641 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642}
9643#endif
9644
9645/**
9646 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
9647 * and sta's operating channel.
9648 * @sta_adapter: Describe the first argument to foobar.
9649 * @ap_adapter: Describe the second argument to foobar.
9650 * @roam_profile: Roam profile of AP to which STA wants to connect.
9651 * @concurrent_chnl_same: If both SAP and STA channels are same then
9652 * set this flag to true else false.
9653 *
9654 * This function checks the sap's operating channel and sta's operating channel.
9655 * if both are same then it will return false else it will restart the sap in
9656 * sta's channel and return true.
9657 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309658 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009659 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309660QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009661 hdd_adapter_t *ap_adapter,
9662 tCsrRoamProfile *roam_profile,
9663 tScanResultHandle *scan_cache,
9664 bool *concurrent_chnl_same)
9665{
9666 hdd_ap_ctx_t *hdd_ap_ctx;
9667 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309668 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009669 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009670 *concurrent_chnl_same = true;
9671
9672 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9673 status =
9674 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
9675 roam_profile,
9676 scan_cache,
9677 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309678 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009679 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009680 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9681 if (hdd_ap_ctx->operatingChannel != channel_id) {
9682 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009683 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009685 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
9687 if (hdd_ap_ctx->operatingChannel != channel_id) {
9688 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009689 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009690 }
9691 }
9692 } else {
9693 /*
9694 * Lets handle worst case scenario here, Scan cache lookup is
9695 * failed so we have to stop the SAP to avoid any channel
9696 * discrepancy between SAP's channel and STA's channel.
9697 * Return the status as failure so caller function could know
9698 * that scan look up is failed.
9699 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07009700 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309701 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009702 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309703 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009704}
9705
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009706/**
9707 * wlan_hdd_stop_sap() - This function stops bss of SAP.
9708 * @ap_adapter: SAP adapter
9709 *
9710 * This function will process the stopping of sap adapter.
9711 *
9712 * Return: None
9713 */
9714void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
9715{
9716 hdd_ap_ctx_t *hdd_ap_ctx;
9717 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309718 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009719 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009720
9721 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009722 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009723 return;
9724 }
9725
9726 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9727 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309728 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009729 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009731 mutex_lock(&hdd_ctx->sap_lock);
9732 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08009733 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
9735 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009736 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309737 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309738 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009739 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309740 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08009741 qdf_stop_bss_event,
9742 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309743 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009744 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009745 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009746 return;
9747 }
9748 }
9749 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08009750 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009751 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009752 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009753 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009754 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009755 }
9756 mutex_unlock(&hdd_ctx->sap_lock);
9757 return;
9758}
9759
9760/**
9761 * wlan_hdd_start_sap() - this function starts bss of SAP.
9762 * @ap_adapter: SAP adapter
9763 *
9764 * This function will process the starting of sap adapter.
9765 *
9766 * Return: None
9767 */
Arun Khandavallicc544b32017-01-30 19:52:16 +05309768void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009769{
9770 hdd_ap_ctx_t *hdd_ap_ctx;
9771 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309772 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009773 hdd_context_t *hdd_ctx;
9774 tsap_Config_t *sap_config;
9775
9776 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009777 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009778 return;
9779 }
9780
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009781 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07009782 hdd_err("SoftAp role has not been enabled");
9783 return;
9784 }
9785
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009786 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
9787 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9788 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9789 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
9790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791 mutex_lock(&hdd_ctx->sap_lock);
9792 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
9793 goto end;
9794
9795 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009796 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009797 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9798 goto end;
9799 }
9800
Wei Song2f76f642016-11-18 16:32:53 +08009801 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009802 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
9803 &hdd_ap_ctx->sapConfig,
9804 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309805 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009806 goto end;
9807
Jeff Johnson28f8a772016-08-15 15:30:36 -07009808 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309809 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -08009810 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309811 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009812 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009813 goto end;
9814 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07009815 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009816 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -08009817 if (hostapd_state->bssState == BSS_START)
9818 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009819 ap_adapter->sessionId);
9820 hostapd_state->bCommit = true;
9821
9822end:
9823 mutex_unlock(&hdd_ctx->sap_lock);
9824 return;
9825}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009826
9827/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08009828 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
9829 * mac scan config
9830 * @status: Status of set antenna mode
9831 *
9832 * Callback on setting the dual mac configuration
9833 *
9834 * Return: None
9835 */
9836void wlan_hdd_soc_set_antenna_mode_cb(
9837 enum set_antenna_mode_status status)
9838{
9839 hdd_context_t *hdd_ctx;
9840
9841 hdd_info("Status: %d", status);
9842
9843 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9844 if (0 != wlan_hdd_validate_context(hdd_ctx))
9845 return;
9846
9847 /* Signal the completion of set dual mac config */
9848 complete(&hdd_ctx->set_antenna_mode_cmpl);
9849}
9850
9851/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009852 * hdd_get_fw_version() - Get FW version
9853 * @hdd_ctx: pointer to HDD context.
9854 * @major_spid: FW version - major spid.
9855 * @minor_spid: FW version - minor spid
9856 * @ssid: FW version - ssid
9857 * @crmid: FW version - crmid
9858 *
9859 * This function is called to get the firmware build version stored
9860 * as part of the HDD context
9861 *
9862 * Return: None
9863 */
9864void hdd_get_fw_version(hdd_context_t *hdd_ctx,
9865 uint32_t *major_spid, uint32_t *minor_spid,
9866 uint32_t *siid, uint32_t *crmid)
9867{
9868 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
9869 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
9870 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
9871 *crmid = hdd_ctx->target_fw_version & 0x7fff;
9872}
9873
9874#ifdef QCA_CONFIG_SMP
9875/**
9876 * wlan_hdd_get_cpu() - get cpu_index
9877 *
9878 * Return: cpu_index
9879 */
9880int wlan_hdd_get_cpu(void)
9881{
9882 int cpu_index = get_cpu();
9883 put_cpu();
9884 return cpu_index;
9885}
9886#endif
9887
9888/**
9889 * hdd_get_fwpath() - get framework path
9890 *
9891 * This function is used to get the string written by
9892 * userspace to start the wlan driver
9893 *
9894 * Return: string
9895 */
9896const char *hdd_get_fwpath(void)
9897{
9898 return fwpath.string;
9899}
9900
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009901/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009902 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009903 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009904 * This function initilizes CDS global context with the help of cds_init. This
9905 * has to be the first function called after probe to get a valid global
9906 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009907 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009908 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009909 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009910int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009911{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009912 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009913 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009914
Houston Hoffman9e06e542016-12-12 12:06:26 -08009915 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009916#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9917 wlan_logging_sock_init_svc();
9918#endif
9919
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009920 if (p_cds_context == NULL) {
9921 hdd_alert("Failed to allocate CDS context");
9922 ret = -ENOMEM;
9923 goto err_out;
9924 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009925
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009926 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309927 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009928
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009929err_out:
9930 return ret;
9931}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009932
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009933/**
9934 * hdd_deinit() - Deinitialize Driver
9935 *
9936 * This function frees CDS global context with the help of cds_deinit. This
9937 * has to be the last function call in remove callback to free the global
9938 * context.
9939 */
9940void hdd_deinit(void)
9941{
9942 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009943
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009944#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9945 wlan_logging_sock_deinit_svc();
9946#endif
9947}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009948
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009949#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009950
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009951/**
9952 * __hdd_module_init - Module init helper
9953 *
9954 * Module init helper function used by both module and static driver.
9955 *
9956 * Return: 0 for success, errno on failure
9957 */
9958static int __hdd_module_init(void)
9959{
9960 int ret = 0;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +05309961 unsigned long rc;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009962
Arun Khandavallifae92942016-08-01 13:31:08 +05309963 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009964 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009965
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009966 pld_init();
9967
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309968 ret = hdd_init();
9969 if (ret) {
9970 pr_err("hdd_init failed %x\n", ret);
9971 goto err_hdd_init;
9972 }
9973
Rajeev Kumar97767a02016-11-30 11:20:40 -08009974 dispatcher_init();
9975
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309976 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009977
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009978 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009979
Arun Khandavalli13cb5da2017-01-19 15:43:52 +05309980 init_completion(&wlan_start_comp);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009981 ret = wlan_hdd_register_driver();
9982 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07009983 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
9984 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009985 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009986 }
9987
Arun Khandavalli13cb5da2017-01-19 15:43:52 +05309988 rc = wait_for_completion_timeout(&wlan_start_comp,
9989 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
9990
9991 if (!rc) {
9992 hdd_alert("Timed-out waiting for wlan_hdd_register_driver");
9993 QDF_BUG(0);
9994 goto out;
9995 }
9996
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309997 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009998
9999 return 0;
10000out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010001 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -080010002 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010003 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010004
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010005err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010006 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010007
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010008 return ret;
10009}
10010
10011/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010012 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
10013 *
10014 * Block the unloading of the driver until the cds recovery is completed
10015 *
10016 * Return: None
10017 */
10018static void hdd_wait_for_recovery_completion(void)
10019{
10020 int retry = 0;
10021
10022 /* Wait for recovery to complete */
10023 while (cds_is_driver_recovering()) {
10024 hdd_alert("Recovery in progress; wait here!!!");
10025 msleep(1000);
10026 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
10027 hdd_alert("SSR never completed, fatal error");
10028 QDF_BUG(0);
10029 }
10030 }
10031}
10032
10033/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010034 * __hdd_module_exit - Module exit helper
10035 *
10036 * Module exit helper function used by both module and static driver.
10037 */
10038static void __hdd_module_exit(void)
10039{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010040 int qdf_print_idx = -1;
10041
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010042 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
10043 QWLAN_VERSIONSTR);
10044
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010045 hdd_wait_for_recovery_completion();
10046
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010047 wlan_hdd_unregister_driver();
10048
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010049 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010050
Rajeev Kumar97767a02016-11-30 11:20:40 -080010051 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010052 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010053 pld_deinit();
10054
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010055 qdf_print_idx = qdf_get_pidx();
10056 qdf_print_ctrl_cleanup(qdf_print_idx);
10057
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010058 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010059}
10060
Arun Khandavallifae92942016-08-01 13:31:08 +053010061#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010062/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010063 * wlan_boot_cb() - Wlan boot callback
10064 * @kobj: object whose directory we're creating the link in.
10065 * @attr: attribute the user is interacting with
10066 * @buff: the buffer containing the user data
10067 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010068 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010069 * This callback is invoked when the fs is ready to start the
10070 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010071 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010072 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010073 */
Arun Khandavallifae92942016-08-01 13:31:08 +053010074static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010075 struct kobj_attribute *attr,
10076 const char *buf,
10077 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010078{
Arun Khandavallifae92942016-08-01 13:31:08 +053010079
Arun Khandavallifae92942016-08-01 13:31:08 +053010080 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010081 pr_err("%s: wlan driver already initialized\n", __func__);
10082 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +053010083 }
10084
Arun Khandavallifae92942016-08-01 13:31:08 +053010085 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010086 pr_err("%s: wlan driver initialization failed\n", __func__);
10087 return -EIO;
10088 }
10089
10090 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +053010091
10092 return count;
10093
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010094}
Arun Khandavallifae92942016-08-01 13:31:08 +053010095
10096/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010097 * hdd_sysfs_cleanup() - cleanup sysfs
10098 *
10099 * Return: None
10100 *
10101 */
10102static void hdd_sysfs_cleanup(void)
10103{
10104
10105 /* remove from group */
10106 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
10107 sysfs_remove_group(wlan_loader->boot_wlan_obj,
10108 wlan_loader->attr_group);
10109
10110 /* unlink the object from parent */
10111 kobject_del(wlan_loader->boot_wlan_obj);
10112
10113 /* free the object */
10114 kobject_put(wlan_loader->boot_wlan_obj);
10115
10116 kfree(wlan_loader->attr_group);
10117 kfree(wlan_loader);
10118
10119 wlan_loader = NULL;
10120}
10121
10122/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010123 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
10124 * ready
10125 *
10126 * This is creates the syfs entry boot_wlan. Which shall be invoked
10127 * when the filesystem is ready.
10128 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010129 * QDF API cannot be used here since this function is called even before
10130 * initializing WLAN driver.
10131 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010132 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +053010133 */
10134static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010135{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010136 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010137
10138 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
10139 if (!wlan_loader) {
10140 pr_err("%s: memory alloc failed\n", __func__);
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010141 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010142 }
10143
10144 wlan_loader->boot_wlan_obj = NULL;
10145 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
10146 GFP_KERNEL);
10147 if (!wlan_loader->attr_group) {
10148 pr_err("%s: malloc attr_group failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010149 goto error_return;
10150 }
10151
10152 wlan_loader->loaded_state = 0;
10153 wlan_loader->attr_group->attrs = attrs;
10154
10155 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
10156 kernel_kobj);
10157 if (!wlan_loader->boot_wlan_obj) {
10158 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010159 goto error_return;
10160 }
10161
10162 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
10163 wlan_loader->attr_group);
10164 if (ret) {
10165 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
10166 goto error_return;
10167 }
10168
10169 return 0;
10170
10171error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010172 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +053010173
10174 return ret;
10175}
10176
10177/**
10178 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
10179 *
10180 * Return: 0 on success or errno on failure
10181 */
10182static int wlan_deinit_sysfs(void)
10183{
Arun Khandavallifae92942016-08-01 13:31:08 +053010184 if (!wlan_loader) {
10185 hdd_alert("wlan loader context is Null!");
10186 return -EINVAL;
10187 }
10188
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010189 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010190 return 0;
10191}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010192
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010193#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +053010194
10195#ifdef MODULE
10196/**
10197 * __hdd_module_init - Module init helper
10198 *
10199 * Module init helper function used by both module and static driver.
10200 *
10201 * Return: 0 for success, errno on failure
10202 */
10203static int hdd_module_init(void)
10204{
10205 int ret = 0;
10206
10207 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
10208 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
10209
10210 if (__hdd_module_init()) {
10211 pr_err("%s: Failed to register handler\n", __func__);
10212 ret = -EINVAL;
10213 }
10214
10215 return ret;
10216}
10217#else
10218static int __init hdd_module_init(void)
10219{
10220 int ret = -EINVAL;
10221
10222 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010223 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +053010224 pr_err("Failed to create sysfs entry for loading wlan");
10225
10226 return ret;
10227}
10228#endif
10229
10230
10231#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010232/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010233 * hdd_module_exit() - Exit function
10234 *
10235 * This is the driver exit point (invoked when module is unloaded using rmmod)
10236 *
10237 * Return: None
10238 */
10239static void __exit hdd_module_exit(void)
10240{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010241 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010242}
Arun Khandavallifae92942016-08-01 13:31:08 +053010243#else
10244static void __exit hdd_module_exit(void)
10245{
10246 __hdd_module_exit();
10247 wlan_deinit_sysfs();
10248}
10249#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010250
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010251static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
10252{
10253 return param_set_copystring(kmessage, kp);
10254}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010255
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010256/**
10257 * is_con_mode_valid() check con mode is valid or not
10258 * @mode: global con mode
10259 *
10260 * Return: TRUE on success FALSE on failure
10261 */
10262static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
10263{
10264 switch (mode) {
10265 case QDF_GLOBAL_MONITOR_MODE:
10266 case QDF_GLOBAL_FTM_MODE:
10267 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010268 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010269 return true;
10270 default:
10271 return false;
10272 }
10273}
10274
10275/**
10276 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
10277 * @mode: global con mode
10278 *
10279 * Return: adapter mode
10280 */
10281static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
10282 enum tQDF_GLOBAL_CON_MODE mode)
10283{
10284
10285 switch (mode) {
10286 case QDF_GLOBAL_MISSION_MODE:
10287 return QDF_STA_MODE;
10288 case QDF_GLOBAL_MONITOR_MODE:
10289 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010290 case QDF_GLOBAL_EPPING_MODE:
10291 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010292 case QDF_GLOBAL_FTM_MODE:
10293 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010294 case QDF_GLOBAL_QVIT_MODE:
10295 return QDF_QVIT_MODE;
10296 default:
10297 return QDF_MAX_NO_OF_MODE;
10298 }
10299}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010300
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010301static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
10302 enum tQDF_GLOBAL_CON_MODE curr_mode)
10303{
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010304 int driver_status;
10305
10306 driver_status = hdd_ctx->driver_status;
10307
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010308 switch (curr_mode) {
10309 case QDF_GLOBAL_MISSION_MODE:
10310 case QDF_GLOBAL_MONITOR_MODE:
10311 case QDF_GLOBAL_FTM_MODE:
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010312 if (driver_status != DRIVER_MODULES_CLOSED) {
10313 hdd_abort_mac_scan_all_adapters(hdd_ctx);
10314 hdd_stop_all_adapters(hdd_ctx);
10315 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010316 hdd_deinit_all_adapters(hdd_ctx, false);
10317 hdd_close_all_adapters(hdd_ctx, false);
10318 break;
10319 case QDF_GLOBAL_EPPING_MODE:
10320 epping_disable();
10321 epping_close();
10322 break;
10323 default:
10324 return;
10325 }
10326}
10327
10328static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
10329 enum tQDF_GLOBAL_CON_MODE mode)
10330{
10331 hdd_adapter_t *adapter;
10332 int ret = 0;
10333 bool rtnl_held;
10334 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
10335 QDF_STATUS status;
10336
10337 if (!qdf_dev) {
10338 hdd_err("qdf device context is Null return!");
10339 return -EINVAL;
10340 }
10341
10342 rtnl_held = hdd_hold_rtnl_lock();
10343 switch (mode) {
10344 case QDF_GLOBAL_MISSION_MODE:
Jeff Johnson957bc272017-02-02 08:54:48 -080010345 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
10346 if (ret)
10347 hdd_alert("Failed to open interfaces: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010348 break;
10349 case QDF_GLOBAL_FTM_MODE:
10350 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
10351 wlan_hdd_get_intf_addr(hdd_ctx),
10352 NET_NAME_UNKNOWN, rtnl_held);
10353 if (adapter == NULL)
10354 ret = -EINVAL;
10355 break;
10356 case QDF_GLOBAL_MONITOR_MODE:
10357 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
10358 wlan_hdd_get_intf_addr(hdd_ctx),
10359 NET_NAME_UNKNOWN, rtnl_held);
10360 if (adapter == NULL)
10361 ret = -EINVAL;
10362 break;
10363 case QDF_GLOBAL_EPPING_MODE:
10364 status = epping_open();
10365 if (status != QDF_STATUS_SUCCESS) {
10366 hdd_err("Failed to open in eeping mode: %d", status);
10367 ret = -EINVAL;
10368 break;
10369 }
10370 ret = epping_enable(qdf_dev->dev);
10371 if (ret) {
10372 hdd_err("Failed to enable in epping mode : %d", ret);
10373 epping_close();
10374 }
10375 break;
10376 default:
10377 hdd_info("Mode not supported");
10378 ret = -ENOTSUPP;
10379 break;
10380 }
10381 hdd_release_rtnl_lock();
10382 rtnl_held = false;
10383 return ret;
10384}
10385
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010386/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010387 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010388 * @kmessage: con mode name on which driver to be bring up
10389 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010390 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010391 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010392 * This function is invoked when user updates con mode using sys entry,
10393 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010394 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010395 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010396 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010397static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
10398 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010399{
10400 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +053010401 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010402 enum tQDF_GLOBAL_CON_MODE curr_mode;
10403 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010404
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010405 ret = wlan_hdd_validate_context(hdd_ctx);
10406 if (ret)
10407 return ret;
10408
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010409 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010410
Arun Khandavallifae92942016-08-01 13:31:08 +053010411 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010412 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +053010413
Arun Khandavallifae92942016-08-01 13:31:08 +053010414
Arun Khandavallia172c3e2016-08-26 17:33:13 +053010415
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010416 if (!(is_con_mode_valid(con_mode))) {
10417 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010418 ret = -EINVAL;
10419 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010420 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010421
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010422 curr_mode = hdd_get_conparam();
10423 if (curr_mode == con_mode) {
10424 hdd_err("curr mode: %d is same as user triggered mode %d",
10425 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010426 ret = 0;
10427 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010428 }
10429
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010430 /* Cleanup present mode before switching to new mode */
10431 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +053010432
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -070010433 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +053010434 if (ret) {
10435 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010436 goto reset_flags;
10437 }
10438
10439 hdd_set_conparam(con_mode);
10440
10441 /* Register for new con_mode & then kick_start modules again */
10442 ret = hdd_register_req_mode(hdd_ctx, con_mode);
10443 if (ret) {
10444 hdd_err("Failed to register for new mode");
10445 goto reset_flags;
10446 }
10447
10448 adapter_mode = hdd_get_adpter_mode(con_mode);
10449 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
10450 hdd_err("invalid adapter");
10451 ret = -EINVAL;
10452 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010453 }
10454
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010455 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +053010456 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010457 hdd_err("Failed to get adapter:%d", adapter_mode);
10458 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010459 }
10460
10461 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
10462 if (ret) {
10463 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010464 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010465 }
10466
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010467 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
10468 con_mode == QDF_GLOBAL_FTM_MODE) {
10469 if (hdd_start_adapter(adapter)) {
10470 hdd_err("Failed to start %s adapter", kmessage);
10471 ret = -EINVAL;
10472 goto reset_flags;
10473 }
Arun Khandavallifae92942016-08-01 13:31:08 +053010474 }
10475
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010476 hdd_info("Mode successfully changed to %s", kmessage);
10477 ret = 0;
10478
10479reset_flags:
10480 cds_set_load_in_progress(false);
10481 return ret;
10482}
10483
10484
10485static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
10486{
10487 int ret;
10488 hdd_context_t *hdd_ctx;
10489
10490 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10491 ret = wlan_hdd_validate_context(hdd_ctx);
10492 if (ret)
10493 return ret;
10494
10495 cds_ssr_protect(__func__);
10496 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
10497 cds_ssr_unprotect(__func__);
10498
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010499 return ret;
10500}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010501
10502/**
10503 * hdd_get_conparam() - driver exit point
10504 *
10505 * This is the driver exit point (invoked when module is unloaded using rmmod)
10506 *
Anurag Chouhan6d760662016-02-20 16:05:43 +053010507 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010508 */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010509enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010510{
Anurag Chouhan6d760662016-02-20 16:05:43 +053010511 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010512}
10513
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010514void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010515{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010516 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010517}
10518
Komal Seelamc11bb222016-01-27 18:57:10 +053010519/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010520 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
10521 * @hdd_ctx: HDD context
10522 *
10523 * Cleans up the pre cac interface, if it exists
10524 *
10525 * Return: None
10526 */
10527void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
10528{
10529 uint8_t session_id;
10530 QDF_STATUS status;
10531 struct hdd_adapter_s *precac_adapter;
10532
10533 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
10534 if (QDF_IS_STATUS_ERROR(status)) {
10535 hdd_err("failed to get pre cac vdev id");
10536 return;
10537 }
10538
10539 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
10540 if (!precac_adapter) {
10541 hdd_err("invalid pre cac adapater");
10542 return;
10543 }
10544
10545 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
10546 wlan_hdd_sap_pre_cac_failure,
10547 (void *)precac_adapter);
10548 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
10549
10550}
10551
10552/**
Komal Seelamec702b02016-02-24 18:42:16 +053010553 * hdd_update_ol_config - API to update ol configuration parameters
10554 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +053010555 *
Komal Seelamc11bb222016-01-27 18:57:10 +053010556 * Return: void
10557 */
Komal Seelamec702b02016-02-24 18:42:16 +053010558static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +053010559{
Komal Seelamec702b02016-02-24 18:42:16 +053010560 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010561 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +053010562
Komal Seelamec702b02016-02-24 18:42:16 +053010563 if (!ol_ctx)
10564 return;
10565
10566 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
10567 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
10568 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
10569 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -070010570 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +053010571
10572 ol_init_ini_config(ol_ctx, &cfg);
10573}
10574
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010575#ifdef FEATURE_RUNTIME_PM
10576/**
10577 * hdd_populate_runtime_cfg() - populate runtime configuration
10578 * @hdd_ctx: hdd context
10579 * @cfg: pointer to the configuration memory being populated
10580 *
10581 * Return: void
10582 */
10583static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10584 struct hif_config_info *cfg)
10585{
10586 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
10587 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
10588}
10589#else
10590static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10591 struct hif_config_info *cfg)
10592{
10593}
10594#endif
10595
Komal Seelamec702b02016-02-24 18:42:16 +053010596/**
10597 * hdd_update_hif_config - API to update HIF configuration parameters
10598 * @hdd_ctx: HDD Context
10599 *
10600 * Return: void
10601 */
10602static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
10603{
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010604 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +053010605 struct hif_config_info cfg;
10606
10607 if (!scn)
10608 return;
10609
10610 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010611 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053010612 hif_init_ini_config(scn, &cfg);
10613}
10614
10615/**
10616 * hdd_update_config() - Initialize driver per module ini parameters
10617 * @hdd_ctx: HDD Context
10618 *
10619 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010620 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053010621 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010622int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053010623{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010624 int ret;
10625
Komal Seelamec702b02016-02-24 18:42:16 +053010626 hdd_update_ol_config(hdd_ctx);
10627 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010628 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
10629 ret = hdd_update_cds_config_ftm(hdd_ctx);
10630 else
10631 ret = hdd_update_cds_config(hdd_ctx);
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -080010632 ret = hdd_update_user_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010633
10634 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053010635}
10636
Mukul Sharma9d797a02017-01-05 20:26:03 +053010637#ifdef FEATURE_WLAN_RA_FILTERING
10638/**
10639 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
10640 * @psoc_cfg: pmo psoc Configuration
10641 * @hdd_ctx: Pointer to hdd context
10642 *
10643 * Return: none
10644 */
10645static inline void hdd_ra_populate_pmo_config(
10646 struct pmo_psoc_cfg *psoc_cfg,
10647 hdd_context_t *hdd_ctx)
10648{
10649 psoc_cfg->ra_ratelimit_interval =
10650 hdd_ctx->config->RArateLimitInterval;
10651 psoc_cfg->ra_ratelimit_enable =
10652 hdd_ctx->config->IsRArateLimitEnabled;
10653}
10654#else
10655static inline void hdd_ra_populate_pmo_config(
10656 struct cds_config_info *cds_cfg,
10657 hdd_context_t *hdd_ctx)
10658{
10659}
10660#endif
10661/**
10662 * hdd_update_pmo_config - API to update pmo configuration parameters
10663 * @hdd_ctx: HDD context
10664 *
10665 * Return: void
10666 */
10667static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
10668{
10669 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10670 struct pmo_psoc_cfg psoc_cfg;
10671 QDF_STATUS status;
10672
10673 /*
10674 * Value of hdd_ctx->wowEnable can be,
10675 * 0 - Disable both magic pattern match and pattern byte match.
10676 * 1 - Enable magic pattern match on all interfaces.
10677 * 2 - Enable pattern byte match on all interfaces.
10678 * 3 - Enable both magic patter and pattern byte match on
10679 * all interfaces.
10680 */
10681 psoc_cfg.magic_ptrn_enable =
10682 (hdd_ctx->config->wowEnable & 0x01) ? true : false;
10683 psoc_cfg.ptrn_match_enable_all_vdev =
10684 (hdd_ctx->config->wowEnable & 0x02) ? true : false;
10685 psoc_cfg.bpf_enable =
10686 hdd_ctx->config->bpf_packet_filter_enable;
10687 psoc_cfg.arp_offload_enable = hdd_ctx->config->fhostArpOffload;
10688 psoc_cfg.ns_offload_enable_static = hdd_ctx->config->fhostNSOffload;
10689 if (hdd_ctx->config->fhostNSOffload)
10690 psoc_cfg.ns_offload_enable_dynamic = true;
10691 psoc_cfg.ssdp = hdd_ctx->config->ssdp;
10692 psoc_cfg.enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
10693 psoc_cfg.active_mode_offload =
10694 hdd_ctx->config->active_mode_offload;
10695 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
10696 psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters;
Mukul Sharma9223f232017-03-08 18:42:27 +053010697 psoc_cfg.sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
10698 psoc_cfg.sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
10699 psoc_cfg.sta_max_li_mod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
10700 psoc_cfg.power_save_mode =
10701 hdd_ctx->config->enablePowersaveOffload;
Mukul Sharma9d797a02017-01-05 20:26:03 +053010702
10703 hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9223f232017-03-08 18:42:27 +053010704 hdd_nan_populate_pmo_config(&psoc_cfg, hdd_ctx);
10705 hdd_lpass_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053010706 status = pmo_ucfg_update_psoc_config(psoc, &psoc_cfg);
10707 if (status != QDF_STATUS_SUCCESS) {
10708 hdd_err("failed pmo psoc configuration");
10709 return -EINVAL;
10710 }
10711
10712 return 0;
10713}
10714
Abhishek Singh257a9482017-03-06 16:52:39 +053010715#ifdef NAPIER_SCAN
10716/**
10717 * hdd_update_scan_config - API to update scan configuration parameters
10718 * @hdd_ctx: HDD context
10719 *
10720 * Return: 0 if success else err
10721 */
10722static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
10723{
10724 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10725 struct scan_user_cfg scan_cfg;
10726 struct hdd_config *cfg = hdd_ctx->config;
10727 QDF_STATUS status;
10728
10729 scan_cfg.active_dwell = cfg->nActiveMaxChnTime;
10730 scan_cfg.passive_dwell = cfg->nPassiveMaxChnTime;
10731 scan_cfg.conc_active_dwell = cfg->nActiveMaxChnTimeConc;
10732 scan_cfg.conc_passive_dwell = cfg->nPassiveMaxChnTimeConc;
10733 scan_cfg.conc_max_rest_time = cfg->nRestTimeConc;
10734 scan_cfg.conc_min_rest_time = cfg->min_rest_time_conc;
10735 scan_cfg.conc_idle_time = cfg->idle_time_conc;
10736 scan_cfg.scan_cache_aging_time = cfg->scanAgingTimeout;
10737 scan_cfg.scan_dwell_time_mode = cfg->scan_adaptive_dwell_mode;
10738
10739 status = ucfg_scan_update_user_config(psoc, &scan_cfg);
10740 if (status != QDF_STATUS_SUCCESS) {
10741 hdd_err("failed pmo psoc configuration");
10742 return -EINVAL;
10743 }
10744
10745 return 0;
10746}
10747#else
10748static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
10749{
10750 return 0;
10751}
10752#endif
10753
Mukul Sharma9d797a02017-01-05 20:26:03 +053010754int hdd_update_components_config(hdd_context_t *hdd_ctx)
10755{
10756 int ret;
10757
10758 ret = hdd_update_pmo_config(hdd_ctx);
Abhishek Singh257a9482017-03-06 16:52:39 +053010759 if (ret)
10760 return ret;
10761 ret = hdd_update_scan_config(hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053010762
10763 return ret;
10764}
10765
Agrawal Ashish65634612016-08-18 13:24:32 +053010766/**
10767 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
10768 * @mode : cfg80211 DFS mode
10769 *
10770 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
10771 */
10772enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
10773{
10774 switch (mode) {
10775 case DFS_MODE_ENABLE:
10776 return ACS_DFS_MODE_ENABLE;
10777 break;
10778 case DFS_MODE_DISABLE:
10779 return ACS_DFS_MODE_DISABLE;
10780 break;
10781 case DFS_MODE_DEPRIORITIZE:
10782 return ACS_DFS_MODE_DEPRIORITIZE;
10783 break;
10784 default:
10785 hdd_err("ACS dfs mode is NONE");
10786 return ACS_DFS_MODE_NONE;
10787 }
10788}
10789
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053010790/**
10791 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
10792 * @hddctx: pointer to hdd context
10793 * @set_value: enable/disable
10794 *
10795 * When Host sends vendor command enable, FW will send *ONE* CA ind to
10796 * Host(even though it is duplicate). When Host send vendor command
10797 * disable,FW doesn't perform any action. Whenever any change in
10798 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
10799 *
10800 * return - 0 on success, appropriate error values on failure.
10801 */
10802int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
10803{
10804 QDF_STATUS status;
10805
10806 if (0 != wlan_hdd_validate_context(hddctx)) {
10807 return -EAGAIN;
10808 }
10809
10810 if (!hddctx->config->goptimize_chan_avoid_event) {
10811 hdd_warn("goptimize_chan_avoid_event ini param disabled");
10812 return -EINVAL;
10813 }
10814
10815 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
10816 if (!QDF_IS_STATUS_SUCCESS(status)) {
10817 hdd_err("Failed to send chan avoid command to SME");
10818 return -EINVAL;
10819 }
10820 return 0;
10821}
Agrawal Ashish65634612016-08-18 13:24:32 +053010822
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010823/**
10824 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
10825 * @value: value to set
10826 *
10827 * This function will set the passed value to roaming in progress flag.
10828 *
10829 * Return: None
10830 */
10831void hdd_set_roaming_in_progress(bool value)
10832{
10833 hdd_context_t *hdd_ctx;
10834
10835 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10836 if (!hdd_ctx) {
10837 hdd_err("HDD context is NULL");
10838 return;
10839 }
10840
10841 hdd_ctx->roaming_in_progress = value;
10842 hdd_info("Roaming in Progress set to %d", value);
10843}
10844
10845/**
10846 * hdd_is_roaming_in_progress() - check if roaming is in progress
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080010847 * @adapter - HDD adapter
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010848 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080010849 * Return: true if roaming is in progress for STA type, else false
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010850 */
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080010851bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter)
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010852{
10853 hdd_context_t *hdd_ctx;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080010854 bool ret_status = false;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010855
10856 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10857 if (!hdd_ctx) {
10858 hdd_err("HDD context is NULL");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080010859 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010860 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080010861 hdd_info("dev mode = %d, roaming_in_progress = %d",
10862 adapter->device_mode, hdd_ctx->roaming_in_progress);
10863 ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
10864 hdd_ctx->roaming_in_progress);
10865
10866 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010867}
10868
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869/* Register the module init/exit functions */
10870module_init(hdd_module_init);
10871module_exit(hdd_module_exit);
10872
10873MODULE_LICENSE("Dual BSD/GPL");
10874MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10875MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10878 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010879
10880module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
10881 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
10882
10883module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
10884
10885module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
10886
10887module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);