blob: 787c14ffbd1bf02e653eb8f012940d7f917a7291 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnsond9f08602016-12-02 11:31:30 -08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053039#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#include <linux/etherdevice.h>
41#include <linux/firmware.h>
42#include <wlan_hdd_tx_rx.h>
43#include <wni_api.h>
44#include <wlan_hdd_cfg.h>
45#include <wlan_ptt_sock_svc.h>
46#include <dbglog_host.h>
47#include <wlan_logging_sock_svc.h>
48#include <wlan_hdd_wowl.h>
49#include <wlan_hdd_misc.h>
50#include <wlan_hdd_wext.h>
51#include "wlan_hdd_trace.h"
52#include "wlan_hdd_ioctl.h"
53#include "wlan_hdd_ftm.h"
54#include "wlan_hdd_power.h"
55#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070056#include "wlan_hdd_scan.h"
Jeff Johnsonce0032c2017-01-20 07:18:27 -080057#include "wlan_hdd_request_manager.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053058#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053059#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070060#include <cdp_txrx_peer_ops.h>
Dhanashri Atrea8f82f22017-01-23 12:58:24 -080061#include <cdp_txrx_misc.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062
63#include <net/addrconf.h>
64#include <linux/wireless.h>
65#include <net/cfg80211.h>
66#include <linux/inetdevice.h>
67#include <net/addrconf.h>
68#include "wlan_hdd_cfg80211.h"
69#include "wlan_hdd_ext_scan.h"
70#include "wlan_hdd_p2p.h"
71#include <linux/rtnetlink.h>
72#include "sap_api.h"
73#include <linux/semaphore.h>
74#include <linux/ctype.h>
75#include <linux/compat.h>
76#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include <soc/qcom/subsystem_restart.h>
78#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079#include <wlan_hdd_hostapd.h>
80#include <wlan_hdd_softap_tx_rx.h>
81#include "cfg_api.h"
82#include "qwlan_version.h"
83#include "wma_types.h"
84#include "wlan_hdd_tdls.h"
85#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053086#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080087#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070089#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080090#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091#include "wlan_hdd_nan.h"
92#include "wlan_hdd_debugfs.h"
93#include "wlan_hdd_driver_ops.h"
94#include "epping_main.h"
95#include "wlan_hdd_memdump.h"
96
97#include <wlan_hdd_ipa.h>
98#include "hif.h"
99#include "wma.h"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -0800100#include "wlan_policy_mgr_api.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700101#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800102#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530103#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700104#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700105#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530106#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700107#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530108#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800109#include <dispatcher_init_deinit.h>
Rajeev Kumar699debf2017-01-06 14:17:00 -0800110#include "wlan_hdd_object_manager.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530111#include "cds_utils.h"
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -0800112#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800113#include <qca_vendor.h>
Mukul Sharma9d797a02017-01-05 20:26:03 +0530114#include "wlan_pmo_ucfg_api.h"
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +0530115#include "sir_api.h"
Naveen Rawat910726a2017-03-06 11:42:51 -0800116#include "os_if_wifi_pos.h"
117#include "wifi_pos_api.h"
118#include "wlan_hdd_oemdata.h"
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800119#include "wlan_hdd_he.h"
Naveen Rawatcb5c5402017-03-22 10:12:19 -0700120#include "os_if_nan.h"
121#include "nan_public_structs.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800122
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +0530123#ifdef CNSS_GENL
124#include <net/cnss_nl.h>
125#endif
126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
144
Arun Khandavallifae92942016-08-01 13:31:08 +0530145#ifndef MODULE
146static struct gwlan_loader *wlan_loader;
147static ssize_t wlan_boot_cb(struct kobject *kobj,
148 struct kobj_attribute *attr,
149 const char *buf, size_t count);
150struct gwlan_loader {
151 bool loaded_state;
152 struct kobject *boot_wlan_obj;
153 struct attribute_group *attr_group;
154};
155
156static struct kobj_attribute wlan_boot_attribute =
157 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
158
159static struct attribute *attrs[] = {
160 &wlan_boot_attribute.attr,
161 NULL,
162};
163
164#define MODULE_INITIALIZED 1
165#endif
166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167/* the Android framework expects this param even though we don't use it */
168#define BUF_LEN 20
169static char fwpath_buffer[BUF_LEN];
170static struct kparam_string fwpath = {
171 .string = fwpath_buffer,
172 .maxlen = BUF_LEN,
173};
174
175static char *country_code;
176static int enable_11d = -1;
177static int enable_dfs_chan_scan = -1;
178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179/*
180 * spinlock for synchronizing asynchronous request/response
181 * (full description of use in wlan_hdd_main.h)
182 */
183DEFINE_SPINLOCK(hdd_context_lock);
184
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800185#define WLAN_NLINK_CESIUM 30
186
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530187static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188
189#define WOW_MAX_FILTER_LISTS 1
190#define WOW_MAX_FILTERS_PER_LIST 4
191#define WOW_MIN_PATTERN_SIZE 6
192#define WOW_MAX_PATTERN_SIZE 64
193
194#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
195static const struct wiphy_wowlan_support wowlan_support_reg_init = {
196 .flags = WIPHY_WOWLAN_ANY |
197 WIPHY_WOWLAN_MAGIC_PKT |
198 WIPHY_WOWLAN_DISCONNECT |
199 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
200 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
201 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
202 WIPHY_WOWLAN_4WAY_HANDSHAKE |
203 WIPHY_WOWLAN_RFKILL_RELEASE,
204 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
205 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
206 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
207};
208#endif
209
210/* internal function declaration */
211
212struct sock *cesium_nl_srv_sock;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +0530213struct completion wlan_start_comp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
215void wlan_hdd_auto_shutdown_cb(void);
216#endif
217
218/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530219 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
220 * @hdd_ctx: pointer to hdd_context_t
221 *
222 * Return: none
223 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700224static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530225{
226 hdd_adapter_t *adapter;
227 hdd_adapter_list_node_t *adapter_node, *next;
228 QDF_STATUS status = QDF_STATUS_SUCCESS;
229
230 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
231 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
232 adapter = adapter_node->pAdapter;
233 if (NULL != adapter)
234 hdd_send_rps_ind(adapter);
235 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
236 adapter_node = next;
237 }
238}
239
240/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800241 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
242 * @vdev_id: vdev_id
243 * @action: action type
244 * @reason: reason type
245 *
246 * Return: none
247 */
248void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
249 enum netif_action_type action, enum netif_reason_type reason)
250{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530251 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 hdd_adapter_t *adapter;
253
254 if (!hdd_ctx) {
255 hdd_err("hdd ctx is NULL");
256 return;
257 }
258 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
259
260 wlan_hdd_netif_queue_control(adapter, action, reason);
261 return;
262}
263
264/*
265 * Store WLAN driver version info in a global variable such that crash debugger
266 * can extract it from driver debug symbol and crashdump for post processing
267 */
268uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
269
270/**
271 * hdd_device_mode_to_string() - return string conversion of device mode
272 * @device_mode: device mode
273 *
274 * This utility function helps log string conversion of device mode.
275 *
276 * Return: string conversion of device mode, if match found;
277 * "Unknown" otherwise.
278 */
279const char *hdd_device_mode_to_string(uint8_t device_mode)
280{
281 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800282 CASE_RETURN_STRING(QDF_STA_MODE);
283 CASE_RETURN_STRING(QDF_SAP_MODE);
284 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
285 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
286 CASE_RETURN_STRING(QDF_FTM_MODE);
287 CASE_RETURN_STRING(QDF_IBSS_MODE);
288 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
289 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700290 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 default:
292 return "Unknown";
293 }
294}
295
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530296/**
297 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
298 * @adapter: HDD adapter
299 * @chan_number: Channel number
300 * @chan_bw: Bandwidth
301 *
302 * Checks if the given bandwidth is valid for the given channel number.
303 *
304 * Return: 0 for success, non-zero for failure
305 */
306int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
307 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800308 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530309{
310 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
311 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
312 bool found = false;
313 tHalHandle hal;
314
315 hal = WLAN_HDD_GET_HAL_CTX(adapter);
316 if (!hal) {
317 hdd_err("Invalid HAL context");
318 return -EINVAL;
319 }
320
321 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
322 hdd_err("No valid channel list");
323 return -EOPNOTSUPP;
324 }
325
326 for (i = 0; i < len; i++) {
327 if (chan[i] == chan_number) {
328 found = true;
329 break;
330 }
331 }
332
333 if (found == false) {
334 hdd_err("Channel not in driver's valid channel list");
335 return -EOPNOTSUPP;
336 }
337
338 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
339 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
340 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
341 return -EINVAL;
342 }
343
344 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
345 if (chan_bw == CH_WIDTH_80MHZ) {
346 hdd_err("BW80 not possible in 2.4GHz band");
347 return -EINVAL;
348 }
349 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
350 (chan_bw != CH_WIDTH_MAX)) {
351 hdd_err("Only BW20 possible on channel 14");
352 return -EINVAL;
353 }
354 }
355
356 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
357 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
358 (chan_bw != CH_WIDTH_MAX)) {
359 hdd_err("Only BW20 possible on channel 165");
360 return -EINVAL;
361 }
362 }
363
364 return 0;
365}
366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800367static int __hdd_netdev_notifier_call(struct notifier_block *nb,
368 unsigned long state, void *data)
369{
370#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
371 struct netdev_notifier_info *dev_notif_info = data;
372 struct net_device *dev = dev_notif_info->dev;
373#else
374 struct net_device *dev = data;
375#endif
376 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
377 hdd_context_t *hdd_ctx;
378
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800379 ENTER_DEV(dev);
380
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800381 /* Make sure that this callback corresponds to our device. */
382 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
383 return NOTIFY_DONE;
384
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530385 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700387 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 return NOTIFY_DONE;
389 }
390
391 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700392 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 return NOTIFY_DONE;
394 }
395
396 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
397 if (NULL == hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800398 hdd_err("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530399 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400 return NOTIFY_DONE;
401 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800402 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800403 return NOTIFY_DONE;
404
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800405 hdd_debug("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800406 dev->name, state);
407
408 switch (state) {
409 case NETDEV_REGISTER:
410 break;
411
412 case NETDEV_UNREGISTER:
413 break;
414
415 case NETDEV_UP:
416 sme_ch_avoid_update_req(hdd_ctx->hHal);
417 break;
418
419 case NETDEV_DOWN:
420 break;
421
422 case NETDEV_CHANGE:
423 if (true == adapter->isLinkUpSvcNeeded)
424 complete(&adapter->linkup_event_var);
425 break;
426
427 case NETDEV_GOING_DOWN:
428 if (adapter->scan_info.mScanPending != false) {
429 unsigned long rc;
430 INIT_COMPLETION(adapter->scan_info.
431 abortscan_event_var);
432 hdd_abort_mac_scan(adapter->pHddCtx,
433 adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530434 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435 eCSR_SCAN_ABORT_DEFAULT);
436 rc = wait_for_completion_timeout(
437 &adapter->scan_info.abortscan_event_var,
438 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
439 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700440 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 }
442 } else {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800443 hdd_debug("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800444 }
445 break;
446
447 default:
448 break;
449 }
450
451 return NOTIFY_DONE;
452}
453
454/**
455 * hdd_netdev_notifier_call() - netdev notifier callback function
456 * @nb: pointer to notifier block
457 * @state: state
458 * @ndev: ndev pointer
459 *
460 * Return: 0 on success, error number otherwise.
461 */
462static int hdd_netdev_notifier_call(struct notifier_block *nb,
463 unsigned long state,
464 void *ndev)
465{
466 int ret;
467
468 cds_ssr_protect(__func__);
469 ret = __hdd_netdev_notifier_call(nb, state, ndev);
470 cds_ssr_unprotect(__func__);
471
472 return ret;
473}
474
475struct notifier_block hdd_netdev_notifier = {
476 .notifier_call = hdd_netdev_notifier_call,
477};
478
479/* variable to hold the insmod parameters */
480static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800481
482/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800484
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530485/**
486 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
487 * @ch_width: NL channel width
488 *
489 * Converts the NL channel width to the driver's internal representation
490 *
491 * Return: Converted channel width. In case of non matching NL channel width,
492 * CH_WIDTH_MAX will be returned.
493 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800494enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530495{
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800496 uint8_t fw_ch_bw;
497 fw_ch_bw = wma_get_vht_ch_width();
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530498 switch (ch_width) {
499 case NL80211_CHAN_WIDTH_20_NOHT:
500 case NL80211_CHAN_WIDTH_20:
501 return CH_WIDTH_20MHZ;
502 case NL80211_CHAN_WIDTH_40:
503 return CH_WIDTH_40MHZ;
504 break;
505 case NL80211_CHAN_WIDTH_80:
506 return CH_WIDTH_80MHZ;
507 case NL80211_CHAN_WIDTH_80P80:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800508 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
509 return CH_WIDTH_80P80MHZ;
510 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
511 return CH_WIDTH_160MHZ;
512 else
513 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530514 case NL80211_CHAN_WIDTH_160:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800515 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
516 return CH_WIDTH_160MHZ;
517 else
518 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530519 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800520 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530521 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800522 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530523 default:
524 hdd_err("Invalid channel width %d, setting to default",
525 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800526 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530527 }
528}
529
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530530/* wlan_hdd_find_opclass() - Find operating class for a channel
531 * @hal: handler to HAL
532 * @channel: channel id
533 * @bw_offset: bandwidth offset
534 *
535 * Function invokes sme api to find the operating class
536 *
537 * Return: operating class
538 */
539uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
540 uint8_t bw_offset)
541{
542 uint8_t opclass = 0;
543
544 sme_get_opclass(hal, channel, bw_offset, &opclass);
545 return opclass;
546}
547
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530549 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530550 * @module_id: Module whose trace level is being configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551 * @bitmask: Bitmask of log levels to be enabled
552 *
553 * Called immediately after the cfg.ini is read in order to configure
554 * the desired trace levels.
555 *
556 * Return: None
557 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530558int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530560 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530561 int qdf_print_idx = -1;
562 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 /*
564 * if the bitmask is the default value, then a bitmask was not
565 * specified in cfg.ini, so leave the logging level alone (it
566 * will remain at the "compiled in" default value)
567 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530568 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530569 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800570 }
571
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530572 qdf_print_idx = qdf_get_pidx();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530574 /* a mask was specified. start by disabling all logging */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530575 status = qdf_print_set_category_verbose(qdf_print_idx, module_id,
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530576 QDF_TRACE_LEVEL_NONE, 0);
577
578 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530579 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530581 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582 while (0 != bitmask) {
583 if (bitmask & 1) {
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530584 status = qdf_print_set_category_verbose(qdf_print_idx,
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530585 module_id, level, 1);
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530586 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530587 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 }
589 level++;
590 bitmask >>= 1;
591 }
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530592 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593}
594
595/**
596 * wlan_hdd_validate_context() - check the HDD context
597 * @hdd_ctx: HDD context pointer
598 *
599 * Return: 0 if the context is valid. Error code otherwise
600 */
601int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
602{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530604 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800605 return -ENODEV;
606 }
607
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800608 if (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800609 hdd_debug("%pS Recovery in Progress. State: 0x%x Ignore!!!",
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530610 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800611 return -EAGAIN;
612 }
613
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800614 if (cds_is_load_or_unload_in_progress()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800615 hdd_debug("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530616 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 return -EAGAIN;
618 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530619
620 if (hdd_ctx->start_modules_in_progress ||
621 hdd_ctx->stop_modules_in_progress) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800622 hdd_debug("%pS Start/Stop Modules in progress. Ignore!!!",
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530623 (void *)_RET_IP_);
624 return -EAGAIN;
625 }
626
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627 return 0;
628}
629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630/**
631 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
632 * @hdd_adapter_t Hdd adapter.
633 *
634 * This function sets the IBSS power save config parameters to WMA
635 * which will send it to firmware if FW supports IBSS power save
636 * before vdev start.
637 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530638 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 * on failure.
640 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530641QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642{
643 int ret;
644 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
645
646 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700647 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530648 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 }
650
651 ret = wma_cli_set_command(adapter->sessionId,
652 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
653 hdd_ctx->config->ibssATIMWinSize,
654 VDEV_CMD);
655 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700656 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530657 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 }
659
660 ret = wma_cli_set_command(adapter->sessionId,
661 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
662 hdd_ctx->config->isIbssPowerSaveAllowed,
663 VDEV_CMD);
664 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700665 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
666 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530667 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668 }
669
670 ret = wma_cli_set_command(adapter->sessionId,
671 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
672 hdd_ctx->config->
673 isIbssPowerCollapseAllowed, VDEV_CMD);
674 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700675 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
676 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530677 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 }
679
680 ret = wma_cli_set_command(adapter->sessionId,
681 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
682 hdd_ctx->config->isIbssAwakeOnTxRx,
683 VDEV_CMD);
684 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700685 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530686 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 }
688
689 ret = wma_cli_set_command(adapter->sessionId,
690 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
691 hdd_ctx->config->ibssInactivityCount,
692 VDEV_CMD);
693 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700694 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530695 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 }
697
698 ret = wma_cli_set_command(adapter->sessionId,
699 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
700 hdd_ctx->config->ibssTxSpEndInactivityTime,
701 VDEV_CMD);
702 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700703 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
704 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530705 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 }
707
708 ret = wma_cli_set_command(adapter->sessionId,
709 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
710 hdd_ctx->config->ibssPsWarmupTime,
711 VDEV_CMD);
712 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700713 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
714 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530715 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 }
717
718 ret = wma_cli_set_command(adapter->sessionId,
719 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
720 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
721 VDEV_CMD);
722 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700723 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
724 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530725 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 }
727
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530728 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729}
730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731#define INTF_MACADDR_MASK 0x7
732
733/**
734 * hdd_update_macaddr() - update mac address
735 * @config: hdd configuration
736 * @hw_macaddr: mac address
737 *
738 * Mac address for multiple virtual interface is found as following
739 * i) The mac address of the first interface is just the actual hw mac address.
740 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
741 * define the mac address for the remaining interfaces and locally
742 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
743 * supported virtual interfaces, right now this is 0x07 (meaning 8
744 * interface).
745 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
746 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
747 *
748 * Return: None
749 */
750void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530751 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800752{
753 int8_t i;
754 uint8_t macaddr_b3, tmp_br3;
755
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530756 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530757 QDF_MAC_ADDR_SIZE);
758 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530759 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530760 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761 macaddr_b3 = config->intfMacAddr[i].bytes[3];
762 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
763 INTF_MACADDR_MASK;
764 macaddr_b3 += tmp_br3;
765
766 /* XOR-ing bit-24 of the mac address. This will give enough
767 * mac address range before collision
768 */
769 macaddr_b3 ^= (1 << 7);
770
771 /* Set locally administered bit */
772 config->intfMacAddr[i].bytes[0] |= 0x02;
773 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800774 hdd_debug("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 MAC_ADDRESS_STR, i,
776 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
777 }
778}
779
780static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
781 struct wma_tgt_services *cfg)
782{
783 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784
785 /* Set up UAPSD */
786 config->apUapsdEnabled &= cfg->uapsd;
787
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800788 /* 11AX mode support */
789 if ((config->dot11Mode == eHDD_DOT11_MODE_11ax ||
790 config->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY) && !cfg->en_11ax)
791 config->dot11Mode = eHDD_DOT11_MODE_11ac;
792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 /* 11AC mode support */
794 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
795 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
796 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800797
798 /* ARP offload: override user setting if invalid */
799 config->fhostArpOffload &= cfg->arp_offload;
800
801#ifdef FEATURE_WLAN_SCAN_PNO
802 /* PNO offload */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800803 hdd_debug("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 if (cfg->pno_offload)
805 config->PnoOffload = true;
806#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807#ifdef FEATURE_WLAN_TDLS
808 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530809 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
810 cfg->en_tdls_offchan;
811 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
812 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
814 config->fEnableTDLSSleepSta = true;
815 } else {
816 config->fEnableTDLSSleepSta = false;
817 }
818#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819#ifdef WLAN_FEATURE_ROAM_OFFLOAD
820 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
821#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700822 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823
824}
825
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700826/**
827 * hdd_update_vdev_nss() - sets the vdev nss
828 * @hdd_ctx: HDD context
829 *
830 * Sets the Nss per vdev type based on INI
831 *
832 * Return: None
833 */
834static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
835{
836 struct hdd_config *cfg_ini = hdd_ctx->config;
837 uint8_t max_supp_nss = 1;
838
Naveen Rawat10b1c152017-01-18 11:16:06 -0800839 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700840 max_supp_nss = 2;
841
842 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
843 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
844
845 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
846 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
847}
848
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530849/**
850 * hdd_update_hw_dbs_capable() - sets the dbs capability of the device
851 * @hdd_ctx: HDD context
852 *
853 * Sets the DBS capability as per INI and firmware capability
854 *
855 * Return: None
856 */
857static void hdd_update_hw_dbs_capable(hdd_context_t *hdd_ctx)
858{
859 struct hdd_config *cfg_ini = hdd_ctx->config;
860 uint8_t hw_dbs_capable = 0;
861
862 if ((!cfg_ini->dual_mac_feature_disable)
Archana Ramachandran62886ce2017-03-24 14:46:32 -0700863 && policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc))
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530864 hw_dbs_capable = 1;
865
866 sme_update_hw_dbs_capable(hdd_ctx->hHal, hw_dbs_capable);
867}
868
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800869static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
870 struct wma_tgt_ht_cap *cfg)
871{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530872 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 uint32_t value, val32;
874 uint16_t val16;
875 struct hdd_config *pconfig = hdd_ctx->config;
876 tSirMacHTCapabilityInfo *phtCapInfo;
877 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
878 uint8_t enable_tx_stbc;
879
880 /* check and update RX STBC */
881 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
882 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
883
884 /* get the MPDU density */
885 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
886
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530887 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700888 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889 value = 0;
890 }
891
892 /*
893 * MPDU density:
894 * override user's setting if value is larger
895 * than the one supported by target
896 */
897 if (value > cfg->mpdu_density) {
898 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
899 cfg->mpdu_density);
900
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530901 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800902 hdd_err("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903 }
904
905 /* get the HT capability info */
906 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530907 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700908 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909 return;
910 }
911 val16 = (uint16_t) val32;
912 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
913
914 /* Set the LDPC capability */
915 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
916
917 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
918 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
919
920 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
921 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
922
923 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
924 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
925
926 enable_tx_stbc = pconfig->enableTxSTBC;
927
928 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
929 pconfig->enable2x2 = 1;
930 } else {
931 pconfig->enable2x2 = 0;
932 enable_tx_stbc = 0;
933
934 /* 1x1 */
935 /* Update Rx Highest Long GI data Rate */
936 if (sme_cfg_set_int(hdd_ctx->hHal,
937 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700938 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530939 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700940 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941 }
942
943 /* Update Tx Highest Long GI data Rate */
944 if (sme_cfg_set_int
945 (hdd_ctx->hHal,
946 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700947 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530948 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700949 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 }
951 }
952 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
953 enable_tx_stbc = 0;
954 phtCapInfo->txSTBC = enable_tx_stbc;
955
956 val32 = val16;
957 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530958 if (status != QDF_STATUS_SUCCESS)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800959 hdd_err("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800960#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
961 value = SIZE_OF_SUPPORTED_MCS_SET;
962 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530963 &value) == QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800964 hdd_debug("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800965
966 if (pconfig->enable2x2) {
967 for (value = 0; value < cfg->num_rf_chains; value++)
968 mcs_set[value] =
969 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
970
971 status =
972 sme_cfg_set_str(hdd_ctx->hHal,
973 WNI_CFG_SUPPORTED_MCS_SET,
974 mcs_set,
975 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530976 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800977 hdd_err("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 }
979 }
980#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
981}
982
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800983static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
984 struct wma_tgt_vht_cap *cfg)
985{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530986 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987 uint32_t value = 0;
988 struct hdd_config *pconfig = hdd_ctx->config;
989 struct wiphy *wiphy = hdd_ctx->wiphy;
990 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700991 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700992 uint32_t temp = 0;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800993 uint32_t ch_width = eHT_CHANNEL_WIDTH_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800994
Dustin Brown5e06bd32016-10-04 12:49:10 -0700995 if (!band_5g) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -0800996 hdd_debug("5GHz band disabled, skipping capability population");
Dustin Brown5e06bd32016-10-04 12:49:10 -0700997 return;
998 }
999
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 /* Get the current MPDU length */
1001 status =
1002 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1003 &value);
1004
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301005 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001006 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001007 value = 0;
1008 }
1009
1010 /*
1011 * VHT max MPDU length:
1012 * override if user configured value is too high
1013 * that the target cannot support
1014 */
1015 if (value > cfg->vht_max_mpdu) {
1016 status = sme_cfg_set_int(hdd_ctx->hHal,
1017 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1018 cfg->vht_max_mpdu);
1019
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001020 if (status == QDF_STATUS_E_FAILURE)
1021 hdd_err("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001022 }
1023
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001024 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1025 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1026
1027 if (pconfig->enable2x2)
1028 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1029
1030 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1031 QDF_STATUS_E_FAILURE) {
1032 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1033 }
1034
1035 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1036 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1037 if (pconfig->enable2x2)
1038 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1039
1040 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1041 QDF_STATUS_E_FAILURE) {
1042 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1043 }
1044
1045 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1046 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1047 if (pconfig->enable2x2)
1048 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1049
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001050 hdd_debug("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001051 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1052
1053 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1054 QDF_STATUS_E_FAILURE) {
1055 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1056 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001057 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001058 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001059 &value);
1060
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301061 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001062 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 value = 0;
1064 }
1065
1066 /* Set the LDPC capability */
1067 if (value && !cfg->vht_rx_ldpc) {
1068 status = sme_cfg_set_int(hdd_ctx->hHal,
1069 WNI_CFG_VHT_LDPC_CODING_CAP,
1070 cfg->vht_rx_ldpc);
1071
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001072 if (status == QDF_STATUS_E_FAILURE)
1073 hdd_err("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 }
1075
1076 /* Get current GI 80 value */
1077 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1078 &value);
1079
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301080 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001081 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 value = 0;
1083 }
1084
1085 /* set the Guard interval 80MHz */
1086 if (value && !cfg->vht_short_gi_80) {
1087 status = sme_cfg_set_int(hdd_ctx->hHal,
1088 WNI_CFG_VHT_SHORT_GI_80MHZ,
1089 cfg->vht_short_gi_80);
1090
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001091 if (status == QDF_STATUS_E_FAILURE)
1092 hdd_err("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001093 }
1094
1095 /* Get current GI 160 value */
1096 status = sme_cfg_get_int(hdd_ctx->hHal,
1097 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1098 &value);
1099
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301100 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001101 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102 value = 0;
1103 }
1104
1105 /* Get VHT TX STBC cap */
1106 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1107
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301108 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001109 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001110 value = 0;
1111 }
1112
1113 /* VHT TX STBC cap */
1114 if (value && !cfg->vht_tx_stbc) {
1115 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1116 cfg->vht_tx_stbc);
1117
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001118 if (status == QDF_STATUS_E_FAILURE)
1119 hdd_err("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001120 }
1121
1122 /* Get VHT RX STBC cap */
1123 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301125 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001126 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001127 value = 0;
1128 }
1129
1130 /* VHT RX STBC cap */
1131 if (value && !cfg->vht_rx_stbc) {
1132 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1133 cfg->vht_rx_stbc);
1134
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001135 if (status == QDF_STATUS_E_FAILURE)
1136 hdd_err("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 }
1138
1139 /* Get VHT SU Beamformer cap */
1140 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1141 &value);
1142
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301143 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001144 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145 value = 0;
1146 }
1147
1148 /* set VHT SU Beamformer cap */
1149 if (value && !cfg->vht_su_bformer) {
1150 status = sme_cfg_set_int(hdd_ctx->hHal,
1151 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1152 cfg->vht_su_bformer);
1153
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001154 if (status == QDF_STATUS_E_FAILURE)
1155 hdd_err("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 }
1157
1158 /* check and update SU BEAMFORMEE capabality */
1159 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1160 pconfig->enableTxBF = cfg->vht_su_bformee;
1161
1162 status = sme_cfg_set_int(hdd_ctx->hHal,
1163 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1164 pconfig->enableTxBF);
1165
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001166 if (status == QDF_STATUS_E_FAILURE)
1167 hdd_err("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001168
1169 /* Get VHT MU Beamformer cap */
1170 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_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 BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001175 value = 0;
1176 }
1177
1178 /* set VHT MU Beamformer cap */
1179 if (value && !cfg->vht_mu_bformer) {
1180 status = sme_cfg_set_int(hdd_ctx->hHal,
1181 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1182 cfg->vht_mu_bformer);
1183
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001184 if (status == QDF_STATUS_E_FAILURE)
1185 hdd_err("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186 }
1187
1188 /* Get VHT MU Beamformee cap */
1189 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1190 &value);
1191
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301192 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001193 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001194 value = 0;
1195 }
1196
1197 /* set VHT MU Beamformee cap */
1198 if (value && !cfg->vht_mu_bformee) {
1199 status = sme_cfg_set_int(hdd_ctx->hHal,
1200 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1201 cfg->vht_mu_bformee);
1202
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001203 if (status == QDF_STATUS_E_FAILURE)
1204 hdd_err("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205 }
1206
1207 /* Get VHT MAX AMPDU Len exp */
1208 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1209 &value);
1210
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301211 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001212 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 value = 0;
1214 }
1215
1216 /*
1217 * VHT max AMPDU len exp:
1218 * override if user configured value is too high
1219 * that the target cannot support.
1220 * Even though Rome publish ampdu_len=7, it can
1221 * only support 4 because of some h/w bug.
1222 */
1223
1224 if (value > cfg->vht_max_ampdu_len_exp) {
1225 status = sme_cfg_set_int(hdd_ctx->hHal,
1226 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1227 cfg->vht_max_ampdu_len_exp);
1228
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001229 if (status == QDF_STATUS_E_FAILURE)
1230 hdd_err("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 }
1232
1233 /* Get VHT TXOP PS CAP */
1234 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1235
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301236 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001237 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 value = 0;
1239 }
1240
1241 /* set VHT TXOP PS cap */
1242 if (value && !cfg->vht_txop_ps) {
1243 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1244 cfg->vht_txop_ps);
1245
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001246 if (status == QDF_STATUS_E_FAILURE)
1247 hdd_err("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 }
1249
1250 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1251 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1252 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1253 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1254 else
1255 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1256
1257
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001258 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1259 status = sme_cfg_set_int(hdd_ctx->hHal,
1260 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1261 VHT_CAP_160_AND_80P80_SUPP);
1262 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001263 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 band_5g->vht_cap.cap |=
1265 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001266 ch_width = eHT_CHANNEL_WIDTH_80P80MHZ;
1267 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1268 status = sme_cfg_set_int(hdd_ctx->hHal,
1269 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1270 VHT_CAP_160_SUPP);
1271 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001272 hdd_err("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001273 band_5g->vht_cap.cap |=
1274 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001275 ch_width = eHT_CHANNEL_WIDTH_160MHZ;
1276 }
1277 pconfig->vhtChannelWidth = QDF_MIN(pconfig->vhtChannelWidth,
1278 ch_width);
1279 /* Get the current supported chan width */
1280 status = sme_cfg_get_int(hdd_ctx->hHal,
1281 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1282 &value);
1283 if (status != QDF_STATUS_SUCCESS) {
1284 hdd_err("could not get CH BW");
1285 value = 0;
1286 }
1287 /* set the Guard interval 80MHz */
1288 if (value) {
1289 status = sme_cfg_set_int(hdd_ctx->hHal,
1290 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1291 cfg->vht_short_gi_160);
1292
1293 if (status == QDF_STATUS_E_FAILURE)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001294 hdd_err("failed to set SHORT GI 80MHZ");
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001295 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001296
1297 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1298 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1299
1300 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1301 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1302 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1303 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1304
1305 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1306 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1307
1308 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1309 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1310 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1311 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1312 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1313 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1314
1315 band_5g->vht_cap.cap |=
1316 (cfg->vht_max_ampdu_len_exp <<
1317 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1318
1319 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1320 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1321 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1322 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1323 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1324 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1325 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1326 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1327
1328 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1329 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1330
1331}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001333/**
1334 * hdd_generate_macaddr_auto() - Auto-generate mac address
1335 * @hdd_ctx: Pointer to the HDD context
1336 *
1337 * Auto-generate mac address using device serial number.
1338 * Keep the first 3 bytes of OUI as before and replace
1339 * the last 3 bytes with the lower 3 bytes of serial number.
1340 *
1341 * Return: 0 for success
1342 * Non zero failure code for errors
1343 */
1344static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1345{
1346 unsigned int serialno = 0;
1347 struct qdf_mac_addr mac_addr = {
1348 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1349 };
1350
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001351 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001352 if (serialno == 0)
1353 return -EINVAL;
1354
1355 serialno &= 0x00ffffff;
1356
1357 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1358 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1359 mac_addr.bytes[5] = serialno & 0xff;
1360
1361 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1362 return 0;
1363}
1364
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301365/**
1366 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1367 * configuration to cfg_ini in HDD
1368 * @hdd_ctx: Pointer to hdd_ctx
1369 * @cfg: target configuration
1370 *
1371 * Return: None
1372 */
1373#ifdef FEATURE_WLAN_RA_FILTERING
1374static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1375 struct wma_tgt_cfg *cfg)
1376{
1377 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1378}
1379#else
1380static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1381 struct wma_tgt_cfg *cfg)
1382{
1383}
1384#endif
1385
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386void hdd_update_tgt_cfg(void *context, void *param)
1387{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001388 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1390 struct wma_tgt_cfg *cfg = param;
1391 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001392 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301393
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07001394 /* Reuse same pdev for module stop and start */
1395 if ((hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) ||
1396 (!cds_is_driver_loading())) {
1397 hdd_err("Reuse pdev for module start/stop");
1398 } else {
1399 ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
1400 if (ret) {
1401 hdd_err("pdev creation fails!");
1402 QDF_BUG(0);
1403 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301404 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001405 if (cds_cfg) {
1406 if (hdd_ctx->config->enable_sub_20_channel_width !=
1407 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1408 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1409 cds_cfg->sub_20_channel_width =
1410 WLAN_SUB_20_CH_WIDTH_NONE;
1411 } else {
1412 cds_cfg->sub_20_channel_width =
1413 hdd_ctx->config->enable_sub_20_channel_width;
1414 }
1415 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001416
1417 /* first store the INI band capability */
1418 temp_band_cap = hdd_ctx->config->nBandCapability;
1419
1420 hdd_ctx->config->nBandCapability = cfg->band_cap;
1421
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001422 /*
1423 * now overwrite the target band capability with INI
1424 * setting if INI setting is a subset
1425 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426
1427 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1428 (temp_band_cap != eCSR_BAND_ALL))
1429 hdd_ctx->config->nBandCapability = temp_band_cap;
1430 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1431 (temp_band_cap != eCSR_BAND_ALL) &&
1432 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001433 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 }
1435
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001436 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001437 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1438 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1439 }
1440
1441 /* This can be extended to other configurations like ht, vht cap... */
1442
Anurag Chouhanc5548422016-02-24 18:33:27 +05301443 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001445 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001447 static struct qdf_mac_addr default_mac_addr = {
1448 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1449 };
1450 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1451 &default_mac_addr)) {
1452 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1453 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1454 MAC_ADDRESS_STR,
1455 MAC_ADDR_ARRAY(hdd_ctx->config->
1456 intfMacAddr[0].bytes));
1457 } else {
1458 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1459 MAC_ADDRESS_STR,
1460 MAC_ADDR_ARRAY(hdd_ctx->config->
1461 intfMacAddr[0].bytes));
1462 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001463 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001464 }
1465
1466 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001467 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468
1469 hdd_ctx->max_intf_count = cfg->max_intf_count;
1470
Jeff Johnsonc875e242016-09-23 18:12:34 -07001471 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001472 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1475 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1476
1477 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1478
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001479 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajaned1efd92016-09-24 18:05:47 -07001480 if (cfg->services.en_11ax) {
1481 hdd_info("11AX: 11ax is enabled - update HDD config");
1482 hdd_update_tgt_he_cap(hdd_ctx, cfg);
1483 }
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001484
1485 hdd_update_vdev_nss(hdd_ctx);
1486
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +05301487 hdd_update_hw_dbs_capable(hdd_ctx);
1488
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001489 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001490 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001491 hdd_debug("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001492 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001493
1494 hdd_ctx->current_antenna_mode =
1495 (hdd_ctx->config->enable2x2 == 0x01) ?
1496 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001497 hdd_debug("Init current antenna mode: %d",
Archana Ramachandran393f3792015-11-13 17:13:21 -08001498 hdd_ctx->current_antenna_mode);
1499
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001500 hdd_debug("Target BPF %d Host BPF %d",
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001501 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1502 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1503 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301504 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301505
Arun Khandavallid454d422016-08-17 12:47:05 +05301506 /*
1507 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1508 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1509 * configure the STA mode wow pattern.
1510 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301511 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301512 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301513
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301514 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1515
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001516 /* Configure NAN datapath features */
1517 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Arif Hussain759a0232017-03-20 13:17:18 -07001518 hdd_ctx->dfs_cac_offload = cfg->dfs_cac_offload;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519}
1520
1521/**
1522 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1523 * @context: HDD context pointer
1524 * @param: HDD radar indication pointer
1525 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001526 * This function is invoked in atomic context when a radar
1527 * is found on the SAP current operating channel and Data Tx
1528 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529 * Actions: Stop the netif Tx queues,Indicate Radar present
1530 * in HDD context for future usage.
1531 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301532 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301534bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535{
1536 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1537 struct wma_dfs_radar_ind *hdd_radar_event =
1538 (struct wma_dfs_radar_ind *)param;
1539 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1540 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301541 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301542 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301544 if (!hdd_ctx || !hdd_radar_event ||
1545 hdd_ctx->config->disableDFSChSwitch)
1546 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547
1548 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001549 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301550 /*
1551 * Application already triggered channel switch
1552 * on current channel, so return here.
1553 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301554 return false;
1555 }
1556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301558 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301560 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1561 if ((QDF_SAP_MODE == adapter->device_mode ||
1562 QDF_P2P_GO_MODE == adapter->device_mode) &&
1563 (CHANNEL_STATE_DFS ==
1564 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001565 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1566 dfs_cac_block_tx = true;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001567 hdd_debug("tx blocked for session:%d",
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301568 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001569 }
1570
1571 status = hdd_get_next_adapter(hdd_ctx,
1572 adapterNode,
1573 &pNext);
1574 adapterNode = pNext;
1575 }
1576 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301577
1578 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580
1581/**
1582 * hdd_is_valid_mac_address() - validate MAC address
1583 * @pMacAddr: Pointer to the input MAC address
1584 *
1585 * This function validates whether the given MAC address is valid or not
1586 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1587 * where X is the hexa decimal digit character and separated by ':'
1588 * This algorithm works even if MAC address is not separated by ':'
1589 *
1590 * This code checks given input string mac contains exactly 12 hexadecimal
1591 * digits and a separator colon : appears in the input string only after
1592 * an even number of hex digits.
1593 *
1594 * Return: 1 for valid and 0 for invalid
1595 */
1596bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1597{
1598 int xdigit = 0;
1599 int separator = 0;
1600 while (*pMacAddr) {
1601 if (isxdigit(*pMacAddr)) {
1602 xdigit++;
1603 } else if (':' == *pMacAddr) {
1604 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1605 break;
1606
1607 ++separator;
1608 } else {
1609 /* Invalid MAC found */
1610 return 0;
1611 }
1612 ++pMacAddr;
1613 }
1614 return xdigit == 12 && (separator == 5 || separator == 0);
1615}
1616
1617/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301618 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1619 * @dev: Handle to struct net_device to be updated.
1620 *
1621 * Return: None
1622 */
1623static void hdd_mon_mode_ether_setup(struct net_device *dev)
1624{
1625 dev->header_ops = NULL;
1626 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1627 dev->hard_header_len = ETH_HLEN;
1628 dev->mtu = ETH_DATA_LEN;
1629 dev->addr_len = ETH_ALEN;
1630 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1631 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1632 dev->priv_flags |= IFF_TX_SKB_SHARING;
1633
1634 memset(dev->broadcast, 0xFF, ETH_ALEN);
1635}
1636
1637/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001638 * __hdd__mon_open() - HDD Open function
1639 * @dev: Pointer to net_device structure
1640 *
1641 * This is called in response to ifconfig up
1642 *
1643 * Return: 0 for success; non-zero for failure
1644 */
1645static int __hdd_mon_open(struct net_device *dev)
1646{
1647 int ret;
1648
1649 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301650 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001651 ret = hdd_set_mon_rx_cb(dev);
1652 return ret;
1653}
1654
1655/**
1656 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1657 * @dev: Pointer to net_device structure
1658 *
1659 * This is called in response to ifconfig up
1660 *
1661 * Return: 0 for success; non-zero for failure
1662 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001663static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001664{
1665 int ret;
1666
1667 cds_ssr_protect(__func__);
1668 ret = __hdd_mon_open(dev);
1669 cds_ssr_unprotect(__func__);
1670
1671 return ret;
1672}
1673
1674/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301675 * hdd_start_adapter() - Wrapper function for device specific adapter
1676 * @adapter: pointer to HDD adapter
1677 *
1678 * This function is called to start the device specific adapter for
1679 * the mode passed in the adapter's device_mode.
1680 *
1681 * Return: 0 for success; non-zero for failure
1682 */
1683int hdd_start_adapter(hdd_adapter_t *adapter)
1684{
1685
1686 int ret;
1687 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1688
1689 ENTER_DEV(adapter->dev);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001690 hdd_debug("Start_adapter for mode : %d", adapter->device_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05301691
1692 switch (device_mode) {
1693 case QDF_P2P_CLIENT_MODE:
1694 case QDF_P2P_DEVICE_MODE:
1695 case QDF_OCB_MODE:
1696 case QDF_STA_MODE:
1697 case QDF_MONITOR_MODE:
1698 ret = hdd_start_station_adapter(adapter);
1699 if (ret)
1700 goto err_start_adapter;
1701 break;
1702 case QDF_P2P_GO_MODE:
1703 case QDF_SAP_MODE:
1704 ret = hdd_start_ap_adapter(adapter);
1705 if (ret)
1706 goto err_start_adapter;
1707 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301708 case QDF_IBSS_MODE:
1709 /*
1710 * For IBSS interface is initialized as part of
1711 * hdd_init_station_mode()
1712 */
1713 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301714 case QDF_FTM_MODE:
1715 ret = hdd_start_ftm_adapter(adapter);
1716 if (ret)
1717 goto err_start_adapter;
1718 break;
1719 default:
1720 hdd_err("Invalid session type %d", device_mode);
1721 QDF_ASSERT(0);
1722 goto err_start_adapter;
1723 }
1724 if (hdd_set_fw_params(adapter))
1725 hdd_err("Failed to set the FW params for the adapter!");
1726
1727 /*
1728 * Action frame registered in one adapter which will
1729 * applicable to all interfaces
1730 */
1731 wlan_hdd_cfg80211_register_frames(adapter);
1732 EXIT();
1733 return 0;
1734err_start_adapter:
1735 return -EINVAL;
1736}
1737
1738/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301739 * hdd_enable_power_management() - API to Enable Power Management
1740 *
1741 * API invokes Bus Interface Layer power management functionality
1742 *
1743 * Return: None
1744 */
1745static void hdd_enable_power_management(void)
1746{
1747 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1748
1749 if (!hif_ctx) {
1750 hdd_err("Bus Interface Context is Invalid");
1751 return;
1752 }
1753
1754 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1755}
1756
1757/**
1758 * hdd_disable_power_management() - API to disable Power Management
1759 *
1760 * API disable Bus Interface Layer Power management functionality
1761 *
1762 * Return: None
1763 */
1764static void hdd_disable_power_management(void)
1765{
1766 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1767
1768 if (!hif_ctx) {
1769 hdd_err("Bus Interface Context is Invalid");
1770 return;
1771 }
1772
1773 hif_disable_power_management(hif_ctx);
1774}
1775
1776/**
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301777 * hdd_update_hw_sw_info() - API to update the HW/SW information
1778 *
1779 * API to update the HW and SW information in the driver
1780 *
1781 * Return: None
1782 */
1783static void hdd_update_hw_sw_info(hdd_context_t *hdd_ctx)
1784{
1785 void *hif_sc;
1786
1787 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
1788 if (!hif_sc) {
1789 hdd_err("HIF context is NULL");
1790 return;
1791 }
1792
1793 /*
1794 * target hw version/revision would only be retrieved after firmware
1795 * download
1796 */
1797 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
1798 &hdd_ctx->target_hw_revision,
1799 &hdd_ctx->target_hw_name);
1800
1801 /* Get the wlan hw/fw version */
1802 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
1803
1804 return;
1805}
1806
1807/**
gbian62edd7e2017-03-07 13:12:13 +08001808 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
1809 * @hdd_ctx: Pointer to hdd context
1810 *
1811 * Return: none
1812 */
1813static void
1814hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
1815{
1816 uint8_t num_entries = 0;
1817 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
1818 uint8_t *tx_sched_wrr_ac;
1819 int i;
1820 cds_context_type *cds_ctx;
1821
1822 if (NULL == hdd_ctx)
1823 return;
1824
1825 if (NULL == hdd_ctx->config) {
1826 /* Do nothing if hdd_ctx is invalid */
1827 hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
1828 return;
1829 }
1830
1831 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1832
1833 if (!cds_ctx) {
1834 hdd_err("Invalid CDS Context");
1835 return;
1836 }
1837
1838 for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
1839 switch (i) {
1840 case OL_TX_WMM_AC_BE:
1841 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
1842 break;
1843 case OL_TX_WMM_AC_BK:
1844 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
1845 break;
1846 case OL_TX_WMM_AC_VI:
1847 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
1848 break;
1849 case OL_TX_WMM_AC_VO:
1850 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
1851 break;
1852 default:
1853 tx_sched_wrr_ac = NULL;
1854 break;
1855 }
1856
1857 hdd_string_to_u8_array(tx_sched_wrr_ac,
1858 tx_sched_wrr_param,
1859 &num_entries,
1860 sizeof(tx_sched_wrr_param));
1861
1862 if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
1863 cds_ctx->ac_specs[i].wrr_skip_weight =
1864 tx_sched_wrr_param[0];
1865 cds_ctx->ac_specs[i].credit_threshold =
1866 tx_sched_wrr_param[1];
1867 cds_ctx->ac_specs[i].send_limit =
1868 tx_sched_wrr_param[2];
1869 cds_ctx->ac_specs[i].credit_reserve =
1870 tx_sched_wrr_param[3];
1871 cds_ctx->ac_specs[i].discard_weight =
1872 tx_sched_wrr_param[4];
1873 }
1874
1875 num_entries = 0;
1876 }
1877}
1878
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001879#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001880static enum policy_mgr_con_mode wlan_hdd_get_mode_for_non_connected_vdev(
1881 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
1882{
1883 hdd_adapter_t *adapter = NULL;
1884 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1885
1886 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
1887 if (!adapter) {
1888 hdd_err("Adapter is NULL");
1889 return PM_MAX_NUM_OF_MODE;
1890 }
1891
1892 return policy_mgr_convert_device_mode_to_qdf_type(
1893 adapter->device_mode);
1894}
1895
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001896static void hdd_register_policy_manager_callback(
1897 struct wlan_objmgr_psoc *psoc)
1898{
1899 struct policy_mgr_hdd_cbacks hdd_cbacks;
1900 hdd_cbacks.sap_restart_chan_switch_cb =
1901 sap_restart_chan_switch_cb;
1902 hdd_cbacks.wlan_hdd_get_channel_for_sap_restart =
1903 wlan_hdd_get_channel_for_sap_restart;
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001904 hdd_cbacks.get_mode_for_non_connected_vdev =
1905 wlan_hdd_get_mode_for_non_connected_vdev;
1906
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001907 if (QDF_STATUS_SUCCESS !=
1908 policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {
1909 hdd_err("HDD callback registration with policy manager failed");
1910 }
1911}
1912#else
1913static void hdd_register_policy_manager_callback(
1914 struct wlan_objmgr_psoc *psoc)
1915{
1916}
1917#endif
1918
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001919#ifdef WLAN_FEATURE_NAN_CONVERGENCE
1920static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1921{
1922 struct nan_callbacks cb_obj = {0};
1923
1924 cb_obj.ndi_open = hdd_ndi_open;
1925 cb_obj.ndi_close = hdd_ndi_close;
1926 cb_obj.ndi_start = hdd_ndi_start;
1927 cb_obj.ndi_delete = hdd_ndi_delete;
1928 cb_obj.drv_ndi_create_rsp_handler = hdd_ndi_drv_ndi_create_rsp_handler;
1929 cb_obj.drv_ndi_delete_rsp_handler = hdd_ndi_drv_ndi_delete_rsp_handler;
1930
Naveen Rawat37f62c82017-03-26 22:24:43 -07001931 cb_obj.new_peer_ind = hdd_ndp_new_peer_handler;
1932 cb_obj.get_peer_idx = hdd_ndp_get_peer_idx;
Naveen Rawatb3143ea2017-03-26 22:25:46 -07001933 cb_obj.peer_departed_ind = hdd_ndp_peer_departed_handler;
Naveen Rawat37f62c82017-03-26 22:24:43 -07001934
Naveen Rawatcb5c5402017-03-22 10:12:19 -07001935 os_if_nan_register_hdd_callbacks(hdd_ctx->hdd_psoc, &cb_obj);
1936}
1937#else
1938static void hdd_nan_register_callbacks(hdd_context_t *hdd_ctx)
1939{
1940}
1941#endif
1942
gbian62edd7e2017-03-07 13:12:13 +08001943/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301944 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1945 * @hdd_ctx: HDD context
1946 * @adapter: HDD adapter
1947 * @reinit: flag to indicate from SSR or normal path
1948 *
1949 * This function maintains the driver state machine it will be invoked from
1950 * startup, reinit and change interface. Depending on the driver state shall
1951 * perform the opening of the modules.
1952 *
1953 * Return: 0 for success; non-zero for failure
1954 */
1955int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1956 bool reinit)
1957{
1958 int ret;
1959 qdf_device_t qdf_dev;
1960 QDF_STATUS status;
1961 p_cds_contextType p_cds_context;
1962 bool unint = false;
1963 void *hif_ctx;
1964
1965 ENTER();
1966
1967 p_cds_context = cds_get_global_context();
1968 if (!p_cds_context) {
1969 hdd_err("Global Context is NULL");
1970 QDF_ASSERT(0);
1971 return -EINVAL;
1972 }
1973
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001974 hdd_debug("start modules called in state! :%d reinit: %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05301975 hdd_ctx->driver_status, reinit);
1976
1977 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1978 if (!qdf_dev) {
1979 hdd_err("QDF Device Context is Invalid return");
1980 return -EINVAL;
1981 }
1982
1983 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301984 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301985
1986 if (QDF_TIMER_STATE_RUNNING ==
1987 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1988
1989 hdd_set_idle_ps_config(hdd_ctx, false);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08001990 hdd_debug("Interface change Timer running Stop timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05301991 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1992 }
1993
1994 switch (hdd_ctx->driver_status) {
1995 case DRIVER_MODULES_UNINITIALIZED:
1996 unint = true;
1997 /* Fall through dont add break here */
1998 case DRIVER_MODULES_CLOSED:
1999 if (!reinit && !unint) {
2000 ret = pld_power_on(qdf_dev->dev);
2001 if (ret) {
2002 hdd_err("Failed to Powerup the device: %d", ret);
2003 goto release_lock;
2004 }
2005 }
2006 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
2007 qdf_dev->bus_type,
2008 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
2009 HIF_ENABLE_TYPE_PROBE);
2010 if (ret) {
2011 hdd_err("Failed to open hif: %d", ret);
2012 goto power_down;
2013 }
2014
2015 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05302016 if (!hif_ctx) {
2017 hdd_err("hif context is null!!");
2018 goto power_down;
2019 }
2020
Arun Khandavallifae92942016-08-01 13:31:08 +05302021 status = ol_cds_init(qdf_dev, hif_ctx);
2022 if (status != QDF_STATUS_SUCCESS) {
2023 hdd_err("No Memory to Create BMI Context :%d", status);
2024 goto hif_close;
2025 }
2026
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002027 ret = hdd_update_config(hdd_ctx);
2028 if (ret) {
2029 hdd_err("Failed to update configuration :%d", ret);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302030 goto ol_cds_free;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002031 }
2032
gbian62edd7e2017-03-07 13:12:13 +08002033 hdd_update_cds_ac_specs_params(hdd_ctx);
2034
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302035 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05302036 if (!QDF_IS_STATUS_SUCCESS(status)) {
2037 hdd_err("Failed to Open CDS: %d", status);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302038 goto ol_cds_free;
Arun Khandavallifae92942016-08-01 13:31:08 +05302039 }
2040
Mukul Sharma9d797a02017-01-05 20:26:03 +05302041 /* initalize components configurations after psoc open */
2042 ret = hdd_update_components_config(hdd_ctx);
2043 if (ret) {
2044 hdd_err("Failed to update components configs :%d",
2045 ret);
2046 goto close;
2047 }
2048
Naveen Rawatcb5c5402017-03-22 10:12:19 -07002049 /*
2050 * NAN compoenet requires certian operations like, open adapter,
2051 * close adapter, etc. to be initiated by HDD, for those
2052 * register HDD callbacks with UMAC's NAN componenet.
2053 */
2054 hdd_nan_register_callbacks(hdd_ctx);
2055
Arun Khandavallifae92942016-08-01 13:31:08 +05302056 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
2057
2058 status = cds_pre_enable(hdd_ctx->pcds_context);
2059 if (!QDF_IS_STATUS_SUCCESS(status)) {
2060 hdd_err("Failed to pre-enable CDS: %d", status);
2061 goto close;
2062 }
2063
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07002064 hdd_register_policy_manager_callback(
2065 hdd_ctx->hdd_psoc);
2066
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302067 hdd_update_hw_sw_info(hdd_ctx);
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05302068 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302069
Arun Khandavallifae92942016-08-01 13:31:08 +05302070 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2071 sme_register_ftm_msg_processor(hdd_ctx->hHal,
2072 hdd_ftm_mc_process_msg);
2073 break;
2074 }
2075 if (unint) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002076 hdd_debug("In phase-1 initialization don't enable modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05302077 break;
2078 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302079
2080 if (reinit) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08002081 if (hdd_ipa_uc_ssr_reinit(hdd_ctx)) {
2082 hdd_err("HDD IPA UC reinit failed");
2083 goto close;
2084 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302085 }
2086
Arun Khandavallifae92942016-08-01 13:31:08 +05302087 /* Fall through dont add break here */
2088 case DRIVER_MODULES_OPENED:
2089 if (!adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002090 hdd_err("adapter is Null");
Arun Khandavallifae92942016-08-01 13:31:08 +05302091 goto close;
2092 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05302093 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2094 hdd_err("in ftm mode, no need to configure cds modules");
2095 break;
2096 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302097 if (hdd_configure_cds(hdd_ctx, adapter)) {
2098 hdd_err("Failed to Enable cds modules");
2099 goto close;
2100 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05302101 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05302102 hdd_info("Driver Modules Successfully Enabled");
2103 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
2104 break;
2105 case DRIVER_MODULES_ENABLED:
2106 hdd_info("Driver modules already Enabled");
2107 break;
2108 default:
2109 hdd_err("WLAN start invoked in wrong state! :%d\n",
2110 hdd_ctx->driver_status);
2111 goto release_lock;
2112 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302113 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302114 mutex_unlock(&hdd_ctx->iface_change_lock);
2115 EXIT();
2116 return 0;
2117
2118close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302119 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05302120
2121ol_cds_free:
2122 ol_cds_free();
2123
2124hif_close:
2125 hdd_hif_close(p_cds_context->pHIFContext);
2126power_down:
2127 if (!reinit && !unint)
2128 pld_power_off(qdf_dev->dev);
2129release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302130 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302131 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302132 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05302133 return -EINVAL;
2134}
2135
Naveen Rawat910726a2017-03-06 11:42:51 -08002136#ifdef WIFI_POS_CONVERGED
2137static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2138{
2139 int ret = os_if_wifi_pos_register_nl();
2140
2141 if (ret)
2142 hdd_err("os_if_wifi_pos_register_nl failed");
2143
2144 return ret;
2145}
2146
2147static int hdd_deactivate_wifi_pos(void)
2148{
2149 int ret = os_if_wifi_pos_deregister_nl();
2150
2151 if (ret)
2152 hdd_err("os_if_wifi_pos_deregister_nl failed");
2153
2154 return ret;
2155}
2156
2157/**
2158 * hdd_populate_wifi_pos_cfg - populates wifi_pos parameters
2159 * @hdd_ctx: hdd context
2160 *
2161 * Return: status of operation
2162 */
2163static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2164{
2165 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2166 struct hdd_config *cfg = hdd_ctx->config;
2167
2168 wifi_pos_set_oem_target_type(psoc, hdd_ctx->target_type);
2169 wifi_pos_set_oem_fw_version(psoc, hdd_ctx->target_fw_version);
2170 wifi_pos_set_drv_ver_major(psoc, QWLAN_VERSION_MAJOR);
2171 wifi_pos_set_drv_ver_minor(psoc, QWLAN_VERSION_MINOR);
2172 wifi_pos_set_drv_ver_patch(psoc, QWLAN_VERSION_PATCH);
2173 wifi_pos_set_drv_ver_build(psoc, QWLAN_VERSION_BUILD);
2174 wifi_pos_set_dwell_time_min(psoc, cfg->nNeighborScanMinChanTime);
2175 wifi_pos_set_dwell_time_max(psoc, cfg->nNeighborScanMaxChanTime);
2176}
2177#else
2178static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2179{
2180 return oem_activate_service(hdd_ctx);
2181}
2182
2183static int hdd_deactivate_wifi_pos(void)
2184{
2185 return 0;
2186}
2187
2188static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2189{
2190}
2191#endif
2192
Arun Khandavallifae92942016-08-01 13:31:08 +05302193/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 * __hdd_open() - HDD Open function
2195 * @dev: Pointer to net_device structure
2196 *
2197 * This is called in response to ifconfig up
2198 *
2199 * Return: 0 for success; non-zero for failure
2200 */
2201static int __hdd_open(struct net_device *dev)
2202{
2203 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2204 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2205 int ret;
2206
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002207 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302208 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05302209 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210
2211 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302212 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002213 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215
Arun Khandavallifae92942016-08-01 13:31:08 +05302216 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
2217 if (ret) {
2218 hdd_err("Failed to start WLAN modules return");
2219 return -ret;
2220 }
2221
2222
2223 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2224 ret = hdd_start_adapter(adapter);
2225 if (ret) {
2226 hdd_err("Failed to start adapter :%d",
2227 adapter->device_mode);
2228 return ret;
2229 }
2230 }
2231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2233 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302234 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235 /* Enable TX queues only when we are connected */
2236 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05302237 WLAN_START_ALL_NETIF_QUEUE,
2238 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002239 }
2240
Naveen Rawat286def52016-09-23 15:38:02 -07002241 /* Enable carrier and transmit queues for NDI */
2242 if (WLAN_HDD_IS_NDI(adapter)) {
2243 hdd_notice("Enabling Tx Queues");
2244 wlan_hdd_netif_queue_control(adapter,
2245 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
2246 WLAN_CONTROL_PATH);
2247 }
2248
Naveen Rawat910726a2017-03-06 11:42:51 -08002249 hdd_populate_wifi_pos_cfg(hdd_ctx);
2250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251 return ret;
2252}
2253
Arun Khandavallifae92942016-08-01 13:31:08 +05302254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002255/**
2256 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
2257 * @dev: Pointer to net_device structure
2258 *
2259 * This is called in response to ifconfig up
2260 *
2261 * Return: 0 for success; non-zero for failure
2262 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002263static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264{
2265 int ret;
2266
2267 cds_ssr_protect(__func__);
2268 ret = __hdd_open(dev);
2269 cds_ssr_unprotect(__func__);
2270
2271 return ret;
2272}
2273
2274/**
2275 * __hdd_stop() - HDD stop function
2276 * @dev: Pointer to net_device structure
2277 *
2278 * This is called in response to ifconfig down
2279 *
2280 * Return: 0 for success; non-zero for failure
2281 */
2282static int __hdd_stop(struct net_device *dev)
2283{
2284 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2285 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2286 int ret;
2287
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002288 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302290 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291 adapter->sessionId, adapter->device_mode));
2292
2293 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302294 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002296
2297 /* Nothing to be done if the interface is not opened */
2298 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002299 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 return -ENODEV;
2301 }
2302
2303 /* Make sure the interface is marked as closed */
2304 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002305 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002306
2307 /*
2308 * Disable TX on the interface, after this hard_start_xmit() will not
2309 * be called on that interface
2310 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002311 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2313 WLAN_CONTROL_PATH);
2314
2315 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002316 * NAN data interface is different in some sense. The traffic on NDI is
2317 * bursty in nature and depends on the need to transfer. The service
2318 * layer may down the interface after the usage and up again when
2319 * required. In some sense, the NDI is expected to be available
2320 * (like SAP) iface until NDI delete request is issued by the service
2321 * layer. Skip BSS termination and adapter deletion for NAN Data
2322 * interface (NDI).
2323 */
2324 if (WLAN_HDD_IS_NDI(adapter))
2325 return 0;
2326
2327 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 * The interface is marked as down for outside world (aka kernel)
2329 * But the driver is pretty much alive inside. The driver needs to
2330 * tear down the existing connection on the netdev (session)
2331 * cleanup the data pipes and wait until the control plane is stabilized
2332 * for this interface. The call also needs to wait until the above
2333 * mentioned actions are completed before returning to the caller.
2334 * Notice that the hdd_stop_adapter is requested not to close the session
2335 * That is intentional to be able to scan if it is a STA/P2P interface
2336 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302337 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338
2339 /* DeInit the adapter. This ensures datapath cleanup as well */
2340 hdd_deinit_adapter(hdd_ctx, adapter, true);
2341
Arun Khandavallifae92942016-08-01 13:31:08 +05302342
2343 /*
2344 * Find if any iface is up. If any iface is up then can't put device to
2345 * sleep/power save mode
2346 */
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05302347 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002348 hdd_debug("Closing all modules from the hdd_stop");
Arun Khandavallifae92942016-08-01 13:31:08 +05302349 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2350 hdd_ctx->config->iface_change_wait_time
2351 * 50000);
2352 }
2353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 EXIT();
2355 return 0;
2356}
2357
2358/**
2359 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2360 * @dev: pointer to net_device structure
2361 *
2362 * This is called in response to ifconfig down
2363 *
2364 * Return: 0 for success and error number for failure
2365 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002366static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367{
2368 int ret;
2369
2370 cds_ssr_protect(__func__);
2371 ret = __hdd_stop(dev);
2372 cds_ssr_unprotect(__func__);
2373
2374 return ret;
2375}
2376
2377/**
2378 * __hdd_uninit() - HDD uninit function
2379 * @dev: Pointer to net_device structure
2380 *
2381 * This is called during the netdev unregister to uninitialize all data
2382 * associated with the device
2383 *
2384 * Return: None
2385 */
2386static void __hdd_uninit(struct net_device *dev)
2387{
2388 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2389
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002390 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391
2392 do {
2393 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002394 hdd_err("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 break;
2396 }
2397
2398 if (NULL == adapter->pHddCtx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002399 hdd_err("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 break;
2401 }
2402
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002403 if (dev != adapter->dev)
2404 hdd_err("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405
2406 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2407
2408 /* after uninit our adapter structure will no longer be valid */
2409 adapter->dev = NULL;
2410 adapter->magic = 0;
2411 } while (0);
2412
2413 EXIT();
2414}
2415
2416/**
2417 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2418 * @dev: pointer to net_device structure
2419 *
2420 * This is called during the netdev unregister to uninitialize all data
2421 * associated with the device
2422 *
2423 * Return: none
2424 */
2425static void hdd_uninit(struct net_device *dev)
2426{
2427 cds_ssr_protect(__func__);
2428 __hdd_uninit(dev);
2429 cds_ssr_unprotect(__func__);
2430}
2431
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002432static int hdd_open_cesium_nl_sock(void)
2433{
2434#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2435 struct netlink_kernel_cfg cfg = {
2436 .groups = WLAN_NLINK_MCAST_GRP_ID,
2437 .input = NULL
2438 };
2439#endif
2440 int ret = 0;
2441
2442#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2443 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2444#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2445 THIS_MODULE,
2446#endif
2447 &cfg);
2448#else
2449 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2450 WLAN_NLINK_MCAST_GRP_ID,
2451 NULL, NULL, THIS_MODULE);
2452#endif
2453
2454 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002455 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002456 ret = -ECONNREFUSED;
2457 }
2458
2459 return ret;
2460}
2461
2462static void hdd_close_cesium_nl_sock(void)
2463{
2464 if (NULL != cesium_nl_srv_sock) {
2465 netlink_kernel_release(cesium_nl_srv_sock);
2466 cesium_nl_srv_sock = NULL;
2467 }
2468}
2469
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470/**
2471 * __hdd_set_mac_address() - set the user specified mac address
2472 * @dev: Pointer to the net device.
2473 * @addr: Pointer to the sockaddr.
2474 *
2475 * This function sets the user specified mac address using
2476 * the command ifconfig wlanX hw ether <mac adress>.
2477 *
2478 * Return: 0 for success, non zero for failure
2479 */
2480static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2481{
2482 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2483 hdd_context_t *hdd_ctx;
2484 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302485 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 int ret;
2487
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002488 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489
2490 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2491 ret = wlan_hdd_validate_context(hdd_ctx);
2492 if (0 != ret)
2493 return ret;
2494
2495 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2496 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2497
2498 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302499 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002500}
2501
2502/**
2503 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2504 * function from SSR
2505 * @dev: pointer to net_device structure
2506 * @addr: Pointer to the sockaddr
2507 *
2508 * This function sets the user specified mac address using
2509 * the command ifconfig wlanX hw ether <mac adress>.
2510 *
2511 * Return: 0 for success.
2512 */
2513static int hdd_set_mac_address(struct net_device *dev, void *addr)
2514{
2515 int ret;
2516
2517 cds_ssr_protect(__func__);
2518 ret = __hdd_set_mac_address(dev, addr);
2519 cds_ssr_unprotect(__func__);
2520
2521 return ret;
2522}
2523
2524uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2525{
2526 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302527 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2529 break;
2530 }
2531
Anurag Chouhan6d760662016-02-20 16:05:43 +05302532 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 return NULL;
2534
2535 hdd_ctx->config->intfAddrMask |= (1 << i);
2536 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2537}
2538
2539void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2540{
2541 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302542 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 if (!memcmp(releaseAddr,
2544 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2545 6)) {
2546 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2547 break;
2548 }
2549 }
2550 return;
2551}
2552
2553#ifdef WLAN_FEATURE_PACKET_FILTERING
2554/**
2555 * __hdd_set_multicast_list() - set the multicast address list
2556 * @dev: Pointer to the WLAN device.
2557 * @skb: Pointer to OS packet (sk_buff).
2558 *
2559 * This funciton sets the multicast address list.
2560 *
2561 * Return: None
2562 */
2563static void __hdd_set_multicast_list(struct net_device *dev)
2564{
2565 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 int i = 0, status;
2567 struct netdev_hw_addr *ha;
2568 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302569 struct pmo_mc_addr_list_params *mc_list_request = NULL;
2570 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2571 int mc_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002573 ENTER_DEV(dev);
Anurag Chouhan6d760662016-02-20 16:05:43 +05302574 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302575 goto out;
Mukul Sharma51c44942015-10-30 19:30:19 +05302576
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302578 if (0 != status)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302579 goto out;
2580
2581 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
2582 if (!mc_list_request) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002583 hdd_err("Cannot allocate mc_list_request");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302584 goto out;
2585 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586
2587 if (dev->flags & IFF_ALLMULTI) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002588 hdd_debug("allow all multicast frames");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302589 hdd_disable_and_flush_mc_addr_list(adapter,
2590 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591 } else {
2592 mc_count = netdev_mc_count(dev);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302593 if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002594 hdd_debug("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302595 pmo_ucfg_max_mc_addr_supported(psoc));
2596 hdd_disable_and_flush_mc_addr_list(adapter,
2597 pmo_mc_list_change_notify);
2598 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 netdev_for_each_mc_addr(ha, dev) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002601 hdd_debug("ha_addr[%d] "MAC_ADDRESS_STR,
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302602 i, MAC_ADDR_ARRAY(ha->addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 if (i == mc_count)
2604 break;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302605 memset(&(mc_list_request->mc_addr[i].bytes),
2606 0, ETH_ALEN);
2607 memcpy(&(mc_list_request->mc_addr[i].bytes),
2608 ha->addr, ETH_ALEN);
2609 hdd_info("mlist[%d] = %pM", i,
2610 mc_list_request->mc_addr[i].bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611 i++;
2612 }
2613 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302614
2615 mc_list_request->psoc = psoc;
2616 mc_list_request->vdev_id = adapter->sessionId;
2617 mc_list_request->count = mc_count;
2618 status = hdd_cache_mc_addr_list(mc_list_request);
2619 if (status == 0) {
2620 hdd_enable_mc_addr_filtering(adapter,
2621 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002622 } else {
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302623 hdd_err("error while caching mc list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302625out:
2626 if (mc_list_request)
2627 qdf_mem_free(mc_list_request);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302628 EXIT();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630}
2631
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633/**
2634 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2635 * @dev: pointer to net_device
2636 *
2637 * Return: none
2638 */
2639static void hdd_set_multicast_list(struct net_device *dev)
2640{
2641 cds_ssr_protect(__func__);
2642 __hdd_set_multicast_list(dev);
2643 cds_ssr_unprotect(__func__);
2644}
2645#endif
2646
2647/**
2648 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2649 * @dev: Pointer to the WLAN device.
2650 * @skb: Pointer to OS packet (sk_buff).
2651 *
2652 * This function is registered with the Linux OS for network
2653 * core to decide which queue to use first.
2654 *
2655 * Return: ac, Queue Index/access category corresponding to UP in IP header
2656 */
2657static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2658#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2659 , void *accel_priv
2660#endif
2661#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2662 , select_queue_fallback_t fallback
2663#endif
2664)
2665{
2666 return hdd_wmm_select_queue(dev, skb);
2667}
2668
2669static struct net_device_ops wlan_drv_ops = {
2670 .ndo_open = hdd_open,
2671 .ndo_stop = hdd_stop,
2672 .ndo_uninit = hdd_uninit,
2673 .ndo_start_xmit = hdd_hard_start_xmit,
2674 .ndo_tx_timeout = hdd_tx_timeout,
2675 .ndo_get_stats = hdd_get_stats,
2676 .ndo_do_ioctl = hdd_ioctl,
2677 .ndo_set_mac_address = hdd_set_mac_address,
2678 .ndo_select_queue = hdd_select_queue,
2679#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681#endif
2682};
2683
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002684/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2685static struct net_device_ops wlan_mon_drv_ops = {
2686 .ndo_open = hdd_mon_open,
2687 .ndo_stop = hdd_stop,
2688 .ndo_get_stats = hdd_get_stats,
2689};
2690
2691/**
2692 * hdd_set_station_ops() - update net_device ops for monitor mode
2693 * @pWlanDev: Handle to struct net_device to be updated.
2694 * Return: None
2695 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696void hdd_set_station_ops(struct net_device *pWlanDev)
2697{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002698 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2699 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2700 else
2701 pWlanDev->netdev_ops = &wlan_drv_ops;
2702}
2703
Komal Seelama89be8d2016-09-29 11:09:26 +05302704#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302705/**
2706 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2707 * @hdd_ctx: HDD context
2708 *
2709 * Return: None
2710 */
2711static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2712{
2713 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2714
2715 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302716 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302717 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302718}
2719
2720/**
2721 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2722 * @hdd_ctx: HDD Context
2723 *
2724 * Return: None
2725 */
2726static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2727{
2728 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2729
2730 qdf_runtime_lock_deinit(ctx->scan);
2731 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302732 qdf_runtime_lock_deinit(ctx->roc);
2733 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302734 qdf_runtime_lock_deinit(ctx->dfs);
2735 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302736}
2737
Komal Seelama89be8d2016-09-29 11:09:26 +05302738static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2739{
2740 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2741
2742 ctx->connect = qdf_runtime_lock_init("connect");
2743}
2744
2745static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2746{
2747 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2748
2749 qdf_runtime_lock_deinit(ctx->connect);
2750 ctx->connect = NULL;
2751}
2752#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302753static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2754static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302755static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2756static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2757#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002758/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002759 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2760 * @hdd_ctx: global hdd context
2761 * @macAddr: mac address to assign to the interface
2762 * @name: User-visible name of the interface
2763 *
2764 * hdd adapter pointer would point to the netdev->priv space, this function
2765 * would retrive the pointer, and setup the hdd adapter configuration.
2766 *
2767 * Return: the pointer to hdd adapter, otherwise NULL
2768 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2770 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002771 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 const char *name)
2773{
2774 struct net_device *pWlanDev = NULL;
2775 hdd_adapter_t *adapter = NULL;
2776 /*
2777 * cfg80211 initialization and registration....
2778 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002779 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2780#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2781 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002783 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2784 hdd_mon_mode_ether_setup : ether_setup),
2785 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786
2787 if (pWlanDev != NULL) {
2788
2789 /* Save the pointer to the net_device in the HDD adapter */
2790 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2791
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302792 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793
2794 adapter->dev = pWlanDev;
2795 adapter->pHddCtx = hdd_ctx;
2796 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302797 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798
2799 init_completion(&adapter->session_open_comp_var);
2800 init_completion(&adapter->session_close_comp_var);
2801 init_completion(&adapter->disconnect_comp_var);
2802 init_completion(&adapter->linkup_event_var);
2803 init_completion(&adapter->cancel_rem_on_chan_var);
2804 init_completion(&adapter->rem_on_chan_ready_event);
2805 init_completion(&adapter->sta_authorized_event);
2806 init_completion(&adapter->offchannel_tx_event);
2807 init_completion(&adapter->tx_action_cnf_event);
2808#ifdef FEATURE_WLAN_TDLS
2809 init_completion(&adapter->tdls_add_station_comp);
2810 init_completion(&adapter->tdls_del_station_comp);
2811 init_completion(&adapter->tdls_mgmt_comp);
2812 init_completion(&adapter->tdls_link_establish_req_comp);
2813#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002814 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002815 init_completion(&adapter->change_country_code);
2816
2817
2818 init_completion(&adapter->scan_info.abortscan_event_var);
2819
2820 adapter->offloads_configured = false;
2821 adapter->isLinkUpSvcNeeded = false;
2822 adapter->higherDtimTransition = true;
2823 /* Init the net_device structure */
2824 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2825
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302826 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002827 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302828 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 sizeof(tSirMacAddr));
2830 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831
2832 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2833 pWlanDev->features |=
2834 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2835 pWlanDev->features |= NETIF_F_RXCSUM;
2836
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002837 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 hdd_set_station_ops(adapter->dev);
2840
2841 pWlanDev->destructor = free_netdev;
2842 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002843 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002844 adapter->wdev.wiphy = hdd_ctx->wiphy;
2845 adapter->wdev.netdev = pWlanDev;
2846 /* set pWlanDev's parent to underlying device */
2847 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2848 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302849 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002850 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302851 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 }
2853
2854 return adapter;
2855}
2856
Jeff Johnson590e2012016-10-05 16:16:24 -07002857static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2858 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002859{
2860 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002861
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002862 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2864 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002865 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302866 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867 }
2868 }
2869 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002870 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302871 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 }
2873 } else {
2874 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002875 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302876 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 }
2878 }
2879 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2880
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302881 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882}
2883
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002884QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885{
2886 hdd_adapter_t *adapter = pContext;
2887
2888 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002889 hdd_err("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302890 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 }
2892
2893 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08002894 hdd_err("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302895 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896 }
2897
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002898 /*
2899 * For NAN Data interface, the close session results in the final
2900 * indication to the userspace
2901 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002902 if (adapter->device_mode == QDF_NDI_MODE)
2903 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002904
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 /*
2908 * We can be blocked while waiting for scheduled work to be
2909 * flushed, and the adapter structure can potentially be freed, in
2910 * which case the magic will have been reset. So make sure the
2911 * magic is still good, and hence the adapter structure is still
2912 * valid, before signaling completion
2913 */
2914 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2915 complete(&adapter->session_close_comp_var);
2916
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302917 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918}
2919
Krunal Soni8c37e322016-02-03 16:08:37 -08002920/**
2921 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2922 * @adapter: pointer to device adapter
Krunal Soni8c37e322016-02-03 16:08:37 -08002923 *
2924 * This routine will check the mode of adapter and if it is required then it
2925 * will initialize the TDLS operations
2926 *
2927 * Return: QDF_STATUS
2928 */
2929#ifdef FEATURE_WLAN_TDLS
Dustin Brownd28772b2017-03-17 14:16:07 -07002930static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002931{
Dustin Brownd28772b2017-03-17 14:16:07 -07002932 if (adapter->device_mode == QDF_IBSS_MODE)
2933 return QDF_STATUS_SUCCESS;
2934
2935 if (wlan_hdd_tdls_init(adapter)) {
2936 hdd_err("wlan_hdd_tdls_init failed");
2937 return QDF_STATUS_E_FAILURE;
Krunal Soni8c37e322016-02-03 16:08:37 -08002938 }
Dustin Brownd28772b2017-03-17 14:16:07 -07002939 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2940
Krunal Soni8c37e322016-02-03 16:08:37 -08002941 return QDF_STATUS_SUCCESS;
2942}
2943#else
Dustin Brownd28772b2017-03-17 14:16:07 -07002944static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002945{
2946 return QDF_STATUS_SUCCESS;
2947}
2948#endif
2949
Dustin Brownd28772b2017-03-17 14:16:07 -07002950int hdd_vdev_ready(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951{
Dustin Brownd28772b2017-03-17 14:16:07 -07002952 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953
Dustin Brownd28772b2017-03-17 14:16:07 -07002954 status = pmo_vdev_ready(adapter->hdd_vdev);
2955
2956 return qdf_status_to_os_return(status);
2957}
2958
2959int hdd_vdev_destroy(hdd_adapter_t *adapter)
2960{
2961 QDF_STATUS status;
2962 int errno;
2963 hdd_context_t *hdd_ctx;
2964 unsigned long rc;
2965
2966 hdd_info("destroying vdev %d", adapter->sessionId);
2967
2968 /* vdev created sanity check */
2969 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2970 hdd_err("vdev for Id %d does not exist", adapter->sessionId);
2971 return -EINVAL;
2972 }
2973
Dustin Brown0d2eeae2017-03-24 15:21:32 -07002974 /* do vdev logical destroy via objmgr */
2975 errno = hdd_objmgr_destroy_vdev(adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07002976 if (errno) {
2977 hdd_err("failed to destroy objmgr vdev: %d", errno);
2978 return errno;
2979 }
2980
2981 /* close sme session (destroy vdev in firmware via legacy API) */
2982 INIT_COMPLETION(adapter->session_close_comp_var);
2983 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2984 status = sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2985 hdd_sme_close_session_callback, adapter);
2986 if (QDF_IS_STATUS_ERROR(status)) {
2987 hdd_err("failed to close sme session: %d", status);
2988 return qdf_status_to_os_return(status);
2989 }
2990
2991 /* block on a completion variable until sme session is closed */
2992 rc = wait_for_completion_timeout(
2993 &adapter->session_close_comp_var,
2994 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2995 if (!rc) {
2996 hdd_err("timed out waiting for close sme session: %ld", rc);
2997 if (adapter->device_mode == QDF_NDI_MODE)
2998 hdd_ndp_session_end_handler(adapter);
2999 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
3000 return -ETIMEDOUT;
3001 }
3002
Dustin Brown0d2eeae2017-03-24 15:21:32 -07003003 /* now that sme session is closed, allow physical vdev destroy */
3004 errno = hdd_objmgr_release_vdev(adapter);
3005 if (errno) {
3006 hdd_err("failed to release objmgr vdev: %d", errno);
3007 return errno;
3008 }
3009
Dustin Brownd28772b2017-03-17 14:16:07 -07003010 hdd_info("vdev destroyed successfully");
3011
3012 return 0;
3013}
3014
3015int hdd_vdev_create(hdd_adapter_t *adapter)
3016{
3017 QDF_STATUS status;
3018 int errno;
3019 hdd_context_t *hdd_ctx;
3020 uint32_t type;
3021 uint32_t sub_type;
3022 unsigned long rc;
3023
3024 hdd_info("creating new vdev");
3025
3026 /* determine vdev (sub)type */
3027 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303028 if (QDF_STATUS_SUCCESS != status) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003029 hdd_err("failed to get vdev type: %d", status);
3030 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003032
3033 /* do vdev create via objmgr */
3034 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown7d043f62017-03-27 12:07:36 -07003035 errno = hdd_objmgr_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07003036 if (errno) {
3037 hdd_err("failed to create objmgr vdev: %d", errno);
3038 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003040
3041 /* Open a SME session (prepare vdev in firmware via legacy API) */
3042 INIT_COMPLETION(adapter->session_open_comp_var);
3043 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
3044 (uint8_t *)&adapter->macAddressCurrent,
3045 adapter->sessionId, type, sub_type);
3046 if (QDF_IS_STATUS_ERROR(status)) {
3047 hdd_err("failed to open sme session: %d", status);
3048 errno = qdf_status_to_os_return(status);
3049 goto objmgr_vdev_destroy;
3050 }
3051
3052 /* block on a completion variable until sme session is opened */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053 rc = wait_for_completion_timeout(
3054 &adapter->session_open_comp_var,
3055 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3056 if (!rc) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003057 hdd_err("timed out waiting for open sme session: %ld", rc);
3058 errno = -ETIMEDOUT;
3059 goto objmgr_vdev_destroy;
3060 }
3061
3062 /* firmware ready for component communication, raise vdev_ready event */
3063 errno = hdd_vdev_ready(adapter);
3064 if (errno) {
3065 hdd_err("failed to dispatch vdev ready event: %d", errno);
3066 goto hdd_vdev_destroy;
3067 }
3068
3069 hdd_info("vdev %d created successfully", adapter->sessionId);
3070
3071 return 0;
3072
3073 /*
3074 * Due to legacy constraints, we need to destroy in the same order as
3075 * create. So, split error handling into 2 cases to accommodate.
3076 */
3077
3078objmgr_vdev_destroy:
Dustin Brown7d043f62017-03-27 12:07:36 -07003079 QDF_BUG(!hdd_objmgr_release_and_destroy_vdev(adapter));
Dustin Brownd28772b2017-03-17 14:16:07 -07003080
3081 return errno;
3082
3083hdd_vdev_destroy:
3084 QDF_BUG(!hdd_vdev_destroy(adapter));
3085
3086 return errno;
3087}
3088
3089QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
3090{
3091 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
3092 hdd_context_t *hdd_ctx;
3093 QDF_STATUS status;
3094 int ret_val;
3095
3096 ret_val = hdd_vdev_create(adapter);
3097 if (ret_val) {
3098 hdd_err("failed to create vdev: %d", ret_val);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303099 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 }
3101
Dustin Brownd28772b2017-03-17 14:16:07 -07003102 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3103 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
3104 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Naveen Rawata410c5a2016-09-19 14:22:33 -07003105 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Dustin Brownd28772b2017-03-17 14:16:07 -07003106
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107 /* Register wireless extensions */
Dustin Brownd28772b2017-03-17 14:16:07 -07003108 status = hdd_register_wext(adapter->dev);
3109 if (QDF_IS_STATUS_ERROR(status)) {
3110 hdd_err("failed to register wireless extensions: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111 goto error_register_wext;
3112 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003114 /* Set the Connection State to Not Connected */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003115 hdd_debug("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3117
Deepak Dhamdherea2785822016-11-17 01:17:45 -08003118 /* set fast roaming capability in sme session */
3119 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
3120 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003121 /* Set the default operation channel */
3122 pHddStaCtx->conn_info.operationChannel =
3123 hdd_ctx->config->OperatingChannel;
3124
3125 /* Make the default Auth Type as OPEN */
3126 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3127
3128 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303129 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003130 hdd_err("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 status, status);
3132 goto error_init_txrx;
3133 }
3134
3135 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3136
3137 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303138 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003139 hdd_err("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140 status, status);
3141 goto error_wmm_init;
3142 }
3143
3144 set_bit(WMM_INIT_DONE, &adapter->event_flags);
3145
3146 ret_val = wma_cli_set_command(adapter->sessionId,
3147 WMI_PDEV_PARAM_BURST_ENABLE,
3148 hdd_ctx->config->enableSifsBurst,
3149 PDEV_CMD);
Dustin Brownd28772b2017-03-17 14:16:07 -07003150 if (ret_val)
3151 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152
Dustin Brownd28772b2017-03-17 14:16:07 -07003153 status = hdd_check_and_init_tdls(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08003154 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303157 status = hdd_lro_enable(hdd_ctx, adapter);
3158 if (status != QDF_STATUS_SUCCESS)
3159 goto error_lro_enable;
3160
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303161 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303163error_lro_enable:
3164 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165error_tdls_init:
3166 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3167 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168error_wmm_init:
3169 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3170 hdd_deinit_tx_rx(adapter);
3171error_init_txrx:
Dustin Brownd28772b2017-03-17 14:16:07 -07003172 hdd_unregister_wext(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173error_register_wext:
Dustin Brownd28772b2017-03-17 14:16:07 -07003174 QDF_BUG(!hdd_vdev_destroy(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 return status;
3177}
3178
3179void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
3180{
3181 hdd_cfg80211_state_t *cfgState;
3182
3183 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3184
3185 if (NULL != cfgState->buf) {
3186 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187 rc = wait_for_completion_timeout(
3188 &adapter->tx_action_cnf_event,
3189 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3190 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003191 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05303192 /*
3193 * Inform tx status as FAILURE to upper layer and free
3194 * cfgState->buf
3195 */
3196 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 }
3198 }
3199 return;
3200}
3201
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303202/**
3203 * hdd_station_adapter_deinit() - De-initialize the station adapter
3204 * @hdd_ctx: global hdd context
3205 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07003206 * @rtnl_held: Used to indicate whether or not the caller is holding
3207 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303208 *
3209 * This function De-initializes the STA/P2P/OCB adapter.
3210 *
3211 * Return: None.
3212 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003213static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
3214 hdd_adapter_t *adapter,
3215 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303216{
3217 ENTER_DEV(adapter->dev);
3218
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303219 if (adapter->dev) {
3220 if (rtnl_held)
3221 adapter->dev->wireless_handlers = NULL;
3222 else {
3223 rtnl_lock();
3224 adapter->dev->wireless_handlers = NULL;
3225 rtnl_unlock();
3226 }
3227 }
3228
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303229 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
3230 hdd_deinit_tx_rx(adapter);
3231 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3232 }
3233
3234 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3235 hdd_wmm_adapter_close(adapter);
3236 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3237 }
3238
3239 hdd_cleanup_actionframe(hdd_ctx, adapter);
3240 wlan_hdd_tdls_exit(adapter);
3241
3242 EXIT();
3243}
3244
3245/**
3246 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
3247 * @hdd_ctx: global hdd context
3248 * @adapter: HDD adapter
3249 * @rtnl_held: the rtnl lock hold flag
3250 * This function De-initializes the AP/P2PGo adapter.
3251 *
3252 * Return: None.
3253 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003254static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
3255 hdd_adapter_t *adapter,
3256 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303257{
3258 ENTER_DEV(adapter->dev);
3259
3260 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3261 hdd_wmm_adapter_close(adapter);
3262 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3263 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003264 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303265
3266 hdd_cleanup_actionframe(hdd_ctx, adapter);
3267
3268 hdd_unregister_hostapd(adapter, rtnl_held);
3269
3270 EXIT();
3271}
3272
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3274 bool rtnl_held)
3275{
3276 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003279 case QDF_STA_MODE:
3280 case QDF_P2P_CLIENT_MODE:
3281 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303283 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 break;
3285 }
3286
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003287 case QDF_SAP_MODE:
3288 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 {
3290
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303291 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 break;
3293 }
3294
3295 default:
3296 break;
3297 }
3298
3299 EXIT();
3300}
3301
Jeff Johnson590e2012016-10-05 16:16:24 -07003302static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3303 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304{
3305 struct net_device *pWlanDev = NULL;
3306
3307 if (adapter)
3308 pWlanDev = adapter->dev;
3309 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003310 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311 return;
3312 }
3313
Rajeev Kumardca5f812016-02-04 17:28:06 -08003314 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303315
3316 if (adapter->scan_info.default_scan_ies) {
3317 qdf_mem_free(adapter->scan_info.default_scan_ies);
3318 adapter->scan_info.default_scan_ies = NULL;
3319 }
3320
Komal Seelama89be8d2016-09-29 11:09:26 +05303321 hdd_adapter_runtime_suspend_denit(adapter);
3322
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003323 /*
3324 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
3325 * the driver is almost closed and cannot handle either control
3326 * messages or data. However, unregister_netdevice() call above will
3327 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
3328 * to close the active connections (basically excites control path) which
3329 * is not right. Setting this flag helps hdd_stop() to recognize that
3330 * the interface is closed and restricts any operations on that
3331 */
3332 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3333
3334 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
3335 if (rtnl_held) {
3336 unregister_netdevice(pWlanDev);
3337 } else {
3338 unregister_netdev(pWlanDev);
3339 }
3340 /*
3341 * Note that the adapter is no longer valid at this point
3342 * since the memory has been reclaimed
3343 */
3344 }
3345}
3346
Jeff Johnson590e2012016-10-05 16:16:24 -07003347static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
3348 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349{
3350 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3351 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303352 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303354 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355 adapter = adapterNode->pAdapter;
3356 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303357 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003358 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303359 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360 }
3361 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3362 adapterNode = pNext;
3363 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303364 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003365}
Ryan Hsu07495ea2016-01-21 15:25:39 -08003366
Arun Khandavalli2358d522016-05-16 18:05:37 +05303367#ifdef CONFIG_FW_LOGS_BASED_ON_INI
3368/**
3369 * hdd_set_fw_log_params() - Set log parameters to FW
3370 * @hdd_ctx: HDD Context
3371 * @adapter: HDD Adapter
3372 *
3373 * This function set the FW Debug log level based on the INI.
3374 *
3375 * Return: None
3376 */
3377static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3378 hdd_adapter_t *adapter)
3379{
3380 uint8_t count = 0, numentries = 0,
3381 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3382 uint32_t value = 0;
3383 int ret;
3384
Arun Khandavallifae92942016-08-01 13:31:08 +05303385 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3386 (!hdd_ctx->config->enable_fw_log)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003387 hdd_debug("enable_fw_log not enabled in INI or in FTM mode return");
Arun Khandavalli2358d522016-05-16 18:05:37 +05303388 return;
3389 }
3390
Arun Khandavallifae92942016-08-01 13:31:08 +05303391 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303392 hdd_ctx->fw_log_settings.dl_type =
3393 hdd_ctx->config->enableFwLogType;
3394 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303395 WMI_DBGLOG_TYPE,
3396 hdd_ctx->config->enableFwLogType,
3397 DBG_CMD);
3398 if (ret != 0)
3399 hdd_err("Failed to enable FW log type ret %d",
3400 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303401
3402 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303403 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303404 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303405 WMI_DBGLOG_LOG_LEVEL,
3406 hdd_ctx->config->enableFwLogLevel,
3407 DBG_CMD);
3408 if (ret != 0)
3409 hdd_err("Failed to enable FW log level ret %d",
3410 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303411
3412 hdd_string_to_u8_array(
3413 hdd_ctx->config->enableFwModuleLogLevel,
3414 moduleloglevel,
3415 &numentries,
3416 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3417
3418 while (count < numentries) {
3419 /*
3420 * FW module log level input string looks like
3421 * below:
3422 * gFwDebugModuleLoglevel=<FW Module ID>,
3423 * <Log Level>,...
3424 * For example:
3425 * gFwDebugModuleLoglevel=
3426 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3427 * Above input string means :
3428 * For FW module ID 1 enable log level 0
3429 * For FW module ID 2 enable log level 1
3430 * For FW module ID 3 enable log level 2
3431 * For FW module ID 4 enable log level 3
3432 * For FW module ID 5 enable log level 4
3433 * For FW module ID 6 enable log level 5
3434 * For FW module ID 7 enable log level 6
3435 */
3436
Nishank Aggarwale239d962017-03-03 12:26:02 +05303437 if ((moduleloglevel[count] > WLAN_MODULE_ID_MAX)
3438 || (moduleloglevel[count + 1] > DBGLOG_LVL_MAX)) {
3439 hdd_err("Module id %d and dbglog level %d input length is more than max",
3440 moduleloglevel[count],
3441 moduleloglevel[count + 1]);
3442 return;
3443 }
3444
3445 value = moduleloglevel[count] << 16;
3446 value |= moduleloglevel[count + 1];
Arun Khandavalli2358d522016-05-16 18:05:37 +05303447 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303448 WMI_DBGLOG_MOD_LOG_LEVEL,
3449 value, DBG_CMD);
3450 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303451 hdd_err("Failed to enable FW module log level %d ret %d",
3452 value, ret);
3453
3454 count += 2;
3455 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303456
Arun Khandavalli2358d522016-05-16 18:05:37 +05303457}
3458#else
3459static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3460 hdd_adapter_t *adapter)
3461{
3462}
3463
3464#endif
3465
3466/**
3467 * hdd_set_fw_params() - Set parameters to firmware
3468 * @adapter: HDD adapter
3469 *
3470 * This function Sets various parameters to fw once the
3471 * adapter is started.
3472 *
3473 * Return: 0 on success or errno on failure
3474 */
3475int hdd_set_fw_params(hdd_adapter_t *adapter)
3476{
3477 int ret;
3478 hdd_context_t *hdd_ctx;
3479
3480 ENTER_DEV(adapter->dev);
3481
3482 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3483 if (!hdd_ctx)
3484 return -EINVAL;
3485
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003486 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303487 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303488#define HDD_DTIM_1CHAIN_RX_ID 0x5
3489#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003490 /*
3491 * Disable DTIM 1 chain Rx when in 1x1,
3492 * we are passing two value
3493 * as param_id << 29 | param_value.
3494 * Below param_value = 0(disable)
3495 */
3496 ret = wma_cli_set_command(adapter->sessionId,
3497 WMI_STA_SMPS_PARAM_CMDID,
3498 HDD_DTIM_1CHAIN_RX_ID <<
3499 HDD_SMPS_PARAM_VALUE_S,
3500 VDEV_CMD);
3501 if (ret) {
3502 hdd_err("DTIM 1 chain set failed %d", ret);
3503 goto error;
3504 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303505
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003506 ret = wma_cli_set_command(adapter->sessionId,
3507 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3508 hdd_ctx->config->txchainmask1x1,
3509 PDEV_CMD);
3510 if (ret) {
3511 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3512 ret);
3513 goto error;
3514 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303515
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003516 ret = wma_cli_set_command(adapter->sessionId,
3517 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3518 hdd_ctx->config->rxchainmask1x1,
3519 PDEV_CMD);
3520 if (ret) {
3521 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3522 ret);
3523 goto error;
3524 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303525#undef HDD_DTIM_1CHAIN_RX_ID
3526#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003527 } else {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003528 hdd_debug("FTM Mode or 2x2 mode - Do not set 1x1 params");
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003529 }
3530
Arun Khandavallifae92942016-08-01 13:31:08 +05303531 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3532 ret = wma_cli_set_command(adapter->sessionId,
3533 WMI_PDEV_PARAM_HYST_EN,
3534 hdd_ctx->config->enableMemDeepSleep,
3535 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303536
Arun Khandavallifae92942016-08-01 13:31:08 +05303537 if (ret) {
3538 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3539 ret);
3540 goto error;
3541 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303542
3543 ret = wma_cli_set_command(adapter->sessionId,
3544 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3545 hdd_ctx->config->rts_profile,
3546 VDEV_CMD);
3547 if (ret) {
3548 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3549 goto error;
3550 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303551 }
3552
3553 hdd_set_fw_log_params(hdd_ctx, adapter);
3554
3555 EXIT();
3556 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303557
Arun Khandavalli2358d522016-05-16 18:05:37 +05303558error:
3559 return -EINVAL;
3560}
3561
Ryan Hsu07495ea2016-01-21 15:25:39 -08003562/**
3563 * hdd_open_adapter() - open and setup the hdd adatper
3564 * @hdd_ctx: global hdd context
3565 * @session_type: type of the interface to be created
3566 * @iface_name: User-visible name of the interface
3567 * @macAddr: MAC address to assign to the interface
3568 * @name_assign_type: the name of assign type of the netdev
3569 * @rtnl_held: the rtnl lock hold flag
3570 *
3571 * This function open and setup the hdd adpater according to the device
3572 * type request, assign the name, the mac address assigned, and then prepared
3573 * the hdd related parameters, queue, lock and ready to start.
3574 *
3575 * Return: the pointer of hdd adapter, otherwise NULL.
3576 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3578 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003579 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003580 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581{
3582 hdd_adapter_t *adapter = NULL;
3583 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303584 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003587 hdd_debug("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588
3589 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3590 /*
3591 * Max limit reached on the number of vdevs configured by the
3592 * host. Return error
3593 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303594 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3595 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003596 return NULL;
3597 }
3598
3599 if (macAddr == NULL) {
3600 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303601 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602 return NULL;
3603 }
3604 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303605 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303606 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3607 " already exists",
3608 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 return NULL;
3610 }
3611
3612 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003613 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003614 /* Reset locally administered bit if the device mode is STA */
3615 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3616 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003617 case QDF_P2P_CLIENT_MODE:
3618 case QDF_P2P_DEVICE_MODE:
3619 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003620 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303621 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003622 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3623 name_assign_type,
3624 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625
3626 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303627 hdd_err("failed to allocate adapter for session %d",
3628 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629 return NULL;
3630 }
3631
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003632 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003634 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303636 else if (QDF_MONITOR_MODE == session_type)
3637 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638 else
3639 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3640
3641 adapter->device_mode = session_type;
3642
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303643 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003644 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303645 if (QDF_STATUS_SUCCESS != status)
3646 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303647 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649 /*
3650 * Workqueue which gets scheduled in IPv4 notification
3651 * callback
3652 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003653 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3654 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655
3656#ifdef WLAN_NS_OFFLOAD
3657 /*
3658 * Workqueue which gets scheduled in IPv6
3659 * notification callback.
3660 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3662 hdd_ipv6_notifier_work_queue);
3663#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303665 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303667 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003668 }
3669
3670 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303671 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303673 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3674 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003675 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003677
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003678 case QDF_P2P_GO_MODE:
3679 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003680 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3681 name_assign_type,
3682 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003683 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003684 hdd_err("failed to allocate adapter for session %d",
Arun Khandavallifae92942016-08-01 13:31:08 +05303685 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 return NULL;
3687 }
3688
3689 adapter->wdev.iftype =
3690 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003691 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 NL80211_IFTYPE_P2P_GO;
3693 adapter->device_mode = session_type;
3694
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003695 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303696 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3698 goto err_free_netdev;
3699 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303700 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303702 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3703 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303705 case QDF_FTM_MODE:
3706 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3707 name_assign_type,
3708 "wlan0");
3709 if (NULL == adapter) {
3710 hdd_err("Failed to allocate adapter for FTM mode");
3711 return NULL;
3712 }
3713 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3714 adapter->device_mode = session_type;
3715 status = hdd_register_interface(adapter, rtnl_held);
3716 if (QDF_STATUS_SUCCESS != status) {
3717 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3718 goto err_free_netdev;
3719 }
3720 /* Stop the Interface TX queue. */
3721 hdd_info("Disabling queues");
3722 wlan_hdd_netif_queue_control(adapter,
3723 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3724 WLAN_CONTROL_PATH);
3725 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003727 hdd_err("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303728 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 return NULL;
3730 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003731
3732 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3733 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3734
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303735 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736 /* Add it to the hdd's session list. */
3737 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303738 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303740 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741 } else {
3742 pHddAdapterNode->pAdapter = adapter;
3743 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3744 }
3745 }
3746
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303747 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748 if (NULL != adapter) {
3749 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3750 adapter = NULL;
3751 }
3752 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303753 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003754 }
3755 return NULL;
3756 }
3757
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303758 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003759 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
3760 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761
3762 /* Initialize the WoWL service */
3763 if (!hdd_init_wowl(adapter)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003764 hdd_err("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303765 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003766 }
3767
3768 /* Adapter successfully added. Increment the vdev count */
3769 hdd_ctx->current_intf_count++;
3770
Jeff Johnson5880d792016-08-15 13:32:30 -07003771 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772 hdd_ctx->current_intf_count);
3773
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003774 hdd_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 }
3776
Rajeev Kumardca5f812016-02-04 17:28:06 -08003777 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3778 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003779
3780 return adapter;
3781
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303782err_close_adapter:
3783 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003784err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303786 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787
3788 return NULL;
3789}
3790
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303791QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003792 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793{
3794 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303795 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796
3797 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303798 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003799 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800 status);
3801 return status;
3802 }
3803
3804 while (pCurrent->pAdapter != adapter) {
3805 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303806 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 break;
3808
3809 pCurrent = pNext;
3810 }
3811 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303812 if (QDF_STATUS_SUCCESS == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003813 hdd_debug("wait for bus bw work to flush");
Dustin Brown5ec6b552017-03-31 12:11:40 -07003814 hdd_bus_bw_compute_timer_stop(hdd_ctx);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303815 cancel_work_sync(&hdd_ctx->bus_bw_work);
Dustin Brown5ec6b552017-03-31 12:11:40 -07003816
3817 /* cleanup adapter */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003818 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
3819 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003820 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303822 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003823 adapterNode = NULL;
3824
Dustin Brown5ec6b552017-03-31 12:11:40 -07003825 /* conditionally restart the bw timer */
3826 hdd_bus_bw_compute_timer_try_start(hdd_ctx);
3827
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828 /* Adapter removed. Decrement vdev count */
3829 if (hdd_ctx->current_intf_count != 0)
3830 hdd_ctx->current_intf_count--;
3831
3832 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303833 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303835
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303836 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837}
3838
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003839/**
3840 * hdd_close_all_adapters - Close all open adapters
3841 * @hdd_ctx: Hdd context
3842 * rtnl_held: True if RTNL lock held
3843 *
3844 * Close all open adapters.
3845 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303846 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003847 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303848QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849{
3850 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303851 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852
3853 ENTER();
3854
3855 do {
3856 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303857 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303858 wlan_hdd_release_intf_addr(hdd_ctx,
3859 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003861 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303862 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303863 /* Adapter removed. Decrement vdev count */
3864 if (hdd_ctx->current_intf_count != 0)
3865 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303867 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868
3869 EXIT();
3870
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303871 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872}
3873
3874void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3875{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303876 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 tSirUpdateIE updateIE;
3878 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003879 case QDF_STA_MODE:
3880 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881 {
3882 hdd_station_ctx_t *pHddStaCtx =
3883 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003884 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 break;
3886 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003887 case QDF_SAP_MODE:
3888 case QDF_P2P_GO_MODE:
3889 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003890 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003891 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892 break;
3893 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003894 case QDF_FTM_MODE:
3895 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 default:
3897 /*
3898 * wlan_hdd_reset_prob_rspies should not have been called
3899 * for these kind of devices
3900 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003901 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902 pHostapdAdapter->device_mode);
3903 return;
3904 }
3905
Anurag Chouhanc5548422016-02-24 18:33:27 +05303906 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3908 updateIE.ieBufferlength = 0;
3909 updateIE.pAdditionIEBuffer = NULL;
3910 updateIE.append = true;
3911 updateIE.notify = false;
3912 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3913 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303914 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003915 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916 }
3917}
3918
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303919QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920 const bool bCloseSession)
3921{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303922 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003923 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3924 union iwreq_data wrqu;
3925 tSirUpdateIE updateIE;
3926 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303927 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003928
3929 ENTER();
3930
Sachin Ahuja988fd102016-09-15 17:16:25 +05303931 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003932 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3934 WLAN_CONTROL_PATH);
3935 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003936 case QDF_STA_MODE:
3937 case QDF_P2P_CLIENT_MODE:
3938 case QDF_IBSS_MODE:
3939 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003940 case QDF_NDI_MODE:
3941 if ((QDF_NDI_MODE == adapter->device_mode) ||
3942 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3944 hdd_is_connecting(
3945 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003946 INIT_COMPLETION(adapter->disconnect_comp_var);
3947 /*
3948 * For NDI do not use pWextState from sta_ctx, if needed
3949 * extract from ndi_ctx.
3950 */
3951 if (QDF_NDI_MODE == adapter->device_mode)
3952 qdf_ret_status = sme_roam_disconnect(
3953 hdd_ctx->hHal,
3954 adapter->sessionId,
3955 eCSR_DISCONNECT_REASON_NDI_DELETE);
3956 else if (pWextState->roamProfile.BSSType ==
3957 eCSR_BSS_TYPE_START_IBSS)
3958 qdf_ret_status = sme_roam_disconnect(
3959 hdd_ctx->hHal,
3960 adapter->sessionId,
3961 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003963 qdf_ret_status = sme_roam_disconnect(
3964 hdd_ctx->hHal,
3965 adapter->sessionId,
3966 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003967 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303968 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003969 rc = wait_for_completion_timeout(
3970 &adapter->disconnect_comp_var,
3971 msecs_to_jiffies
3972 (WLAN_WAIT_TIME_DISCONNECT));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08003973 if (!rc)
3974 hdd_warn("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003976 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003977 }
3978 memset(&wrqu, '\0', sizeof(wrqu));
3979 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3980 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3981 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3982 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303983 }
3984 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303985 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003986 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303987 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303988 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989
3990#ifdef WLAN_OPEN_SOURCE
3991 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3992#endif
3993
3994 hdd_deregister_tx_flow_control(adapter);
3995
3996#ifdef WLAN_NS_OFFLOAD
3997#ifdef WLAN_OPEN_SOURCE
3998 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3999#endif
4000#endif
4001
4002 /*
4003 * It is possible that the caller of this function does not
4004 * wish to close the session
4005 */
Krunal Soni985b8132017-02-10 18:49:08 -08004006 if (true == bCloseSession) {
4007 if (0 != wlan_hdd_try_disconnect(adapter)) {
4008 hdd_err("Error: Can't disconnect adapter");
4009 return QDF_STATUS_E_FAILURE;
4010 }
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004011 hdd_vdev_destroy(adapter);
Krunal Soni985b8132017-02-10 18:49:08 -08004012 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013 break;
4014
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004015 case QDF_SAP_MODE:
4016 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004018 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004019 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
4020
4021 hdd_deregister_tx_flow_control(adapter);
4022
4023 mutex_lock(&hdd_ctx->sap_lock);
4024 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304025 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05304026 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027
4028 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029 status = wlansap_stop_bss(
4030 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304032 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 hdd_hostapd_state_t *hostapd_state =
4034 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304035 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304036 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304037 qdf_status =
4038 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08004039 qdf_stop_bss_event,
4040 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041
Anurag Chouhance0dc992016-02-16 18:18:03 +05304042 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004043 hdd_err("failure waiting for wlansap_stop_bss %d",
4044 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045 }
4046 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07004047 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 }
4049 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004050 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4051 adapter->device_mode,
4052 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053
Anurag Chouhanc5548422016-02-24 18:33:27 +05304054 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08004055 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 updateIE.smeSessionId = adapter->sessionId;
4057 updateIE.ieBufferlength = 0;
4058 updateIE.pAdditionIEBuffer = NULL;
4059 updateIE.append = false;
4060 updateIE.notify = false;
4061 /* Probe bcn reset */
4062 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4063 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304064 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004065 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 }
4067 /* Assoc resp reset */
4068 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4069 &updateIE,
4070 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304071 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004072 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 }
4074 /* Reset WNI_CFG_PROBE_RSP Flags */
4075 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304076 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077 adapter->sessionCtx.ap.beacon = NULL;
4078 }
Peng Xu66162de2016-02-11 17:01:20 -08004079 if (true == bCloseSession)
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004080 hdd_vdev_destroy(adapter);
Manikandan Mohan5df78272017-03-22 16:28:50 -07004081 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004083 case QDF_OCB_MODE:
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -08004084 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004085 (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
Leo Changfdb45c32016-10-28 11:09:23 -07004086 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004087 break;
4088 default:
4089 break;
4090 }
4091
4092 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304093 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094}
4095
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05304096/**
4097 * hdd_deinit_all_adapters - deinit all adapters
4098 * @hdd_ctx: HDD context
4099 * @rtnl_held: True if RTNL lock held
4100 *
4101 */
4102void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
4103{
4104 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4105 QDF_STATUS status;
4106 hdd_adapter_t *adapter;
4107
4108 ENTER();
4109
4110 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4111
4112 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4113 adapter = adapter_node->pAdapter;
4114 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
4115 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4116 adapter_node = next;
4117 }
4118
4119 EXIT();
4120}
4121
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304122QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123{
4124 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304125 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126 hdd_adapter_t *adapter;
4127
4128 ENTER();
4129
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304130 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4133
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304134 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 adapter = adapterNode->pAdapter;
4136 hdd_stop_adapter(hdd_ctx, adapter, true);
4137 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4138 adapterNode = pNext;
4139 }
4140
4141 EXIT();
4142
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304143 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144}
4145
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304146QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147{
4148 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304149 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 hdd_adapter_t *adapter;
4151
4152 ENTER();
4153
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304154 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304158 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07004160 hdd_notice("Disabling queues");
Arun Khandavallicc544b32017-01-30 19:52:16 +05304161 if (hdd_ctx->config->sap_internal_restart &&
4162 adapter->device_mode == QDF_SAP_MODE) {
4163 wlan_hdd_netif_queue_control(adapter,
4164 WLAN_NETIF_TX_DISABLE,
4165 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004166 if (test_bit(SOFTAP_BSS_STARTED,
4167 &adapter->event_flags)) {
4168 hdd_sap_indicate_disconnect_for_sta(adapter);
4169 hdd_cleanup_actionframe(hdd_ctx, adapter);
4170 hdd_sap_destroy_events(adapter);
4171 }
4172 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
4173 } else {
Arun Khandavallicc544b32017-01-30 19:52:16 +05304174 wlan_hdd_netif_queue_control(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004175 WLAN_NETIF_TX_DISABLE_N_CARRIER,
4176 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004177 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178
4179 adapter->sessionCtx.station.hdd_ReassocScenario = false;
4180
4181 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004182 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4183 adapter->device_mode, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
4185 hdd_wmm_adapter_close(adapter);
4186 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
4187 }
4188
Wu Gao36717432016-11-21 15:09:48 +08004189 /*
4190 * If adapter is SAP, set session ID to invalid since SAP
4191 * session will be cleanup during SSR.
4192 */
4193 if (adapter->device_mode == QDF_SAP_MODE)
4194 wlansap_set_invalid_session(
4195 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
4196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4198 adapterNode = pNext;
4199 }
4200
4201 EXIT();
4202
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304203 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204}
4205
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304206bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
4207{
4208 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4209 QDF_STATUS status;
4210 bool close_modules = true;
4211
4212 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4213 while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
4214 if (test_bit(DEVICE_IFACE_OPENED,
4215 &adapter_node->pAdapter->event_flags)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004216 hdd_debug("Still other ifaces are up cannot close modules");
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304217 close_modules = false;
4218 break;
4219 }
4220 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4221 adapter_node = next;
4222 }
4223
4224 return close_modules;
4225}
4226
Arun Khandavallifae92942016-08-01 13:31:08 +05304227/**
4228 * hdd_is_interface_up()- Checkfor interface up before ssr
4229 * @hdd_ctx: HDD context
4230 *
4231 * check if there are any wlan interfaces before SSR accordingly start
4232 * the interface.
4233 *
4234 * Return: 0 if interface was opened else false
4235 */
4236static bool hdd_is_interface_up(hdd_adapter_t *adapter)
4237{
4238 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
4239 return true;
4240 else
4241 return false;
4242}
4243
Anurag Chouhanc4092922016-09-08 15:56:11 +05304244#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05304245 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304246struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4247 struct ieee80211_channel *channel,
4248 const u8 *bssid, const u8 *ssid,
4249 size_t ssid_len)
4250{
4251 return cfg80211_get_bss(wiphy, channel, bssid,
4252 ssid, ssid_len,
4253 WLAN_CAPABILITY_ESS,
4254 WLAN_CAPABILITY_ESS);
4255}
4256#else
4257struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4258 struct ieee80211_channel *channel,
4259 const u8 *bssid, const u8 *ssid,
4260 size_t ssid_len)
4261{
4262 return cfg80211_get_bss(wiphy, channel, bssid,
4263 ssid, ssid_len,
4264 IEEE80211_BSS_TYPE_ESS,
4265 IEEE80211_PRIVACY_ANY);
4266}
4267#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304268
Abhishek Singha84d3952016-09-13 13:45:05 +05304269#if defined CFG80211_CONNECT_BSS
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304270#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
4271 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
4272/**
4273 * hdd_convert_timeout_reason() - Convert to kernel specific enum
4274 * @timeout_reason: reason for connect timeout
4275 *
4276 * This function is used to convert host timeout
4277 * reason enum to kernel specific enum.
4278 *
4279 * Return: nl timeout enum
4280 */
4281static enum nl80211_timeout_reason hdd_convert_timeout_reason(
4282 tSirResultCodes timeout_reason)
4283{
4284 switch (timeout_reason) {
4285 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
4286 return NL80211_TIMEOUT_SCAN;
4287 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
4288 return NL80211_TIMEOUT_AUTH;
4289 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
4290 return NL80211_TIMEOUT_ASSOC;
4291 default:
4292 return NL80211_TIMEOUT_UNSPECIFIED;
4293 }
4294}
4295
4296/**
4297 * hdd_cfg80211_connect_timeout() - API to send connection timeout reason
4298 * @dev: network device
4299 * @bssid: bssid to which we want to associate
4300 * @timeout_reason: reason for connect timeout
4301 *
4302 * This API is used to send connection timeout reason to supplicant
4303 *
4304 * Return: void
4305 */
4306static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4307 const u8 *bssid,
4308 tSirResultCodes timeout_reason)
4309{
4310 enum nl80211_timeout_reason nl_timeout_reason;
4311 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4312
4313 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
4314 nl_timeout_reason);
4315}
4316
4317/**
4318 * __hdd_connect_bss() - API to send connection status to supplicant
4319 * @dev: network device
4320 * @bssid: bssid to which we want to associate
4321 * @req_ie: Request Information Element
4322 * @req_ie_len: len of the req IE
4323 * @resp_ie: Response IE
4324 * @resp_ie_len: len of ht response IE
4325 * @status: status
4326 * @gfp: Kernel Flag
4327 * @timeout_reason: reason for connect timeout
4328 *
4329 * Return: void
4330 */
4331static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4332 struct cfg80211_bss *bss, const u8 *req_ie,
4333 size_t req_ie_len, const u8 *resp_ie,
4334 size_t resp_ie_len, int status, gfp_t gfp,
4335 tSirResultCodes timeout_reason)
4336{
4337 enum nl80211_timeout_reason nl_timeout_reason;
4338 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4339
4340 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4341 resp_ie, resp_ie_len, status, gfp,
4342 nl_timeout_reason);
4343}
4344#else
4345#if defined CFG80211_CONNECT_TIMEOUT
4346static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4347 const u8 *bssid,
4348 tSirResultCodes timeout_reason)
4349{
4350 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
4351}
4352#endif
4353
4354static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4355 struct cfg80211_bss *bss, const u8 *req_ie,
4356 size_t req_ie_len, const u8 *resp_ie,
4357 size_t resp_ie_len, int status, gfp_t gfp,
4358 tSirResultCodes timeout_reason)
4359{
4360 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4361 resp_ie, resp_ie_len, status, gfp);
4362}
4363#endif
4364
Abhishek Singha84d3952016-09-13 13:45:05 +05304365/**
4366 * hdd_connect_bss() - API to send connection status to supplicant
4367 * @dev: network device
4368 * @bssid: bssid to which we want to associate
4369 * @req_ie: Request Information Element
4370 * @req_ie_len: len of the req IE
4371 * @resp_ie: Response IE
4372 * @resp_ie_len: len of ht response IE
4373 * @status: status
4374 * @gfp: Kernel Flag
4375 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304376 * @timeout_reason: reason for connect timeout
Abhishek Singha84d3952016-09-13 13:45:05 +05304377 *
4378 * The API is a wrapper to send connection status to supplicant
4379 *
4380 * Return: Void
4381 */
4382#if defined CFG80211_CONNECT_TIMEOUT
4383static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4384 struct cfg80211_bss *bss, const u8 *req_ie,
4385 size_t req_ie_len, const u8 *resp_ie,
4386 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304387 bool connect_timeout,
4388 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304389{
4390 if (connect_timeout)
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304391 hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304392 else
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304393 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4394 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304395}
4396#else
4397static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4398 struct cfg80211_bss *bss, const u8 *req_ie,
4399 size_t req_ie_len, const u8 *resp_ie,
4400 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304401 bool connect_timeout,
4402 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304403{
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304404 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4405 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304406}
4407#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304408
4409/**
4410 * hdd_connect_result() - API to send connection status to supplicant
4411 * @dev: network device
4412 * @bssid: bssid to which we want to associate
4413 * @roam_info: information about connected bss
4414 * @req_ie: Request Information Element
4415 * @req_ie_len: len of the req IE
4416 * @resp_ie: Response IE
4417 * @resp_ie_len: len of ht response IE
4418 * @status: status
4419 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05304420 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304421 * @timeout_reason: reason for connect timeout
Anurag Chouhanc4092922016-09-08 15:56:11 +05304422 *
4423 * The API is a wrapper to send connection status to supplicant
4424 * and allow runtime suspend
4425 *
4426 * Return: Void
4427 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304428void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4429 tCsrRoamInfo *roam_info, const u8 *req_ie,
4430 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304431 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304432 bool connect_timeout,
4433 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304434{
4435 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4436 struct cfg80211_bss *bss = NULL;
4437
4438 if (WLAN_STATUS_SUCCESS == status) {
4439 struct ieee80211_channel *chan;
4440 int freq;
4441 int chan_no = roam_info->pBssDesc->channelId;
4442
4443 if (chan_no <= 14)
4444 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004445 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304446 else
4447 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004448 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304449
4450 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
4451 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
4452 roam_info->u.pConnectedProfile->SSID.ssId,
4453 roam_info->u.pConnectedProfile->SSID.length);
4454 }
Komal Seelama89be8d2016-09-29 11:09:26 +05304455
Abhishek Singha84d3952016-09-13 13:45:05 +05304456 hdd_connect_bss(dev, bssid, bss, req_ie,
4457 req_ie_len, resp_ie, resp_ie_len,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304458 status, gfp, connect_timeout, timeout_reason);
Komal Seelama89be8d2016-09-29 11:09:26 +05304459
4460 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304461}
4462#else
4463void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4464 tCsrRoamInfo *roam_info, const u8 *req_ie,
4465 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304466 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304467 bool connect_timeout,
4468 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304469{
Komal Seelama89be8d2016-09-29 11:09:26 +05304470 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4471
Anurag Chouhanc4092922016-09-08 15:56:11 +05304472 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4473 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304474 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304475}
4476#endif
4477
4478
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304479QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480{
4481 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304482 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 hdd_adapter_t *adapter;
4484#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304485 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004486#endif
4487 eConnectionState connState;
4488
4489 ENTER();
4490
4491 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304492 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 adapter = adapterNode->pAdapter;
4494
Arun Khandavallifae92942016-08-01 13:31:08 +05304495 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304496 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304497
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 hdd_wmm_init(adapter);
4499
4500 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004501 case QDF_STA_MODE:
4502 case QDF_P2P_CLIENT_MODE:
4503 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004504
4505 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4506 ->conn_info.connState;
4507
4508 hdd_init_station_mode(adapter);
4509 /* Open the gates for HDD to receive Wext commands */
4510 adapter->isLinkUpSvcNeeded = false;
4511 adapter->scan_info.mScanPending = false;
4512
4513 /* Indicate disconnect event to supplicant if associated previously */
4514 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004515 eConnectionState_IbssConnected == connState ||
4516 eConnectionState_NotConnected == connState ||
4517 eConnectionState_IbssDisconnected == connState ||
4518 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519 union iwreq_data wrqu;
4520 memset(&wrqu, '\0', sizeof(wrqu));
4521 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4522 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4523 wireless_send_event(adapter->dev, SIOCGIWAP,
4524 &wrqu, NULL);
4525 adapter->sessionCtx.station.
4526 hdd_ReassocScenario = false;
4527
4528 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304529 wlan_hdd_cfg80211_indicate_disconnect(
4530 adapter->dev, false,
4531 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004532 } else if (eConnectionState_Connecting == connState) {
4533 /*
4534 * Indicate connect failure to supplicant if we were in the
4535 * process of connecting
4536 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304537 hdd_connect_result(adapter->dev, NULL, NULL,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304538 NULL, 0, NULL, 0,
4539 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4540 GFP_KERNEL, false,
4541 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004542 }
4543
4544 hdd_register_tx_flow_control(adapter,
4545 hdd_tx_resume_timer_expired_handler,
4546 hdd_tx_resume_cb);
4547
4548 break;
4549
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004550 case QDF_SAP_MODE:
Arun Khandavallicc544b32017-01-30 19:52:16 +05304551 if (hdd_ctx->config->sap_internal_restart)
4552 hdd_init_ap_mode(adapter, true);
4553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 break;
4555
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004556 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004558 hdd_debug("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4560#else
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004561 hdd_debug("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004562 /* event supplicant to restart */
4563 cfg80211_del_sta(adapter->dev,
4564 (const u8 *)&bcastMac.bytes[0],
4565 GFP_KERNEL);
4566#endif
4567 break;
4568
4569 default:
4570 break;
4571 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304572get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4574 adapterNode = pNext;
4575 }
4576
4577 EXIT();
4578
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304579 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580}
4581
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304582QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 hdd_adapter_list_node_t **padapterNode)
4584{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304585 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004586 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304587 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4588 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004589 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004590 return status;
4591}
4592
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304593QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594 hdd_adapter_list_node_t *adapterNode,
4595 hdd_adapter_list_node_t **pNextAdapterNode)
4596{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304597 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004598 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304599 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4600 (qdf_list_node_t *) adapterNode,
4601 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004602
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004603 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004604 return status;
4605}
4606
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304607QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 hdd_adapter_list_node_t *adapterNode)
4609{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304610 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004611 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304612 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004614 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004615 return status;
4616}
4617
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304618QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004619 hdd_adapter_list_node_t **padapterNode)
4620{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304621 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004622 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304623 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4624 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004625 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626 return status;
4627}
4628
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304629QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 hdd_adapter_list_node_t *adapterNode)
4631{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304632 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004633 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304634 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4635 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004636 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 return status;
4638}
4639
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304640QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004641 hdd_adapter_list_node_t *adapterNode)
4642{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304643 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004644 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304645 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4646 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004647 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004648 return status;
4649}
4650
4651hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4652 tSirMacAddr macAddr)
4653{
4654 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4655 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304656 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004657
4658 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4659
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304660 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661 adapter = adapterNode->pAdapter;
4662
4663 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304664 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 macAddr, sizeof(tSirMacAddr))) {
4666 return adapter;
4667 }
4668 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4669 adapterNode = pNext;
4670 }
4671
4672 return NULL;
4673
4674}
4675
4676hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4677 uint32_t vdev_id)
4678{
4679 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4680 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304681 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304683 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304685 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 adapter = adapterNode->pAdapter;
4687
4688 if (adapter->sessionId == vdev_id)
4689 return adapter;
4690
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304691 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4693 adapterNode = pNext;
4694 }
4695
Jeff Johnson5880d792016-08-15 13:32:30 -07004696 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697
4698 return NULL;
4699}
4700
Abhishek Singh7996eb72015-12-30 17:24:02 +05304701/**
4702 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4703 * the sessionid
4704 * @hdd_ctx: hdd context.
4705 * @sme_session_id: sme session is for the adapter to get.
4706 *
4707 * This function is used to get the adapter with provided session id
4708 *
4709 * Return: adapter pointer if found
4710 *
4711 */
4712hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4713 uint32_t sme_session_id)
4714{
4715 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4716 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304717 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304718
4719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304720 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304721
4722 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304723 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304724 adapter = adapter_node->pAdapter;
4725
4726 if (adapter &&
4727 adapter->sessionId == sme_session_id)
4728 return adapter;
4729
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304730 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304731 hdd_get_next_adapter(hdd_ctx,
4732 adapter_node, &next);
4733 adapter_node = next;
4734 }
4735 return NULL;
4736}
4737
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004738/**
4739 * hdd_get_adapter() - to get adapter matching the mode
4740 * @hdd_ctx: hdd context
4741 * @mode: adapter mode
4742 *
4743 * This routine will return the pointer to adapter matching
4744 * with the passed mode.
4745 *
4746 * Return: pointer to adapter or null
4747 */
4748hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4749 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750{
4751 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4752 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304753 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754
4755 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4756
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304757 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758 adapter = adapterNode->pAdapter;
4759
4760 if (adapter && (mode == adapter->device_mode))
4761 return adapter;
4762
4763 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4764 adapterNode = pNext;
4765 }
4766
4767 return NULL;
4768
4769}
4770
4771/**
4772 * hdd_get_operating_channel() - return operating channel of the device mode
4773 * @hdd_ctx: Pointer to the HDD context.
4774 * @mode: Device mode for which operating channel is required.
4775 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004776 * QDF_STA_MODE,
4777 * QDF_P2P_CLIENT_MODE,
4778 * QDF_SAP_MODE,
4779 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004780 *
4781 * This API returns the operating channel of the requested device mode
4782 *
4783 * Return: channel number. "0" id the requested device is not found OR it is
4784 * not connected.
4785 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004786uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4787 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004788{
4789 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304790 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004791 hdd_adapter_t *adapter;
4792 uint8_t operatingChannel = 0;
4793
4794 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4795
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304796 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797 adapter = adapterNode->pAdapter;
4798
4799 if (mode == adapter->device_mode) {
4800 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004801 case QDF_STA_MODE:
4802 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803 if (hdd_conn_is_connected
4804 (WLAN_HDD_GET_STATION_CTX_PTR
4805 (adapter))) {
4806 operatingChannel =
4807 (WLAN_HDD_GET_STATION_CTX_PTR
4808 (adapter))->conn_info.
4809 operationChannel;
4810 }
4811 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004812 case QDF_SAP_MODE:
4813 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004814 /* softap connection info */
4815 if (test_bit
4816 (SOFTAP_BSS_STARTED,
4817 &adapter->event_flags))
4818 operatingChannel =
4819 (WLAN_HDD_GET_AP_CTX_PTR
4820 (adapter))->operatingChannel;
4821 break;
4822 default:
4823 break;
4824 }
4825
4826 break; /* Found the device of interest. break the loop */
4827 }
4828
4829 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4830 adapterNode = pNext;
4831 }
4832 return operatingChannel;
4833}
4834
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304835static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004836 hdd_ctx)
4837{
4838 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304839 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004840 hdd_adapter_t *adapter;
4841
4842 ENTER();
4843
4844 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4845
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304846 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004847 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004848 if ((adapter->device_mode == QDF_STA_MODE) ||
4849 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4850 (adapter->device_mode == QDF_IBSS_MODE) ||
4851 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4852 (adapter->device_mode == QDF_SAP_MODE) ||
4853 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 wlan_hdd_cfg80211_deregister_frames(adapter);
4855 hdd_unregister_wext(adapter->dev);
4856 }
4857 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4858 adapterNode = pNext;
4859 }
4860
4861 EXIT();
4862
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304863 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004864}
4865
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304866QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867{
4868 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304869 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 hdd_adapter_t *adapter;
4871
4872 ENTER();
4873
4874 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4875
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304876 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004878 if ((adapter->device_mode == QDF_STA_MODE) ||
4879 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4880 (adapter->device_mode == QDF_IBSS_MODE) ||
4881 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4882 (adapter->device_mode == QDF_SAP_MODE) ||
4883 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004884 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05304885 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886 eCSR_SCAN_ABORT_DEFAULT);
4887 }
4888 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4889 adapterNode = pNext;
4890 }
4891
4892 EXIT();
4893
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304894 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895}
4896
Dustin Brownf27bce82016-11-03 12:52:27 -07004897/**
4898 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4899 * adapters
4900 * @hdd_ctx: The HDD context containing the adapters to operate on
4901 *
4902 * return: QDF_STATUS_SUCCESS
4903 */
4904static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4905{
4906 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4907 QDF_STATUS status;
4908 hdd_adapter_t *adapter;
4909 int err;
4910
4911 ENTER();
4912
4913 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4914
4915 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4916 adapter = adapter_node->pAdapter;
4917 if ((adapter->device_mode == QDF_STA_MODE) ||
4918 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4919 (adapter->device_mode == QDF_IBSS_MODE) ||
4920 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4921 (adapter->device_mode == QDF_SAP_MODE) ||
4922 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4923 err = wlan_hdd_sched_scan_stop(adapter->dev);
4924 if (err)
4925 hdd_err("Unable to stop scheduled scan");
4926 }
4927 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node);
4928 adapter_node = next_node;
4929 }
4930
4931 EXIT();
4932
4933 return QDF_STATUS_SUCCESS;
4934}
4935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004936#ifdef WLAN_NS_OFFLOAD
4937/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004938 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939 * @hdd_ctx: Pointer to hdd context
4940 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004941 * Unregister for IPv6 address change notifications.
4942 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004943 * Return: None
4944 */
4945static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4946{
4947 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4948
4949 return;
4950}
4951
4952/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004953 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004954 * @hdd_ctx: Pointer to hdd context
4955 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004956 * Register for IPv6 address change notifications.
4957 *
4958 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004960static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004961{
4962 int ret;
4963
4964 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4965 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004966 if (ret) {
4967 hdd_err("Failed to register IPv6 notifier: %d", ret);
4968 goto out;
4969 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08004971 hdd_debug("Registered IPv6 notifier");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004972out:
4973 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004974}
4975#else
4976/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004977 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004978 * @hdd_ctx: Pointer to hdd context
4979 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004980 * Unregister for IPv6 address change notifications.
4981 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004982 * Return: None
4983 */
4984static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4985{
4986}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004987
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004988/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004989 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990 * @hdd_ctx: Pointer to hdd context
4991 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004992 * Register for IPv6 address change notifications.
4993 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004994 * Return: None
4995 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004996static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004998 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999}
5000#endif
5001
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305002#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
5003/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005004 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305005 * @hdd_ctx: HDD context
5006 *
5007 * Activates the logging service
5008 *
5009 * Return: Zero in case of success, negative value otherwise
5010 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005011static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305012{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005013 int ret;
5014 struct hdd_config *config = hdd_ctx->config;
5015
5016 if (!config->wlanLoggingEnable)
5017 return 0;
5018
Srinivas Girigowda8187e792017-03-03 11:50:59 -08005019 ret = wlan_logging_sock_activate_svc(config->wlanLoggingToConsole,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005020 config->wlanLoggingNumBuf);
5021 if (ret)
5022 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
5023 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305024}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005025
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305026/**
5027 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
5028 * @hdd_ctx: HDD context
5029 *
5030 * Deactivates the logging service
5031 *
5032 * Return: 0 on deactivating the logging service
5033 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005034static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305035{
5036 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
5037 return wlan_logging_sock_deactivate_svc();
5038
5039 return 0;
5040}
5041#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005042static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305043{
5044 return 0;
5045}
5046
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005047static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305048{
5049 return 0;
5050}
5051#endif
5052
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005054 * hdd_register_notifiers - Register netdev notifiers.
5055 * @hdd_ctx: HDD context
5056 *
5057 * Register netdev notifiers like IPv4 and IPv6.
5058 *
5059 * Return: 0 on success and errno on failure
5060 */
5061static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
5062{
5063 int ret;
5064
5065 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5066 if (ret) {
5067 hdd_err("register_netdevice_notifier failed: %d", ret);
5068 goto out;
5069 }
5070
5071 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
5072 if (ret)
5073 goto unregister_notifier;
5074
5075 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5076 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5077 if (ret) {
5078 hdd_err("Failed to register IPv4 notifier: %d", ret);
5079 goto unregister_ip6_notifier;
5080 }
5081
5082 return 0;
5083
5084unregister_ip6_notifier:
5085 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5086unregister_notifier:
5087 unregister_netdevice_notifier(&hdd_netdev_notifier);
5088out:
5089 return ret;
5090
5091}
5092
5093/**
5094 * hdd_unregister_notifiers - Unregister netdev notifiers.
5095 * @hdd_ctx: HDD context
5096 *
5097 * Unregister netdev notifiers like IPv4 and IPv6.
5098 *
5099 * Return: None.
5100 */
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305101void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005102{
5103 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5104
5105 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5106
5107 unregister_netdevice_notifier(&hdd_netdev_notifier);
5108}
5109
5110/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005111 * hdd_exit_netlink_services - Exit netlink services
5112 * @hdd_ctx: HDD context
5113 *
5114 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
5115 * nl service.
5116 *
5117 * Return: None.
5118 */
5119static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
5120{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005121 hdd_close_cesium_nl_sock();
Naveen Rawat910726a2017-03-06 11:42:51 -08005122 hdd_deactivate_wifi_pos();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005123 ptt_sock_deactivate_svc();
5124
5125 nl_srv_exit();
5126}
5127
5128/**
5129 * hdd_init_netlink_services- Init netlink services
5130 * @hdd_ctx: HDD context
5131 *
5132 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
5133 * nl service.
5134 *
5135 * Return: 0 on success and errno on failure.
5136 */
5137static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
5138{
5139 int ret;
5140
Ryan Hsuceddceb2016-04-28 10:20:14 -07005141 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005142 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005143 hdd_err("nl_srv_init failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005144 goto out;
5145 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07005146 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005147
Naveen Rawat910726a2017-03-06 11:42:51 -08005148 ret = hdd_activate_wifi_pos(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005149 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005150 hdd_err("hdd_activate_wifi_pos failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005151 goto err_nl_srv;
5152 }
5153
5154 ret = ptt_sock_activate_svc();
5155 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005156 hdd_err("ptt_sock_activate_svc failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005157 goto err_nl_srv;
5158 }
5159
5160 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07005161 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005162 hdd_err("hdd_open_cesium_nl_sock failed ret: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005163
5164 ret = cnss_diag_activate_service();
5165 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005166 hdd_err("cnss_diag_activate_service failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005167 goto err_close_cesium;
5168 }
5169
5170 return 0;
5171
5172err_close_cesium:
5173 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005174 ptt_sock_deactivate_svc();
5175err_nl_srv:
5176 nl_srv_exit();
5177out:
5178 return ret;
5179}
5180
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005181/**
5182 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
5183 * @hdd_ctx: HDD context.
5184 *
5185 * Destroy RX wakelock.
5186 *
5187 * Return: None.
5188 */
5189static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
5190{
5191 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
5192}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005193
5194/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005195 * hdd_rx_wake_lock_create() - Create RX wakelock
5196 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005197 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005198 * Create RX wakelock.
5199 *
5200 * Return: None.
5201 */
5202static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
5203{
5204 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5205}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005206
5207/**
5208 * hdd_roc_context_init() - Init ROC context
5209 * @hdd_ctx: HDD context.
5210 *
5211 * Initialize ROC context.
5212 *
5213 * Return: 0 on success and errno on failure.
5214 */
5215static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
5216{
5217 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
5218 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
5219
5220 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5221
5222 return 0;
5223}
5224
5225/**
5226 * hdd_roc_context_destroy() - Destroy ROC context
5227 * @hdd_ctx: HDD context.
5228 *
5229 * Destroy roc list and flush the pending roc work.
5230 *
5231 * Return: None.
5232 */
5233static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
5234{
5235 flush_delayed_work(&hdd_ctx->roc_req_work);
5236 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08005237 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005238}
5239
5240/**
Houston Hoffman160db392016-10-10 17:37:51 -07005241 * hdd_context_deinit() - Deinitialize HDD context
5242 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005243 *
Houston Hoffman160db392016-10-10 17:37:51 -07005244 * Deinitialize HDD context along with all the feature specific contexts but
5245 * do not free hdd context itself. Caller of this API is supposed to free
5246 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005247 *
Houston Hoffman160db392016-10-10 17:37:51 -07005248 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005249 */
Houston Hoffman160db392016-10-10 17:37:51 -07005250static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005251{
Houston Hoffman160db392016-10-10 17:37:51 -07005252 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005253
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005254 hdd_roc_context_destroy(hdd_ctx);
5255
5256 hdd_sap_context_destroy(hdd_ctx);
5257
5258 hdd_rx_wake_lock_destroy(hdd_ctx);
5259
5260 hdd_tdls_context_destroy(hdd_ctx);
5261
5262 hdd_scan_context_destroy(hdd_ctx);
5263
5264 qdf_list_destroy(&hdd_ctx->hddAdapters);
5265
Houston Hoffman160db392016-10-10 17:37:51 -07005266 return 0;
5267}
5268
5269/**
5270 * hdd_context_destroy() - Destroy HDD context
5271 * @hdd_ctx: HDD context to be destroyed.
5272 *
5273 * Free config and HDD context as well as destroy all the resources.
5274 *
5275 * Return: None
5276 */
5277static void hdd_context_destroy(hdd_context_t *hdd_ctx)
5278{
5279 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
5280 hdd_logging_sock_deactivate_svc(hdd_ctx);
5281
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05305282 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5283
Houston Hoffman160db392016-10-10 17:37:51 -07005284 hdd_context_deinit(hdd_ctx);
5285
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305286 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005287 hdd_ctx->config = NULL;
5288
5289 wiphy_free(hdd_ctx->wiphy);
5290}
5291
5292/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 * hdd_wlan_exit() - HDD WLAN exit function
5294 * @hdd_ctx: Pointer to the HDD Context
5295 *
5296 * This is the driver exit point (invoked during rmmod)
5297 *
5298 * Return: None
5299 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005300static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301{
5302 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305303 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05305305 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306
5307 ENTER();
5308
Arun Khandavallifae92942016-08-01 13:31:08 +05305309 if (QDF_TIMER_STATE_RUNNING ==
5310 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005311 hdd_debug("Stop interface change timer");
Arun Khandavallifae92942016-08-01 13:31:08 +05305312 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313 }
5314
Arun Khandavallifae92942016-08-01 13:31:08 +05305315 if (!QDF_IS_STATUS_SUCCESS
5316 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
5317 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005318
Arun Khandavallifae92942016-08-01 13:31:08 +05305319
5320 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321
Nitesh Shah61c10d92016-10-19 19:29:15 +05305322 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
5323
Prashanth Bhattaab004382016-10-11 16:08:11 -07005324 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325
5326#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305327 if (QDF_TIMER_STATE_RUNNING ==
5328 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
5329 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 }
5331
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305332 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05305333 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005334 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335 }
Liangwei Dongaef84342016-10-21 05:28:00 -04005336 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5337 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5338 hdd_ctx->last_acs_channel_list = NULL;
5339 hdd_ctx->num_of_channels = 0;
5340 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342
Arun Khandavallifae92942016-08-01 13:31:08 +05305343 mutex_lock(&hdd_ctx->iface_change_lock);
5344 driver_status = hdd_ctx->driver_status;
5345 mutex_unlock(&hdd_ctx->iface_change_lock);
5346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005347 /*
5348 * Powersave Offload Case
5349 * Disable Idle Power Save Mode
5350 */
5351 hdd_set_idle_ps_config(hdd_ctx, false);
5352
Arun Khandavallifae92942016-08-01 13:31:08 +05305353 if (driver_status != DRIVER_MODULES_CLOSED) {
5354 hdd_unregister_wext_all_adapters(hdd_ctx);
5355 /*
5356 * Cancel any outstanding scan requests. We are about to close
5357 * all of our adapters, but an adapter structure is what SME
5358 * passes back to our callback function. Hence if there
5359 * are any outstanding scan requests then there is a
5360 * race condition between when the adapter is closed and
5361 * when the callback is invoked. We try to resolve that
5362 * race condition here by canceling any outstanding scans
5363 * before we close the adapters.
5364 * Note that the scans may be cancelled in an asynchronous
5365 * manner, so ideally there needs to be some kind of
5366 * synchronization. Rather than introduce a new
5367 * synchronization here, we will utilize the fact that we are
5368 * about to Request Full Power, and since that is synchronized,
5369 * the expectation is that by the time Request Full Power has
5370 * completed, all scans will be cancelled
5371 */
Sandeep Puligilla1fcdb772017-02-22 21:14:59 -08005372#ifndef NAPIER_SCAN
Jeff Johnsonf337b0c2017-03-10 10:48:30 -08005373 hdd_cleanup_scan_queue(hdd_ctx);
Sandeep Puligilla1fcdb772017-02-22 21:14:59 -08005374#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05305375 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07005376 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305377 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378 }
5379
5380 /*
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305381 * Close the scheduler before calling cds_close to make sure
5382 * no thread is scheduled after the each module close is
5383 * is called i.e after all the data structures are freed.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005384 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305385 qdf_status = cds_sched_close(p_cds_context);
5386 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005387 hdd_err("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305388 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07005391 hdd_wlan_stop_modules(hdd_ctx, false);
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05305392
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305393 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
5394 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
5395 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
5396
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397 /*
5398 * Close CDS
5399 * This frees pMac(HAL) context. There should not be any call
5400 * that requires pMac access after this.
5401 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07005403 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08005404 hdd_request_manager_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405
Komal Seelam8634b772016-09-29 12:12:24 +05305406 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005407 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408
5409 hdd_ipa_cleanup(hdd_ctx);
5410
5411 /* Free up RoC request queue and flush workqueue */
5412 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05305414 wlansap_global_deinit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05305415 wlan_hdd_deinit_chan_info(hdd_ctx);
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305416 /*
5417 * If there is re_init failure wiphy would have already de-registered
5418 * check the wiphy status before un-registering again
5419 */
Ashish Kumar Dhanotiyae16feb72017-03-31 19:39:37 +05305420 if (wiphy && wiphy->registered) {
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05305421 wiphy_unregister(wiphy);
5422 wlan_hdd_cfg80211_deinit(wiphy);
5423 hdd_lpass_notify_stop(hdd_ctx);
5424 }
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07005425
Arun Khandavallifae92942016-08-01 13:31:08 +05305426 hdd_exit_netlink_services(hdd_ctx);
5427 mutex_destroy(&hdd_ctx->iface_change_lock);
Abhishek Singhe9068f12017-03-31 14:14:52 +05305428
5429 driver_status = hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
5430 if (driver_status)
5431 hdd_err("Pdev delete failed");
5432
5433 driver_status = hdd_objmgr_release_and_destroy_psoc(hdd_ctx);
5434 if (driver_status)
5435 hdd_err("Psoc delete failed");
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005436 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437}
5438
5439void __hdd_wlan_exit(void)
5440{
5441 hdd_context_t *hdd_ctx;
5442
5443 ENTER();
5444
Anurag Chouhan6d760662016-02-20 16:05:43 +05305445 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 if (!hdd_ctx) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005447 hdd_err("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005448 EXIT();
5449 return;
5450 }
5451
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005452 /* Check IPA HW Pipe shutdown */
5453 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
5454
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005455 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05305456 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005457
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458 /* Do all the cleanup before deregistering the driver */
5459 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07005460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461 EXIT();
5462}
5463
5464#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04005465/**
5466 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
5467 * @data: pointer to hdd_context_t
5468 *
5469 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
5470 * Then new ACS request will do a fresh scan without reusing the cached
5471 * scan information.
5472 *
5473 * Return: void
5474 */
Tang Yingying523322d2017-01-17 23:28:43 +08005475static void hdd_skip_acs_scan_timer_handler(void *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476{
5477 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
5478
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005479 hdd_debug("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005480 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04005481 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5482 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5483 hdd_ctx->last_acs_channel_list = NULL;
5484 hdd_ctx->num_of_channels = 0;
5485 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486
5487 if (!hdd_ctx->hHal)
5488 return;
5489 sme_scan_flush_result(hdd_ctx->hHal);
5490}
5491#endif
5492
5493#ifdef QCA_HT_2040_COEX
5494/**
5495 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5496 * @adapter: pointer to adapter
5497 * @staId: station id
5498 * @macAddrSTA: station MAC address
5499 * @channel_type: channel type
5500 *
5501 * This function notifies FW with HT20/HT40 mode
5502 *
5503 * Return: 0 if successful, error number otherwise
5504 */
5505int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305506 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005507{
5508 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305509 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005510 hdd_context_t *hdd_ctx = NULL;
5511
5512 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5513
5514 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305515 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305517
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 if (!hdd_ctx->hHal)
5519 return -EINVAL;
5520
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305521 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305523 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005524 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 return -EINVAL;
5526 }
5527
5528 return 0;
5529}
5530#endif
5531
5532/**
5533 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5534 * @state: state
5535 *
5536 * This function notifies FW with modem power status
5537 *
5538 * Return: 0 if successful, error number otherwise
5539 */
5540int hdd_wlan_notify_modem_power_state(int state)
5541{
5542 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305543 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 hdd_context_t *hdd_ctx;
5545
Anurag Chouhan6d760662016-02-20 16:05:43 +05305546 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005547 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305548 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305550
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551 if (!hdd_ctx->hHal)
5552 return -EINVAL;
5553
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305554 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5555 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005556 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 state);
5558 return -EINVAL;
5559 }
5560 return 0;
5561}
5562
5563/**
5564 *
5565 * hdd_post_cds_enable_config() - HDD post cds start config helper
5566 * @adapter - Pointer to the HDD
5567 *
5568 * Return: None
5569 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305570QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305572 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573
5574 /*
5575 * Send ready indication to the HDD. This will kick off the MAC
5576 * into a 'running' state and should kick off an initial scan.
5577 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305578 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5579 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005580 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5581 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305582 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583 }
5584
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305585 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586}
5587
5588/* wake lock APIs for HDD */
5589void hdd_prevent_suspend(uint32_t reason)
5590{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305591 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592}
5593
5594void hdd_allow_suspend(uint32_t reason)
5595{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305596 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005597}
5598
5599void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5600{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305601 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5602 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005603}
5604
5605/**
5606 * hdd_exchange_version_and_caps() - exchange version and capability with target
5607 * @hdd_ctx: Pointer to HDD context
5608 *
5609 * This is the HDD function to exchange version and capability information
5610 * between Host and Target
5611 *
5612 * This function gets reported version of FW.
5613 * It also finds the version of target headers used to compile the host;
5614 * It compares the above two and prints a warning if they are different;
5615 * It gets the SW and HW version string;
5616 * Finally, it exchanges capabilities between host and target i.e. host
5617 * and target exchange a msg indicating the features they support through a
5618 * bitmap
5619 *
5620 * Return: None
5621 */
5622void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5623{
5624
5625 tSirVersionType versionCompiled;
5626 tSirVersionType versionReported;
5627 tSirVersionString versionString;
5628 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305629 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630
5631 memset(&versionCompiled, 0, sizeof(versionCompiled));
5632 memset(&versionReported, 0, sizeof(versionReported));
5633
5634 /* retrieve and display WCNSS version information */
5635 do {
5636
5637 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5638 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305639 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005640 hdd_err("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 break;
5642 }
5643
5644 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5645 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305646 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005647 hdd_err("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005648 break;
5649 }
5650
5651 if ((versionCompiled.major != versionReported.major) ||
5652 (versionCompiled.minor != versionReported.minor) ||
5653 (versionCompiled.version != versionReported.version) ||
5654 (versionCompiled.revision != versionReported.revision)) {
5655 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5656 "Host expected %u.%u.%u.%u\n",
5657 WLAN_MODULE_NAME,
5658 (int)versionReported.major,
5659 (int)versionReported.minor,
5660 (int)versionReported.version,
5661 (int)versionReported.revision,
5662 (int)versionCompiled.major,
5663 (int)versionCompiled.minor,
5664 (int)versionCompiled.version,
5665 (int)versionCompiled.revision);
5666 } else {
5667 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5668 WLAN_MODULE_NAME,
5669 (int)versionReported.major,
5670 (int)versionReported.minor,
5671 (int)versionReported.version,
5672 (int)versionReported.revision);
5673 }
5674
5675 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5676 versionString,
5677 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305678 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005679 hdd_err("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680 break;
5681 }
5682
5683 pr_info("%s: WCNSS software version %s\n",
5684 WLAN_MODULE_NAME, versionString);
5685
5686 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5687 versionString,
5688 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305689 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005690 hdd_err("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691 break;
5692 }
5693
5694 pr_info("%s: WCNSS hardware version %s\n",
5695 WLAN_MODULE_NAME, versionString);
5696
5697 /*
5698 * 1.Check if FW version is greater than 0.1.1.0. Only then
5699 * send host-FW capability exchange message
5700 * 2.Host-FW capability exchange message is only present on
5701 * target 1.1 so send the message only if it the target is 1.1
5702 * minor numbers for different target branches:
5703 * 0 -> (1.0)Mainline Build
5704 * 1 -> (1.1)Mainline Build
5705 * 2->(1.04) Stability Build
5706 */
5707 if (((versionReported.major > 0) || (versionReported.minor > 1)
5708 || ((versionReported.minor >= 1)
5709 && (versionReported.version >= 1)))
5710 && ((versionReported.major == 1)
5711 && (versionReported.minor >= 1)))
5712 fwFeatCapsMsgSupported = 1;
5713
5714 if (fwFeatCapsMsgSupported) {
5715 /*
5716 * Indicate if IBSS heartbeat monitoring needs to be
5717 * offloaded
5718 */
5719 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5720 sme_disable_feature_capablity
5721 (IBSS_HEARTBEAT_OFFLOAD);
5722 }
5723
5724 sme_feature_caps_exchange(hdd_ctx->hHal);
5725 }
5726
5727 } while (0);
5728
5729}
5730
5731/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305732QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733{
5734 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5735 hdd_ctx->reg.cc_src);
5736}
5737
5738/**
5739 * hdd_is_5g_supported() - check if hardware supports 5GHz
5740 * @hdd_ctx: Pointer to the hdd context
5741 *
5742 * HDD function to know if hardware supports 5GHz
5743 *
5744 * Return: true if hardware supports 5GHz
5745 */
5746bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5747{
zdingf54169a2016-10-12 17:08:45 +08005748 if (!hdd_ctx || !hdd_ctx->config)
5749 return true;
5750
5751 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5752 return true;
5753 else
5754 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005755}
5756
Amar Singhale4f28ee2015-10-21 14:36:56 -07005757static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005758{
5759 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005760 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761
5762 wiphy = hdd_ctx->wiphy;
5763
5764 /*
5765 * The channel information in
5766 * wiphy needs to be initialized before wiphy registration
5767 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005768 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5769 if (ret_val) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08005770 hdd_err("regulatory init failed");
Amar Singhale4f28ee2015-10-21 14:36:56 -07005771 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005772 }
5773
5774#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5775 wiphy->wowlan = &wowlan_support_reg_init;
5776#else
5777 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5778 WIPHY_WOWLAN_MAGIC_PKT |
5779 WIPHY_WOWLAN_DISCONNECT |
5780 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5781 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5782 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5783 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5784 WIPHY_WOWLAN_RFKILL_RELEASE;
5785
5786 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5787 WOW_MAX_FILTERS_PER_LIST);
5788 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5789 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5790#endif
5791
5792 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005793 ret_val = wlan_hdd_cfg80211_register(wiphy);
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305794 if (0 > ret_val) {
Amar Singhale4f28ee2015-10-21 14:36:56 -07005795 hdd_err("wiphy registration failed");
Ashish Kumar Dhanotiya4da37922017-04-05 14:17:56 +05305796 return ret_val;
5797 }
5798
5799 hdd_program_country_code(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800
Amar Singhale4f28ee2015-10-21 14:36:56 -07005801 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005802}
5803
Ravi Joshie2331e82015-07-01 18:18:54 -07005804/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005805 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005806 * @hdd_ctx - handle to hdd context
5807 * @tx_packets - transmit packet count
5808 * @rx_packets - receive packet count
5809 *
5810 * The function controls the bus bandwidth and dynamic control of
5811 * tcp delayed ack configuration
5812 *
5813 * Returns: None
5814 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005815#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005816static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5817 const uint64_t tx_packets,
5818 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005821 uint64_t temp_rx = 0;
5822 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005823 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannac3da7062017-02-08 21:08:56 -08005824 static enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005825 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005826 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005827 uint16_t index = 0;
5828 bool vote_level_change = false;
5829 bool rx_level_change = false;
5830 bool tx_level_change = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005833 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005834 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005835 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005836 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005837 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005838 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005839 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005842 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5843 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 hdd_ctx->cur_vote_level = next_vote_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005845 vote_level_change = true;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005846 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305847 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305848 if (hdd_ctx->hbw_requested) {
5849 pld_remove_pm_qos(hdd_ctx->parent_dev);
5850 hdd_ctx->hbw_requested = false;
5851 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305852 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005853 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305854 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305855 if (!hdd_ctx->hbw_requested) {
5856 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5857 hdd_ctx->hbw_requested = true;
5858 }
5859
Nirav Shah3bbfa512016-05-12 16:43:49 +05305860 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005861 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305862 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005863 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005865
5866 /* fine-tuning parameters for RX Flows */
5867 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5868
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869 hdd_ctx->prev_rx = rx_packets;
Mohit Khannab1dd1e82017-02-04 15:14:38 -08005870
Ravi Joshifed83572016-10-07 16:20:37 -07005871 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5872 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5873 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5874 next_rx_level = WLAN_SVC_TP_HIGH;
5875 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005876 } else {
Ravi Joshib89e7f72016-09-07 13:43:15 -07005877 hdd_ctx->rx_high_ind_cnt = 0;
Mohit Khannac3da7062017-02-08 21:08:56 -08005878 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005879 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005881 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005882 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005883 next_rx_level, temp_rx);
5884 hdd_ctx->cur_rx_level = next_rx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005885 rx_level_change = true;
Ravi Joshie2331e82015-07-01 18:18:54 -07005886 /* Send throughput indication only if it is enabled.
5887 * Disabling tcp_del_ack will revert the tcp stack behavior
5888 * to default delayed ack. Note that this will disable the
5889 * dynamic delayed ack mechanism across the system
5890 */
5891 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305892 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5893 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005894 &next_rx_level,
5895 sizeof(next_rx_level));
5896 }
5897
Mohit Khannae71e2262015-11-10 09:37:24 -08005898 /* fine-tuning parameters for TX Flows */
5899 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5900 hdd_ctx->prev_tx = tx_packets;
5901 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5902 next_tx_level = WLAN_SVC_TP_HIGH;
5903 else
5904 next_tx_level = WLAN_SVC_TP_LOW;
5905
5906 if (hdd_ctx->cur_tx_level != next_tx_level) {
5907 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5908 next_tx_level, temp_tx);
5909 hdd_ctx->cur_tx_level = next_tx_level;
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005910 tx_level_change = true;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305911 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5912 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005913 &next_tx_level,
5914 sizeof(next_tx_level));
5915 }
5916
Mohit Khannaafff9fb2016-11-16 20:22:03 -08005917 index = hdd_ctx->hdd_txrx_hist_idx;
5918
5919 if (vote_level_change || tx_level_change || rx_level_change) {
5920 hdd_ctx->hdd_txrx_hist[index].next_tx_level = next_tx_level;
5921 hdd_ctx->hdd_txrx_hist[index].next_rx_level = next_rx_level;
5922 hdd_ctx->hdd_txrx_hist[index].next_vote_level = next_vote_level;
5923 hdd_ctx->hdd_txrx_hist[index].interval_rx = rx_packets;
5924 hdd_ctx->hdd_txrx_hist[index].interval_tx = tx_packets;
5925 hdd_ctx->hdd_txrx_hist[index].qtime = qdf_get_log_timestamp();
5926 hdd_ctx->hdd_txrx_hist_idx++;
5927 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
5928 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929}
5930
5931#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305932static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005933{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305934 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5935 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005936 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305937 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305938 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5939 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940 uint64_t total_tx = 0, total_rx = 0;
5941 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305942 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305943 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005944 bool connected = false;
5945 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5946
Prashanth Bhattaab004382016-10-11 16:08:11 -07005947 if (wlan_hdd_validate_context(hdd_ctx))
5948 return;
5949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305951 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005952 status =
5953 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5954
5955 if (adapterNode->pAdapter == NULL)
5956 continue;
5957 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305958 /*
5959 * Validate magic so we don't end up accessing
5960 * an invalid adapter.
5961 */
5962 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5963 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005965 if ((adapter->device_mode == QDF_STA_MODE ||
5966 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5968 != eConnectionState_Associated) {
5969
5970 continue;
5971 }
5972
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005973 if ((adapter->device_mode == QDF_SAP_MODE ||
5974 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005975 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5976
5977 continue;
5978 }
5979
5980 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5981 adapter->prev_tx_packets);
5982 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5983 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305984
5985 if (adapter->device_mode == QDF_SAP_MODE ||
5986 adapter->device_mode == QDF_P2P_GO_MODE ||
5987 adapter->device_mode == QDF_IBSS_MODE) {
5988
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08005989 ret = cdp_get_intra_bss_fwd_pkts_count(
5990 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305991 adapter->sessionId,
5992 &fwd_tx_packets, &fwd_rx_packets);
5993 if (ret == A_OK) {
5994 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5995 fwd_tx_packets,
5996 adapter->prev_fwd_tx_packets);
5997 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5998 fwd_tx_packets,
5999 adapter->prev_fwd_rx_packets);
6000 }
6001 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006002
6003 total_rx += adapter->stats.rx_packets;
6004 total_tx += adapter->stats.tx_packets;
6005
6006 spin_lock_bh(&hdd_ctx->bus_bw_lock);
6007 adapter->prev_tx_packets = adapter->stats.tx_packets;
6008 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306009 adapter->prev_fwd_tx_packets = fwd_tx_packets;
6010 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006011 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
6012 connected = true;
6013 }
6014
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05306015 /* add intra bss forwarded tx and rx packets */
6016 tx_packets += fwd_tx_packets_diff;
6017 rx_packets += fwd_rx_packets_diff;
6018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006019 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
6020 tx_packets += (uint64_t)ipa_tx_packets;
6021 rx_packets += (uint64_t)ipa_rx_packets;
6022
6023 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006024 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006025 return;
6026 }
6027
Yuanyuan Liu13738502016-04-06 17:41:37 -07006028 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006029
6030 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
6031 hdd_ipa_uc_stat_request(adapter, 2);
6032
Dustin Brown2ed60362017-01-18 12:25:50 -08006033 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08006034 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08006035 if (hdd_ctx->bus_bw_timer_running)
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05306036 qdf_timer_mod(&hdd_ctx->bus_bw_timer,
Dustin Brownfce08d12017-01-17 16:29:38 -08006037 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08006038 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006039}
Prashanth Bhattaab004382016-10-11 16:08:11 -07006040
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306041/**
6042 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
6043 * @arg: Argument of timer function
6044 *
6045 * Schedule a workqueue in this function where all the processing is done.
6046 *
6047 * Return: None.
6048 */
6049static void __hdd_bus_bw_cbk(void *arg)
6050{
6051 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
6052
6053 if (wlan_hdd_validate_context(hdd_ctx))
6054 return;
6055
6056 schedule_work(&hdd_ctx->bus_bw_work);
6057}
6058
6059/**
6060 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
6061 * @arg: Argument of timer function
6062 *
6063 * Return: None.
6064 */
6065static void hdd_bus_bw_cbk(void *arg)
6066{
6067 cds_ssr_protect(__func__);
6068 __hdd_bus_bw_cbk(arg);
6069 cds_ssr_unprotect(__func__);
6070}
6071
Prashanth Bhattaab004382016-10-11 16:08:11 -07006072int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
6073{
6074 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306075 INIT_WORK(&hdd_ctx->bus_bw_work,
6076 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08006077 hdd_ctx->bus_bw_timer_running = false;
6078 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306079 qdf_timer_init(NULL,
6080 &hdd_ctx->bus_bw_timer,
6081 hdd_bus_bw_cbk, (void *)hdd_ctx,
6082 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006083
6084 return 0;
6085}
6086
6087void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
6088{
Dustin Brownfce08d12017-01-17 16:29:38 -08006089 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07006090 hdd_reset_tcp_delack(hdd_ctx);
6091
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006092 hdd_debug("wait for bus bw work to flush");
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306093 cancel_work_sync(&hdd_ctx->bus_bw_work);
6094 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08006095 hdd_ctx->bus_bw_timer_running = false;
6096 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006097}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098#endif
6099
6100/**
Nirav Shahed34b212016-04-25 10:59:16 +05306101 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
6102 * @hdd_ctx: hdd context
6103 *
6104 * Return: 0 for success or error code
6105 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006106static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05306107{
6108 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
6109 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
6110 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006111 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05306112 return -ENOMEM;
6113 }
6114 return 0;
6115}
6116
6117/**
6118 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
6119 * @hdd_ctx: hdd context
6120 *
6121 * Return: none
6122 */
6123void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
6124{
Ashish Kumar Dhanotiyaaa2b17c2017-03-29 00:41:32 +05306125 if (!hdd_ctx || hdd_ctx->hdd_txrx_hist == NULL)
6126 return;
6127
6128 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
6129 hdd_ctx->hdd_txrx_hist = NULL;
Nirav Shahed34b212016-04-25 10:59:16 +05306130}
6131
Nirav Shahda008342016-05-17 18:50:40 +05306132static uint8_t *convert_level_to_string(uint32_t level)
6133{
6134 switch (level) {
6135 /* initialize the wlan sub system */
6136 case WLAN_SVC_TP_NONE:
6137 return "NONE";
6138 case WLAN_SVC_TP_LOW:
6139 return "LOW";
6140 case WLAN_SVC_TP_MEDIUM:
6141 return "MED";
6142 case WLAN_SVC_TP_HIGH:
6143 return "HIGH";
6144 default:
6145 return "INVAL";
6146 }
6147}
6148
Nirav Shahed34b212016-04-25 10:59:16 +05306149
6150/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006151 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
6152 * @hdd_ctx: hdd context
6153 *
6154 * Return: none
6155 */
6156void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
6157{
6158 int i;
6159
6160#ifdef MSM_PLATFORM
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006161 hdd_debug("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05306162 hdd_ctx->config->busBandwidthComputeInterval);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006163 hdd_debug("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006164 hdd_ctx->config->busBandwidthHighThreshold,
6165 hdd_ctx->config->busBandwidthMediumThreshold,
6166 hdd_ctx->config->busBandwidthLowThreshold);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006167 hdd_debug("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306168 hdd_ctx->config->enable_tcp_delack);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006169 hdd_debug("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006170 hdd_ctx->config->tcpDelackThresholdHigh,
6171 hdd_ctx->config->tcpDelackThresholdLow);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006172 hdd_debug("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05306173 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174#endif
6175
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006176 hdd_debug("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306177 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
6178
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006179 hdd_debug("[index][timestamp]: interval_rx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006180
6181 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006182 /* using hdd_log to avoid printing function name */
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006183 if (hdd_ctx->hdd_txrx_hist[i].qtime > 0)
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006184 hdd_log(QDF_TRACE_LEVEL_ERROR,
Mohit Khannaafff9fb2016-11-16 20:22:03 -08006185 "[%3d][%15llu]: %6llu, %6llu, %s, %s, %s",
6186 i, hdd_ctx->hdd_txrx_hist[i].qtime,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006187 hdd_ctx->hdd_txrx_hist[i].interval_rx,
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006188 hdd_ctx->hdd_txrx_hist[i].interval_tx,
6189 convert_level_to_string(
6190 hdd_ctx->hdd_txrx_hist[i].
6191 next_vote_level),
6192 convert_level_to_string(
6193 hdd_ctx->hdd_txrx_hist[i].
6194 next_rx_level),
6195 convert_level_to_string(
6196 hdd_ctx->hdd_txrx_hist[i].
6197 next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006198 }
6199 return;
6200}
6201
6202/**
6203 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
6204 * @hdd_ctx: hdd context
6205 *
6206 * Return: none
6207 */
6208void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
6209{
6210 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05306211 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
6212 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006213}
6214
6215/**
6216 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
6217 * @pHddCtx: hdd context
6218 *
6219 * Return: none
6220 */
6221void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
6222{
6223
6224 hdd_adapter_t *adapter = NULL;
6225 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306226 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006227 int i;
Nirav Shahda008342016-05-17 18:50:40 +05306228 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006229
6230 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306231 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006232 adapter = adapter_node->pAdapter;
6233
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006234 hdd_debug("Netif queue operation statistics:");
6235 hdd_debug("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05306236 adapter->sessionId, adapter->device_mode);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006237 hdd_debug("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05306238 curr_time = qdf_system_ticks();
6239 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05306240 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05306241 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05306242 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306243 unpause = adapter->total_unpause_time;
6244 } else {
Nirav Shahda008342016-05-17 18:50:40 +05306245 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306246 pause = adapter->total_pause_time;
6247 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006248 hdd_debug("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05306249 qdf_system_ticks_to_msecs(total),
6250 qdf_system_ticks_to_msecs(pause),
6251 qdf_system_ticks_to_msecs(unpause));
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006252 hdd_debug("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006253
Nirav Shahda008342016-05-17 18:50:40 +05306254 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
6255 qdf_time_t pause_delta = 0;
6256
6257 if (adapter->pause_map & (1 << i))
6258 pause_delta = delta;
6259
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006260 /* using hdd_log to avoid printing function name */
6261 hdd_log(QDF_TRACE_LEVEL_ERROR,
6262 "%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006263 hdd_reason_type_to_string(i),
6264 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05306265 adapter->queue_oper_stats[i].unpause_count,
6266 qdf_system_ticks_to_msecs(
6267 adapter->queue_oper_stats[i].total_pause_time +
6268 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006269 }
6270
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006271 hdd_debug("Netif queue operation history:");
6272 hdd_debug("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05306273 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
6274
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006275 hdd_debug("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006276
6277 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Mohit Khanna3e2115b2016-10-11 13:18:29 -07006278 /* using hdd_log to avoid printing function name */
6279 if (adapter->queue_oper_history[i].time == 0)
6280 continue;
6281 hdd_log(QDF_TRACE_LEVEL_ERROR,
6282 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05306283 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006284 adapter->queue_oper_history[i].time),
6285 hdd_action_type_to_string(
6286 adapter->queue_oper_history[i].netif_action),
6287 hdd_reason_type_to_string(
6288 adapter->queue_oper_history[i].netif_reason),
6289 adapter->queue_oper_history[i].pause_map);
6290 }
6291
6292 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6293 adapter_node = next;
6294 }
6295
6296
6297}
6298
6299/**
6300 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
6301 * @hdd_ctx: hdd context
6302 *
6303 * Return: none
6304 */
6305void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
6306{
6307 hdd_adapter_t *adapter = NULL;
6308 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306309 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006310
6311 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306312 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006313 adapter = adapter_node->pAdapter;
6314
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306315 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006316 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306317 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006318 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05306319 adapter->history_index = 0;
6320 adapter->start_time = adapter->last_time = qdf_system_ticks();
6321 adapter->total_pause_time = 0;
6322 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006323 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6324 adapter_node = next;
6325 }
6326}
6327
6328/**
6329 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
6330 * @halHandle: Hal handle
6331 * @pContext: Pointer to the context
6332 * @sessionId: Session ID
6333 * @scanId: Scan ID
6334 * @status: Status
6335 *
6336 * This is the callback to be executed when 11d scan is completed to flush out
6337 * the scan results
6338 *
6339 * 11d scan is done during driver load and is a passive scan on all
6340 * channels supported by the device, 11d scans may find some APs on
6341 * frequencies which are forbidden to be used in the regulatory domain
6342 * the device is operating in. If these APs are notified to the supplicant
6343 * it may try to connect to these APs, thus flush out all the scan results
6344 * which are present in SME after 11d scan is done.
6345 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306346 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306348static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006349 uint8_t sessionId, uint32_t scanId,
6350 eCsrScanStatus status)
6351{
6352 ENTER();
6353
6354 sme_scan_flush_result(halHandle);
6355
6356 EXIT();
6357
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306358 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006359}
6360
6361#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6362/**
6363 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
6364 * @hdd_ctx: hdd global context
6365 *
6366 * Return: none
6367 */
6368static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6369{
6370 uint8_t i;
6371
6372 mutex_init(&hdd_ctx->op_ctx.op_lock);
6373 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6374 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6375 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
6376 }
6377}
6378#else
6379static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6380{
6381}
6382#endif
6383
Yingying Tang95409972016-10-20 15:16:15 +08006384#ifdef WLAN_FEATURE_WOW_PULSE
6385/**
6386 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
6387 * @phddctx: hdd_context_t structure pointer
6388 * @enable: enable or disable this behaviour
6389 *
6390 * Return: int
6391 */
6392static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6393{
6394 struct hdd_config *pcfg_ini = phddctx->config;
6395 struct wow_pulse_mode wow_pulse_set_info;
6396 QDF_STATUS status;
6397
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006398 hdd_debug("wow pulse enable flag is %d", enable);
Yingying Tang95409972016-10-20 15:16:15 +08006399
6400 if (false == phddctx->config->wow_pulse_support)
6401 return 0;
6402
6403 /* prepare the request to send to SME */
6404 if (enable == true) {
6405 wow_pulse_set_info.wow_pulse_enable = true;
6406 wow_pulse_set_info.wow_pulse_pin =
6407 pcfg_ini->wow_pulse_pin;
6408 wow_pulse_set_info.wow_pulse_interval_low =
6409 pcfg_ini->wow_pulse_interval_low;
6410 wow_pulse_set_info.wow_pulse_interval_high =
6411 pcfg_ini->wow_pulse_interval_high;
6412 } else {
6413 wow_pulse_set_info.wow_pulse_enable = false;
6414 wow_pulse_set_info.wow_pulse_pin = 0;
6415 wow_pulse_set_info.wow_pulse_interval_low = 0;
6416 wow_pulse_set_info.wow_pulse_interval_high = 0;
6417 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006418 hdd_debug("enable %d pin %d low %d high %d",
Yingying Tang95409972016-10-20 15:16:15 +08006419 wow_pulse_set_info.wow_pulse_enable,
6420 wow_pulse_set_info.wow_pulse_pin,
6421 wow_pulse_set_info.wow_pulse_interval_low,
6422 wow_pulse_set_info.wow_pulse_interval_high);
6423
6424 status = sme_set_wow_pulse(&wow_pulse_set_info);
6425 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006426 hdd_debug("sme_set_wow_pulse failure!");
Yingying Tang95409972016-10-20 15:16:15 +08006427 return -EIO;
6428 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006429 hdd_debug("sme_set_wow_pulse success!");
Yingying Tang95409972016-10-20 15:16:15 +08006430 return 0;
6431}
6432#else
6433static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6434{
6435 return 0;
6436}
6437#endif
6438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006439#ifdef WLAN_FEATURE_FASTPATH
6440/**
6441 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
6442 * @hdd_cfg: hdd config
6443 * @context: lower layer context
6444 *
6445 * Return: none
6446 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306447void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006448 void *context)
6449{
6450 if (hdd_cfg->fastpath_enable)
6451 hif_enable_fastpath(context);
6452}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006453#endif
6454
Yuanyuan Liu13738502016-04-06 17:41:37 -07006455#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006456/**
6457 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006458 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006459 * @level: thermal level
6460 *
6461 * Change IPA data path to SW path when the thermal throttle level greater
6462 * than 0, and restore the original data path when throttle level is 0
6463 *
6464 * Return: none
6465 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006466static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006467{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006468 hdd_context_t *hdd_ctx = context;
6469
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006470 /* Change IPA to SW path when throttle level greater than 0 */
6471 if (level > THROTTLE_LEVEL_0)
6472 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
6473 else
6474 /* restore original concurrency mode */
6475 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
6476}
6477
6478/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306479 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
6480 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05306481 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306483 * Get a safe channel to restart SAP. PCL already takes into account the
6484 * unsafe channels. So, the PCL is validated with the ACS range to provide
6485 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006486 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306487 * Return: Channel number to restart SAP in case of success. In case of any
6488 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006489 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306490static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
6491 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006492{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306493 struct sir_pcl_list pcl;
6494 QDF_STATUS status;
6495 uint32_t i, j;
6496 tHalHandle *hal_handle;
6497 hdd_context_t *hdd_ctx;
6498 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006499
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306500 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6501 if (!hdd_ctx) {
6502 hdd_err("invalid HDD context");
6503 return INVALID_CHANNEL_ID;
6504 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006505
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306506 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6507 if (!hal_handle) {
6508 hdd_err("invalid HAL handle");
6509 return INVALID_CHANNEL_ID;
6510 }
6511
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006512 status = policy_mgr_get_pcl_for_existing_conn(hdd_ctx->hdd_psoc,
6513 PM_SAP_MODE, pcl.pcl_list, &pcl.pcl_len,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306514 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6515 if (QDF_IS_STATUS_ERROR(status)) {
6516 hdd_err("Get PCL failed");
6517 return INVALID_CHANNEL_ID;
6518 }
6519
6520 if (!pcl.pcl_len) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006521 hdd_err("pcl length is zero. this is not expected");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306522 return INVALID_CHANNEL_ID;
6523 }
6524
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006525 hdd_debug("start:%d end:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306526 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6527 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6528
6529 /* PCL already takes unsafe channel into account */
6530 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006531 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306532 if ((pcl.pcl_list[i] >=
6533 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6534 (pcl.pcl_list[i] <=
6535 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006536 hdd_debug("found PCL safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306537 return pcl.pcl_list[i];
6538 }
6539 }
6540
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006541 hdd_debug("no safe channel from PCL found in ACS range");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306542
6543 /* Try for safe channel from all valid channel */
6544 pcl.pcl_len = MAX_NUM_CHAN;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006545 status = sme_get_cfg_valid_channels(pcl.pcl_list,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306546 &pcl.pcl_len);
6547 if (QDF_IS_STATUS_ERROR(status)) {
6548 hdd_err("error in getting valid channel list");
6549 return INVALID_CHANNEL_ID;
6550 }
6551
6552 for (i = 0; i < pcl.pcl_len; i++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006553 hdd_debug("chan[%d]:%d", i, pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306554 found = false;
6555 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006556 if (pcl.pcl_list[i] ==
6557 hdd_ctx->unsafe_channel_list[j]) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006558 hdd_debug("unsafe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306559 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006560 break;
6561 }
6562 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306563
6564 if (found)
6565 continue;
6566
6567 if ((pcl.pcl_list[i] >=
6568 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6569 (pcl.pcl_list[i] <=
6570 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006571 hdd_debug("found safe chan:%d", pcl.pcl_list[i]);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306572 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006573 }
6574 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306575
6576 return INVALID_CHANNEL_ID;
6577}
6578
6579/**
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006580 * hdd_switch_sap_channel() - Move SAP to the given channel
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306581 * @adapter: AP adapter
6582 * @channel: Channel
6583 *
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006584 * Moves the SAP interface by invoking the function which
6585 * executes the callback to perform channel switch using (E)CSA.
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306586 *
6587 * Return: None
6588 */
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006589void hdd_switch_sap_channel(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306590{
6591 hdd_ap_ctx_t *hdd_ap_ctx;
6592 tHalHandle *hal_handle;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006593 hdd_context_t *hdd_ctx;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306594
6595 if (!adapter) {
6596 hdd_err("invalid adapter");
6597 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006598 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306599
6600 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6601
6602 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6603 if (!hal_handle) {
6604 hdd_err("invalid HAL handle");
6605 return;
6606 }
6607
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006608 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6609
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306610 hdd_ap_ctx->sapConfig.channel = channel;
6611 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6612 hdd_ap_ctx->sapConfig.ch_width_orig;
6613
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006614 hdd_debug("chan:%d width:%d",
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306615 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6616
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006617 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306618 hdd_ap_ctx->sapConfig.sec_ch,
6619 &hdd_ap_ctx->sapConfig.ch_params);
6620
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006621 policy_mgr_change_sap_channel_with_csa(hdd_ctx->hdd_psoc,
6622 adapter->sessionId, channel,
6623 hdd_ap_ctx->sapConfig.ch_width_orig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006624}
Kapil Gupta8878ad92017-02-13 11:56:04 +05306625
6626int hdd_update_acs_timer_reason(hdd_adapter_t *adapter, uint8_t reason)
6627{
6628 struct hdd_external_acs_timer_context *timer_context;
6629
6630 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6631
6632 if (QDF_TIMER_STATE_RUNNING ==
6633 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
6634 ap.vendor_acs_timer)) {
6635 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
6636 }
6637 timer_context = (struct hdd_external_acs_timer_context *)
6638 adapter->sessionCtx.ap.vendor_acs_timer.user_data;
6639 timer_context->reason = reason;
6640 qdf_mc_timer_start(&adapter->sessionCtx.ap.vendor_acs_timer,
6641 WLAN_VENDOR_ACS_WAIT_TIME);
6642 /* Update config to application */
6643 hdd_cfg80211_update_acs_config(adapter, reason);
6644 hdd_notice("Updated ACS config to nl with reason %d", reason);
6645
6646 return 0;
6647}
6648
Agrawal Ashish467dde42016-09-08 18:44:22 +05306649/**
6650 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6651 * @hdd_ctx: hdd context pointer
6652 *
6653 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6654 * and if ACS is enabled, driver will ask userspace to restart the
6655 * sap. User space on LTE coex indication restart driver.
6656 *
6657 * Return - none
6658 */
6659void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6660{
6661 QDF_STATUS status;
6662 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6663 hdd_adapter_t *adapter_temp;
6664 uint32_t i;
6665 bool found = false;
6666 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006667
Agrawal Ashish467dde42016-09-08 18:44:22 +05306668 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6669 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6670 adapter_temp = adapter_node->pAdapter;
6671
6672 if (!adapter_temp) {
6673 hdd_err("adapter is NULL, moving to next one");
6674 goto next_adapater;
6675 }
6676
6677 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6678 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006679 hdd_debug("skip device mode:%d acs:%d",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306680 adapter_temp->device_mode,
6681 adapter_temp->sessionCtx.ap.sapConfig.
6682 acs_cfg.acs_mode);
6683 goto next_adapater;
6684 }
6685
6686 found = false;
6687 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006688 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306689 hdd_ctxt->unsafe_channel_list[i]) {
6690 found = true;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006691 hdd_debug("operating ch:%d is unsafe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306692 adapter_temp->sessionCtx.ap.operatingChannel);
6693 break;
6694 }
6695 }
6696
6697 if (!found) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006698 hdd_debug("ch:%d is safe. no need to change channel",
Agrawal Ashish467dde42016-09-08 18:44:22 +05306699 adapter_temp->sessionCtx.ap.operatingChannel);
6700 goto next_adapater;
6701 }
6702
Kapil Gupta8878ad92017-02-13 11:56:04 +05306703 if (hdd_ctxt->config->vendor_acs_support &&
6704 hdd_ctxt->config->acs_support_for_dfs_ltecoex) {
6705 hdd_update_acs_timer_reason(adapter_temp,
6706 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
6707 goto next_adapater;
6708 } else
6709 restart_chan =
6710 hdd_get_safe_channel_from_pcl_and_acs_range(
Agrawal Ashish467dde42016-09-08 18:44:22 +05306711 adapter_temp);
6712 if (!restart_chan) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006713 hdd_err("fail to restart SAP");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306714 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006715 /*
6716 * SAP restart due to unsafe channel. While
6717 * restarting the SAP, make sure to clear
6718 * acs_channel, channel to reset to
6719 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306720 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006721 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306722 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6723 adapter_temp->sessionCtx.ap.sapConfig.channel =
6724 AUTO_CHANNEL_SELECT;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006725 hdd_debug("sending coex indication");
Agrawal Ashish467dde42016-09-08 18:44:22 +05306726 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6727 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006728 hdd_switch_sap_channel(adapter_temp, restart_chan);
Agrawal Ashish467dde42016-09-08 18:44:22 +05306729 }
6730
6731next_adapater:
6732 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6733 adapter_node = next;
6734 }
6735}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006736/**
6737 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6738 * @adapter: HDD adapter pointer
6739 * @indParam: Channel avoid notification parameter
6740 *
6741 * Avoid channel notification from FW handler.
6742 * FW will send un-safe channel list to avoid over wrapping.
6743 * hostapd should not use notified channel
6744 *
6745 * Return: None
6746 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306747void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006748{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006749 hdd_context_t *hdd_ctxt;
6750 tSirChAvoidIndType *ch_avoid_indi;
6751 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006752 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6753 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006754 uint16_t start_channel;
6755 uint16_t end_channel;
6756 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006757 tHddAvoidFreqList hdd_avoid_freq_list;
6758 uint32_t i;
6759
6760 /* Basic sanity */
6761 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006762 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006763 return;
6764 }
6765
6766 hdd_ctxt = (hdd_context_t *) hdd_context;
6767 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6768 cds_context = hdd_ctxt->pcds_context;
6769
6770 /* Make unsafe channel list */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006771 hdd_debug("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006772 ch_avoid_indi->avoid_range_count);
6773
6774 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306775 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006776 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6777 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6778 ch_avoid_indi->avoid_freq_range[i].start_freq;
6779 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6780 ch_avoid_indi->avoid_freq_range[i].end_freq;
6781 }
6782 hdd_avoid_freq_list.avoidFreqRangeCount =
6783 ch_avoid_indi->avoid_range_count;
6784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006785 /* clear existing unsafe channel cache */
6786 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306787 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006788 sizeof(hdd_ctxt->unsafe_channel_list));
6789
6790 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6791 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006792 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006793 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006794 break;
6795 }
6796
6797 start_channel = ieee80211_frequency_to_channel(
6798 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6799 end_channel = ieee80211_frequency_to_channel(
6800 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006801 hdd_debug("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006802 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6803 start_channel,
6804 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6805 end_channel);
6806
6807 /* do not process frequency bands that are not mapped to
6808 * predefined channels
6809 */
6810 if (start_channel == 0 || end_channel == 0)
6811 continue;
6812
Amar Singhalb8d4f152016-02-10 10:21:43 -08006813 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6814 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006815 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006816 ch_avoid_indi->avoid_freq_range[
6817 range_loop].start_freq) {
6818 start_channel_idx = channel_loop;
6819 break;
6820 }
6821 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006822 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6823 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006824 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006825 ch_avoid_indi->avoid_freq_range[
6826 range_loop].end_freq) {
6827 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006828 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006829 ch_avoid_indi->avoid_freq_range[
6830 range_loop].end_freq)
6831 end_channel_idx--;
6832 break;
6833 }
6834 }
6835
Amar Singhalb8d4f152016-02-10 10:21:43 -08006836 if (start_channel_idx == INVALID_CHANNEL ||
6837 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006838 continue;
6839
6840 for (channel_loop = start_channel_idx; channel_loop <=
6841 end_channel_idx; channel_loop++) {
6842 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006843 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006844 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006845 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006846 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006847 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006848 break;
6849 }
6850 }
6851 }
6852
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006853 hdd_debug("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006854 hdd_ctxt->unsafe_channel_count);
6855
Yuanyuan Liu13738502016-04-06 17:41:37 -07006856 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6857 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006858 hdd_ctxt->unsafe_channel_count)) {
6859 hdd_err("Failed to set unsafe channel");
6860
6861 /* clear existing unsafe channel cache */
6862 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306863 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006864 sizeof(hdd_ctxt->unsafe_channel_list));
6865
6866 return;
6867 }
6868
6869 for (channel_loop = 0;
6870 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006871 hdd_debug("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006872 hdd_ctxt->unsafe_channel_list[channel_loop]);
6873 }
6874
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306875 /*
6876 * first update the unsafe channel list to the platform driver and
6877 * send the avoid freq event to the application
6878 */
6879 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6880
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306881 if (!hdd_ctxt->unsafe_channel_count) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006882 hdd_debug("no unsafe channels - not restarting SAP");
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306883 return;
6884 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306885 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006886 return;
6887}
6888
6889/**
6890 * hdd_init_channel_avoidance() - Initialize channel avoidance
6891 * @hdd_ctx: HDD global context
6892 *
6893 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006894 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006895 * down to the lower layers. Then subscribe to subsequent channel
6896 * avoidance events.
6897 *
6898 * Return: None
6899 */
6900static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6901{
6902 uint16_t unsafe_channel_count;
6903 int index;
6904
Yuanyuan Liu13738502016-04-06 17:41:37 -07006905 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6906 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006907 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006908 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006909
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006910 hdd_debug("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006911 hdd_ctx->unsafe_channel_count);
6912
Anurag Chouhan6d760662016-02-20 16:05:43 +05306913 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006914 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006915
6916 for (index = 0; index < unsafe_channel_count; index++) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08006917 hdd_debug("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006918 hdd_ctx->unsafe_channel_list[index]);
6919
6920 }
6921
6922 /* Plug in avoid channel notification callback */
6923 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6924}
6925#else
6926static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6927{
6928}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006929static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006930{
6931}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006932#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006933
6934/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006935 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6936 * user space
6937 * @frame_ind: Management frame data to be informed.
6938 *
6939 * This function is used to indicate management frame to
6940 * user space
6941 *
6942 * Return: None
6943 *
6944 */
6945void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6946{
6947 hdd_context_t *hdd_ctx = NULL;
6948 hdd_adapter_t *adapter = NULL;
6949 void *cds_context = NULL;
6950 int i;
6951
6952 /* Get the global VOSS context.*/
6953 cds_context = cds_get_global_context();
6954 if (!cds_context) {
6955 hdd_err("Global CDS context is Null");
6956 return;
6957 }
6958 /* Get the HDD context.*/
6959 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6960
6961 if (0 != wlan_hdd_validate_context(hdd_ctx))
6962 return;
6963
6964 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6965 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6966 adapter =
6967 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6968 if (adapter)
6969 break;
6970 }
6971 } else {
6972 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6973 frame_ind->sessionId);
6974 }
6975
6976 if ((NULL != adapter) &&
6977 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6978 __hdd_indicate_mgmt_frame(adapter,
6979 frame_ind->frame_len,
6980 frame_ind->frameBuf,
6981 frame_ind->frameType,
6982 frame_ind->rxChan,
6983 frame_ind->rxRssi);
6984 return;
6985}
6986
Kapil Gupta8878ad92017-02-13 11:56:04 +05306987static void hdd_lte_coex_restart_sap(hdd_adapter_t *adapter,
6988 hdd_context_t *hdd_ctx)
6989{
6990 uint8_t restart_chan = 0;
6991
6992 restart_chan =
6993 hdd_get_safe_channel_from_pcl_and_acs_range(adapter);
6994 if (!restart_chan) {
6995 hdd_alert("fail to restart SAP");
6996 } else {
6997 /* SAP restart due to unsafe channel. While restarting
6998 * the SAP, make sure to clear acs_channel, channel to
6999 * reset to 0. Otherwise these settings will override
7000 * the ACS while restart.
7001 */
7002 hdd_ctx->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
7003 adapter->sessionCtx.ap.sapConfig.channel =
7004 AUTO_CHANNEL_SELECT;
7005 hdd_info("sending coex indication");
7006 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
7007 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08007008 hdd_switch_sap_channel(adapter, restart_chan);
Kapil Gupta8878ad92017-02-13 11:56:04 +05307009 }
7010}
7011
7012void hdd_acs_response_timeout_handler(void *context)
7013{
7014 struct hdd_external_acs_timer_context *timer_context =
7015 (struct hdd_external_acs_timer_context *)context;
7016 hdd_adapter_t *adapter;
7017 hdd_context_t *hdd_ctx;
7018 uint8_t reason;
7019
7020 ENTER();
7021 if (!timer_context) {
7022 hdd_err("invlaid timer context");
7023 return;
7024 }
7025 adapter = timer_context->adapter;
7026 reason = timer_context->reason;
7027
7028
7029 if ((!adapter) ||
7030 (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
7031 hdd_err("invalid adapter or adapter has invalid magic");
7032 return;
7033 }
7034 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7035 if (wlan_hdd_validate_context(hdd_ctx))
7036 return;
7037
7038 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
7039 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
7040 else
7041 return;
7042
7043 hdd_err("ACS timeout happened for %s reason %d",
7044 adapter->dev->name, reason);
7045 switch (reason) {
7046 /* SAP init case */
7047 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
7048 wlan_sap_set_vendor_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7049 false);
7050 wlan_hdd_cfg80211_start_acs(adapter);
7051 break;
7052 /* DFS detected on current channel */
7053 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
7054 wlan_sap_update_next_channel(
7055 WLAN_HDD_GET_SAP_CTX_PTR(adapter), 0, 0);
7056 sme_update_new_channel_event(WLAN_HDD_GET_HAL_CTX(adapter),
7057 adapter->sessionId);
7058 break;
7059 /* LTE coex event on current channel */
7060 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
7061 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
7062 break;
7063 default:
7064 hdd_info("invalid reason for timer invoke");
7065
7066 }
7067}
7068
Rajeev Kumard004abc2016-02-17 12:09:56 -08007069/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007070 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
7071 * @hdd_ctx: HDD context
7072 *
7073 * Disables all the dual mac features like DBS, Agile DFS etc.
7074 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307075 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007076 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307077static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007078{
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007079 struct policy_mgr_dual_mac_config cfg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307080 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007081
7082 if (!hdd_ctx) {
7083 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307084 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007085 }
7086
7087 cfg.scan_config = 0;
7088 cfg.fw_mode_config = 0;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007089 cfg.set_dual_mac_cb = policy_mgr_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007090
7091 hdd_debug("Disabling all dual mac features...");
7092
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007093 status = sme_soc_set_dual_mac_config(cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307094 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007095 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
7096 return status;
7097 }
7098
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307099 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007100}
7101
7102/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007103 * hdd_override_ini_config - Override INI config
7104 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007105 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007106 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007107 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007108 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007109 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007110static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007111{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007112
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007113 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
7114 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007115 hdd_debug("Module enable_dfs_chan_scan set to %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007116 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007117 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007118 if (0 == enable_11d || 1 == enable_11d) {
7119 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007120 hdd_debug("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007121 }
Leo Chang11545d62016-10-17 14:53:50 -07007122
7123 if (!hdd_ipa_is_present(hdd_ctx))
7124 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007125}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007126
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007127/**
7128 * hdd_set_trace_level_for_each - Set trace level for each INI config
7129 * @hdd_ctx - HDD context
7130 *
7131 * Set trace level for each module based on INI config.
7132 *
7133 * Return: None
7134 */
7135static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
7136{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307137 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
7138 hdd_ctx->config->qdf_trace_enable_wdi);
7139 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
7140 hdd_ctx->config->qdf_trace_enable_hdd);
7141 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
7142 hdd_ctx->config->qdf_trace_enable_sme);
7143 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
7144 hdd_ctx->config->qdf_trace_enable_pe);
7145 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
7146 hdd_ctx->config->qdf_trace_enable_wma);
7147 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
7148 hdd_ctx->config->qdf_trace_enable_sys);
7149 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
7150 hdd_ctx->config->qdf_trace_enable_qdf);
7151 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
7152 hdd_ctx->config->qdf_trace_enable_sap);
7153 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
7154 hdd_ctx->config->qdf_trace_enable_hdd_sap);
7155 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
7156 hdd_ctx->config->qdf_trace_enable_bmi);
7157 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
7158 hdd_ctx->config->qdf_trace_enable_cfg);
7159 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
7160 hdd_ctx->config->qdf_trace_enable_epping);
7161 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
7162 hdd_ctx->config->qdf_trace_enable_qdf_devices);
7163 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05307164 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307165 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
7166 hdd_ctx->config->qdf_trace_enable_htc);
7167 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
7168 hdd_ctx->config->qdf_trace_enable_hif);
7169 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
7170 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
7171 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
7172 hdd_ctx->config->qdf_trace_enable_hdd_data);
Naveen Rawat7df31862017-03-01 17:09:30 -08007173 hdd_qdf_trace_enable(QDF_MODULE_ID_WIFIPOS,
7174 hdd_ctx->config->qdf_trace_enable_wifi_pos);
Naveen Rawatf2b0dbd2017-03-27 10:00:15 -07007175 hdd_qdf_trace_enable(QDF_MODULE_ID_NAN,
7176 hdd_ctx->config->qdf_trace_enable_nan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007177 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007178}
7179
7180/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007181 * hdd_context_init() - Initialize HDD context
7182 * @hdd_ctx: HDD context.
7183 *
7184 * Initialize HDD context along with all the feature specific contexts.
7185 *
7186 * return: 0 on success and errno on failure.
7187 */
7188static int hdd_context_init(hdd_context_t *hdd_ctx)
7189{
7190 int ret;
7191
7192 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
7193 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
7194
7195 hdd_init_ll_stats_ctx();
7196
7197 init_completion(&hdd_ctx->mc_sus_event_var);
7198 init_completion(&hdd_ctx->ready_to_suspend);
7199
7200 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307201 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007202 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307203
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007204 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
7205
7206 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
7207
7208 ret = hdd_scan_context_init(hdd_ctx);
7209 if (ret)
7210 goto list_destroy;
7211
Nitesh Shahd1266d72017-01-25 22:07:07 +05307212 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007213
7214 hdd_rx_wake_lock_create(hdd_ctx);
7215
7216 ret = hdd_sap_context_init(hdd_ctx);
7217 if (ret)
7218 goto scan_destroy;
7219
7220 ret = hdd_roc_context_init(hdd_ctx);
7221 if (ret)
7222 goto sap_destroy;
7223
7224 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
7225
7226 hdd_init_offloaded_packets_ctx(hdd_ctx);
7227
7228 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
7229 hdd_ctx->config);
7230 if (ret)
7231 goto roc_destroy;
7232
7233 return 0;
7234
7235roc_destroy:
7236 hdd_roc_context_destroy(hdd_ctx);
7237
7238sap_destroy:
7239 hdd_sap_context_destroy(hdd_ctx);
7240
7241scan_destroy:
7242 hdd_scan_context_destroy(hdd_ctx);
7243 hdd_rx_wake_lock_destroy(hdd_ctx);
7244 hdd_tdls_context_destroy(hdd_ctx);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007245list_destroy:
7246 qdf_list_destroy(&hdd_ctx->hddAdapters);
Sandeep Puligillad0004212017-02-26 18:34:56 -08007247
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007248 return ret;
7249}
7250
7251/**
7252 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05307253 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007254 *
7255 * Allocate and initialize HDD context. HDD context is allocated as part of
7256 * wiphy allocation and then context is initialized.
7257 *
7258 * Return: HDD context on success and ERR_PTR on failure
7259 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007260static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007261{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307262 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007263 int ret = 0;
7264 hdd_context_t *hdd_ctx;
7265 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307266 int qdf_print_idx = -1;
7267
7268 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
7269 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
7270 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
7271 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
7272 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
7273 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
7274 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
7275 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
7276 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
7277 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
7278 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
7279 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
7280 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7281 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7282 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
7283 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
7284 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
7285 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
7286 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
7287 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
7288 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiyaf928edf2017-02-06 14:43:24 +05307289 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
7290 [QDF_MODULE_ID_DP] = {QDF_TRACE_LEVEL_ALL},
7291 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
7292 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
7293 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
7294 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
Mukul Sharma4d7d6b02017-02-13 20:45:22 +05307295 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
Abhishek Singh9679dbf2017-02-15 11:35:41 +05307296 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
Tushnim Bhattacharyya6796d8d2017-03-17 11:06:03 -07007297 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL},
7298 [QDF_MODULE_ID_POLICY_MGR] = {QDF_TRACE_LEVEL_ALL},
Wu Gao9a704f42017-03-10 18:42:11 +08007299 [QDF_MODULE_ID_P2P] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307300 };
7301
7302 status = qdf_print_setup();
7303 if (status != QDF_STATUS_SUCCESS) {
7304 pr_err("QDF print control object setup failed\n");
7305 ret = -EINVAL;
7306 goto err_out;
7307 }
7308 /* Register the module here with QDF */
7309 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
7310 "MCL_WLAN");
7311
7312 /* if qdf_print_idx is negative */
7313 if (qdf_print_idx < 0) {
7314 pr_err("QDF print control can not be registered %d\n",
7315 qdf_print_idx);
7316 ret = -EINVAL;
7317 goto err_out;
7318 }
7319
7320 /* Store the qdf_pidx information into qdf module */
7321 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007322
7323 ENTER();
7324
7325 p_cds_context = cds_get_global_context();
7326 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007327 hdd_err("Failed to get CDS global context");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007328 ret = -EINVAL;
7329 goto err_out;
7330 }
7331
7332 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
7333
7334 if (hdd_ctx == NULL) {
7335 ret = -ENOMEM;
7336 goto err_out;
7337 }
7338
7339 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007340 hdd_ctx->parent_dev = dev;
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05307341 hdd_ctx->last_scan_reject_session_id = 0xFF;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007342
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307343 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007344 if (hdd_ctx->config == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007345 hdd_err("Failed to alloc memory for HDD config!");
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007346 ret = -ENOMEM;
7347 goto err_free_hdd_context;
7348 }
7349
7350 /* Read and parse the qcom_cfg.ini file */
7351 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307352 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307353 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007354 WLAN_INI_FILE);
7355 ret = -EINVAL;
7356 goto err_free_config;
7357 }
7358
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007359 hdd_debug("Setting configuredMcastBcastFilter: %d",
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007360 hdd_ctx->config->mcastBcastFilterSetting);
7361
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307362 if (hdd_ctx->config->fhostNSOffload)
7363 hdd_ctx->ns_offload_enable = true;
7364
Abhishek Singh5ea86532016-04-27 14:10:53 +05307365 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
7366
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007367 hdd_override_ini_config(hdd_ctx);
7368
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007369 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007370
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007371 ret = hdd_context_init(hdd_ctx);
7372
7373 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007374 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007375
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007376
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -08007377 pld_set_fw_log_mode(hdd_ctx->parent_dev,
7378 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007379
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007380
7381 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05307382 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007383
Anurag Chouhan6d760662016-02-20 16:05:43 +05307384 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007385 goto skip_multicast_logging;
7386
7387 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
7388
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007389 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
7390 if (ret)
7391 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05307392
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007393 ret = hdd_logging_sock_activate_svc(hdd_ctx);
7394 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05307395 goto err_free_histogram;
7396
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007397skip_multicast_logging:
7398 hdd_set_trace_level_for_each(hdd_ctx);
7399
7400 return hdd_ctx;
7401
Nirav Shahed34b212016-04-25 10:59:16 +05307402err_free_histogram:
7403 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
7404
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007405err_deinit_hdd_context:
7406 hdd_context_deinit(hdd_ctx);
7407
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007408err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307409 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007410
7411err_free_hdd_context:
7412 wiphy_free(hdd_ctx->wiphy);
7413
7414err_out:
7415 return ERR_PTR(ret);
7416}
7417
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007418#ifdef WLAN_OPEN_P2P_INTERFACE
7419/**
7420 * hdd_open_p2p_interface - Open P2P interface
7421 * @hdd_ctx: HDD context
7422 * @rtnl_held: True if RTNL lock held
7423 *
7424 * Open P2P interface during probe. This function called to open the P2P
7425 * interface at probe along with STA interface.
7426 *
7427 * Return: 0 on success and errno on failure
7428 */
7429static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7430{
7431 hdd_adapter_t *adapter;
7432 uint8_t *p2p_dev_addr;
7433
7434 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
7435 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307436 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007437 hdd_ctx->config->intfMacAddr[0].bytes,
7438 sizeof(tSirMacAddr));
7439
7440 /*
7441 * Generate the P2P Device Address. This consists of
7442 * the device's primary MAC address with the locally
7443 * administered bit set.
7444 */
7445 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
7446 } else {
7447 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7448 if (p2p_dev_addr == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007449 hdd_err("Failed to allocate mac_address for p2p_device");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007450 return -ENOSPC;
7451 }
7452
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307453 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307454 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007455 }
7456
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007457 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007458 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08007459 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007460
7461 if (NULL == adapter) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007462 hdd_err("Failed to do hdd_open_adapter for P2P Device Interface");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007463 return -ENOSPC;
7464 }
7465
7466 return 0;
7467}
7468#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05307469static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007470 bool rtnl_held)
7471{
7472 return 0;
7473}
7474#endif
7475
Jeff Johnson957bc272017-02-02 08:54:48 -08007476static int hdd_open_ocb_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7477{
7478 hdd_adapter_t *adapter;
7479 int ret = 0;
7480
7481 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
7482 wlan_hdd_get_intf_addr(hdd_ctx),
7483 NET_NAME_UNKNOWN, rtnl_held);
7484 if (adapter == NULL) {
7485 hdd_err("Failed to open 802.11p interface");
7486 ret = -ENOSPC;
7487 }
7488
7489 return ret;
7490}
7491
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007492/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307493 * hdd_start_station_adapter()- Start the Station Adapter
7494 * @adapter: HDD adapter
7495 *
7496 * This function initializes the adapter for the station mode.
7497 *
7498 * Return: 0 on success or errno on failure.
7499 */
7500int hdd_start_station_adapter(hdd_adapter_t *adapter)
7501{
7502 QDF_STATUS status;
7503
7504 ENTER_DEV(adapter->dev);
7505
7506 status = hdd_init_station_mode(adapter);
7507
7508 if (QDF_STATUS_SUCCESS != status) {
7509 hdd_err("Error Initializing station mode: %d", status);
7510 return qdf_status_to_os_return(status);
7511 }
7512
Arun Khandavallifae92942016-08-01 13:31:08 +05307513 hdd_register_tx_flow_control(adapter,
7514 hdd_tx_resume_timer_expired_handler,
7515 hdd_tx_resume_cb);
7516
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307517 EXIT();
7518 return 0;
7519}
7520
7521/**
7522 * hdd_start_ap_adapter()- Start AP Adapter
7523 * @adapter: HDD adapter
7524 *
7525 * This function initializes the adapter for the AP mode.
7526 *
7527 * Return: 0 on success errno on failure.
7528 */
7529int hdd_start_ap_adapter(hdd_adapter_t *adapter)
7530{
7531 QDF_STATUS status;
7532
7533 ENTER();
7534
Arun Khandavallicc544b32017-01-30 19:52:16 +05307535 status = hdd_init_ap_mode(adapter, false);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307536
7537 if (QDF_STATUS_SUCCESS != status) {
7538 hdd_err("Error Initializing the AP mode: %d", status);
7539 return qdf_status_to_os_return(status);
7540 }
7541
Arun Khandavallifae92942016-08-01 13:31:08 +05307542 hdd_register_tx_flow_control(adapter,
7543 hdd_softap_tx_resume_timer_expired_handler,
7544 hdd_softap_tx_resume_cb);
7545
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307546 EXIT();
7547 return 0;
7548}
7549
7550/**
7551 * hdd_start_ftm_adapter()- Start FTM adapter
7552 * @adapter: HDD adapter
7553 *
7554 * This function initializes the adapter for the FTM mode.
7555 *
7556 * Return: 0 on success or errno on failure.
7557 */
7558int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
7559{
7560 QDF_STATUS qdf_status;
7561
7562 ENTER_DEV(adapter->dev);
7563
7564 qdf_status = hdd_init_tx_rx(adapter);
7565
7566 if (QDF_STATUS_SUCCESS != qdf_status) {
7567 hdd_err("Failed to start FTM adapter: %d", qdf_status);
7568 return qdf_status_to_os_return(qdf_status);
7569 }
7570
7571 return 0;
7572 EXIT();
7573}
7574
7575/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007576 * hdd_open_interfaces - Open all required interfaces
7577 * hdd_ctx: HDD context
7578 * rtnl_held: True if RTNL lock is held
7579 *
7580 * Open all the interfaces like STA, P2P and OCB based on the configuration.
7581 *
Jeff Johnson957bc272017-02-02 08:54:48 -08007582 * Return: 0 if all interfaces were created, otherwise negative errno
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007583 */
Jeff Johnson957bc272017-02-02 08:54:48 -08007584static int hdd_open_interfaces(hdd_context_t *hdd_ctx, bool rtnl_held)
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007585{
Jeff Johnson957bc272017-02-02 08:54:48 -08007586 hdd_adapter_t *adapter;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007587 int ret;
7588
Jeff Johnson957bc272017-02-02 08:54:48 -08007589 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
Arun Khandavallifae92942016-08-01 13:31:08 +05307590 /* Create only 802.11p interface */
Jeff Johnson957bc272017-02-02 08:54:48 -08007591 return hdd_open_ocb_interface(hdd_ctx, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007592
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007593 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007594 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08007595 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007596
7597 if (adapter == NULL)
Jeff Johnson957bc272017-02-02 08:54:48 -08007598 return -ENOSPC;
7599
Deepak Dhamdherea2785822016-11-17 01:17:45 -08007600 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
7601 adapter->fast_roaming_allowed = true;
7602
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007603 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
7604 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08007605 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007606
7607 /* Open 802.11p Interface */
7608 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Jeff Johnson957bc272017-02-02 08:54:48 -08007609 ret = hdd_open_ocb_interface(hdd_ctx, rtnl_held);
7610 if (ret)
7611 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007612 }
7613
Jeff Johnson957bc272017-02-02 08:54:48 -08007614 return 0;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007615
Jeff Johnson957bc272017-02-02 08:54:48 -08007616err_close_adapters:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007617 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Jeff Johnson957bc272017-02-02 08:54:48 -08007618 return ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007619}
7620
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007621/**
7622 * hdd_update_country_code - Update country code
7623 * @hdd_ctx: HDD context
7624 * @adapter: Primary adapter context
7625 *
7626 * Update country code based on module parameter country_code at SME and wait
7627 * for the settings to take effect.
7628 *
7629 * Return: 0 on success and errno on failure
7630 */
7631static int hdd_update_country_code(hdd_context_t *hdd_ctx,
7632 hdd_adapter_t *adapter)
7633{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307634 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007635 int ret = 0;
7636 unsigned long rc;
7637
7638 if (country_code == NULL)
7639 return 0;
7640
7641 INIT_COMPLETION(adapter->change_country_code);
7642
7643 status = sme_change_country_code(hdd_ctx->hHal,
7644 wlan_hdd_change_country_code_callback,
7645 country_code, adapter,
7646 hdd_ctx->pcds_context, eSIR_TRUE,
7647 eSIR_TRUE);
7648
7649
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307650 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007651 hdd_err("SME Change Country code from module param fail ret=%d",
7652 ret);
7653 return -EINVAL;
7654 }
7655
7656 rc = wait_for_completion_timeout(&adapter->change_country_code,
7657 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
7658 if (!rc) {
7659 hdd_err("SME while setting country code timed out");
7660 ret = -ETIMEDOUT;
7661 }
7662
7663 return ret;
7664}
7665
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307666#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7667/**
7668 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7669 * @cds_cfg: CDS Configuration
7670 * @hdd_ctx: Pointer to hdd context
7671 *
7672 * Return: none
7673 */
7674static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7675 *cds_cfg,
7676 hdd_context_t *hdd_ctx)
7677{
7678 cds_cfg->tx_flow_stop_queue_th =
7679 hdd_ctx->config->TxFlowStopQueueThreshold;
7680 cds_cfg->tx_flow_start_queue_offset =
7681 hdd_ctx->config->TxFlowStartQueueOffset;
7682}
7683#else
7684static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7685 *cds_cfg,
7686 hdd_context_t *hdd_ctx)
7687{
7688}
7689#endif
7690
7691#ifdef FEATURE_WLAN_RA_FILTERING
7692/**
7693 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7694 * @cds_cfg: CDS Configuration
7695 * @hdd_ctx: Pointer to hdd context
7696 *
7697 * Return: none
7698 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307699static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307700 hdd_context_t *hdd_ctx)
7701{
7702 cds_cfg->ra_ratelimit_interval =
7703 hdd_ctx->config->RArateLimitInterval;
7704 cds_cfg->is_ra_ratelimit_enabled =
7705 hdd_ctx->config->IsRArateLimitEnabled;
7706}
7707#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307708static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307709 hdd_context_t *hdd_ctx)
7710{
7711}
7712#endif
7713
7714/**
7715 * hdd_update_cds_config() - API to update cds configuration parameters
7716 * @hdd_ctx: HDD Context
7717 *
7718 * Return: 0 for Success, errno on failure
7719 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007720static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307721{
7722 struct cds_config_info *cds_cfg;
7723
7724 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7725 if (!cds_cfg) {
7726 hdd_err("failed to allocate cds config");
7727 return -ENOMEM;
7728 }
7729
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307730 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08007731 if (!hdd_ctx->config->nMaxPsPoll ||
7732 !hdd_ctx->config->enablePowersaveOffload) {
7733 cds_cfg->powersave_offload_enabled =
7734 hdd_ctx->config->enablePowersaveOffload;
7735 } else {
7736 if ((hdd_ctx->config->enablePowersaveOffload ==
7737 PS_QPOWER_NODEEPSLEEP) ||
7738 (hdd_ctx->config->enablePowersaveOffload ==
7739 PS_LEGACY_NODEEPSLEEP))
7740 cds_cfg->powersave_offload_enabled =
7741 PS_LEGACY_NODEEPSLEEP;
7742 else
7743 cds_cfg->powersave_offload_enabled =
7744 PS_LEGACY_DEEPSLEEP;
7745 hdd_info("Qpower disabled in cds config, %d",
7746 cds_cfg->powersave_offload_enabled);
7747 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307748 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7749 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7750 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7751 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7752 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7753
7754 /* Here ol_ini_info is used to store ini status of arp offload
7755 * ns offload and others. Currently 1st bit is used for arp
7756 * off load and 2nd bit for ns offload currently, rest bits are unused
7757 */
7758 if (hdd_ctx->config->fhostArpOffload)
7759 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7760 if (hdd_ctx->config->fhostNSOffload)
7761 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7762
7763 /*
7764 * Copy the DFS Phyerr Filtering Offload status.
7765 * This parameter reflects the value of the
7766 * dfs_phyerr_filter_offload flag as set in the ini.
7767 */
7768 cds_cfg->dfs_phyerr_filter_offload =
7769 hdd_ctx->config->fDfsPhyerrFilterOffload;
7770 if (hdd_ctx->config->ssdp)
7771 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7772
7773 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7774 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7775
7776 cds_cfg->ap_maxoffload_reorderbuffs =
7777 hdd_ctx->config->apMaxOffloadReorderBuffs;
7778
7779 cds_cfg->ap_disable_intrabss_fwd =
7780 hdd_ctx->config->apDisableIntraBssFwd;
7781
7782 cds_cfg->dfs_pri_multiplier =
7783 hdd_ctx->config->dfsRadarPriMultiplier;
7784 cds_cfg->reorder_offload =
7785 hdd_ctx->config->reorderOffloadSupport;
7786
7787 /* IPA micro controller data path offload resource config item */
7788 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007789 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7790 /* IpaUcTxBufCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007791 hdd_debug("Round down IpaUcTxBufCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007792 hdd_ctx->config->IpaUcTxBufCount);
7793 hdd_ctx->config->IpaUcTxBufCount =
7794 rounddown_pow_of_two(
7795 hdd_ctx->config->IpaUcTxBufCount);
7796 if (!hdd_ctx->config->IpaUcTxBufCount) {
7797 hdd_err("Failed to round down IpaUcTxBufCount");
7798 return -EINVAL;
7799 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007800 hdd_debug("IpaUcTxBufCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007801 hdd_ctx->config->IpaUcTxBufCount);
7802 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307803 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7804 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007805 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7806 /* IpaUcRxIndRingCount should be power of 2 */
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007807 hdd_debug("Round down IpaUcRxIndRingCount %d to nearest power of 2",
Yun Parkde380782016-08-17 16:26:54 -07007808 hdd_ctx->config->IpaUcRxIndRingCount);
7809 hdd_ctx->config->IpaUcRxIndRingCount =
7810 rounddown_pow_of_two(
7811 hdd_ctx->config->IpaUcRxIndRingCount);
7812 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7813 hdd_err("Failed to round down IpaUcRxIndRingCount");
7814 return -EINVAL;
7815 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08007816 hdd_debug("IpaUcRxIndRingCount rounded down to %d",
Yun Parkde380782016-08-17 16:26:54 -07007817 hdd_ctx->config->IpaUcRxIndRingCount);
7818 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307819 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007820 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307821 cds_cfg->uc_tx_partition_base =
7822 hdd_ctx->config->IpaUcTxPartitionBase;
7823 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7824
7825 cds_cfg->ip_tcp_udp_checksum_offload =
7826 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307827 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307828 cds_cfg->ce_classify_enabled =
7829 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007830 cds_cfg->bpf_packet_filter_enable =
7831 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307832 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7833 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7834 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007835 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007836 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007837 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007838 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Dustin Brown13995f02017-01-12 15:38:42 -08007839 cds_cfg->active_bpf_mode = hdd_ctx->config->active_bpf_mode;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307840
7841 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7842 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7843 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007844 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307845 cds_init_ini_config(cds_cfg);
7846 return 0;
7847}
7848
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007849/**
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007850 * hdd_update_user_config() - API to update user configuration
7851 * parameters to obj mgr which are used by multiple components
7852 * @hdd_ctx: HDD Context
7853 *
7854 * Return: 0 for Success, errno on failure
7855 */
7856static int hdd_update_user_config(hdd_context_t *hdd_ctx)
7857{
7858 struct wlan_objmgr_psoc_user_config *user_config;
7859
7860 user_config = qdf_mem_malloc(sizeof(*user_config));
7861 if (user_config == NULL) {
7862 hdd_alert("Failed to alloc memory for user_config!");
7863 return -ENOMEM;
7864 }
7865
7866 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
7867 user_config->dual_mac_feature_disable =
7868 hdd_ctx->config->dual_mac_feature_disable;
7869 user_config->indoor_channel_support =
7870 hdd_ctx->config->indoor_channel_support;
7871 user_config->is_11d_support_enabled =
7872 hdd_ctx->config->Is11dSupportEnabled;
7873 user_config->is_11h_support_enabled =
7874 hdd_ctx->config->Is11hSupportEnabled;
7875 user_config->optimize_chan_avoid_event =
7876 hdd_ctx->config->goptimize_chan_avoid_event;
7877 user_config->skip_dfs_chnl_in_p2p_search =
7878 hdd_ctx->config->skipDfsChnlInP2pSearch;
Naveen Rawat222b2e92017-03-16 09:52:21 -07007879 user_config->band_capability = hdd_ctx->config->nBandCapability;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007880 wlan_objmgr_psoc_set_user_config(hdd_ctx->hdd_psoc, user_config);
7881
7882 qdf_mem_free(user_config);
7883 return 0;
7884}
7885
7886/**
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007887 * hdd_init_thermal_info - Initialize thermal level
7888 * @hdd_ctx: HDD context
7889 *
7890 * Initialize thermal level at SME layer and set the thermal level callback
7891 * which would be called when a configured thermal threshold is hit.
7892 *
7893 * Return: 0 on success and errno on failure
7894 */
7895static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7896{
7897 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307898 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007899
7900 thermal_param.smeThermalMgmtEnabled =
7901 hdd_ctx->config->thermalMitigationEnable;
7902 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7903
Poddar, Siddarth83905022016-04-16 17:56:08 -07007904 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7905 hdd_ctx->config->throttle_dutycycle_level0;
7906 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7907 hdd_ctx->config->throttle_dutycycle_level1;
7908 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7909 hdd_ctx->config->throttle_dutycycle_level2;
7910 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7911 hdd_ctx->config->throttle_dutycycle_level3;
7912
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007913 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7914 hdd_ctx->config->thermalTempMinLevel0;
7915 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7916 hdd_ctx->config->thermalTempMaxLevel0;
7917 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7918 hdd_ctx->config->thermalTempMinLevel1;
7919 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7920 hdd_ctx->config->thermalTempMaxLevel1;
7921 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7922 hdd_ctx->config->thermalTempMinLevel2;
7923 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7924 hdd_ctx->config->thermalTempMaxLevel2;
7925 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7926 hdd_ctx->config->thermalTempMinLevel3;
7927 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7928 hdd_ctx->config->thermalTempMaxLevel3;
7929
7930 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7931
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307932 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307933 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007934
7935 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7936 hdd_set_thermal_level_cb);
7937
7938 return 0;
7939
7940}
7941
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007942#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7943/**
7944 * hdd_hold_rtnl_lock - Hold RTNL lock
7945 *
7946 * Hold RTNL lock
7947 *
7948 * Return: True if held and false otherwise
7949 */
7950static inline bool hdd_hold_rtnl_lock(void)
7951{
7952 rtnl_lock();
7953 return true;
7954}
7955
7956/**
7957 * hdd_release_rtnl_lock - Release RTNL lock
7958 *
7959 * Release RTNL lock
7960 *
7961 * Return: None
7962 */
7963static inline void hdd_release_rtnl_lock(void)
7964{
7965 rtnl_unlock();
7966}
7967#else
7968static inline bool hdd_hold_rtnl_lock(void) { return false; }
7969static inline void hdd_release_rtnl_lock(void) { }
7970#endif
7971
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007972#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007973
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307974/* MAX iwpriv command support */
7975#define PKTLOG_SET_BUFF_SIZE 3
7976#define MAX_PKTLOG_SIZE 16
7977
7978/**
7979 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7980 * @hdd_ctx: hdd context
7981 * @set_value2: pktlog buffer size value
7982 *
7983 *
7984 * Return: 0 for success or error.
7985 */
7986static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7987{
7988 struct sir_wifi_start_log start_log = { 0 };
7989 QDF_STATUS status;
7990
7991 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7992 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7993 start_log.ini_triggered = cds_is_packet_log_enabled();
7994 start_log.user_triggered = 1;
7995 start_log.size = set_value2;
7996
7997 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7998 if (!QDF_IS_STATUS_SUCCESS(status)) {
7999 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8000 EXIT();
8001 return -EINVAL;
8002 }
8003
8004 return 0;
8005}
8006
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008007/**
8008 * hdd_process_pktlog_command() - process pktlog command
8009 * @hdd_ctx: hdd context
8010 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308011 * @set_value2: pktlog buffer size value
8012 *
8013 * This function process pktlog command.
8014 * set_value2 only matters when set_value is 3 (set buff size)
8015 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008016 *
8017 * Return: 0 for success or error.
8018 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308019int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
8020 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008021{
8022 int ret;
8023 bool enable;
8024 uint8_t user_triggered = 0;
8025
8026 ret = wlan_hdd_validate_context(hdd_ctx);
8027 if (0 != ret)
8028 return ret;
8029
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008030 hdd_debug("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008031
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308032 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008033 hdd_err("invalid pktlog value %d", set_value);
8034 return -EINVAL;
8035 }
8036
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308037 if (set_value == PKTLOG_SET_BUFF_SIZE) {
8038 if (set_value2 <= 0) {
8039 hdd_err("invalid pktlog size %d", set_value2);
8040 return -EINVAL;
8041 } else if (set_value2 > MAX_PKTLOG_SIZE) {
8042 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
8043 return -EINVAL;
8044 }
8045 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
8046 }
8047
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008048 /*
8049 * set_value = 0 then disable packetlog
8050 * set_value = 1 enable packetlog forcefully
8051 * set_vlaue = 2 then disable packetlog if disabled through ini or
8052 * enable packetlog with AUTO type.
8053 */
8054 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
8055 true : false;
8056
8057 if (1 == set_value) {
8058 enable = true;
8059 user_triggered = 1;
8060 }
8061
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308062 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008063}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008064/**
8065 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
8066 * @hdd_ctx: HDD context
8067 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308068 * @user_triggered: triggered through iwpriv
8069 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008070 *
8071 * Return: 0 on success; error number otherwise
8072 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008073int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308074 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008075{
8076 struct sir_wifi_start_log start_log;
8077 QDF_STATUS status;
8078
8079 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8080 start_log.verbose_level =
8081 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008082 start_log.ini_triggered = cds_is_packet_log_enabled();
8083 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308084 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05308085 /*
8086 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
8087 * commands. Host uses this flag to decide whether to send pktlog
8088 * disable command to fw without sending pktlog enable command
8089 * previously. For eg, If vendor sends pktlog disable command without
8090 * sending pktlog enable command, then host discards the packet
8091 * but for iwpriv command, host will send it to fw.
8092 */
8093 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008094 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8095 if (!QDF_IS_STATUS_SUCCESS(status)) {
8096 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8097 EXIT();
8098 return -EINVAL;
8099 }
8100
8101 return 0;
8102}
8103#endif /* REMOVE_PKT_LOG */
8104
Komal Seelam92fff912016-03-24 11:51:41 +05308105/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008106 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
8107 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05308108 * @dev: Device Pointer
8109 * @num: Number of Valid Mac address
8110 *
8111 * Return: Pointer to MAC address buffer
8112 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008113static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
8114 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05308115{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008116 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05308117}
Komal Seelam92fff912016-03-24 11:51:41 +05308118
8119/**
8120 * hdd_populate_random_mac_addr() - API to populate random mac addresses
8121 * @hdd_ctx: HDD Context
8122 * @num: Number of random mac addresses needed
8123 *
8124 * Generate random addresses using bit manipulation on the base mac address
8125 *
8126 * Return: None
8127 */
8128static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
8129{
8130 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
8131 uint32_t iter;
8132 struct hdd_config *ini = hdd_ctx->config;
8133 uint8_t *buf = NULL;
8134 uint8_t macaddr_b3, tmp_br3;
8135 uint8_t *src = ini->intfMacAddr[0].bytes;
8136
8137 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
8138 buf = ini->intfMacAddr[iter].bytes;
8139 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
8140 macaddr_b3 = buf[3];
8141 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
8142 INTF_MACADDR_MASK;
8143 macaddr_b3 += tmp_br3;
8144 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
8145 buf[0] |= 0x02;
8146 buf[3] = macaddr_b3;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008147 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308148 }
8149}
8150
8151/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008152 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05308153 * @hdd_ctx: HDD Context
8154 *
8155 * API to get mac addresses from platform driver and update the driver
8156 * structures and configure FW with the base mac address.
8157 * Return: int
8158 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008159static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05308160{
8161 uint32_t no_of_mac_addr, iter;
8162 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
8163 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
8164 uint8_t *addr, *buf;
8165 struct device *dev = hdd_ctx->parent_dev;
8166 struct hdd_config *ini = hdd_ctx->config;
8167 tSirMacAddr mac_addr;
8168 QDF_STATUS status;
8169
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008170 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05308171
8172 if (no_of_mac_addr == 0 || !addr) {
8173 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
8174 return -EINVAL;
8175 }
8176
8177 if (no_of_mac_addr > max_mac_addr)
8178 no_of_mac_addr = max_mac_addr;
8179
8180 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
8181
8182 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
8183 buf = ini->intfMacAddr[iter].bytes;
8184 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008185 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308186 }
8187
8188 status = sme_set_custom_mac_addr(mac_addr);
8189
8190 if (!QDF_IS_STATUS_SUCCESS(status))
8191 return -EAGAIN;
8192 if (no_of_mac_addr < max_mac_addr)
8193 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
8194 no_of_mac_addr);
8195 return 0;
8196}
8197
8198/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008199 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
8200 * @hdd_ctx: HDD Context
8201 *
8202 * Update MAC address to FW. If MAC address passed by FW is invalid, host
8203 * will generate its own MAC and update it to FW.
8204 *
8205 * Return: 0 for success
8206 * Non-zero error code for failure
8207 */
8208static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
8209{
8210 tSirMacAddr customMacAddr;
8211 QDF_STATUS status;
8212
8213 qdf_mem_copy(&customMacAddr,
8214 &hdd_ctx->config->intfMacAddr[0].bytes[0],
8215 sizeof(tSirMacAddr));
8216 status = sme_set_custom_mac_addr(customMacAddr);
8217 if (!QDF_IS_STATUS_SUCCESS(status))
8218 return -EAGAIN;
8219 return 0;
8220}
8221
8222/**
Komal Seelam92fff912016-03-24 11:51:41 +05308223 * hdd_initialize_mac_address() - API to get wlan mac addresses
8224 * @hdd_ctx: HDD Context
8225 *
8226 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
8227 * is provisioned with mac addresses, driver uses it, else it will use
8228 * wlan_mac.bin to update HW MAC addresses.
8229 *
8230 * Return: None
8231 */
8232static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
8233{
8234 QDF_STATUS status;
8235 int ret;
8236
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008237 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05308238 if (ret == 0)
8239 return;
8240
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008241 hdd_warn("Can't update mac config via platform driver ret: %d", ret);
Komal Seelam92fff912016-03-24 11:51:41 +05308242
8243 status = hdd_update_mac_config(hdd_ctx);
8244
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008245 if (QDF_IS_STATUS_SUCCESS(status))
8246 return;
8247
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008248 hdd_warn("Can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008249
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008250 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008251 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008252 if (ret != 0) {
8253 hdd_err("MAC address out-of-sync, ret:%d", ret);
8254 QDF_ASSERT(ret);
8255 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008256 }
Komal Seelam92fff912016-03-24 11:51:41 +05308257}
8258
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008259/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008260 * hdd_tsf_init() - Initialize the TSF synchronization interface
8261 * @hdd_ctx: HDD global context
8262 *
8263 * When TSF synchronization via GPIO is supported by the driver and
8264 * has been enabled in the configuration file, this function plumbs
8265 * the GPIO value down to firmware via SME.
8266 *
8267 * Return: None
8268 */
8269#ifdef WLAN_FEATURE_TSF
8270static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8271{
8272 QDF_STATUS status;
8273
8274 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
8275 return;
8276
8277 status = sme_set_tsf_gpio(hdd_ctx->hHal,
8278 hdd_ctx->config->tsf_gpio_pin);
8279 if (!QDF_IS_STATUS_SUCCESS(status))
8280 hdd_err("Set tsf GPIO failed, status: %d", status);
8281}
8282#else
8283static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8284{
8285}
8286#endif
8287
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008288static int hdd_set_smart_chainmask_enabled(hdd_context_t *hdd_ctx)
8289{
8290 int vdev_id = 0;
8291 int param_id = WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME;
8292 int value = hdd_ctx->config->smart_chainmask_enabled;
8293 int vpdev = PDEV_CMD;
8294 int ret;
8295
8296 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8297 if (ret)
8298 hdd_err("WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME failed %d", ret);
8299
8300 return ret;
8301}
8302
8303static int hdd_set_alternative_chainmask_enabled(hdd_context_t *hdd_ctx)
8304{
8305 int vdev_id = 0;
8306 int param_id = WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME;
8307 int value = hdd_ctx->config->alternative_chainmask_enabled;
8308 int vpdev = PDEV_CMD;
8309 int ret;
8310
8311 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8312 if (ret)
8313 hdd_err("WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME failed %d",
8314 ret);
8315
8316 return ret;
8317}
8318
Jeff Johnson12a744b2017-04-04 08:19:37 -07008319static int hdd_set_ani_enabled(hdd_context_t *hdd_ctx)
8320{
8321 int vdev_id = 0;
8322 int param_id = WMI_PDEV_PARAM_ANI_ENABLE;
8323 int value = hdd_ctx->config->ani_enabled;
8324 int vpdev = PDEV_CMD;
8325 int ret;
8326
8327 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8328 if (ret)
8329 hdd_err("WMI_PDEV_PARAM_ANI_ENABLE failed %d", ret);
8330
8331 return ret;
8332}
8333
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008334/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07008335 * hdd_pre_enable_configure() - Configurations prior to cds_enable
8336 * @hdd_ctx: HDD context
8337 *
8338 * Pre configurations to be done at lower layer before calling cds enable.
8339 *
8340 * Return: 0 on success and errno on failure.
8341 */
8342static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
8343{
8344 int ret;
8345 QDF_STATUS status;
8346 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07008347 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008348
Leo Changfdb45c32016-10-28 11:09:23 -07008349 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008350 /*
8351 * Set 802.11p config
8352 * TODO-OCB: This has been temporarily added here to ensure this
8353 * parameter is set in CSR when we init the channel list. This should
8354 * be removed once the 5.9 GHz channels are added to the regulatory
8355 * domain.
8356 */
8357 hdd_set_dot11p_config(hdd_ctx);
8358
8359 /*
8360 * Note that the cds_pre_enable() sequence triggers the cfg download.
8361 * The cfg download must occur before we update the SME config
8362 * since the SME config operation must access the cfg database
8363 */
8364 status = hdd_set_sme_config(hdd_ctx);
8365
8366 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008367 hdd_err("Failed hdd_set_sme_config: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008368 ret = qdf_status_to_os_return(status);
8369 goto out;
8370 }
8371
Tushnim Bhattacharyyaba8ee932017-03-23 09:27:40 -07008372 status = hdd_set_policy_mgr_user_cfg(hdd_ctx);
8373 if (QDF_STATUS_SUCCESS != status) {
8374 hdd_alert("Failed hdd_set_policy_mgr_user_cfg: %d", status);
8375 ret = qdf_status_to_os_return(status);
8376 goto out;
8377 }
8378
Prashanth Bhatta07998752016-04-28 12:35:33 -07008379 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
8380 hdd_ctx->config->tx_chain_mask_1ss,
8381 PDEV_CMD);
8382 if (0 != ret) {
8383 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
8384 goto out;
8385 }
8386
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008387 ret = hdd_set_smart_chainmask_enabled(hdd_ctx);
8388 if (ret)
8389 goto out;
8390
8391 ret = hdd_set_alternative_chainmask_enabled(hdd_ctx);
8392 if (ret)
8393 goto out;
8394
Jeff Johnson12a744b2017-04-04 08:19:37 -07008395 ret = hdd_set_ani_enabled(hdd_ctx);
8396 if (ret)
8397 goto out;
8398
Srinivas Girigowda70e169a2017-03-07 23:55:57 -08008399 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
8400 hdd_ctx->config->arp_ac_category,
8401 PDEV_CMD);
8402 if (0 != ret) {
8403 hdd_err("WMI_PDEV_PARAM_ARP_AC_OVERRIDE ac: %d ret: %d",
8404 hdd_ctx->config->arp_ac_category, ret);
8405 goto out;
8406 }
8407
8408
Prashanth Bhatta07998752016-04-28 12:35:33 -07008409 status = hdd_set_sme_chan_list(hdd_ctx);
8410 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008411 hdd_err("Failed to init channel list: %d", status);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008412 ret = qdf_status_to_os_return(status);
8413 goto out;
8414 }
8415
8416 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07008417 if (!hdd_update_config_cfg(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008418 hdd_err("config update failed");
Prashanth Bhatta07998752016-04-28 12:35:33 -07008419 ret = -EINVAL;
8420 goto out;
8421 }
8422
Prashanth Bhatta07998752016-04-28 12:35:33 -07008423 /*
8424 * Set the MAC Address Currently this is used by HAL to add self sta.
8425 * Remove this once self sta is added as part of session open.
8426 */
8427 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
8428 hdd_ctx->config->intfMacAddr[0].bytes,
8429 sizeof(hdd_ctx->config->intfMacAddr[0]));
8430
8431 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
8432 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
8433 hal_status, hal_status);
8434 ret = -EINVAL;
8435 goto out;
8436 }
8437
8438 hdd_init_channel_avoidance(hdd_ctx);
8439
8440out:
8441 return ret;
8442}
8443
8444/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008445 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
8446 * @context_ptr - hdd context pointer
8447 * @event_ptr - event structure pointer
8448 *
8449 * This is the p2p listen offload stop event handler, it sends vendor
8450 * event back to supplicant to notify the stop reason.
8451 *
8452 * Return: None
8453 */
8454static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
8455 void *event_ptr)
8456{
8457 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
8458 struct sir_p2p_lo_event *evt = event_ptr;
8459 struct sk_buff *vendor_event;
8460
8461 ENTER();
8462
8463 if (hdd_ctx == NULL) {
8464 hdd_err("Invalid HDD context pointer");
8465 return;
8466 }
8467
8468 vendor_event =
8469 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8470 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
8471 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
8472 GFP_KERNEL);
8473
8474 if (!vendor_event) {
8475 hdd_err("cfg80211_vendor_event_alloc failed");
8476 return;
8477 }
8478
8479 if (nla_put_u32(vendor_event,
8480 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
8481 evt->reason_code)) {
8482 hdd_err("nla put failed");
8483 kfree_skb(vendor_event);
8484 return;
8485 }
8486
8487 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8488}
8489
8490/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308491 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
8492 * @hdd_ctx: HDD context
8493 *
8494 * This function sends the adaptive dwell time config configuration to the
8495 * firmware via WMA
8496 *
8497 * Return: 0 - success, < 0 - failure
8498 */
8499static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
8500{
8501 QDF_STATUS status;
8502 struct adaptive_dwelltime_params dwelltime_params;
8503
8504 dwelltime_params.is_enabled =
8505 hdd_ctx->config->adaptive_dwell_mode_enabled;
8506 dwelltime_params.dwelltime_mode =
8507 hdd_ctx->config->global_adapt_dwelltime_mode;
8508 dwelltime_params.lpf_weight =
8509 hdd_ctx->config->adapt_dwell_lpf_weight;
8510 dwelltime_params.passive_mon_intval =
8511 hdd_ctx->config->adapt_dwell_passive_mon_intval;
8512 dwelltime_params.wifi_act_threshold =
8513 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
8514
8515 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
8516 &dwelltime_params);
8517
8518 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
8519 if (!QDF_IS_STATUS_SUCCESS(status)) {
8520 hdd_err("Failed to send Adaptive Dwelltime configuration!");
8521 return -EAGAIN;
8522 }
8523 return 0;
8524}
8525
Arun Khandavallid4349a92016-07-25 11:10:43 +05308526#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8527/**
8528 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
8529 * @hdd_ctx: HDD context
8530 *
8531 * Set auto shutdown callback to get indications from firmware to indicate
8532 * userspace to shutdown WLAN after a configured amount of inactivity.
8533 *
8534 * Return: 0 on success and errno on failure.
8535 */
8536static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8537{
8538 QDF_STATUS status;
8539
8540 if (!hdd_ctx->config->WlanAutoShutdown)
8541 return 0;
8542
8543 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
8544 wlan_hdd_auto_shutdown_cb);
8545 if (status != QDF_STATUS_SUCCESS)
8546 hdd_err("Auto shutdown feature could not be enabled: %d",
8547 status);
8548
8549 return qdf_status_to_os_return(status);
8550}
8551#else
8552static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8553{
8554 return 0;
8555}
8556#endif
8557
8558/**
8559 * hdd_features_init() - Init features
8560 * @hdd_ctx: HDD context
8561 * @adapter: Primary adapter context
8562 *
8563 * Initialize features and their feature context after WLAN firmware is up.
8564 *
8565 * Return: 0 on success and errno on failure.
8566 */
8567static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8568{
8569 tSirTxPowerLimit hddtxlimit;
8570 QDF_STATUS status;
8571 int ret;
8572
8573 ENTER();
8574
8575 ret = hdd_update_country_code(hdd_ctx, adapter);
8576 if (ret) {
8577 hdd_err("Failed to update country code: %d", ret);
8578 goto out;
8579 }
8580
8581 /* FW capabilities received, Set the Dot11 mode */
8582 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07008583 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
8584 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308585
Arun Khandavallid4349a92016-07-25 11:10:43 +05308586
8587 if (hdd_ctx->config->fIsImpsEnabled)
8588 hdd_set_idle_ps_config(hdd_ctx, true);
8589 else
8590 hdd_set_idle_ps_config(hdd_ctx, false);
8591
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308592 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8593 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
8594
Arun Khandavallid4349a92016-07-25 11:10:43 +05308595 if (hdd_lro_init(hdd_ctx))
8596 hdd_err("Unable to initialize LRO in fw");
8597
8598 if (hdd_adaptive_dwelltime_init(hdd_ctx))
8599 hdd_err("Unable to send adaptive dwelltime setting to FW");
8600
8601 ret = hdd_init_thermal_info(hdd_ctx);
8602 if (ret) {
8603 hdd_err("Error while initializing thermal information");
8604 goto deregister_frames;
8605 }
8606
Poddar, Siddarth66a46592017-02-22 11:44:44 +05308607 if (cds_is_packet_log_enabled())
8608 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
8609
Arun Khandavallid4349a92016-07-25 11:10:43 +05308610 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
8611 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
8612 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
8613 if (!QDF_IS_STATUS_SUCCESS(status))
8614 hdd_err("Error setting txlimit in sme: %d", status);
8615
8616 hdd_tsf_init(hdd_ctx);
8617
Arun Khandavallid4349a92016-07-25 11:10:43 +05308618 ret = hdd_register_cb(hdd_ctx);
8619 if (ret) {
8620 hdd_err("Failed to register HDD callbacks!");
8621 goto deregister_frames;
8622 }
8623
8624 if (hdd_ctx->config->dual_mac_feature_disable) {
8625 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
8626 if (status != QDF_STATUS_SUCCESS) {
8627 hdd_err("Failed to disable dual mac features");
8628 goto deregister_cb;
8629 }
8630 }
Selvaraj, Sridhar371f55e2017-02-21 10:36:15 +05308631 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8632 status = sme_enable_disable_chanavoidind_event(
8633 hdd_ctx->hHal, 0);
8634 if (!QDF_IS_STATUS_SUCCESS(status)) {
8635 hdd_err("Failed to disable Chan Avoidance Indication");
8636 goto deregister_cb;
8637 }
8638 }
Arun Khandavallid4349a92016-07-25 11:10:43 +05308639
8640 /* register P2P Listen Offload event callback */
8641 if (wma_is_p2p_lo_capable())
8642 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
8643 wlan_hdd_p2p_lo_event_callback);
8644
8645 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
8646
8647 if (ret)
8648 goto deregister_cb;
8649
8650 EXIT();
8651 return 0;
8652
8653deregister_cb:
8654 hdd_deregister_cb(hdd_ctx);
8655deregister_frames:
8656 wlan_hdd_cfg80211_deregister_frames(adapter);
8657out:
8658 return -EINVAL;
8659
8660}
8661
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308662#ifdef NAPIER_SCAN
8663/**
8664 *
8665 * hdd_post_cds_enable_config() - HDD post cds start config helper
8666 * @adapter - Pointer to the HDD
8667 *
8668 * Return: None
8669 */
8670static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8671{
8672 QDF_STATUS status;
8673
8674 status = ucfg_scan_register_bcn_cb(hdd_ctx->hdd_psoc,
8675 wlan_cfg80211_inform_bss_frame,
8676 SCAN_CB_TYPE_INFORM_BCN);
8677 if (!QDF_IS_STATUS_SUCCESS(status)) {
8678 hdd_err("failed with status code %08d [x%08x]",
8679 status, status);
8680 return status;
8681 }
8682
8683 return QDF_STATUS_SUCCESS;
8684}
8685#else
8686static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8687{
8688 return QDF_STATUS_SUCCESS;
8689}
8690
8691#endif
Arun Khandavallid4349a92016-07-25 11:10:43 +05308692
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308693/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308694 * hdd_configure_cds() - Configure cds modules
8695 * @hdd_ctx: HDD context
8696 * @adapter: Primary adapter context
8697 *
8698 * Enable Cds modules after WLAN firmware is up.
8699 *
8700 * Return: 0 on success and errno on failure.
8701 */
8702int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8703{
8704 int ret;
8705 QDF_STATUS status;
Arun Khandavallifae92942016-08-01 13:31:08 +05308706
8707 ret = hdd_pre_enable_configure(hdd_ctx);
8708 if (ret) {
8709 hdd_err("Failed to pre-configure cds");
8710 goto out;
8711 }
8712
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008713 /* Always get latest IPA resources allocated from cds_open and configure
8714 * IPA module before configuring them to FW. Sequence required as crash
8715 * observed otherwise.
8716 */
8717 if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
8718 if (hdd_ipa_uc_ol_init(hdd_ctx)) {
8719 hdd_err("Failed to setup pipes");
8720 goto out;
8721 }
8722 }
8723
Arun Khandavallifae92942016-08-01 13:31:08 +05308724 /*
8725 * Start CDS which starts up the SME/MAC/HAL modules and everything
8726 * else
8727 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308728 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308729
8730 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008731 hdd_err("cds_enable failed");
Arun Khandavallifae92942016-08-01 13:31:08 +05308732 goto out;
8733 }
8734
8735 status = hdd_post_cds_enable_config(hdd_ctx);
8736 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008737 hdd_err("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008738 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308739 }
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308740 status = hdd_register_bcn_cb(hdd_ctx);
8741 if (!QDF_IS_STATUS_SUCCESS(status)) {
8742 hdd_alert("hdd_post_cds_enable_config failed");
8743 goto cds_disable;
8744 }
Arun Khandavallifae92942016-08-01 13:31:08 +05308745
8746 ret = hdd_features_init(hdd_ctx, adapter);
8747 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008748 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308749
Arun Khandavallifae92942016-08-01 13:31:08 +05308750
8751 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008752
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008753cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308754 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008755
Arun Khandavallifae92942016-08-01 13:31:08 +05308756out:
8757 return -EINVAL;
8758}
8759
8760/**
8761 * hdd_deconfigure_cds() -De-Configure cds
8762 * @hdd_ctx: HDD context
8763 *
8764 * Deconfigure Cds modules before WLAN firmware is down.
8765 *
8766 * Return: 0 on success and errno on failure.
8767 */
Jeff Johnson590e2012016-10-05 16:16:24 -07008768static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308769{
8770 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07008771 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308772
8773 ENTER();
8774 /* De-register the SME callbacks */
8775 hdd_deregister_cb(hdd_ctx);
8776
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308777 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308778 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8779 hdd_err("Failed to Disable the CDS Modules! :%d",
8780 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07008781 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308782 }
8783
8784 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07008785 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308786}
8787
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008788#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
8789static void hdd_deregister_policy_manager_callback(
8790 struct wlan_objmgr_psoc *psoc)
8791{
8792 if (QDF_STATUS_SUCCESS !=
8793 policy_mgr_deregister_hdd_cb(psoc)) {
8794 hdd_err("HDD callback deregister with policy manager failed");
8795 }
8796}
8797#else
8798static void hdd_deregister_policy_manager_callback(
8799 struct wlan_objmgr_psoc *psoc)
8800{
8801}
8802#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05308803
8804/**
8805 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
8806 * @hdd_ctx: HDD context
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008807 * @ftm_mode: ftm mode
Arun Khandavallifae92942016-08-01 13:31:08 +05308808 *
8809 * This function maintains the driver state machine it will be invoked from
8810 * exit, shutdown and con_mode change handler. Depending on the driver state
8811 * shall perform the stopping/closing of the modules.
8812 *
8813 * Return: 0 for success; non-zero for failure
8814 */
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008815int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
Arun Khandavallifae92942016-08-01 13:31:08 +05308816{
8817 void *hif_ctx;
8818 qdf_device_t qdf_ctx;
8819 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308820 int ret = 0;
Dustin Brown70111822017-03-30 15:31:40 -07008821 bool is_idle_stop = !cds_is_driver_unloading() &&
8822 !cds_is_driver_recovering();
8823 int active_threads;
Arun Khandavallifae92942016-08-01 13:31:08 +05308824
8825 ENTER();
8826
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008827 hdd_deregister_policy_manager_callback(hdd_ctx->hdd_psoc);
8828
Arun Khandavallifae92942016-08-01 13:31:08 +05308829 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8830 if (!qdf_ctx) {
8831 hdd_err("QDF device context NULL");
8832 return -EINVAL;
8833 }
8834
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308835 mutex_lock(&hdd_ctx->iface_change_lock);
8836 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05308837
Dustin Brown70111822017-03-30 15:31:40 -07008838 active_threads = cds_return_external_threads_count();
8839 if (active_threads > 0 || hdd_ctx->isWiphySuspended) {
Rajeev Kumar86177c22017-03-16 19:44:39 -07008840 hdd_warn("External threads %d wiphy suspend %d",
Dustin Brown70111822017-03-30 15:31:40 -07008841 active_threads, hdd_ctx->isWiphySuspended);
8842
8843 cds_print_external_threads();
8844
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008845 if (is_idle_stop && !ftm_mode) {
Dustin Brown70111822017-03-30 15:31:40 -07008846 mutex_unlock(&hdd_ctx->iface_change_lock);
8847 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008848 hdd_ctx->config->iface_change_wait_time);
8849 hdd_ctx->stop_modules_in_progress = false;
Dustin Brown70111822017-03-30 15:31:40 -07008850 return 0;
8851 }
Rajeev Kumar86177c22017-03-16 19:44:39 -07008852 }
8853
Arun Khandavallifae92942016-08-01 13:31:08 +05308854 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
8855
8856 switch (hdd_ctx->driver_status) {
8857 case DRIVER_MODULES_UNINITIALIZED:
8858 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308859 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308860 case DRIVER_MODULES_CLOSED:
8861 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308862 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308863 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05308864 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308865 if (hdd_deconfigure_cds(hdd_ctx)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008866 hdd_err("Failed to de-configure CDS");
Arun Khandavallifae92942016-08-01 13:31:08 +05308867 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308868 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308869 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008870 hdd_debug("successfully Disabled the CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05308871 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8872 break;
8873 case DRIVER_MODULES_OPENED:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008874 hdd_debug("Closing CDS modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05308875 break;
8876 default:
8877 hdd_err("Trying to stop wlan in a wrong state: %d",
8878 hdd_ctx->driver_status);
8879 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308880 ret = -EINVAL;
8881 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308882 }
8883
Govind Singhb048e872016-09-27 22:07:43 +05308884 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8885 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8886 hdd_err("Failed to process post CDS disable Modules! :%d",
8887 qdf_status);
8888 ret = -EINVAL;
8889 QDF_ASSERT(0);
8890 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308891 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308892 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008893 hdd_warn("Failed to stop CDS: %d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308894 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308895 QDF_ASSERT(0);
8896 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008897
Arun Khandavallifae92942016-08-01 13:31:08 +05308898 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8899 if (!hif_ctx) {
8900 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308901 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308902 }
8903
8904 hdd_hif_close(hif_ctx);
8905
8906 ol_cds_free();
8907
Dustin Brown70111822017-03-30 15:31:40 -07008908 if (is_idle_stop) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308909 ret = pld_power_off(qdf_ctx->dev);
8910 if (ret)
8911 hdd_err("CNSS power down failed put device into Low power mode:%d",
8912 ret);
8913 }
8914 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
Sandeep Puligilla1cf6ebe2017-04-04 14:40:27 -07008915 /*
8916 * Reset total mac phy during module stop such that during
8917 * next module start same psoc is used to populate new service
8918 * ready data
8919 */
8920 hdd_ctx->hdd_psoc->total_mac_phy = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308921
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308922done:
8923 hdd_ctx->stop_modules_in_progress = false;
8924 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308925 EXIT();
8926
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308927 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308928
8929}
8930
8931/**
8932 * hdd_iface_change_callback() - Function invoked when stop modules expires
8933 * @priv: pointer to hdd context
8934 *
8935 * This function is invoked when the timer waiting for the interface change
8936 * expires, it shall cut-down the power to wlan and stop all the modules.
8937 *
8938 * Return: void
8939 */
8940static void hdd_iface_change_callback(void *priv)
8941{
8942 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
8943 int ret;
8944 int status = wlan_hdd_validate_context(hdd_ctx);
8945
8946 if (status)
8947 return;
8948
8949 ENTER();
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008950 hdd_debug("Interface change timer expired close the modules!");
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008951 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05308952 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008953 hdd_err("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05308954 EXIT();
8955}
8956
8957/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308958 * hdd_state_info_dump() - prints state information of hdd layer
8959 * @buf: buffer pointer
8960 * @size: size of buffer to be filled
8961 *
8962 * This function is used to dump state information of hdd layer
8963 *
8964 * Return: None
8965 */
8966static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
8967{
8968 hdd_context_t *hdd_ctx;
8969 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8970 QDF_STATUS status;
8971 hdd_station_ctx_t *hdd_sta_ctx;
8972 hdd_adapter_t *adapter;
8973 uint16_t len = 0;
8974 char *buf = *buf_ptr;
8975
8976 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8977 if (!hdd_ctx) {
8978 hdd_err("Failed to get hdd context ");
8979 return;
8980 }
8981
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08008982 hdd_debug("size of buffer: %d", *size);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308983
8984 len += scnprintf(buf + len, *size - len,
8985 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8986 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008987 "\n is_scheduler_suspended %d",
8988 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308989
8990 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8991
8992 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8993 adapter = adapter_node->pAdapter;
8994 if (adapter->dev)
8995 len += scnprintf(buf + len, *size - len,
8996 "\n device name: %s", adapter->dev->name);
8997 len += scnprintf(buf + len, *size - len,
8998 "\n device_mode: %d", adapter->device_mode);
8999 switch (adapter->device_mode) {
9000 case QDF_STA_MODE:
9001 case QDF_P2P_CLIENT_MODE:
9002 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9003 len += scnprintf(buf + len, *size - len,
9004 "\n connState: %d",
9005 hdd_sta_ctx->conn_info.connState);
9006 break;
9007
9008 default:
9009 break;
9010 }
9011 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
9012 adapter_node = next;
9013 }
9014
9015 *size -= len;
9016 *buf_ptr += len;
9017}
9018
9019/**
9020 * hdd_register_debug_callback() - registration function for hdd layer
9021 * to print hdd state information
9022 *
9023 * Return: None
9024 */
9025static void hdd_register_debug_callback(void)
9026{
9027 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
9028}
9029
9030/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009031 * hdd_wlan_startup() - HDD init function
9032 * @dev: Pointer to the underlying device
9033 *
9034 * This is the driver startup code executed once a WLAN device has been detected
9035 *
9036 * Return: 0 for success, < 0 for failure
9037 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309038int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009039{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309040 QDF_STATUS status;
Jeff Johnson957bc272017-02-02 08:54:48 -08009041 hdd_context_t *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009042 int ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009043 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309044 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009045
9046 ENTER();
9047
Arun Khandavallifae92942016-08-01 13:31:08 +05309048 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009049
9050 if (IS_ERR(hdd_ctx))
9051 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009052
Abhishek Singhe9068f12017-03-31 14:14:52 +05309053 ret = hdd_objmgr_create_and_store_psoc(hdd_ctx,
9054 DEFAULT_PSOC_ID);
9055 if (ret) {
9056 hdd_err("Psoc creation fails!");
9057 QDF_BUG(0);
9058 goto err_hdd_free_context;
9059 }
9060
Arun Khandavallifae92942016-08-01 13:31:08 +05309061 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
9062 hdd_iface_change_callback, (void *)hdd_ctx);
9063
9064 mutex_init(&hdd_ctx->iface_change_lock);
9065
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009066 ret = hdd_init_netlink_services(hdd_ctx);
9067 if (ret)
9068 goto err_hdd_free_context;
9069
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009070 hdd_request_manager_init();
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07009071 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309072
Jeff Johnson957bc272017-02-02 08:54:48 -08009073 ret = hdd_wlan_start_modules(hdd_ctx, NULL, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309074 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009075 hdd_err("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009076 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009077 }
9078
Yingying Tang80e15f32016-09-27 18:23:01 +08009079 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009080
Yingying Tang95409972016-10-20 15:16:15 +08009081 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009082 hdd_debug("Failed to set wow pulse");
Yingying Tang95409972016-10-20 15:16:15 +08009083
Anurag Chouhan6d760662016-02-20 16:05:43 +05309084 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009085
9086 if (NULL == hdd_ctx->hHal) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009087 hdd_err("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05309088 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009089 }
9090
Prashanth Bhatta07998752016-04-28 12:35:33 -07009091 ret = hdd_wiphy_init(hdd_ctx);
9092 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009093 hdd_err("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05309094 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009095 }
9096
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05309097 if (hdd_ctx->config->enable_dp_trace)
9098 qdf_dp_trace_init();
9099
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309100 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009101 goto err_wiphy_unregister;
9102
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05309103 wlan_hdd_init_chan_info(hdd_ctx);
9104
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07009105 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08009106
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009107 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009108
Jeff Johnson957bc272017-02-02 08:54:48 -08009109 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
9110 if (ret) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009111 hdd_err("Failed to open interfaces: %d", ret);
Jeff Johnson46bde382017-02-01 15:31:16 -08009112 goto err_release_rtnl_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113 }
9114
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009115 hdd_release_rtnl_lock();
9116 rtnl_held = false;
9117
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009118 wlan_hdd_update_11n_mode(hdd_ctx->config);
9119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009120#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05309121 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309122 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009123 hdd_skip_acs_scan_timer_handler,
9124 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309125 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07009126 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04009127 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009128#endif
9129
Nitesh Shah61c10d92016-10-19 19:29:15 +05309130 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
9131 QDF_TIMER_TYPE_SW,
9132 wlan_hdd_change_tdls_mode,
9133 hdd_ctx);
9134
Prashanth Bhattaab004382016-10-11 16:08:11 -07009135 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009136
Jeff Johnson9afc5012016-09-23 13:56:27 -07009137 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009138
Nirav Shahbd36b062016-07-18 11:12:59 +05309139 if (hdd_ctx->rps)
9140 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07009141
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009142 ret = hdd_register_notifiers(hdd_ctx);
9143 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08009144 goto err_close_adapters;
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05309145
9146 status = wlansap_global_init();
9147 if (QDF_IS_STATUS_ERROR(status))
Jeff Johnson957bc272017-02-02 08:54:48 -08009148 goto err_close_adapters;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009149
Komal Seelam8634b772016-09-29 12:12:24 +05309150 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009151 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309152 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009153
bings612b9c42016-11-07 10:52:03 +08009154 if (hdd_enable_egap(hdd_ctx))
9155 hdd_err("enhance green ap is not enabled");
9156
Arun Khandavallifae92942016-08-01 13:31:08 +05309157 if (hdd_ctx->config->fIsImpsEnabled)
9158 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309159
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309160 if (hdd_ctx->config->sifs_burst_duration) {
9161 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
9162 hdd_ctx->config->sifs_burst_duration;
9163
9164 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
9165 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
9166 set_value, PDEV_CMD);
9167 }
9168
Arun Khandavallifae92942016-08-01 13:31:08 +05309169 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
9170 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309171
Selvaraj, Sridhar1ffa0ec2017-03-10 09:52:12 +05309172 complete(&wlan_start_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009173 goto success;
9174
Jeff Johnson957bc272017-02-02 08:54:48 -08009175err_close_adapters:
Jeff Johnson46bde382017-02-01 15:31:16 -08009176 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009177
Jeff Johnson46bde382017-02-01 15:31:16 -08009178err_release_rtnl_lock:
Arun Khandavallid4349a92016-07-25 11:10:43 +05309179 if (rtnl_held)
9180 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009181
Anurag Chouhance6a4052016-09-14 18:20:42 +05309182 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08009183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009184err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009185 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009186
Arun Khandavallifae92942016-08-01 13:31:08 +05309187err_stop_modules:
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009188 hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309189
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05309190err_exit_nl_srv:
Arunk Khandavallifbc1ef02017-03-14 21:25:05 +05309191 if (DRIVER_MODULES_CLOSED == hdd_ctx->driver_status) {
9192 status = cds_sched_close(hdd_ctx->pcds_context);
9193 if (!QDF_IS_STATUS_SUCCESS(status)) {
9194 hdd_err("Failed to close CDS Scheduler");
9195 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
9196 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009197 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009198
Houston Hoffman47a4a052016-11-14 23:22:44 -08009199 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009200 hdd_request_manager_deinit();
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009201 hdd_exit_netlink_services(hdd_ctx);
9202
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309203 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009204err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05309205 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
9206 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07009207 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309208 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009209
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009210 return -EIO;
9211
9212success:
9213 EXIT();
9214 return 0;
9215}
9216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009217/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309218 * hdd_wlan_update_target_info() - update target type info
9219 * @hdd_ctx: HDD context
9220 * @context: hif context
9221 *
9222 * Update target info received from firmware in hdd context
9223 * Return:None
9224 */
9225
9226void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
9227{
9228 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
9229
9230 if (!tgt_info) {
9231 hdd_err("Target info is Null");
9232 return;
9233 }
9234
9235 hdd_ctx->target_type = tgt_info->target_type;
9236}
9237
9238/**
9239 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309240 * @hdd_ctx: HDD context
9241 *
9242 * Register the HDD callbacks to CDS/SME.
9243 *
9244 * Return: 0 for success or Error code for failure
9245 */
9246int hdd_register_cb(hdd_context_t *hdd_ctx)
9247{
9248 QDF_STATUS status;
9249 int ret = 0;
9250
9251 ENTER();
9252
9253 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
9254
9255 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
9256 hdd_send_oem_data_rsp_msg);
9257
9258 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
9259 wlan_hdd_cfg80211_fw_mem_dump_cb);
9260 if (!QDF_IS_STATUS_SUCCESS(status)) {
9261 hdd_err("Failed to register memdump callback");
9262 ret = -EINVAL;
9263 return ret;
9264 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05309265 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
9266 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309267 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
9268 sme_nan_register_callback(hdd_ctx->hHal,
9269 wlan_hdd_cfg80211_nan_callback);
9270 sme_stats_ext_register_callback(hdd_ctx->hHal,
9271 wlan_hdd_cfg80211_stats_ext_callback);
9272
9273 sme_ext_scan_register_callback(hdd_ctx->hHal,
9274 wlan_hdd_cfg80211_extscan_callback);
9275
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309276 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
9277 hdd_rssi_threshold_breached);
9278
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309279 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
9280 wlan_hdd_cfg80211_link_layer_stats_callback);
9281
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05309282 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
9283 hdd_lost_link_info_cb);
9284 /* print error and not block the startup process */
9285 if (!QDF_IS_STATUS_SUCCESS(status))
9286 hdd_err("set lost link info callback failed");
9287
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309288 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
9289
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009290 sme_register_set_connection_info_cb(hdd_ctx->hHal,
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009291 hdd_set_connection_in_progress,
9292 hdd_is_connection_in_progress);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309293 EXIT();
9294
9295 return ret;
9296}
9297
9298/**
9299 * hdd_deregister_cb() - De-Register HDD callbacks.
9300 * @hdd_ctx: HDD context
9301 *
9302 * De-Register the HDD callbacks to CDS/SME.
9303 *
9304 * Return: void
9305 */
9306void hdd_deregister_cb(hdd_context_t *hdd_ctx)
9307{
9308 QDF_STATUS status;
9309
9310 ENTER();
9311
9312 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
9313 if (!QDF_IS_STATUS_SUCCESS(status))
9314 hdd_err("De-register of dcc stats callback failed: %d",
9315 status);
9316
9317 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309318 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
9319
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309320 sme_stats_ext_register_callback(hdd_ctx->hHal,
9321 wlan_hdd_cfg80211_stats_ext_callback);
9322
9323 sme_nan_deregister_callback(hdd_ctx->hHal);
9324 status = sme_reset_tsfcb(hdd_ctx->hHal);
9325 if (!QDF_IS_STATUS_SUCCESS(status))
9326 hdd_err("Failed to de-register tsfcb the callback:%d",
9327 status);
9328 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
9329 if (!QDF_IS_STATUS_SUCCESS(status))
9330 hdd_err("Failed to de-register the fw mem dump callback: %d",
9331 status);
9332
9333 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
9334 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
9335
9336 EXIT();
9337}
9338
9339/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340 * hdd_softap_sta_deauth() - handle deauth req from HDD
9341 * @adapter: Pointer to the HDD
9342 * @enable: bool value
9343 *
9344 * This to take counter measure to handle deauth req from HDD
9345 *
9346 * Return: None
9347 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309348QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009349 struct tagCsrDelStaParams *pDelStaParams)
9350{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309351 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009352
9353 ENTER();
9354
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009355 hdd_debug("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009356 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9357
9358 /* Ignore request to deauth bcmc station */
9359 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309360 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009361
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309362 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009363 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9364 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009365
9366 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309367 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009368}
9369
9370/**
9371 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
9372 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309373 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009374 *
9375 * This to take counter measure to handle deauth req from HDD
9376 *
9377 * Return: None
9378 */
9379void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309380 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009381{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009382 ENTER();
9383
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009384 hdd_debug("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009385 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9386
9387 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309388 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009389 return;
9390
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009391 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309392 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009393}
9394
9395void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
9396 bool enable)
9397{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398 ENTER();
9399
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009400 hdd_debug("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009401 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009403 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9404 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009405}
9406
9407/**
9408 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
9409 * @hdd_ctx: HDD Context
9410 *
9411 * API to find if there is any STA or P2P-Client is connected
9412 *
9413 * Return: true if connected; false otherwise
9414 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309415QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009416{
9417 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
9418}
9419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009420/**
9421 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
9422 * @adapter: HDD adapter pointer
9423 *
9424 * This function loop through each adapter and disable roaming on each STA
9425 * device mode except the input adapter.
9426 *
9427 * Note: On the input adapter roaming is not enabled yet hence no need to
9428 * disable.
9429 *
9430 * Return: None
9431 */
9432void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
9433{
9434 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9435 hdd_adapter_t *adapterIdx = NULL;
9436 hdd_adapter_list_node_t *adapterNode = NULL;
9437 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309438 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009439
9440 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009441 hdd_ctx->config->isRoamOffloadScanEnabled &&
9442 QDF_STA_MODE == adapter->device_mode &&
9443 policy_mgr_is_sta_active_connection_exists(
9444 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009445 hdd_debug("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446 adapter->sessionId);
9447 /*
9448 * Loop through adapter and disable roaming for each STA device
9449 * mode except the input adapter.
9450 */
9451 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9452
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309453 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009454 adapterIdx = adapterNode->pAdapter;
9455
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009456 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009457 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009458 hdd_debug("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009459 adapterIdx->sessionId);
9460 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
9461 (adapterIdx),
9462 adapterIdx->sessionId, 0);
9463 }
9464
9465 status = hdd_get_next_adapter(hdd_ctx,
9466 adapterNode,
9467 &pNext);
9468 adapterNode = pNext;
9469 }
9470 }
9471}
9472
9473/**
9474 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
9475 * @adapter: HDD adapter pointer
9476 *
9477 * This function loop through each adapter and enable roaming on each STA
9478 * device mode except the input adapter.
9479 * Note: On the input adapter no need to enable roaming because link got
9480 * disconnected on this.
9481 *
9482 * Return: None
9483 */
9484void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
9485{
9486 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9487 hdd_adapter_t *adapterIdx = NULL;
9488 hdd_adapter_list_node_t *adapterNode = NULL;
9489 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309490 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009491
9492 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009493 hdd_ctx->config->isRoamOffloadScanEnabled &&
9494 QDF_STA_MODE == adapter->device_mode &&
9495 policy_mgr_is_sta_active_connection_exists(
9496 hdd_ctx->hdd_psoc)) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009497 hdd_debug("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009498 adapter->sessionId);
9499 /*
9500 * Loop through adapter and enable roaming for each STA device
9501 * mode except the input adapter.
9502 */
9503 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9504
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309505 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009506 adapterIdx = adapterNode->pAdapter;
9507
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009508 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009509 && adapter->sessionId != adapterIdx->sessionId) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009510 hdd_debug("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009511 adapterIdx->sessionId);
9512 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
9513 (adapterIdx),
9514 adapterIdx->sessionId,
9515 REASON_CONNECT);
9516 }
9517
9518 status = hdd_get_next_adapter(hdd_ctx,
9519 adapterNode,
9520 &pNext);
9521 adapterNode = pNext;
9522 }
9523 }
9524}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009525
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309526/**
9527 * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
9528 * @skb: sk buffer pointer
9529 *
9530 * Sends the bcast message to SVC multicast group with generic nl socket
9531 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
9532 *
9533 * Return: None
9534 */
9535static void nl_srv_bcast_svc(struct sk_buff *skb)
9536{
9537#ifdef CNSS_GENL
9538 nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
9539#else
9540 nl_srv_bcast(skb);
9541#endif
9542}
9543
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309544void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009545{
9546 struct sk_buff *skb;
9547 struct nlmsghdr *nlh;
9548 tAniMsgHdr *ani_hdr;
9549 void *nl_data = NULL;
9550 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309551 struct radio_index_tlv *radio_info;
9552 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553
9554 if (in_interrupt() || irqs_disabled() || in_atomic())
9555 flags = GFP_ATOMIC;
9556
9557 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
9558
9559 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009560 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009561 return;
9562 }
9563
9564 nlh = (struct nlmsghdr *)skb->data;
9565 nlh->nlmsg_pid = 0; /* from kernel */
9566 nlh->nlmsg_flags = 0;
9567 nlh->nlmsg_seq = 0;
9568 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
9569
9570 ani_hdr = NLMSG_DATA(nlh);
9571 ani_hdr->type = type;
9572
9573 switch (type) {
9574 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05309575 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009576 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009577 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009578 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009579 ani_hdr->length = 0;
9580 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581 break;
9582 case WLAN_SVC_WLAN_STATUS_IND:
9583 case WLAN_SVC_WLAN_VERSION_IND:
9584 case WLAN_SVC_DFS_CAC_START_IND:
9585 case WLAN_SVC_DFS_CAC_END_IND:
9586 case WLAN_SVC_DFS_RADAR_DETECT_IND:
9587 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
9588 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08009589 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05309590 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009591 ani_hdr->length = len;
9592 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
9593 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
9594 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595 break;
9596
9597 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07009598 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009599 type);
9600 kfree_skb(skb);
9601 return;
9602 }
9603
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309604 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08009605 * Add radio index at the end of the svc event in TLV format
9606 * to maintain the backward compatibility with userspace
9607 * applications.
9608 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309609
9610 tlv_len = 0;
9611
9612 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
9613 < WLAN_NL_MAX_PAYLOAD) {
9614 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
9615 sizeof(*ani_hdr) + len);
9616 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
9617 radio_info->length = (unsigned short) sizeof(radio_info->radio);
9618 radio_info->radio = radio;
9619 tlv_len = sizeof(*radio_info);
9620 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
9621 "Added radio index tlv - radio index %d",
9622 radio_info->radio);
9623 }
9624
9625 nlh->nlmsg_len += tlv_len;
9626 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
9627
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309628 nl_srv_bcast_svc(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009629
9630 return;
9631}
9632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009633#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
9634void wlan_hdd_auto_shutdown_cb(void)
9635{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07009636 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309637
9638 if (!hdd_ctx)
9639 return;
9640
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009641 hdd_debug("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309642 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
9643 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009644}
9645
9646void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
9647{
9648 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309649 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009650 hdd_adapter_t *adapter;
9651 bool ap_connected = false, sta_connected = false;
9652 tHalHandle hal_handle;
9653
9654 hal_handle = hdd_ctx->hHal;
9655 if (hal_handle == NULL)
9656 return;
9657
9658 if (hdd_ctx->config->WlanAutoShutdown == 0)
9659 return;
9660
9661 if (enable == false) {
9662 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309663 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009664 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009665 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309666 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009667 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009668 return;
9669 }
9670
9671 /* To enable shutdown timer check conncurrency */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009672 if (policy_mgr_concurrent_open_sessions_running(
9673 hdd_ctx->hdd_psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009674 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9675
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309676 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009677 adapter = adapterNode->pAdapter;
9678 if (adapter
9679 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009680 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009681 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9682 conn_info.connState ==
9683 eConnectionState_Associated) {
9684 sta_connected = true;
9685 break;
9686 }
9687 }
9688 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009689 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009690 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
9691 bApActive == true) {
9692 ap_connected = true;
9693 break;
9694 }
9695 }
9696 status = hdd_get_next_adapter(hdd_ctx,
9697 adapterNode,
9698 &pNext);
9699 adapterNode = pNext;
9700 }
9701 }
9702
9703 if (ap_connected == true || sta_connected == true) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009704 hdd_debug("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009705 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009706 }
Jeff Johnson68755312017-02-10 11:46:55 -08009707
9708 if (sme_set_auto_shutdown_timer(hal_handle,
9709 hdd_ctx->config->WlanAutoShutdown)
9710 != QDF_STATUS_SUCCESS)
9711 hdd_err("Failed to start wlan auto shutdown timer");
9712 else
9713 hdd_notice("Auto Shutdown timer for %d seconds enabled",
9714 hdd_ctx->config->WlanAutoShutdown);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009715}
9716#endif
9717
9718hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
9719 bool check_start_bss)
9720{
9721 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
9722 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309723 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
9725
9726 con_sap_adapter = NULL;
9727
9728 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309729 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009730 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009731 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
9732 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009733 adapter != this_sap_adapter) {
9734 if (check_start_bss) {
9735 if (test_bit(SOFTAP_BSS_STARTED,
9736 &adapter->event_flags)) {
9737 con_sap_adapter = adapter;
9738 break;
9739 }
9740 } else {
9741 con_sap_adapter = adapter;
9742 break;
9743 }
9744 }
9745 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
9746 adapterNode = pNext;
9747 }
9748
9749 return con_sap_adapter;
9750}
9751
9752#ifdef MSM_PLATFORM
Dustin Brown5ec6b552017-03-31 12:11:40 -07009753static inline bool hdd_adapter_is_sta(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009754{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009755 return adapter->device_mode == QDF_STA_MODE ||
9756 adapter->device_mode == QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009757}
9758
Dustin Brown5ec6b552017-03-31 12:11:40 -07009759static inline bool hdd_adapter_is_ap(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009761 return adapter->device_mode == QDF_SAP_MODE ||
9762 adapter->device_mode == QDF_P2P_GO_MODE;
9763}
9764
9765static bool hdd_any_adapter_is_assoc(hdd_context_t *hdd_ctx)
9766{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309767 QDF_STATUS status;
Dustin Brown5ec6b552017-03-31 12:11:40 -07009768 hdd_adapter_list_node_t *node;
9769
9770 status = hdd_get_front_adapter(hdd_ctx, &node);
9771 while (QDF_IS_STATUS_SUCCESS(status) && node) {
9772 hdd_adapter_t *adapter = node->pAdapter;
9773
9774 if (adapter &&
9775 hdd_adapter_is_sta(adapter) &&
9776 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9777 conn_info.connState == eConnectionState_Associated) {
9778 return true;
9779 }
9780
9781 if (adapter &&
9782 hdd_adapter_is_ap(adapter) &&
9783 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive) {
9784 return true;
9785 }
9786
9787 status = hdd_get_next_adapter(hdd_ctx, node, &node);
9788 }
9789
9790 return false;
9791}
9792
9793static bool hdd_bus_bw_compute_timer_is_running(hdd_context_t *hdd_ctx)
9794{
9795 bool is_running;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009796
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309797 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown5ec6b552017-03-31 12:11:40 -07009798 is_running = hdd_ctx->bus_bw_timer_running;
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309799 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009800
Dustin Brown5ec6b552017-03-31 12:11:40 -07009801 return is_running;
9802}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009803
Dustin Brown5ec6b552017-03-31 12:11:40 -07009804static void __hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9805{
9806 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9807 hdd_ctx->bus_bw_timer_running = true;
9808 qdf_timer_start(&hdd_ctx->bus_bw_timer,
9809 hdd_ctx->config->busBandwidthComputeInterval);
9810 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9811}
9812
9813void hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9814{
9815 ENTER();
9816
9817 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9818 hdd_debug("Bandwidth compute timer already started");
9819 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009820 }
9821
Dustin Brown5ec6b552017-03-31 12:11:40 -07009822 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9823
9824 EXIT();
9825}
9826
9827void hdd_bus_bw_compute_timer_try_start(hdd_context_t *hdd_ctx)
9828{
9829 ENTER();
9830
9831 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9832 hdd_debug("Bandwidth compute timer already started");
9833 return;
Ravi Joshib89e7f72016-09-07 13:43:15 -07009834 }
Dustin Brown5ec6b552017-03-31 12:11:40 -07009835
9836 if (hdd_any_adapter_is_assoc(hdd_ctx))
9837 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9838
9839 EXIT();
9840}
9841
9842static void __hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9843{
9844 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
9845
9846 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9847 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
9848 hdd_ctx->bus_bw_timer_running = false;
9849 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9850
9851 hdd_reset_tcp_delack(hdd_ctx);
9852}
9853
9854void hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9855{
9856 ENTER();
9857
9858 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9859 hdd_debug("Bandwidth compute timer already stopped");
9860 return;
9861 }
9862
9863 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9864
9865 EXIT();
9866}
9867
9868void hdd_bus_bw_compute_timer_try_stop(hdd_context_t *hdd_ctx)
9869{
9870 ENTER();
9871
9872 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9873 hdd_debug("Bandwidth compute timer already stopped");
9874 return;
9875 }
9876
9877 if (!hdd_any_adapter_is_assoc(hdd_ctx))
9878 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9879
9880 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009881}
9882#endif
9883
9884/**
9885 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
9886 * and sta's operating channel.
9887 * @sta_adapter: Describe the first argument to foobar.
9888 * @ap_adapter: Describe the second argument to foobar.
9889 * @roam_profile: Roam profile of AP to which STA wants to connect.
9890 * @concurrent_chnl_same: If both SAP and STA channels are same then
9891 * set this flag to true else false.
9892 *
9893 * This function checks the sap's operating channel and sta's operating channel.
9894 * if both are same then it will return false else it will restart the sap in
9895 * sta's channel and return true.
9896 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309897 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009898 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309899QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009900 hdd_adapter_t *ap_adapter,
9901 tCsrRoamProfile *roam_profile,
9902 tScanResultHandle *scan_cache,
9903 bool *concurrent_chnl_same)
9904{
9905 hdd_ap_ctx_t *hdd_ap_ctx;
9906 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309907 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009908 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009909 *concurrent_chnl_same = true;
9910
9911 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9912 status =
Archana Ramachandran2eb7a612017-03-23 22:58:42 -07009913 sme_get_ap_channel_from_scan_cache(roam_profile,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009914 scan_cache,
9915 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309916 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009917 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009918 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9919 if (hdd_ap_ctx->operatingChannel != channel_id) {
9920 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009921 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009922 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009923 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009924 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
9925 if (hdd_ap_ctx->operatingChannel != channel_id) {
9926 *concurrent_chnl_same = false;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009927 hdd_debug("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009928 }
9929 }
9930 } else {
9931 /*
9932 * Lets handle worst case scenario here, Scan cache lookup is
9933 * failed so we have to stop the SAP to avoid any channel
9934 * discrepancy between SAP's channel and STA's channel.
9935 * Return the status as failure so caller function could know
9936 * that scan look up is failed.
9937 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07009938 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309939 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009940 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309941 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009942}
9943
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009944/**
9945 * wlan_hdd_stop_sap() - This function stops bss of SAP.
9946 * @ap_adapter: SAP adapter
9947 *
9948 * This function will process the stopping of sap adapter.
9949 *
9950 * Return: None
9951 */
9952void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
9953{
9954 hdd_ap_ctx_t *hdd_ap_ctx;
9955 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309956 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009958
9959 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009960 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961 return;
9962 }
9963
9964 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9965 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309966 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009967 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309968
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009969 mutex_lock(&hdd_ctx->sap_lock);
9970 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08009971 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
9973 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009974 hdd_debug("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309975 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309976 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009977 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309978 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08009979 qdf_stop_bss_event,
9980 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309981 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009982 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009983 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009984 return;
9985 }
9986 }
9987 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009988 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
9989 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 ap_adapter->sessionId);
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -08009991 hdd_debug("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009993 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 }
9995 mutex_unlock(&hdd_ctx->sap_lock);
9996 return;
9997}
9998
9999/**
10000 * wlan_hdd_start_sap() - this function starts bss of SAP.
10001 * @ap_adapter: SAP adapter
10002 *
10003 * This function will process the starting of sap adapter.
10004 *
10005 * Return: None
10006 */
Arun Khandavallicc544b32017-01-30 19:52:16 +053010007void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010008{
10009 hdd_ap_ctx_t *hdd_ap_ctx;
10010 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010011 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012 hdd_context_t *hdd_ctx;
10013 tsap_Config_t *sap_config;
10014
10015 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010016 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017 return;
10018 }
10019
Krunal Soni9b04c9b2016-03-10 13:08:05 -080010020 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -070010021 hdd_err("SoftAp role has not been enabled");
10022 return;
10023 }
10024
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010025 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
10026 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10027 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10028 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
10029
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010030 mutex_lock(&hdd_ctx->sap_lock);
10031 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
10032 goto end;
10033
10034 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010035 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010036 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
10037 goto end;
10038 }
10039
Wei Song2f76f642016-11-18 16:32:53 +080010040 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010041 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
10042 &hdd_ap_ctx->sapConfig,
10043 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010044 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010045 goto end;
10046
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010047 hdd_debug("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010048 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -080010049 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010050 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -070010051 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010052 goto end;
10053 }
Jeff Johnson28f8a772016-08-15 15:30:36 -070010054 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010055 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -080010056 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080010057 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
10058 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010059 ap_adapter->sessionId);
10060 hostapd_state->bCommit = true;
10061
10062end:
10063 mutex_unlock(&hdd_ctx->sap_lock);
10064 return;
10065}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010066
10067/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010068 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
10069 * mac scan config
10070 * @status: Status of set antenna mode
10071 *
10072 * Callback on setting the dual mac configuration
10073 *
10074 * Return: None
10075 */
10076void wlan_hdd_soc_set_antenna_mode_cb(
10077 enum set_antenna_mode_status status)
10078{
10079 hdd_context_t *hdd_ctx;
10080
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010081 hdd_debug("Status: %d", status);
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010082
10083 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10084 if (0 != wlan_hdd_validate_context(hdd_ctx))
10085 return;
10086
10087 /* Signal the completion of set dual mac config */
10088 complete(&hdd_ctx->set_antenna_mode_cmpl);
10089}
10090
10091/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010092 * hdd_get_fw_version() - Get FW version
10093 * @hdd_ctx: pointer to HDD context.
10094 * @major_spid: FW version - major spid.
10095 * @minor_spid: FW version - minor spid
10096 * @ssid: FW version - ssid
10097 * @crmid: FW version - crmid
10098 *
10099 * This function is called to get the firmware build version stored
10100 * as part of the HDD context
10101 *
10102 * Return: None
10103 */
10104void hdd_get_fw_version(hdd_context_t *hdd_ctx,
10105 uint32_t *major_spid, uint32_t *minor_spid,
10106 uint32_t *siid, uint32_t *crmid)
10107{
10108 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
10109 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
10110 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
10111 *crmid = hdd_ctx->target_fw_version & 0x7fff;
10112}
10113
10114#ifdef QCA_CONFIG_SMP
10115/**
10116 * wlan_hdd_get_cpu() - get cpu_index
10117 *
10118 * Return: cpu_index
10119 */
10120int wlan_hdd_get_cpu(void)
10121{
10122 int cpu_index = get_cpu();
10123 put_cpu();
10124 return cpu_index;
10125}
10126#endif
10127
10128/**
10129 * hdd_get_fwpath() - get framework path
10130 *
10131 * This function is used to get the string written by
10132 * userspace to start the wlan driver
10133 *
10134 * Return: string
10135 */
10136const char *hdd_get_fwpath(void)
10137{
10138 return fwpath.string;
10139}
10140
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010141/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010142 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010143 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010144 * This function initilizes CDS global context with the help of cds_init. This
10145 * has to be the first function called after probe to get a valid global
10146 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010147 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010148 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010149 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010150int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010151{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010152 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010153 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010154
Houston Hoffman9e06e542016-12-12 12:06:26 -080010155 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010156#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10157 wlan_logging_sock_init_svc();
10158#endif
10159
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010160 if (p_cds_context == NULL) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010161 hdd_err("Failed to allocate CDS context");
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010162 ret = -ENOMEM;
10163 goto err_out;
10164 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010165
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010166 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +053010167 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010168
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010169err_out:
10170 return ret;
10171}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010172
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010173/**
10174 * hdd_deinit() - Deinitialize Driver
10175 *
10176 * This function frees CDS global context with the help of cds_deinit. This
10177 * has to be the last function call in remove callback to free the global
10178 * context.
10179 */
10180void hdd_deinit(void)
10181{
10182 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010183
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010184#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10185 wlan_logging_sock_deinit_svc();
10186#endif
10187}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010188
Yue Ma6e7b1a02017-04-03 14:17:46 -070010189#ifdef QCA_WIFI_NAPIER_EMULATION
10190#define HDD_WLAN_START_WAIT_TIME ((CDS_WMA_TIMEOUT + 5000) * 100)
10191#else
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010192#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
Yue Ma6e7b1a02017-04-03 14:17:46 -070010193#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010194
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010195/**
10196 * __hdd_module_init - Module init helper
10197 *
10198 * Module init helper function used by both module and static driver.
10199 *
10200 * Return: 0 for success, errno on failure
10201 */
10202static int __hdd_module_init(void)
10203{
10204 int ret = 0;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010205 unsigned long rc;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010206
Arun Khandavallifae92942016-08-01 13:31:08 +053010207 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010208 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010209
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010210 pld_init();
10211
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010212 ret = hdd_init();
10213 if (ret) {
10214 pr_err("hdd_init failed %x\n", ret);
10215 goto err_hdd_init;
10216 }
10217
Rajeev Kumar97767a02016-11-30 11:20:40 -080010218 dispatcher_init();
10219
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010220 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010221
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010222 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010223
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010224 init_completion(&wlan_start_comp);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010225 ret = wlan_hdd_register_driver();
10226 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -070010227 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
10228 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010229 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010230 }
10231
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010232 rc = wait_for_completion_timeout(&wlan_start_comp,
10233 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
10234
10235 if (!rc) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010236 hdd_err("Timed-out waiting for wlan_hdd_register_driver");
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010237 QDF_BUG(0);
10238 goto out;
10239 }
10240
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010241 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010242
10243 return 0;
10244out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010245 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -080010246 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010247 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010248
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010249err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010250 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010251
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010252 return ret;
10253}
10254
10255/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010256 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
10257 *
10258 * Block the unloading of the driver until the cds recovery is completed
10259 *
10260 * Return: None
10261 */
10262static void hdd_wait_for_recovery_completion(void)
10263{
10264 int retry = 0;
10265
10266 /* Wait for recovery to complete */
10267 while (cds_is_driver_recovering()) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010268 hdd_err("Recovery in progress; wait here!!!");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010269 msleep(1000);
10270 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010271 hdd_err("SSR never completed, error");
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010272 QDF_BUG(0);
10273 }
10274 }
10275}
10276
10277/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010278 * __hdd_module_exit - Module exit helper
10279 *
10280 * Module exit helper function used by both module and static driver.
10281 */
10282static void __hdd_module_exit(void)
10283{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010284 int qdf_print_idx = -1;
10285
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010286 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
10287 QWLAN_VERSIONSTR);
10288
bings6028ee82017-03-29 07:51:40 +080010289 cds_set_unload_in_progress(true);
10290
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010291 hdd_wait_for_recovery_completion();
10292
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010293 wlan_hdd_unregister_driver();
10294
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010295 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010296
Rajeev Kumar97767a02016-11-30 11:20:40 -080010297 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010298 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010299 pld_deinit();
10300
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010301 qdf_print_idx = qdf_get_pidx();
10302 qdf_print_ctrl_cleanup(qdf_print_idx);
10303
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010304 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010305}
10306
Arun Khandavallifae92942016-08-01 13:31:08 +053010307#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010308/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010309 * wlan_boot_cb() - Wlan boot callback
10310 * @kobj: object whose directory we're creating the link in.
10311 * @attr: attribute the user is interacting with
10312 * @buff: the buffer containing the user data
10313 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010314 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010315 * This callback is invoked when the fs is ready to start the
10316 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010317 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010318 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010319 */
Arun Khandavallifae92942016-08-01 13:31:08 +053010320static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010321 struct kobj_attribute *attr,
10322 const char *buf,
10323 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010324{
Arun Khandavallifae92942016-08-01 13:31:08 +053010325
Arun Khandavallifae92942016-08-01 13:31:08 +053010326 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010327 pr_err("%s: wlan driver already initialized\n", __func__);
10328 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +053010329 }
10330
Arun Khandavallifae92942016-08-01 13:31:08 +053010331 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010332 pr_err("%s: wlan driver initialization failed\n", __func__);
10333 return -EIO;
10334 }
10335
10336 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +053010337
10338 return count;
10339
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010340}
Arun Khandavallifae92942016-08-01 13:31:08 +053010341
10342/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010343 * hdd_sysfs_cleanup() - cleanup sysfs
10344 *
10345 * Return: None
10346 *
10347 */
10348static void hdd_sysfs_cleanup(void)
10349{
10350
10351 /* remove from group */
10352 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
10353 sysfs_remove_group(wlan_loader->boot_wlan_obj,
10354 wlan_loader->attr_group);
10355
10356 /* unlink the object from parent */
10357 kobject_del(wlan_loader->boot_wlan_obj);
10358
10359 /* free the object */
10360 kobject_put(wlan_loader->boot_wlan_obj);
10361
10362 kfree(wlan_loader->attr_group);
10363 kfree(wlan_loader);
10364
10365 wlan_loader = NULL;
10366}
10367
10368/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010369 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
10370 * ready
10371 *
10372 * This is creates the syfs entry boot_wlan. Which shall be invoked
10373 * when the filesystem is ready.
10374 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010375 * QDF API cannot be used here since this function is called even before
10376 * initializing WLAN driver.
10377 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010378 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +053010379 */
10380static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010381{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010382 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010383
10384 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
10385 if (!wlan_loader) {
10386 pr_err("%s: memory alloc failed\n", __func__);
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010387 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010388 }
10389
10390 wlan_loader->boot_wlan_obj = NULL;
10391 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
10392 GFP_KERNEL);
10393 if (!wlan_loader->attr_group) {
10394 pr_err("%s: malloc attr_group failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010395 goto error_return;
10396 }
10397
10398 wlan_loader->loaded_state = 0;
10399 wlan_loader->attr_group->attrs = attrs;
10400
10401 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
10402 kernel_kobj);
10403 if (!wlan_loader->boot_wlan_obj) {
10404 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010405 goto error_return;
10406 }
10407
10408 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
10409 wlan_loader->attr_group);
10410 if (ret) {
10411 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
10412 goto error_return;
10413 }
10414
10415 return 0;
10416
10417error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010418 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +053010419
10420 return ret;
10421}
10422
10423/**
10424 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
10425 *
10426 * Return: 0 on success or errno on failure
10427 */
10428static int wlan_deinit_sysfs(void)
10429{
Arun Khandavallifae92942016-08-01 13:31:08 +053010430 if (!wlan_loader) {
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010431 hdd_err("wlan loader context is Null!");
Arun Khandavallifae92942016-08-01 13:31:08 +053010432 return -EINVAL;
10433 }
10434
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010435 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010436 return 0;
10437}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010438
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010439#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +053010440
10441#ifdef MODULE
10442/**
10443 * __hdd_module_init - Module init helper
10444 *
10445 * Module init helper function used by both module and static driver.
10446 *
10447 * Return: 0 for success, errno on failure
10448 */
10449static int hdd_module_init(void)
10450{
10451 int ret = 0;
10452
10453 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
10454 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
10455
10456 if (__hdd_module_init()) {
10457 pr_err("%s: Failed to register handler\n", __func__);
10458 ret = -EINVAL;
10459 }
10460
10461 return ret;
10462}
10463#else
10464static int __init hdd_module_init(void)
10465{
10466 int ret = -EINVAL;
10467
10468 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010469 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +053010470 pr_err("Failed to create sysfs entry for loading wlan");
10471
10472 return ret;
10473}
10474#endif
10475
10476
10477#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010478/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010479 * hdd_module_exit() - Exit function
10480 *
10481 * This is the driver exit point (invoked when module is unloaded using rmmod)
10482 *
10483 * Return: None
10484 */
10485static void __exit hdd_module_exit(void)
10486{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010487 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010488}
Arun Khandavallifae92942016-08-01 13:31:08 +053010489#else
10490static void __exit hdd_module_exit(void)
10491{
10492 __hdd_module_exit();
10493 wlan_deinit_sysfs();
10494}
10495#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010496
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010497static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
10498{
10499 return param_set_copystring(kmessage, kp);
10500}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010501
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010502/**
10503 * is_con_mode_valid() check con mode is valid or not
10504 * @mode: global con mode
10505 *
10506 * Return: TRUE on success FALSE on failure
10507 */
10508static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
10509{
10510 switch (mode) {
10511 case QDF_GLOBAL_MONITOR_MODE:
10512 case QDF_GLOBAL_FTM_MODE:
10513 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010514 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010515 return true;
10516 default:
10517 return false;
10518 }
10519}
10520
10521/**
10522 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
10523 * @mode: global con mode
10524 *
10525 * Return: adapter mode
10526 */
10527static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
10528 enum tQDF_GLOBAL_CON_MODE mode)
10529{
10530
10531 switch (mode) {
10532 case QDF_GLOBAL_MISSION_MODE:
10533 return QDF_STA_MODE;
10534 case QDF_GLOBAL_MONITOR_MODE:
10535 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010536 case QDF_GLOBAL_EPPING_MODE:
10537 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010538 case QDF_GLOBAL_FTM_MODE:
10539 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010540 case QDF_GLOBAL_QVIT_MODE:
10541 return QDF_QVIT_MODE;
10542 default:
10543 return QDF_MAX_NO_OF_MODE;
10544 }
10545}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010546
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010547static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
10548 enum tQDF_GLOBAL_CON_MODE curr_mode)
10549{
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010550 int driver_status;
10551
10552 driver_status = hdd_ctx->driver_status;
10553
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010554 switch (curr_mode) {
10555 case QDF_GLOBAL_MISSION_MODE:
10556 case QDF_GLOBAL_MONITOR_MODE:
10557 case QDF_GLOBAL_FTM_MODE:
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010558 if (driver_status != DRIVER_MODULES_CLOSED) {
10559 hdd_abort_mac_scan_all_adapters(hdd_ctx);
10560 hdd_stop_all_adapters(hdd_ctx);
10561 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010562 hdd_deinit_all_adapters(hdd_ctx, false);
10563 hdd_close_all_adapters(hdd_ctx, false);
10564 break;
10565 case QDF_GLOBAL_EPPING_MODE:
10566 epping_disable();
10567 epping_close();
10568 break;
10569 default:
10570 return;
10571 }
10572}
10573
10574static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
10575 enum tQDF_GLOBAL_CON_MODE mode)
10576{
10577 hdd_adapter_t *adapter;
10578 int ret = 0;
10579 bool rtnl_held;
10580 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
10581 QDF_STATUS status;
10582
10583 if (!qdf_dev) {
10584 hdd_err("qdf device context is Null return!");
10585 return -EINVAL;
10586 }
10587
10588 rtnl_held = hdd_hold_rtnl_lock();
10589 switch (mode) {
10590 case QDF_GLOBAL_MISSION_MODE:
Jeff Johnson957bc272017-02-02 08:54:48 -080010591 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
10592 if (ret)
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010593 hdd_err("Failed to open interfaces: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010594 break;
10595 case QDF_GLOBAL_FTM_MODE:
10596 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
10597 wlan_hdd_get_intf_addr(hdd_ctx),
10598 NET_NAME_UNKNOWN, rtnl_held);
10599 if (adapter == NULL)
10600 ret = -EINVAL;
10601 break;
10602 case QDF_GLOBAL_MONITOR_MODE:
10603 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
10604 wlan_hdd_get_intf_addr(hdd_ctx),
10605 NET_NAME_UNKNOWN, rtnl_held);
10606 if (adapter == NULL)
10607 ret = -EINVAL;
10608 break;
10609 case QDF_GLOBAL_EPPING_MODE:
10610 status = epping_open();
10611 if (status != QDF_STATUS_SUCCESS) {
10612 hdd_err("Failed to open in eeping mode: %d", status);
10613 ret = -EINVAL;
10614 break;
10615 }
10616 ret = epping_enable(qdf_dev->dev);
10617 if (ret) {
10618 hdd_err("Failed to enable in epping mode : %d", ret);
10619 epping_close();
10620 }
10621 break;
10622 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010623 hdd_err("Mode not supported");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010624 ret = -ENOTSUPP;
10625 break;
10626 }
10627 hdd_release_rtnl_lock();
10628 rtnl_held = false;
10629 return ret;
10630}
10631
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010632/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010633 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010634 * @kmessage: con mode name on which driver to be bring up
10635 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010636 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010637 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010638 * This function is invoked when user updates con mode using sys entry,
10639 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010640 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010641 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010642 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010643static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
10644 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010645{
10646 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +053010647 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010648 enum tQDF_GLOBAL_CON_MODE curr_mode;
10649 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010650
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010651 ret = wlan_hdd_validate_context(hdd_ctx);
10652 if (ret)
10653 return ret;
10654
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010655 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010656
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080010657 hdd_debug("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010658 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +053010659
Arun Khandavallifae92942016-08-01 13:31:08 +053010660
Arun Khandavallia172c3e2016-08-26 17:33:13 +053010661
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010662 if (!(is_con_mode_valid(con_mode))) {
10663 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010664 ret = -EINVAL;
10665 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010666 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010667
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010668 curr_mode = hdd_get_conparam();
10669 if (curr_mode == con_mode) {
10670 hdd_err("curr mode: %d is same as user triggered mode %d",
10671 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010672 ret = 0;
10673 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010674 }
10675
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010676 /* Cleanup present mode before switching to new mode */
10677 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +053010678
Rajeev Kumar3fef4e82017-03-31 20:25:23 -070010679 ret = hdd_wlan_stop_modules(hdd_ctx, true);
Arun Khandavallifae92942016-08-01 13:31:08 +053010680 if (ret) {
10681 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010682 goto reset_flags;
10683 }
10684
10685 hdd_set_conparam(con_mode);
10686
10687 /* Register for new con_mode & then kick_start modules again */
10688 ret = hdd_register_req_mode(hdd_ctx, con_mode);
10689 if (ret) {
10690 hdd_err("Failed to register for new mode");
10691 goto reset_flags;
10692 }
10693
10694 adapter_mode = hdd_get_adpter_mode(con_mode);
10695 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
10696 hdd_err("invalid adapter");
10697 ret = -EINVAL;
10698 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010699 }
10700
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010701 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +053010702 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010703 hdd_err("Failed to get adapter:%d", adapter_mode);
10704 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010705 }
10706
10707 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
10708 if (ret) {
10709 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010710 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010711 }
10712
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010713 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
10714 con_mode == QDF_GLOBAL_FTM_MODE) {
10715 if (hdd_start_adapter(adapter)) {
10716 hdd_err("Failed to start %s adapter", kmessage);
10717 ret = -EINVAL;
10718 goto reset_flags;
10719 }
Arun Khandavallifae92942016-08-01 13:31:08 +053010720 }
10721
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010722 hdd_info("Mode successfully changed to %s", kmessage);
10723 ret = 0;
10724
10725reset_flags:
10726 cds_set_load_in_progress(false);
10727 return ret;
10728}
10729
10730
10731static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
10732{
10733 int ret;
10734 hdd_context_t *hdd_ctx;
10735
10736 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10737 ret = wlan_hdd_validate_context(hdd_ctx);
10738 if (ret)
10739 return ret;
10740
10741 cds_ssr_protect(__func__);
10742 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
10743 cds_ssr_unprotect(__func__);
10744
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010745 return ret;
10746}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010747
10748/**
10749 * hdd_get_conparam() - driver exit point
10750 *
10751 * This is the driver exit point (invoked when module is unloaded using rmmod)
10752 *
Anurag Chouhan6d760662016-02-20 16:05:43 +053010753 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010754 */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010755enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010756{
Anurag Chouhan6d760662016-02-20 16:05:43 +053010757 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010758}
10759
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010760void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010761{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010762 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010763}
10764
Komal Seelamc11bb222016-01-27 18:57:10 +053010765/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010766 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
10767 * @hdd_ctx: HDD context
10768 *
10769 * Cleans up the pre cac interface, if it exists
10770 *
10771 * Return: None
10772 */
10773void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
10774{
10775 uint8_t session_id;
10776 QDF_STATUS status;
10777 struct hdd_adapter_s *precac_adapter;
10778
10779 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
10780 if (QDF_IS_STATUS_ERROR(status)) {
10781 hdd_err("failed to get pre cac vdev id");
10782 return;
10783 }
10784
10785 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
10786 if (!precac_adapter) {
10787 hdd_err("invalid pre cac adapater");
10788 return;
10789 }
10790
10791 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
10792 wlan_hdd_sap_pre_cac_failure,
10793 (void *)precac_adapter);
10794 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
10795
10796}
10797
10798/**
Komal Seelamec702b02016-02-24 18:42:16 +053010799 * hdd_update_ol_config - API to update ol configuration parameters
10800 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +053010801 *
Komal Seelamc11bb222016-01-27 18:57:10 +053010802 * Return: void
10803 */
Komal Seelamec702b02016-02-24 18:42:16 +053010804static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +053010805{
Komal Seelamec702b02016-02-24 18:42:16 +053010806 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010807 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +053010808
Komal Seelamec702b02016-02-24 18:42:16 +053010809 if (!ol_ctx)
10810 return;
10811
10812 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
10813 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
10814 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
10815 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -070010816 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +053010817
10818 ol_init_ini_config(ol_ctx, &cfg);
10819}
10820
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010821#ifdef FEATURE_RUNTIME_PM
10822/**
10823 * hdd_populate_runtime_cfg() - populate runtime configuration
10824 * @hdd_ctx: hdd context
10825 * @cfg: pointer to the configuration memory being populated
10826 *
10827 * Return: void
10828 */
10829static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10830 struct hif_config_info *cfg)
10831{
10832 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
10833 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
10834}
10835#else
10836static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10837 struct hif_config_info *cfg)
10838{
10839}
10840#endif
10841
Komal Seelamec702b02016-02-24 18:42:16 +053010842/**
10843 * hdd_update_hif_config - API to update HIF configuration parameters
10844 * @hdd_ctx: HDD Context
10845 *
10846 * Return: void
10847 */
10848static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
10849{
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010850 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +053010851 struct hif_config_info cfg;
10852
10853 if (!scn)
10854 return;
10855
10856 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010857 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053010858 hif_init_ini_config(scn, &cfg);
10859}
10860
10861/**
10862 * hdd_update_config() - Initialize driver per module ini parameters
10863 * @hdd_ctx: HDD Context
10864 *
10865 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010866 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053010867 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010868int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053010869{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010870 int ret;
10871
Komal Seelamec702b02016-02-24 18:42:16 +053010872 hdd_update_ol_config(hdd_ctx);
10873 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010874 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
10875 ret = hdd_update_cds_config_ftm(hdd_ctx);
10876 else
10877 ret = hdd_update_cds_config(hdd_ctx);
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -080010878 ret = hdd_update_user_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010879
10880 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053010881}
10882
Mukul Sharma9d797a02017-01-05 20:26:03 +053010883#ifdef FEATURE_WLAN_RA_FILTERING
10884/**
10885 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
10886 * @psoc_cfg: pmo psoc Configuration
10887 * @hdd_ctx: Pointer to hdd context
10888 *
10889 * Return: none
10890 */
10891static inline void hdd_ra_populate_pmo_config(
10892 struct pmo_psoc_cfg *psoc_cfg,
10893 hdd_context_t *hdd_ctx)
10894{
10895 psoc_cfg->ra_ratelimit_interval =
10896 hdd_ctx->config->RArateLimitInterval;
10897 psoc_cfg->ra_ratelimit_enable =
10898 hdd_ctx->config->IsRArateLimitEnabled;
10899}
10900#else
10901static inline void hdd_ra_populate_pmo_config(
10902 struct cds_config_info *cds_cfg,
10903 hdd_context_t *hdd_ctx)
10904{
10905}
10906#endif
10907/**
10908 * hdd_update_pmo_config - API to update pmo configuration parameters
10909 * @hdd_ctx: HDD context
10910 *
10911 * Return: void
10912 */
10913static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
10914{
10915 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10916 struct pmo_psoc_cfg psoc_cfg;
10917 QDF_STATUS status;
10918
10919 /*
10920 * Value of hdd_ctx->wowEnable can be,
10921 * 0 - Disable both magic pattern match and pattern byte match.
10922 * 1 - Enable magic pattern match on all interfaces.
10923 * 2 - Enable pattern byte match on all interfaces.
10924 * 3 - Enable both magic patter and pattern byte match on
10925 * all interfaces.
10926 */
10927 psoc_cfg.magic_ptrn_enable =
10928 (hdd_ctx->config->wowEnable & 0x01) ? true : false;
10929 psoc_cfg.ptrn_match_enable_all_vdev =
10930 (hdd_ctx->config->wowEnable & 0x02) ? true : false;
10931 psoc_cfg.bpf_enable =
10932 hdd_ctx->config->bpf_packet_filter_enable;
10933 psoc_cfg.arp_offload_enable = hdd_ctx->config->fhostArpOffload;
10934 psoc_cfg.ns_offload_enable_static = hdd_ctx->config->fhostNSOffload;
10935 if (hdd_ctx->config->fhostNSOffload)
10936 psoc_cfg.ns_offload_enable_dynamic = true;
10937 psoc_cfg.ssdp = hdd_ctx->config->ssdp;
10938 psoc_cfg.enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
10939 psoc_cfg.active_mode_offload =
10940 hdd_ctx->config->active_mode_offload;
10941 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
10942 psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters;
Mukul Sharma9223f232017-03-08 18:42:27 +053010943 psoc_cfg.sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
10944 psoc_cfg.sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
10945 psoc_cfg.sta_max_li_mod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
10946 psoc_cfg.power_save_mode =
10947 hdd_ctx->config->enablePowersaveOffload;
Mukul Sharma9d797a02017-01-05 20:26:03 +053010948
10949 hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9223f232017-03-08 18:42:27 +053010950 hdd_nan_populate_pmo_config(&psoc_cfg, hdd_ctx);
10951 hdd_lpass_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053010952 status = pmo_ucfg_update_psoc_config(psoc, &psoc_cfg);
10953 if (status != QDF_STATUS_SUCCESS) {
10954 hdd_err("failed pmo psoc configuration");
10955 return -EINVAL;
10956 }
10957
10958 return 0;
10959}
10960
Abhishek Singh257a9482017-03-06 16:52:39 +053010961#ifdef NAPIER_SCAN
Abhishek Singhb20db962017-03-03 21:28:46 +053010962
10963#ifdef FEATURE_WLAN_SCAN_PNO
10964static inline void hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
10965 struct hdd_config *cfg)
10966{
10967 pno_cfg->channel_prediction = cfg->pno_channel_prediction;
10968 pno_cfg->top_k_num_of_channels = cfg->top_k_num_of_channels;
10969 pno_cfg->stationary_thresh = cfg->stationary_thresh;
10970 pno_cfg->adaptive_dwell_mode = cfg->adaptive_dwell_mode_enabled;
10971 pno_cfg->channel_prediction_full_scan =
10972 cfg->channel_prediction_full_scan;
10973}
10974#else
10975static inline void
10976hdd_update_pno_config(struct pno_user_cfg *pno_cfg,
10977 struct hdd_config *cfg)
10978{
10979 return;
10980}
10981#endif
10982
Abhishek Singh257a9482017-03-06 16:52:39 +053010983/**
10984 * hdd_update_scan_config - API to update scan configuration parameters
10985 * @hdd_ctx: HDD context
10986 *
10987 * Return: 0 if success else err
10988 */
10989static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
10990{
10991 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10992 struct scan_user_cfg scan_cfg;
10993 struct hdd_config *cfg = hdd_ctx->config;
10994 QDF_STATUS status;
10995
10996 scan_cfg.active_dwell = cfg->nActiveMaxChnTime;
10997 scan_cfg.passive_dwell = cfg->nPassiveMaxChnTime;
10998 scan_cfg.conc_active_dwell = cfg->nActiveMaxChnTimeConc;
10999 scan_cfg.conc_passive_dwell = cfg->nPassiveMaxChnTimeConc;
11000 scan_cfg.conc_max_rest_time = cfg->nRestTimeConc;
11001 scan_cfg.conc_min_rest_time = cfg->min_rest_time_conc;
11002 scan_cfg.conc_idle_time = cfg->idle_time_conc;
11003 scan_cfg.scan_cache_aging_time = cfg->scanAgingTimeout;
11004 scan_cfg.scan_dwell_time_mode = cfg->scan_adaptive_dwell_mode;
Kapil Guptafa9a8c62017-04-10 15:25:40 +053011005 scan_cfg.is_snr_monitoring_enabled = cfg->fEnableSNRMonitoring;
Abhishek Singh257a9482017-03-06 16:52:39 +053011006
Abhishek Singhb20db962017-03-03 21:28:46 +053011007 hdd_update_pno_config(&scan_cfg.pno_cfg, cfg);
11008
Abhishek Singh257a9482017-03-06 16:52:39 +053011009 status = ucfg_scan_update_user_config(psoc, &scan_cfg);
11010 if (status != QDF_STATUS_SUCCESS) {
11011 hdd_err("failed pmo psoc configuration");
11012 return -EINVAL;
11013 }
11014
11015 return 0;
11016}
11017#else
11018static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
11019{
11020 return 0;
11021}
11022#endif
11023
Mukul Sharma9d797a02017-01-05 20:26:03 +053011024int hdd_update_components_config(hdd_context_t *hdd_ctx)
11025{
11026 int ret;
11027
11028 ret = hdd_update_pmo_config(hdd_ctx);
Abhishek Singh257a9482017-03-06 16:52:39 +053011029 if (ret)
11030 return ret;
11031 ret = hdd_update_scan_config(hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053011032
11033 return ret;
11034}
11035
Agrawal Ashish65634612016-08-18 13:24:32 +053011036/**
11037 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
11038 * @mode : cfg80211 DFS mode
11039 *
11040 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
11041 */
11042enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
11043{
11044 switch (mode) {
11045 case DFS_MODE_ENABLE:
11046 return ACS_DFS_MODE_ENABLE;
11047 break;
11048 case DFS_MODE_DISABLE:
11049 return ACS_DFS_MODE_DISABLE;
11050 break;
11051 case DFS_MODE_DEPRIORITIZE:
11052 return ACS_DFS_MODE_DEPRIORITIZE;
11053 break;
11054 default:
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011055 hdd_debug("ACS dfs mode is NONE");
11056 return ACS_DFS_MODE_NONE;
Agrawal Ashish65634612016-08-18 13:24:32 +053011057 }
11058}
11059
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053011060/**
11061 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
11062 * @hddctx: pointer to hdd context
11063 * @set_value: enable/disable
11064 *
11065 * When Host sends vendor command enable, FW will send *ONE* CA ind to
11066 * Host(even though it is duplicate). When Host send vendor command
11067 * disable,FW doesn't perform any action. Whenever any change in
11068 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
11069 *
11070 * return - 0 on success, appropriate error values on failure.
11071 */
11072int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
11073{
11074 QDF_STATUS status;
11075
11076 if (0 != wlan_hdd_validate_context(hddctx)) {
11077 return -EAGAIN;
11078 }
11079
11080 if (!hddctx->config->goptimize_chan_avoid_event) {
11081 hdd_warn("goptimize_chan_avoid_event ini param disabled");
11082 return -EINVAL;
11083 }
11084
11085 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
11086 if (!QDF_IS_STATUS_SUCCESS(status)) {
11087 hdd_err("Failed to send chan avoid command to SME");
11088 return -EINVAL;
11089 }
11090 return 0;
11091}
Agrawal Ashish65634612016-08-18 13:24:32 +053011092
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011093/**
11094 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
11095 * @value: value to set
11096 *
11097 * This function will set the passed value to roaming in progress flag.
11098 *
11099 * Return: None
11100 */
11101void hdd_set_roaming_in_progress(bool value)
11102{
11103 hdd_context_t *hdd_ctx;
11104
11105 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11106 if (!hdd_ctx) {
11107 hdd_err("HDD context is NULL");
11108 return;
11109 }
11110
11111 hdd_ctx->roaming_in_progress = value;
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011112 hdd_debug("Roaming in Progress set to %d", value);
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011113}
11114
11115/**
11116 * hdd_is_roaming_in_progress() - check if roaming is in progress
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011117 * @adapter - HDD adapter
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011118 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011119 * Return: true if roaming is in progress for STA type, else false
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011120 */
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011121bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter)
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011122{
11123 hdd_context_t *hdd_ctx;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011124 bool ret_status = false;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011125
11126 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11127 if (!hdd_ctx) {
11128 hdd_err("HDD context is NULL");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011129 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011130 }
Srinivas Girigowda3d5250d2017-03-06 17:32:16 -080011131 hdd_debug("dev mode = %d, roaming_in_progress = %d",
11132 adapter->device_mode, hdd_ctx->roaming_in_progress);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011133 ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
11134 hdd_ctx->roaming_in_progress);
11135
11136 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011137}
11138
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011139/**
11140 * hdd_is_connection_in_progress() - check if connection is in
11141 * progress
11142 * @session_id: session id
11143 * @reason: scan reject reason
11144 *
11145 * Go through each adapter and check if Connection is in progress
11146 *
11147 * Return: true if connection is in progress else false
11148 */
11149bool hdd_is_connection_in_progress(uint8_t *session_id,
11150 enum scan_reject_states *reason)
11151{
11152 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
11153 hdd_station_ctx_t *hdd_sta_ctx = NULL;
11154 hdd_adapter_t *adapter = NULL;
11155 QDF_STATUS status = 0;
11156 uint8_t sta_id = 0;
11157 uint8_t *sta_mac = NULL;
11158 hdd_context_t *hdd_ctx;
11159
11160 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11161 if (!hdd_ctx) {
11162 hdd_err("HDD context is NULL");
11163 return false;
11164 }
11165
11166 if (true == hdd_ctx->btCoexModeSet) {
11167 hdd_info("BTCoex Mode operation in progress");
11168 return true;
11169 }
11170 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
11171 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
11172 adapter = adapter_node->pAdapter;
11173 if (!adapter)
11174 goto end;
11175
11176 hdd_info("Adapter with device mode %s(%d) exists",
11177 hdd_device_mode_to_string(adapter->device_mode),
11178 adapter->device_mode);
11179 if (((QDF_STA_MODE == adapter->device_mode)
11180 || (QDF_P2P_CLIENT_MODE == adapter->device_mode)
11181 || (QDF_P2P_DEVICE_MODE == adapter->device_mode))
11182 && (eConnectionState_Connecting ==
11183 (WLAN_HDD_GET_STATION_CTX_PTR(adapter))->
11184 conn_info.connState)) {
11185 hdd_err("%p(%d) Connection is in progress",
11186 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11187 adapter->sessionId);
11188 if (session_id && reason) {
11189 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011190 *reason = CONNECTION_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011191 }
11192 return true;
11193 }
Archana Ramachandran62886ce2017-03-24 14:46:32 -070011194 /*
11195 * sme_neighbor_middle_of_roaming is for LFR2
11196 * hdd_is_roaming_in_progress is for LFR3
11197 */
11198 if (((QDF_STA_MODE == adapter->device_mode) &&
11199 sme_neighbor_middle_of_roaming(
11200 WLAN_HDD_GET_HAL_CTX(adapter),
11201 adapter->sessionId)) ||
11202 hdd_is_roaming_in_progress(adapter)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011203 hdd_err("%p(%d) Reassociation in progress",
11204 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11205 adapter->sessionId);
11206 if (session_id && reason) {
11207 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011208 *reason = REASSOC_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011209 }
11210 return true;
11211 }
11212 if ((QDF_STA_MODE == adapter->device_mode) ||
11213 (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
11214 (QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
11215 hdd_sta_ctx =
11216 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
11217 if ((eConnectionState_Associated ==
11218 hdd_sta_ctx->conn_info.connState)
11219 && (false ==
11220 hdd_sta_ctx->conn_info.uIsAuthenticated)) {
11221 sta_mac = (uint8_t *)
11222 &(adapter->macAddressCurrent.bytes[0]);
11223 hdd_err("client " MAC_ADDRESS_STR
11224 " is in middle of WPS/EAPOL exchange.",
11225 MAC_ADDR_ARRAY(sta_mac));
11226 if (session_id && reason) {
11227 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011228 *reason = EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011229 }
11230 return true;
11231 }
11232 } else if ((QDF_SAP_MODE == adapter->device_mode) ||
11233 (QDF_P2P_GO_MODE == adapter->device_mode)) {
11234 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
11235 sta_id++) {
11236 if (!((adapter->aStaInfo[sta_id].isUsed)
11237 && (OL_TXRX_PEER_STATE_CONN ==
11238 adapter->aStaInfo[sta_id].tlSTAState)))
11239 continue;
11240
11241 sta_mac = (uint8_t *)
11242 &(adapter->aStaInfo[sta_id].
11243 macAddrSTA.bytes[0]);
11244 hdd_err("client " MAC_ADDRESS_STR
11245 " of SAP/GO is in middle of WPS/EAPOL exchange",
11246 MAC_ADDR_ARRAY(sta_mac));
11247 if (session_id && reason) {
11248 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011249 *reason = SAP_EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011250 }
11251 return true;
11252 }
11253 if (hdd_ctx->connection_in_progress) {
11254 hdd_err("AP/GO: connection is in progress");
11255 return true;
11256 }
11257 }
11258end:
11259 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
11260 adapter_node = next;
11261 }
11262 return false;
11263}
11264
11265/**
11266 * hdd_restart_sap() - to restart SAP in driver internally
11267 * @ap_adapter: Pointer to SAP hdd_adapter_t structure
11268 *
11269 * Return: None
11270 */
11271void hdd_restart_sap(hdd_adapter_t *ap_adapter)
11272{
11273 hdd_ap_ctx_t *hdd_ap_ctx;
11274 hdd_hostapd_state_t *hostapd_state;
11275 QDF_STATUS qdf_status;
11276 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
11277 tsap_Config_t *sap_config;
11278 void *sap_ctx;
11279
11280 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11281 sap_config = &hdd_ap_ctx->sapConfig;
11282 sap_ctx = hdd_ap_ctx->sapContext;
11283
11284 mutex_lock(&hdd_ctx->sap_lock);
11285 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
11286 wlan_hdd_del_station(ap_adapter);
11287 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
11288 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11289 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
11290 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {
11291 qdf_status =
11292 qdf_wait_single_event(&hostapd_state->
11293 qdf_stop_bss_event,
11294 SME_CMD_TIMEOUT_VALUE);
11295
11296 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11297 cds_err("SAP Stop Failed");
11298 goto end;
11299 }
11300 }
11301 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011302 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011303 ap_adapter->device_mode, ap_adapter->sessionId);
11304 cds_err("SAP Stop Success");
11305
11306 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
11307 cds_err("SAP Not able to set AP IEs");
11308 wlansap_reset_sap_config_add_ie(sap_config,
11309 eUPDATE_IE_ALL);
11310 goto end;
11311 }
11312
11313 qdf_event_reset(&hostapd_state->qdf_event);
11314 if (wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb,
11315 sap_config,
11316 ap_adapter->dev) != QDF_STATUS_SUCCESS) {
11317 cds_err("SAP Start Bss fail");
11318 wlansap_reset_sap_config_add_ie(sap_config,
11319 eUPDATE_IE_ALL);
11320 goto end;
11321 }
11322
11323 cds_info("Waiting for SAP to start");
11324 qdf_status =
11325 qdf_wait_single_event(&hostapd_state->qdf_event,
11326 SME_CMD_TIMEOUT_VALUE);
11327 wlansap_reset_sap_config_add_ie(sap_config,
11328 eUPDATE_IE_ALL);
11329 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11330 cds_err("SAP Start failed");
11331 goto end;
11332 }
11333 cds_err("SAP Start Success");
11334 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
11335 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011336 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
11337 ap_adapter->device_mode,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011338 ap_adapter->sessionId);
11339 hostapd_state->bCommit = true;
11340 }
11341end:
11342 mutex_unlock(&hdd_ctx->sap_lock);
11343 return;
11344}
11345
11346/**
11347 * hdd_check_and_restart_sap_with_non_dfs_acs() - Restart SAP
11348 * with non dfs acs
11349 *
11350 * Restarts SAP in non-DFS ACS mode when STA-AP mode DFS is not supported
11351 *
11352 * Return: None
11353 */
11354void hdd_check_and_restart_sap_with_non_dfs_acs(void)
11355{
11356 hdd_adapter_t *ap_adapter;
11357 hdd_context_t *hdd_ctx;
11358 cds_context_type *cds_ctx;
11359
11360 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11361 if (!hdd_ctx) {
11362 cds_err("HDD context is NULL");
11363 return;
11364 }
11365
11366 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
11367 if (!cds_ctx) {
11368 cds_err("Invalid CDS Context");
11369 return;
11370 }
11371
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011372 if (policy_mgr_get_concurrency_mode(hdd_ctx->hdd_psoc)
11373 != (QDF_STA_MASK | QDF_SAP_MASK)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011374 cds_info("Concurrency mode is not SAP");
11375 return;
11376 }
11377
11378 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11379 if (ap_adapter != NULL &&
11380 test_bit(SOFTAP_BSS_STARTED,
11381 &ap_adapter->event_flags)
11382 && CDS_IS_DFS_CH(ap_adapter->sessionCtx.ap.
11383 operatingChannel)) {
11384
11385 cds_warn("STA-AP Mode DFS not supported. Restart SAP with Non DFS ACS");
11386 ap_adapter->sessionCtx.ap.sapConfig.channel =
11387 AUTO_CHANNEL_SELECT;
11388 ap_adapter->sessionCtx.ap.sapConfig.
11389 acs_cfg.acs_mode = true;
11390
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011391 hdd_restart_sap(ap_adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011392 }
11393}
11394
11395/**
11396 * hdd_set_connection_in_progress() - to set the connection in
11397 * progress flag
11398 * @value: value to set
11399 *
11400 * This function will set the passed value to connection in progress flag.
11401 * If value is previously being set to true then no need to set it again.
11402 *
11403 * Return: true if value is being set correctly and false otherwise.
11404 */
11405bool hdd_set_connection_in_progress(bool value)
11406{
11407 bool status = true;
11408 hdd_context_t *hdd_ctx;
11409
11410 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11411 if (!hdd_ctx) {
11412 cds_err("HDD context is NULL");
11413 return false;
11414 }
11415
11416 qdf_spin_lock(&hdd_ctx->connection_status_lock);
11417 /*
11418 * if the value is set to true previously and if someone is
11419 * trying to make it true again then it could be some race
11420 * condition being triggered. Avoid this situation by returning
11421 * false
11422 */
11423 if (hdd_ctx->connection_in_progress && value)
11424 status = false;
11425 else
11426 hdd_ctx->connection_in_progress = value;
11427 qdf_spin_unlock(&hdd_ctx->connection_status_lock);
11428 return status;
11429}
11430
Archana Ramachandranb8c04f92017-03-17 20:05:47 -070011431int wlan_hdd_send_p2p_quota(hdd_adapter_t *adapter, int set_value)
11432{
11433 if (!adapter) {
11434 hdd_err("Invalid adapter");
11435 return -EINVAL;
11436 }
11437 hdd_info("Send MCC P2P QUOTA to WMA: %d", set_value);
11438 wma_cli_set_command(adapter->sessionId,
11439 WMA_VDEV_MCC_SET_TIME_QUOTA,
11440 set_value, VDEV_CMD);
11441 return 0;
11442
11443}
11444
11445int wlan_hdd_send_mcc_latency(hdd_adapter_t *adapter, int set_value)
11446{
11447 if (!adapter) {
11448 hdd_err("Invalid adapter");
11449 return -EINVAL;
11450 }
11451
11452 hdd_info("Send MCC latency WMA: %d", set_value);
11453 wma_cli_set_command(adapter->sessionId,
11454 WMA_VDEV_MCC_SET_TIME_LATENCY,
11455 set_value, VDEV_CMD);
11456 return 0;
11457}
11458
Archana Ramachandranea34c4f2017-03-19 18:56:18 -070011459hdd_adapter_t *wlan_hdd_get_adapter_from_vdev(struct wlan_objmgr_psoc
11460 *psoc, uint8_t vdev_id)
11461{
11462 hdd_adapter_t *adapter = NULL;
11463 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11464
11465 /*
11466 * Currently PSOC is not being used. But this logic will
11467 * change once we have the converged implementation of
11468 * HDD context per PSOC in place. This would break if
11469 * multiple vdev objects reuse the vdev id.
11470 */
11471 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
11472 if (!adapter)
11473 hdd_err("Get adapter by vdev id failed");
11474
11475 return adapter;
11476}
11477
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011478/* Register the module init/exit functions */
11479module_init(hdd_module_init);
11480module_exit(hdd_module_exit);
11481
11482MODULE_LICENSE("Dual BSD/GPL");
11483MODULE_AUTHOR("Qualcomm Atheros, Inc.");
11484MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
11485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011486module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
11487 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011488
11489module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
11490 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
11491
11492module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
11493
11494module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
11495
11496module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);