blob: b5a3d98efc60992c25d163e2a0de800baf8d4d13 [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"
Anurag Chouhan6d760662016-02-20 16:05:43 +053057#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053058#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070059#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080060
61#include <net/addrconf.h>
62#include <linux/wireless.h>
63#include <net/cfg80211.h>
64#include <linux/inetdevice.h>
65#include <net/addrconf.h>
66#include "wlan_hdd_cfg80211.h"
67#include "wlan_hdd_ext_scan.h"
68#include "wlan_hdd_p2p.h"
69#include <linux/rtnetlink.h>
70#include "sap_api.h"
71#include <linux/semaphore.h>
72#include <linux/ctype.h>
73#include <linux/compat.h>
74#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075#include <soc/qcom/subsystem_restart.h>
76#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include <wlan_hdd_hostapd.h>
78#include <wlan_hdd_softap_tx_rx.h>
79#include "cfg_api.h"
80#include "qwlan_version.h"
81#include "wma_types.h"
82#include "wlan_hdd_tdls.h"
83#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053084#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080085#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080086#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070087#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080088#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089#include "wlan_hdd_nan.h"
90#include "wlan_hdd_debugfs.h"
91#include "wlan_hdd_driver_ops.h"
92#include "epping_main.h"
93#include "wlan_hdd_memdump.h"
94
95#include <wlan_hdd_ipa.h>
96#include "hif.h"
97#include "wma.h"
98#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -070099#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530101#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700102#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530103#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700104#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530105#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700106#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530107#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800108#include <dispatcher_init_deinit.h>
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +0530109#include <wlan_objmgr_cmn.h>
110#include <wlan_objmgr_global_obj.h>
111#include <wlan_objmgr_psoc_obj.h>
112#include <wlan_objmgr_pdev_obj.h>
113#include <wlan_objmgr_vdev_obj.h>
114#include <wlan_objmgr_peer_obj.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115
116#ifdef MODULE
117#define WLAN_MODULE_NAME module_name(THIS_MODULE)
118#else
119#define WLAN_MODULE_NAME "wlan"
120#endif
121
122#ifdef TIMER_MANAGER
123#define TIMER_MANAGER_STR " +TIMER_MANAGER"
124#else
125#define TIMER_MANAGER_STR ""
126#endif
127
128#ifdef MEMORY_DEBUG
129#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
130#else
131#define MEMORY_DEBUG_STR ""
132#endif
133
Arun Khandavallifae92942016-08-01 13:31:08 +0530134#ifndef MODULE
135static struct gwlan_loader *wlan_loader;
136static ssize_t wlan_boot_cb(struct kobject *kobj,
137 struct kobj_attribute *attr,
138 const char *buf, size_t count);
139struct gwlan_loader {
140 bool loaded_state;
141 struct kobject *boot_wlan_obj;
142 struct attribute_group *attr_group;
143};
144
145static struct kobj_attribute wlan_boot_attribute =
146 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
147
148static struct attribute *attrs[] = {
149 &wlan_boot_attribute.attr,
150 NULL,
151};
152
153#define MODULE_INITIALIZED 1
154#endif
155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156/* the Android framework expects this param even though we don't use it */
157#define BUF_LEN 20
158static char fwpath_buffer[BUF_LEN];
159static struct kparam_string fwpath = {
160 .string = fwpath_buffer,
161 .maxlen = BUF_LEN,
162};
163
164static char *country_code;
165static int enable_11d = -1;
166static int enable_dfs_chan_scan = -1;
167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168/*
169 * spinlock for synchronizing asynchronous request/response
170 * (full description of use in wlan_hdd_main.h)
171 */
172DEFINE_SPINLOCK(hdd_context_lock);
173
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800174#define WLAN_NLINK_CESIUM 30
175
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530176static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177
178#define WOW_MAX_FILTER_LISTS 1
179#define WOW_MAX_FILTERS_PER_LIST 4
180#define WOW_MIN_PATTERN_SIZE 6
181#define WOW_MAX_PATTERN_SIZE 64
182
183#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
184static const struct wiphy_wowlan_support wowlan_support_reg_init = {
185 .flags = WIPHY_WOWLAN_ANY |
186 WIPHY_WOWLAN_MAGIC_PKT |
187 WIPHY_WOWLAN_DISCONNECT |
188 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
189 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
190 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
191 WIPHY_WOWLAN_4WAY_HANDSHAKE |
192 WIPHY_WOWLAN_RFKILL_RELEASE,
193 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
194 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
195 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
196};
197#endif
198
199/* internal function declaration */
200
201struct sock *cesium_nl_srv_sock;
202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
204void wlan_hdd_auto_shutdown_cb(void);
205#endif
206
207/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530208 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
209 * @hdd_ctx: pointer to hdd_context_t
210 *
211 * Return: none
212 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700213static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530214{
215 hdd_adapter_t *adapter;
216 hdd_adapter_list_node_t *adapter_node, *next;
217 QDF_STATUS status = QDF_STATUS_SUCCESS;
218
219 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
220 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
221 adapter = adapter_node->pAdapter;
222 if (NULL != adapter)
223 hdd_send_rps_ind(adapter);
224 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
225 adapter_node = next;
226 }
227}
228
229/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
231 * @vdev_id: vdev_id
232 * @action: action type
233 * @reason: reason type
234 *
235 * Return: none
236 */
237void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
238 enum netif_action_type action, enum netif_reason_type reason)
239{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530240 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800241 hdd_adapter_t *adapter;
242
243 if (!hdd_ctx) {
244 hdd_err("hdd ctx is NULL");
245 return;
246 }
247 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
248
249 wlan_hdd_netif_queue_control(adapter, action, reason);
250 return;
251}
252
253/*
254 * Store WLAN driver version info in a global variable such that crash debugger
255 * can extract it from driver debug symbol and crashdump for post processing
256 */
257uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
258
259/**
260 * hdd_device_mode_to_string() - return string conversion of device mode
261 * @device_mode: device mode
262 *
263 * This utility function helps log string conversion of device mode.
264 *
265 * Return: string conversion of device mode, if match found;
266 * "Unknown" otherwise.
267 */
268const char *hdd_device_mode_to_string(uint8_t device_mode)
269{
270 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800271 CASE_RETURN_STRING(QDF_STA_MODE);
272 CASE_RETURN_STRING(QDF_SAP_MODE);
273 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
274 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
275 CASE_RETURN_STRING(QDF_FTM_MODE);
276 CASE_RETURN_STRING(QDF_IBSS_MODE);
277 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
278 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700279 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800280 default:
281 return "Unknown";
282 }
283}
284
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530285/**
286 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
287 * @adapter: HDD adapter
288 * @chan_number: Channel number
289 * @chan_bw: Bandwidth
290 *
291 * Checks if the given bandwidth is valid for the given channel number.
292 *
293 * Return: 0 for success, non-zero for failure
294 */
295int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
296 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800297 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530298{
299 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
300 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
301 bool found = false;
302 tHalHandle hal;
303
304 hal = WLAN_HDD_GET_HAL_CTX(adapter);
305 if (!hal) {
306 hdd_err("Invalid HAL context");
307 return -EINVAL;
308 }
309
310 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
311 hdd_err("No valid channel list");
312 return -EOPNOTSUPP;
313 }
314
315 for (i = 0; i < len; i++) {
316 if (chan[i] == chan_number) {
317 found = true;
318 break;
319 }
320 }
321
322 if (found == false) {
323 hdd_err("Channel not in driver's valid channel list");
324 return -EOPNOTSUPP;
325 }
326
327 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
328 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
329 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
330 return -EINVAL;
331 }
332
333 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
334 if (chan_bw == CH_WIDTH_80MHZ) {
335 hdd_err("BW80 not possible in 2.4GHz band");
336 return -EINVAL;
337 }
338 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
339 (chan_bw != CH_WIDTH_MAX)) {
340 hdd_err("Only BW20 possible on channel 14");
341 return -EINVAL;
342 }
343 }
344
345 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
346 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
347 (chan_bw != CH_WIDTH_MAX)) {
348 hdd_err("Only BW20 possible on channel 165");
349 return -EINVAL;
350 }
351 }
352
353 return 0;
354}
355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800356static int __hdd_netdev_notifier_call(struct notifier_block *nb,
357 unsigned long state, void *data)
358{
359#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
360 struct netdev_notifier_info *dev_notif_info = data;
361 struct net_device *dev = dev_notif_info->dev;
362#else
363 struct net_device *dev = data;
364#endif
365 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
366 hdd_context_t *hdd_ctx;
367
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800368 ENTER_DEV(dev);
369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370 /* Make sure that this callback corresponds to our device. */
371 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
372 return NOTIFY_DONE;
373
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530374 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700376 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 return NOTIFY_DONE;
378 }
379
380 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700381 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800382 return NOTIFY_DONE;
383 }
384
385 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
386 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700387 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530388 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800389 return NOTIFY_DONE;
390 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800391 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800392 return NOTIFY_DONE;
393
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700394 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800395 dev->name, state);
396
397 switch (state) {
398 case NETDEV_REGISTER:
399 break;
400
401 case NETDEV_UNREGISTER:
402 break;
403
404 case NETDEV_UP:
405 sme_ch_avoid_update_req(hdd_ctx->hHal);
406 break;
407
408 case NETDEV_DOWN:
409 break;
410
411 case NETDEV_CHANGE:
412 if (true == adapter->isLinkUpSvcNeeded)
413 complete(&adapter->linkup_event_var);
414 break;
415
416 case NETDEV_GOING_DOWN:
417 if (adapter->scan_info.mScanPending != false) {
418 unsigned long rc;
419 INIT_COMPLETION(adapter->scan_info.
420 abortscan_event_var);
421 hdd_abort_mac_scan(adapter->pHddCtx,
422 adapter->sessionId,
423 eCSR_SCAN_ABORT_DEFAULT);
424 rc = wait_for_completion_timeout(
425 &adapter->scan_info.abortscan_event_var,
426 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
427 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700428 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429 }
430 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700431 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432 }
433 break;
434
435 default:
436 break;
437 }
438
439 return NOTIFY_DONE;
440}
441
442/**
443 * hdd_netdev_notifier_call() - netdev notifier callback function
444 * @nb: pointer to notifier block
445 * @state: state
446 * @ndev: ndev pointer
447 *
448 * Return: 0 on success, error number otherwise.
449 */
450static int hdd_netdev_notifier_call(struct notifier_block *nb,
451 unsigned long state,
452 void *ndev)
453{
454 int ret;
455
456 cds_ssr_protect(__func__);
457 ret = __hdd_netdev_notifier_call(nb, state, ndev);
458 cds_ssr_unprotect(__func__);
459
460 return ret;
461}
462
463struct notifier_block hdd_netdev_notifier = {
464 .notifier_call = hdd_netdev_notifier_call,
465};
466
467/* variable to hold the insmod parameters */
468static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800469
470/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530473/**
474 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
475 * @ch_width: NL channel width
476 *
477 * Converts the NL channel width to the driver's internal representation
478 *
479 * Return: Converted channel width. In case of non matching NL channel width,
480 * CH_WIDTH_MAX will be returned.
481 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800482enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530483{
484 switch (ch_width) {
485 case NL80211_CHAN_WIDTH_20_NOHT:
486 case NL80211_CHAN_WIDTH_20:
487 return CH_WIDTH_20MHZ;
488 case NL80211_CHAN_WIDTH_40:
489 return CH_WIDTH_40MHZ;
490 break;
491 case NL80211_CHAN_WIDTH_80:
492 return CH_WIDTH_80MHZ;
493 case NL80211_CHAN_WIDTH_80P80:
494 return CH_WIDTH_80P80MHZ;
495 case NL80211_CHAN_WIDTH_160:
496 return CH_WIDTH_160MHZ;
497 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800498 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530499 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800500 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530501 default:
502 hdd_err("Invalid channel width %d, setting to default",
503 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800504 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530505 }
506}
507
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530508/* wlan_hdd_find_opclass() - Find operating class for a channel
509 * @hal: handler to HAL
510 * @channel: channel id
511 * @bw_offset: bandwidth offset
512 *
513 * Function invokes sme api to find the operating class
514 *
515 * Return: operating class
516 */
517uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
518 uint8_t bw_offset)
519{
520 uint8_t opclass = 0;
521
522 sme_get_opclass(hal, channel, bw_offset, &opclass);
523 return opclass;
524}
525
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 * @moduleId: Module whose trace level is being configured
529 * @bitmask: Bitmask of log levels to be enabled
530 *
531 * Called immediately after the cfg.ini is read in order to configure
532 * the desired trace levels.
533 *
534 * Return: None
535 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530536static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530538 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539
540 /*
541 * if the bitmask is the default value, then a bitmask was not
542 * specified in cfg.ini, so leave the logging level alone (it
543 * will remain at the "compiled in" default value)
544 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530545 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546 return;
547 }
548
549 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530550 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551
552 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530553 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554 while (0 != bitmask) {
555 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530556 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557 }
558 level++;
559 bitmask >>= 1;
560 }
561}
562
563/**
564 * wlan_hdd_validate_context() - check the HDD context
565 * @hdd_ctx: HDD context pointer
566 *
567 * Return: 0 if the context is valid. Error code otherwise
568 */
569int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
570{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530572 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573 return -ENODEV;
574 }
575
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800576 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530577 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
578 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579 return -EAGAIN;
580 }
581
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800582 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530583 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
584 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585 return -EAGAIN;
586 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530587
588 if (hdd_ctx->start_modules_in_progress ||
589 hdd_ctx->stop_modules_in_progress) {
590 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
591 (void *)_RET_IP_);
592 return -EAGAIN;
593 }
594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 return 0;
596}
597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598/**
599 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
600 * @hdd_adapter_t Hdd adapter.
601 *
602 * This function sets the IBSS power save config parameters to WMA
603 * which will send it to firmware if FW supports IBSS power save
604 * before vdev start.
605 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530606 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607 * on failure.
608 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530609QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610{
611 int ret;
612 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
613
614 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700615 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530616 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 }
618
619 ret = wma_cli_set_command(adapter->sessionId,
620 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
621 hdd_ctx->config->ibssATIMWinSize,
622 VDEV_CMD);
623 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700624 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530625 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626 }
627
628 ret = wma_cli_set_command(adapter->sessionId,
629 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
630 hdd_ctx->config->isIbssPowerSaveAllowed,
631 VDEV_CMD);
632 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700633 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
634 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530635 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636 }
637
638 ret = wma_cli_set_command(adapter->sessionId,
639 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
640 hdd_ctx->config->
641 isIbssPowerCollapseAllowed, VDEV_CMD);
642 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700643 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
644 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530645 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646 }
647
648 ret = wma_cli_set_command(adapter->sessionId,
649 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
650 hdd_ctx->config->isIbssAwakeOnTxRx,
651 VDEV_CMD);
652 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700653 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530654 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655 }
656
657 ret = wma_cli_set_command(adapter->sessionId,
658 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
659 hdd_ctx->config->ibssInactivityCount,
660 VDEV_CMD);
661 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700662 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530663 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 }
665
666 ret = wma_cli_set_command(adapter->sessionId,
667 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
668 hdd_ctx->config->ibssTxSpEndInactivityTime,
669 VDEV_CMD);
670 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700671 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
672 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530673 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800674 }
675
676 ret = wma_cli_set_command(adapter->sessionId,
677 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
678 hdd_ctx->config->ibssPsWarmupTime,
679 VDEV_CMD);
680 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700681 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
682 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530683 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 }
685
686 ret = wma_cli_set_command(adapter->sessionId,
687 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
688 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
689 VDEV_CMD);
690 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700691 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
692 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530693 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 }
695
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530696 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697}
698
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699#define INTF_MACADDR_MASK 0x7
700
701/**
702 * hdd_update_macaddr() - update mac address
703 * @config: hdd configuration
704 * @hw_macaddr: mac address
705 *
706 * Mac address for multiple virtual interface is found as following
707 * i) The mac address of the first interface is just the actual hw mac address.
708 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
709 * define the mac address for the remaining interfaces and locally
710 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
711 * supported virtual interfaces, right now this is 0x07 (meaning 8
712 * interface).
713 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
714 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
715 *
716 * Return: None
717 */
718void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530719 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720{
721 int8_t i;
722 uint8_t macaddr_b3, tmp_br3;
723
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530724 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530725 QDF_MAC_ADDR_SIZE);
726 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530727 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530728 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729 macaddr_b3 = config->intfMacAddr[i].bytes[3];
730 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
731 INTF_MACADDR_MASK;
732 macaddr_b3 += tmp_br3;
733
734 /* XOR-ing bit-24 of the mac address. This will give enough
735 * mac address range before collision
736 */
737 macaddr_b3 ^= (1 << 7);
738
739 /* Set locally administered bit */
740 config->intfMacAddr[i].bytes[0] |= 0x02;
741 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700742 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743 MAC_ADDRESS_STR, i,
744 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
745 }
746}
747
748static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
749 struct wma_tgt_services *cfg)
750{
751 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800752
753 /* Set up UAPSD */
754 config->apUapsdEnabled &= cfg->uapsd;
755
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800756 /* 11AC mode support */
757 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
758 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
759 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760
761 /* ARP offload: override user setting if invalid */
762 config->fhostArpOffload &= cfg->arp_offload;
763
764#ifdef FEATURE_WLAN_SCAN_PNO
765 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700766 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 if (cfg->pno_offload)
768 config->PnoOffload = true;
769#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770#ifdef FEATURE_WLAN_TDLS
771 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530772 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
773 cfg->en_tdls_offchan;
774 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
775 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
777 config->fEnableTDLSSleepSta = true;
778 } else {
779 config->fEnableTDLSSleepSta = false;
780 }
781#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782#ifdef WLAN_FEATURE_ROAM_OFFLOAD
783 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
784#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700785 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786
787}
788
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700789/**
790 * hdd_update_vdev_nss() - sets the vdev nss
791 * @hdd_ctx: HDD context
792 *
793 * Sets the Nss per vdev type based on INI
794 *
795 * Return: None
796 */
797static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
798{
799 struct hdd_config *cfg_ini = hdd_ctx->config;
800 uint8_t max_supp_nss = 1;
801
802 if (cfg_ini->enable2x2)
803 max_supp_nss = 2;
804
805 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
806 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
807
808 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
809 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
810}
811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
813 struct wma_tgt_ht_cap *cfg)
814{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530815 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816 uint32_t value, val32;
817 uint16_t val16;
818 struct hdd_config *pconfig = hdd_ctx->config;
819 tSirMacHTCapabilityInfo *phtCapInfo;
820 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
821 uint8_t enable_tx_stbc;
822
823 /* check and update RX STBC */
824 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
825 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
826
827 /* get the MPDU density */
828 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
829
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530830 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700831 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832 value = 0;
833 }
834
835 /*
836 * MPDU density:
837 * override user's setting if value is larger
838 * than the one supported by target
839 */
840 if (value > cfg->mpdu_density) {
841 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
842 cfg->mpdu_density);
843
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530844 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700845 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 }
847
848 /* get the HT capability info */
849 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530850 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700851 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852 return;
853 }
854 val16 = (uint16_t) val32;
855 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
856
857 /* Set the LDPC capability */
858 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
859
860 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
861 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
862
863 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
864 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
865
866 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
867 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
868
869 enable_tx_stbc = pconfig->enableTxSTBC;
870
871 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
872 pconfig->enable2x2 = 1;
873 } else {
874 pconfig->enable2x2 = 0;
875 enable_tx_stbc = 0;
876
877 /* 1x1 */
878 /* Update Rx Highest Long GI data Rate */
879 if (sme_cfg_set_int(hdd_ctx->hHal,
880 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700881 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530882 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700883 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 }
885
886 /* Update Tx Highest Long GI data Rate */
887 if (sme_cfg_set_int
888 (hdd_ctx->hHal,
889 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700890 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530891 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700892 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800893 }
894 }
895 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
896 enable_tx_stbc = 0;
897 phtCapInfo->txSTBC = enable_tx_stbc;
898
899 val32 = val16;
900 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530901 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700902 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
904 value = SIZE_OF_SUPPORTED_MCS_SET;
905 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530906 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700907 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908
909 if (pconfig->enable2x2) {
910 for (value = 0; value < cfg->num_rf_chains; value++)
911 mcs_set[value] =
912 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
913
914 status =
915 sme_cfg_set_str(hdd_ctx->hHal,
916 WNI_CFG_SUPPORTED_MCS_SET,
917 mcs_set,
918 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530919 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700920 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921 }
922 }
923#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
924}
925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
927 struct wma_tgt_vht_cap *cfg)
928{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530929 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800930 uint32_t value = 0;
931 struct hdd_config *pconfig = hdd_ctx->config;
932 struct wiphy *wiphy = hdd_ctx->wiphy;
933 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700934 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700935 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936
Dustin Brown5e06bd32016-10-04 12:49:10 -0700937 if (!band_5g) {
938 hdd_info("5GHz band disabled, skipping capability population");
939 return;
940 }
941
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 /* Get the current MPDU length */
943 status =
944 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
945 &value);
946
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530947 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700948 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 value = 0;
950 }
951
952 /*
953 * VHT max MPDU length:
954 * override if user configured value is too high
955 * that the target cannot support
956 */
957 if (value > cfg->vht_max_mpdu) {
958 status = sme_cfg_set_int(hdd_ctx->hHal,
959 WNI_CFG_VHT_MAX_MPDU_LENGTH,
960 cfg->vht_max_mpdu);
961
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530962 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700963 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800964 }
965 }
966
967 /* Get the current supported chan width */
968 status = sme_cfg_get_int(hdd_ctx->hHal,
969 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
970 &value);
971
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530972 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700973 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974 value = 0;
975 }
976
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700977 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
978 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
979
980 if (pconfig->enable2x2)
981 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
982
983 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
984 QDF_STATUS_E_FAILURE) {
985 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
986 }
987
988 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
989 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
990 if (pconfig->enable2x2)
991 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
992
993 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
994 QDF_STATUS_E_FAILURE) {
995 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
996 }
997
998 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
999 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1000 if (pconfig->enable2x2)
1001 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1002
1003 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1004 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1005
1006 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1007 QDF_STATUS_E_FAILURE) {
1008 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1009 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001011 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 &value);
1013
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301014 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001015 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016 value = 0;
1017 }
1018
1019 /* Set the LDPC capability */
1020 if (value && !cfg->vht_rx_ldpc) {
1021 status = sme_cfg_set_int(hdd_ctx->hHal,
1022 WNI_CFG_VHT_LDPC_CODING_CAP,
1023 cfg->vht_rx_ldpc);
1024
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301025 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001026 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001027 }
1028 }
1029
1030 /* Get current GI 80 value */
1031 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1032 &value);
1033
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301034 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001035 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001036 value = 0;
1037 }
1038
1039 /* set the Guard interval 80MHz */
1040 if (value && !cfg->vht_short_gi_80) {
1041 status = sme_cfg_set_int(hdd_ctx->hHal,
1042 WNI_CFG_VHT_SHORT_GI_80MHZ,
1043 cfg->vht_short_gi_80);
1044
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301045 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001046 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001047 }
1048 }
1049
1050 /* Get current GI 160 value */
1051 status = sme_cfg_get_int(hdd_ctx->hHal,
1052 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1053 &value);
1054
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301055 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001056 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001057 value = 0;
1058 }
1059
1060 /* Get VHT TX STBC cap */
1061 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301063 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001064 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001065 value = 0;
1066 }
1067
1068 /* VHT TX STBC cap */
1069 if (value && !cfg->vht_tx_stbc) {
1070 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1071 cfg->vht_tx_stbc);
1072
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301073 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001074 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 }
1076 }
1077
1078 /* Get VHT RX STBC cap */
1079 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1080
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301081 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001082 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001083 value = 0;
1084 }
1085
1086 /* VHT RX STBC cap */
1087 if (value && !cfg->vht_rx_stbc) {
1088 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1089 cfg->vht_rx_stbc);
1090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301091 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001092 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001093 }
1094 }
1095
1096 /* Get VHT SU Beamformer cap */
1097 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
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 VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102 value = 0;
1103 }
1104
1105 /* set VHT SU Beamformer cap */
1106 if (value && !cfg->vht_su_bformer) {
1107 status = sme_cfg_set_int(hdd_ctx->hHal,
1108 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1109 cfg->vht_su_bformer);
1110
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301111 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001112 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001113 }
1114 }
1115
1116 /* check and update SU BEAMFORMEE capabality */
1117 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1118 pconfig->enableTxBF = cfg->vht_su_bformee;
1119
1120 status = sme_cfg_set_int(hdd_ctx->hHal,
1121 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1122 pconfig->enableTxBF);
1123
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301124 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001125 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126 }
1127
1128 /* Get VHT MU Beamformer cap */
1129 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1130 &value);
1131
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301132 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001133 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 value = 0;
1135 }
1136
1137 /* set VHT MU Beamformer cap */
1138 if (value && !cfg->vht_mu_bformer) {
1139 status = sme_cfg_set_int(hdd_ctx->hHal,
1140 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1141 cfg->vht_mu_bformer);
1142
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301143 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001144 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145 }
1146 }
1147
1148 /* Get VHT MU Beamformee cap */
1149 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1150 &value);
1151
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301152 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001153 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 value = 0;
1155 }
1156
1157 /* set VHT MU Beamformee cap */
1158 if (value && !cfg->vht_mu_bformee) {
1159 status = sme_cfg_set_int(hdd_ctx->hHal,
1160 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1161 cfg->vht_mu_bformee);
1162
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301163 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001164 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 }
1166 }
1167
1168 /* Get VHT MAX AMPDU Len exp */
1169 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1170 &value);
1171
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301172 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001173 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 value = 0;
1175 }
1176
1177 /*
1178 * VHT max AMPDU len exp:
1179 * override if user configured value is too high
1180 * that the target cannot support.
1181 * Even though Rome publish ampdu_len=7, it can
1182 * only support 4 because of some h/w bug.
1183 */
1184
1185 if (value > cfg->vht_max_ampdu_len_exp) {
1186 status = sme_cfg_set_int(hdd_ctx->hHal,
1187 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1188 cfg->vht_max_ampdu_len_exp);
1189
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301190 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001191 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 }
1193 }
1194
1195 /* Get VHT TXOP PS CAP */
1196 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1197
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301198 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001199 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001200 value = 0;
1201 }
1202
1203 /* set VHT TXOP PS cap */
1204 if (value && !cfg->vht_txop_ps) {
1205 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1206 cfg->vht_txop_ps);
1207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301208 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001209 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210 }
1211 }
1212
1213 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1214 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1215 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1216 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1217 else
1218 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1219
1220
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001221 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222 band_5g->vht_cap.cap |=
1223 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001224 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 band_5g->vht_cap.cap |=
1226 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227
1228 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1229 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1230
1231 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1232 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1233 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1234 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1235
1236 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1237 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1238
1239 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1240 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1241 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1242 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1243 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1244 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1245
1246 band_5g->vht_cap.cap |=
1247 (cfg->vht_max_ampdu_len_exp <<
1248 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1249
1250 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1251 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1252 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1253 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1254 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1255 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1256 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1257 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1258
1259 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1260 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1261
1262}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001264/**
1265 * hdd_generate_macaddr_auto() - Auto-generate mac address
1266 * @hdd_ctx: Pointer to the HDD context
1267 *
1268 * Auto-generate mac address using device serial number.
1269 * Keep the first 3 bytes of OUI as before and replace
1270 * the last 3 bytes with the lower 3 bytes of serial number.
1271 *
1272 * Return: 0 for success
1273 * Non zero failure code for errors
1274 */
1275static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1276{
1277 unsigned int serialno = 0;
1278 struct qdf_mac_addr mac_addr = {
1279 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1280 };
1281
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001282 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001283 if (serialno == 0)
1284 return -EINVAL;
1285
1286 serialno &= 0x00ffffff;
1287
1288 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1289 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1290 mac_addr.bytes[5] = serialno & 0xff;
1291
1292 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1293 return 0;
1294}
1295
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301296/**
1297 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1298 * configuration to cfg_ini in HDD
1299 * @hdd_ctx: Pointer to hdd_ctx
1300 * @cfg: target configuration
1301 *
1302 * Return: None
1303 */
1304#ifdef FEATURE_WLAN_RA_FILTERING
1305static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1306 struct wma_tgt_cfg *cfg)
1307{
1308 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1309}
1310#else
1311static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1312 struct wma_tgt_cfg *cfg)
1313{
1314}
1315#endif
1316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317void hdd_update_tgt_cfg(void *context, void *param)
1318{
1319 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1320 struct wma_tgt_cfg *cfg = param;
1321 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001322 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301323 QDF_STATUS qdf_status;
1324
1325 qdf_status = hdd_create_and_store_pdev(hdd_ctx);
1326 if (QDF_IS_STATUS_ERROR(qdf_status)) {
1327 hdd_err("Pdev creation fails!");
1328 QDF_BUG(0);
1329 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001330
1331 if (cds_cfg) {
1332 if (hdd_ctx->config->enable_sub_20_channel_width !=
1333 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1334 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1335 cds_cfg->sub_20_channel_width =
1336 WLAN_SUB_20_CH_WIDTH_NONE;
1337 } else {
1338 cds_cfg->sub_20_channel_width =
1339 hdd_ctx->config->enable_sub_20_channel_width;
1340 }
1341 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001342
1343 /* first store the INI band capability */
1344 temp_band_cap = hdd_ctx->config->nBandCapability;
1345
1346 hdd_ctx->config->nBandCapability = cfg->band_cap;
1347
1348 /* now overwrite the target band capability with INI
1349 setting if INI setting is a subset */
1350
1351 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1352 (temp_band_cap != eCSR_BAND_ALL))
1353 hdd_ctx->config->nBandCapability = temp_band_cap;
1354 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1355 (temp_band_cap != eCSR_BAND_ALL) &&
1356 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001357 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358 }
1359
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001360 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1362 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1363 }
1364
1365 /* This can be extended to other configurations like ht, vht cap... */
1366
Anurag Chouhanc5548422016-02-24 18:33:27 +05301367 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001369 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001371 static struct qdf_mac_addr default_mac_addr = {
1372 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1373 };
1374 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1375 &default_mac_addr)) {
1376 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1377 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1378 MAC_ADDRESS_STR,
1379 MAC_ADDR_ARRAY(hdd_ctx->config->
1380 intfMacAddr[0].bytes));
1381 } else {
1382 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1383 MAC_ADDRESS_STR,
1384 MAC_ADDR_ARRAY(hdd_ctx->config->
1385 intfMacAddr[0].bytes));
1386 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001387 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 }
1389
1390 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001391 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392
1393 hdd_ctx->max_intf_count = cfg->max_intf_count;
1394
Jeff Johnsonc875e242016-09-23 18:12:34 -07001395 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001396 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1399 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1400
1401 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001403 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001404
1405 hdd_update_vdev_nss(hdd_ctx);
1406
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001407 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001408 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001409 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001410 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001411
1412 hdd_ctx->current_antenna_mode =
1413 (hdd_ctx->config->enable2x2 == 0x01) ?
1414 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1415 hdd_info("Init current antenna mode: %d",
1416 hdd_ctx->current_antenna_mode);
1417
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001418 hdd_info("Target BPF %d Host BPF %d",
1419 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1420 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1421 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301422 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301423
Arun Khandavallid454d422016-08-17 12:47:05 +05301424 /*
1425 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1426 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1427 * configure the STA mode wow pattern.
1428 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301429 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301430 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301431
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301432 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1433
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001434 /* Configure NAN datapath features */
1435 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436}
1437
1438/**
1439 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1440 * @context: HDD context pointer
1441 * @param: HDD radar indication pointer
1442 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001443 * This function is invoked in atomic context when a radar
1444 * is found on the SAP current operating channel and Data Tx
1445 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 * Actions: Stop the netif Tx queues,Indicate Radar present
1447 * in HDD context for future usage.
1448 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301449 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301451bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001452{
1453 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1454 struct wma_dfs_radar_ind *hdd_radar_event =
1455 (struct wma_dfs_radar_ind *)param;
1456 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1457 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301458 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301459 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301461 if (!hdd_ctx || !hdd_radar_event ||
1462 hdd_ctx->config->disableDFSChSwitch)
1463 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001464
1465 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001466 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301467 /*
1468 * Application already triggered channel switch
1469 * on current channel, so return here.
1470 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301471 return false;
1472 }
1473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301475 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001476 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301477 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1478 if ((QDF_SAP_MODE == adapter->device_mode ||
1479 QDF_P2P_GO_MODE == adapter->device_mode) &&
1480 (CHANNEL_STATE_DFS ==
1481 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1483 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301484 hdd_info("tx blocked for session:%d",
1485 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001486 }
1487
1488 status = hdd_get_next_adapter(hdd_ctx,
1489 adapterNode,
1490 &pNext);
1491 adapterNode = pNext;
1492 }
1493 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301494
1495 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001496}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001497
1498/**
1499 * hdd_is_valid_mac_address() - validate MAC address
1500 * @pMacAddr: Pointer to the input MAC address
1501 *
1502 * This function validates whether the given MAC address is valid or not
1503 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1504 * where X is the hexa decimal digit character and separated by ':'
1505 * This algorithm works even if MAC address is not separated by ':'
1506 *
1507 * This code checks given input string mac contains exactly 12 hexadecimal
1508 * digits and a separator colon : appears in the input string only after
1509 * an even number of hex digits.
1510 *
1511 * Return: 1 for valid and 0 for invalid
1512 */
1513bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1514{
1515 int xdigit = 0;
1516 int separator = 0;
1517 while (*pMacAddr) {
1518 if (isxdigit(*pMacAddr)) {
1519 xdigit++;
1520 } else if (':' == *pMacAddr) {
1521 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1522 break;
1523
1524 ++separator;
1525 } else {
1526 /* Invalid MAC found */
1527 return 0;
1528 }
1529 ++pMacAddr;
1530 }
1531 return xdigit == 12 && (separator == 5 || separator == 0);
1532}
1533
1534/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301535 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1536 * @dev: Handle to struct net_device to be updated.
1537 *
1538 * Return: None
1539 */
1540static void hdd_mon_mode_ether_setup(struct net_device *dev)
1541{
1542 dev->header_ops = NULL;
1543 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1544 dev->hard_header_len = ETH_HLEN;
1545 dev->mtu = ETH_DATA_LEN;
1546 dev->addr_len = ETH_ALEN;
1547 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1548 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1549 dev->priv_flags |= IFF_TX_SKB_SHARING;
1550
1551 memset(dev->broadcast, 0xFF, ETH_ALEN);
1552}
1553
1554/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001555 * __hdd__mon_open() - HDD Open function
1556 * @dev: Pointer to net_device structure
1557 *
1558 * This is called in response to ifconfig up
1559 *
1560 * Return: 0 for success; non-zero for failure
1561 */
1562static int __hdd_mon_open(struct net_device *dev)
1563{
1564 int ret;
1565
1566 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301567 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001568 ret = hdd_set_mon_rx_cb(dev);
1569 return ret;
1570}
1571
1572/**
1573 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1574 * @dev: Pointer to net_device structure
1575 *
1576 * This is called in response to ifconfig up
1577 *
1578 * Return: 0 for success; non-zero for failure
1579 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001580static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001581{
1582 int ret;
1583
1584 cds_ssr_protect(__func__);
1585 ret = __hdd_mon_open(dev);
1586 cds_ssr_unprotect(__func__);
1587
1588 return ret;
1589}
1590
1591/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301592 * hdd_start_adapter() - Wrapper function for device specific adapter
1593 * @adapter: pointer to HDD adapter
1594 *
1595 * This function is called to start the device specific adapter for
1596 * the mode passed in the adapter's device_mode.
1597 *
1598 * Return: 0 for success; non-zero for failure
1599 */
1600int hdd_start_adapter(hdd_adapter_t *adapter)
1601{
1602
1603 int ret;
1604 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1605
1606 ENTER_DEV(adapter->dev);
1607 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1608
1609 switch (device_mode) {
1610 case QDF_P2P_CLIENT_MODE:
1611 case QDF_P2P_DEVICE_MODE:
1612 case QDF_OCB_MODE:
1613 case QDF_STA_MODE:
1614 case QDF_MONITOR_MODE:
1615 ret = hdd_start_station_adapter(adapter);
1616 if (ret)
1617 goto err_start_adapter;
1618 break;
1619 case QDF_P2P_GO_MODE:
1620 case QDF_SAP_MODE:
1621 ret = hdd_start_ap_adapter(adapter);
1622 if (ret)
1623 goto err_start_adapter;
1624 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301625 case QDF_IBSS_MODE:
1626 /*
1627 * For IBSS interface is initialized as part of
1628 * hdd_init_station_mode()
1629 */
1630 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301631 case QDF_FTM_MODE:
1632 ret = hdd_start_ftm_adapter(adapter);
1633 if (ret)
1634 goto err_start_adapter;
1635 break;
1636 default:
1637 hdd_err("Invalid session type %d", device_mode);
1638 QDF_ASSERT(0);
1639 goto err_start_adapter;
1640 }
1641 if (hdd_set_fw_params(adapter))
1642 hdd_err("Failed to set the FW params for the adapter!");
1643
1644 /*
1645 * Action frame registered in one adapter which will
1646 * applicable to all interfaces
1647 */
1648 wlan_hdd_cfg80211_register_frames(adapter);
1649 EXIT();
1650 return 0;
1651err_start_adapter:
1652 return -EINVAL;
1653}
1654
1655/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301656 * hdd_enable_power_management() - API to Enable Power Management
1657 *
1658 * API invokes Bus Interface Layer power management functionality
1659 *
1660 * Return: None
1661 */
1662static void hdd_enable_power_management(void)
1663{
1664 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1665
1666 if (!hif_ctx) {
1667 hdd_err("Bus Interface Context is Invalid");
1668 return;
1669 }
1670
1671 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1672}
1673
1674/**
1675 * hdd_disable_power_management() - API to disable Power Management
1676 *
1677 * API disable Bus Interface Layer Power management functionality
1678 *
1679 * Return: None
1680 */
1681static void hdd_disable_power_management(void)
1682{
1683 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1684
1685 if (!hif_ctx) {
1686 hdd_err("Bus Interface Context is Invalid");
1687 return;
1688 }
1689
1690 hif_disable_power_management(hif_ctx);
1691}
1692
1693/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301694 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1695 * @hdd_ctx: HDD context
1696 * @adapter: HDD adapter
1697 * @reinit: flag to indicate from SSR or normal path
1698 *
1699 * This function maintains the driver state machine it will be invoked from
1700 * startup, reinit and change interface. Depending on the driver state shall
1701 * perform the opening of the modules.
1702 *
1703 * Return: 0 for success; non-zero for failure
1704 */
1705int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1706 bool reinit)
1707{
1708 int ret;
1709 qdf_device_t qdf_dev;
1710 QDF_STATUS status;
1711 p_cds_contextType p_cds_context;
1712 bool unint = false;
1713 void *hif_ctx;
1714
1715 ENTER();
1716
1717 p_cds_context = cds_get_global_context();
1718 if (!p_cds_context) {
1719 hdd_err("Global Context is NULL");
1720 QDF_ASSERT(0);
1721 return -EINVAL;
1722 }
1723
1724 hdd_info("start modules called in state! :%d reinit: %d",
1725 hdd_ctx->driver_status, reinit);
1726
1727 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1728 if (!qdf_dev) {
1729 hdd_err("QDF Device Context is Invalid return");
1730 return -EINVAL;
1731 }
1732
1733 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301734 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301735
1736 if (QDF_TIMER_STATE_RUNNING ==
1737 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1738
1739 hdd_set_idle_ps_config(hdd_ctx, false);
1740 hdd_info("Interface change Timer running Stop timer");
1741 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1742 }
1743
1744 switch (hdd_ctx->driver_status) {
1745 case DRIVER_MODULES_UNINITIALIZED:
1746 unint = true;
1747 /* Fall through dont add break here */
1748 case DRIVER_MODULES_CLOSED:
1749 if (!reinit && !unint) {
1750 ret = pld_power_on(qdf_dev->dev);
1751 if (ret) {
1752 hdd_err("Failed to Powerup the device: %d", ret);
1753 goto release_lock;
1754 }
1755 }
1756 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1757 qdf_dev->bus_type,
1758 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1759 HIF_ENABLE_TYPE_PROBE);
1760 if (ret) {
1761 hdd_err("Failed to open hif: %d", ret);
1762 goto power_down;
1763 }
1764
1765 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301766 if (!hif_ctx) {
1767 hdd_err("hif context is null!!");
1768 goto power_down;
1769 }
1770
Arun Khandavallifae92942016-08-01 13:31:08 +05301771 status = ol_cds_init(qdf_dev, hif_ctx);
1772 if (status != QDF_STATUS_SUCCESS) {
1773 hdd_err("No Memory to Create BMI Context :%d", status);
1774 goto hif_close;
1775 }
1776
Arun Khandavallif6246632016-08-17 17:43:06 +05301777 ret = hdd_update_config(hdd_ctx);
1778 if (ret) {
1779 hdd_err("Failed to update configuration :%d", ret);
1780 goto ol_cds_free;
1781 }
1782
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301783 status = hdd_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID);
1784 if (QDF_IS_STATUS_ERROR(status)) {
1785 hdd_err("Psoc creation fails!");
1786 goto ol_cds_free;
1787 }
1788
1789 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05301790 if (!QDF_IS_STATUS_SUCCESS(status)) {
1791 hdd_err("Failed to Open CDS: %d", status);
1792 goto ol_cds_free;
1793 }
1794
1795 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1796
1797 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1798
1799 status = cds_pre_enable(hdd_ctx->pcds_context);
1800 if (!QDF_IS_STATUS_SUCCESS(status)) {
1801 hdd_err("Failed to pre-enable CDS: %d", status);
1802 goto close;
1803 }
1804
1805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1806 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1807 hdd_ftm_mc_process_msg);
1808 break;
1809 }
1810 if (unint) {
1811 hdd_info("In phase-1 initialization don't enable modules");
1812 break;
1813 }
1814 /* Fall through dont add break here */
1815 case DRIVER_MODULES_OPENED:
1816 if (!adapter) {
1817 hdd_alert("adapter is Null");
1818 goto close;
1819 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05301820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1821 hdd_err("in ftm mode, no need to configure cds modules");
1822 break;
1823 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301824 if (hdd_configure_cds(hdd_ctx, adapter)) {
1825 hdd_err("Failed to Enable cds modules");
1826 goto close;
1827 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05301828 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05301829 hdd_info("Driver Modules Successfully Enabled");
1830 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1831 break;
1832 case DRIVER_MODULES_ENABLED:
1833 hdd_info("Driver modules already Enabled");
1834 break;
1835 default:
1836 hdd_err("WLAN start invoked in wrong state! :%d\n",
1837 hdd_ctx->driver_status);
1838 goto release_lock;
1839 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301840 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301841 mutex_unlock(&hdd_ctx->iface_change_lock);
1842 EXIT();
1843 return 0;
1844
1845close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301846 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05301847
1848ol_cds_free:
1849 ol_cds_free();
1850
1851hif_close:
1852 hdd_hif_close(p_cds_context->pHIFContext);
1853power_down:
1854 if (!reinit && !unint)
1855 pld_power_off(qdf_dev->dev);
1856release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301857 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301858 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301859 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301860 return -EINVAL;
1861}
1862
1863/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001864 * __hdd_open() - HDD Open function
1865 * @dev: Pointer to net_device structure
1866 *
1867 * This is called in response to ifconfig up
1868 *
1869 * Return: 0 for success; non-zero for failure
1870 */
1871static int __hdd_open(struct net_device *dev)
1872{
1873 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1874 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1875 int ret;
1876
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001877 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301878 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301879 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880
1881 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301882 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301884
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885
Arun Khandavallifae92942016-08-01 13:31:08 +05301886 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1887 if (ret) {
1888 hdd_err("Failed to start WLAN modules return");
1889 return -ret;
1890 }
1891
1892
1893 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1894 ret = hdd_start_adapter(adapter);
1895 if (ret) {
1896 hdd_err("Failed to start adapter :%d",
1897 adapter->device_mode);
1898 return ret;
1899 }
1900 }
1901
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1903 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301904 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 /* Enable TX queues only when we are connected */
1906 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301907 WLAN_START_ALL_NETIF_QUEUE,
1908 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 }
1910
Naveen Rawat286def52016-09-23 15:38:02 -07001911 /* Enable carrier and transmit queues for NDI */
1912 if (WLAN_HDD_IS_NDI(adapter)) {
1913 hdd_notice("Enabling Tx Queues");
1914 wlan_hdd_netif_queue_control(adapter,
1915 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
1916 WLAN_CONTROL_PATH);
1917 }
1918
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 return ret;
1920}
1921
Arun Khandavallifae92942016-08-01 13:31:08 +05301922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923/**
1924 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1925 * @dev: Pointer to net_device structure
1926 *
1927 * This is called in response to ifconfig up
1928 *
1929 * Return: 0 for success; non-zero for failure
1930 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001931static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932{
1933 int ret;
1934
1935 cds_ssr_protect(__func__);
1936 ret = __hdd_open(dev);
1937 cds_ssr_unprotect(__func__);
1938
1939 return ret;
1940}
1941
1942/**
1943 * __hdd_stop() - HDD stop function
1944 * @dev: Pointer to net_device structure
1945 *
1946 * This is called in response to ifconfig down
1947 *
1948 * Return: 0 for success; non-zero for failure
1949 */
1950static int __hdd_stop(struct net_device *dev)
1951{
1952 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1953 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301954 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301956 bool close_modules = true;
1957 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001959 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301961 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 adapter->sessionId, adapter->device_mode));
1963
1964 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301965 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001967
1968 /* Nothing to be done if the interface is not opened */
1969 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001970 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 return -ENODEV;
1972 }
1973
1974 /* Make sure the interface is marked as closed */
1975 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001976 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977
1978 /*
1979 * Disable TX on the interface, after this hard_start_xmit() will not
1980 * be called on that interface
1981 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001982 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1984 WLAN_CONTROL_PATH);
1985
1986 /*
Naveen Rawat286def52016-09-23 15:38:02 -07001987 * NAN data interface is different in some sense. The traffic on NDI is
1988 * bursty in nature and depends on the need to transfer. The service
1989 * layer may down the interface after the usage and up again when
1990 * required. In some sense, the NDI is expected to be available
1991 * (like SAP) iface until NDI delete request is issued by the service
1992 * layer. Skip BSS termination and adapter deletion for NAN Data
1993 * interface (NDI).
1994 */
1995 if (WLAN_HDD_IS_NDI(adapter))
1996 return 0;
1997
1998 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001999 * The interface is marked as down for outside world (aka kernel)
2000 * But the driver is pretty much alive inside. The driver needs to
2001 * tear down the existing connection on the netdev (session)
2002 * cleanup the data pipes and wait until the control plane is stabilized
2003 * for this interface. The call also needs to wait until the above
2004 * mentioned actions are completed before returning to the caller.
2005 * Notice that the hdd_stop_adapter is requested not to close the session
2006 * That is intentional to be able to scan if it is a STA/P2P interface
2007 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302008 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009
2010 /* DeInit the adapter. This ensures datapath cleanup as well */
2011 hdd_deinit_adapter(hdd_ctx, adapter, true);
2012
Arun Khandavallifae92942016-08-01 13:31:08 +05302013
2014 /*
2015 * Find if any iface is up. If any iface is up then can't put device to
2016 * sleep/power save mode
2017 */
2018 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2019 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2020 if (test_bit(DEVICE_IFACE_OPENED,
2021 &adapternode->pAdapter->event_flags)) {
2022 hdd_info("Still other ifaces are up cannot close modules");
2023 close_modules = false;
2024 break;
2025 }
2026 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2027 adapternode = next;
2028
2029 }
2030
2031 if (close_modules) {
2032 hdd_info("Closing all modules from the hdd_stop");
2033 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2034 hdd_ctx->config->iface_change_wait_time
2035 * 50000);
2036 }
2037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 EXIT();
2039 return 0;
2040}
2041
2042/**
2043 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2044 * @dev: pointer to net_device structure
2045 *
2046 * This is called in response to ifconfig down
2047 *
2048 * Return: 0 for success and error number for failure
2049 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002050static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051{
2052 int ret;
2053
2054 cds_ssr_protect(__func__);
2055 ret = __hdd_stop(dev);
2056 cds_ssr_unprotect(__func__);
2057
2058 return ret;
2059}
2060
2061/**
2062 * __hdd_uninit() - HDD uninit function
2063 * @dev: Pointer to net_device structure
2064 *
2065 * This is called during the netdev unregister to uninitialize all data
2066 * associated with the device
2067 *
2068 * Return: None
2069 */
2070static void __hdd_uninit(struct net_device *dev)
2071{
2072 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2073
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002074 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075
2076 do {
2077 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002078 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 break;
2080 }
2081
2082 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002083 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 break;
2085 }
2086
2087 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002088 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002089 /*
2090 * we haven't validated all cases so let this go for
2091 * now
2092 */
2093 }
2094
2095 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2096
2097 /* after uninit our adapter structure will no longer be valid */
2098 adapter->dev = NULL;
2099 adapter->magic = 0;
2100 } while (0);
2101
2102 EXIT();
2103}
2104
2105/**
2106 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2107 * @dev: pointer to net_device structure
2108 *
2109 * This is called during the netdev unregister to uninitialize all data
2110 * associated with the device
2111 *
2112 * Return: none
2113 */
2114static void hdd_uninit(struct net_device *dev)
2115{
2116 cds_ssr_protect(__func__);
2117 __hdd_uninit(dev);
2118 cds_ssr_unprotect(__func__);
2119}
2120
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002121static int hdd_open_cesium_nl_sock(void)
2122{
2123#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2124 struct netlink_kernel_cfg cfg = {
2125 .groups = WLAN_NLINK_MCAST_GRP_ID,
2126 .input = NULL
2127 };
2128#endif
2129 int ret = 0;
2130
2131#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2132 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2133#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2134 THIS_MODULE,
2135#endif
2136 &cfg);
2137#else
2138 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2139 WLAN_NLINK_MCAST_GRP_ID,
2140 NULL, NULL, THIS_MODULE);
2141#endif
2142
2143 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002144 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002145 ret = -ECONNREFUSED;
2146 }
2147
2148 return ret;
2149}
2150
2151static void hdd_close_cesium_nl_sock(void)
2152{
2153 if (NULL != cesium_nl_srv_sock) {
2154 netlink_kernel_release(cesium_nl_srv_sock);
2155 cesium_nl_srv_sock = NULL;
2156 }
2157}
2158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002159/**
2160 * __hdd_set_mac_address() - set the user specified mac address
2161 * @dev: Pointer to the net device.
2162 * @addr: Pointer to the sockaddr.
2163 *
2164 * This function sets the user specified mac address using
2165 * the command ifconfig wlanX hw ether <mac adress>.
2166 *
2167 * Return: 0 for success, non zero for failure
2168 */
2169static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2170{
2171 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2172 hdd_context_t *hdd_ctx;
2173 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302174 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 int ret;
2176
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002177 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178
2179 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2180 ret = wlan_hdd_validate_context(hdd_ctx);
2181 if (0 != ret)
2182 return ret;
2183
2184 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2185 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2186
2187 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302188 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189}
2190
2191/**
2192 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2193 * function from SSR
2194 * @dev: pointer to net_device structure
2195 * @addr: Pointer to the sockaddr
2196 *
2197 * This function sets the user specified mac address using
2198 * the command ifconfig wlanX hw ether <mac adress>.
2199 *
2200 * Return: 0 for success.
2201 */
2202static int hdd_set_mac_address(struct net_device *dev, void *addr)
2203{
2204 int ret;
2205
2206 cds_ssr_protect(__func__);
2207 ret = __hdd_set_mac_address(dev, addr);
2208 cds_ssr_unprotect(__func__);
2209
2210 return ret;
2211}
2212
2213uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2214{
2215 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302216 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2218 break;
2219 }
2220
Anurag Chouhan6d760662016-02-20 16:05:43 +05302221 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 return NULL;
2223
2224 hdd_ctx->config->intfAddrMask |= (1 << i);
2225 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2226}
2227
2228void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2229{
2230 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302231 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 if (!memcmp(releaseAddr,
2233 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2234 6)) {
2235 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2236 break;
2237 }
2238 }
2239 return;
2240}
2241
2242#ifdef WLAN_FEATURE_PACKET_FILTERING
2243/**
2244 * __hdd_set_multicast_list() - set the multicast address list
2245 * @dev: Pointer to the WLAN device.
2246 * @skb: Pointer to OS packet (sk_buff).
2247 *
2248 * This funciton sets the multicast address list.
2249 *
2250 * Return: None
2251 */
2252static void __hdd_set_multicast_list(struct net_device *dev)
2253{
2254 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2255 int mc_count;
2256 int i = 0, status;
2257 struct netdev_hw_addr *ha;
2258 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2259 static const uint8_t ipv6_router_solicitation[]
2260 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2261
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002262 ENTER_DEV(dev);
2263
Anurag Chouhan6d760662016-02-20 16:05:43 +05302264 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302265 return;
2266
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302268 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270
2271 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002272 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002273 adapter->mc_addr_list.mc_cnt = 0;
2274 } else {
2275 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302276 hdd_notice("mc_count : %u", mc_count);
2277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Dustin Brown61269462016-09-19 13:25:45 -07002279 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
2280 WLAN_HDD_MAX_MC_ADDR_LIST);
2281 wlan_hdd_set_mc_addr_list(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282 adapter->mc_addr_list.mc_cnt = 0;
2283 return;
2284 }
2285
2286 adapter->mc_addr_list.mc_cnt = mc_count;
2287
2288 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302289 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2290 i, MAC_ADDR_ARRAY(ha->addr));
2291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002292 if (i == mc_count)
2293 break;
2294 /*
2295 * Skip following addresses:
2296 * 1)IPv6 router solicitation address
2297 * 2)Any other address pattern if its set during
2298 * RXFILTER REMOVE driver command based on
2299 * addr_filter_pattern
2300 */
2301 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2302 ETH_ALEN)) ||
2303 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2304 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002305 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002306 MAC_ADDR_ARRAY(ha->addr));
2307 adapter->mc_addr_list.mc_cnt--;
2308 continue;
2309 }
2310
2311 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2312 ETH_ALEN);
2313 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2314 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002315 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2317 i++;
2318 }
2319 }
2320 if (hdd_ctx->config->active_mode_offload) {
2321 hdd_info("enable mc filtering");
2322 wlan_hdd_set_mc_addr_list(adapter, true);
2323 } else {
2324 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2325 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302326 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 return;
2328}
2329
2330/**
2331 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2332 * @dev: pointer to net_device
2333 *
2334 * Return: none
2335 */
2336static void hdd_set_multicast_list(struct net_device *dev)
2337{
2338 cds_ssr_protect(__func__);
2339 __hdd_set_multicast_list(dev);
2340 cds_ssr_unprotect(__func__);
2341}
2342#endif
2343
2344/**
2345 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2346 * @dev: Pointer to the WLAN device.
2347 * @skb: Pointer to OS packet (sk_buff).
2348 *
2349 * This function is registered with the Linux OS for network
2350 * core to decide which queue to use first.
2351 *
2352 * Return: ac, Queue Index/access category corresponding to UP in IP header
2353 */
2354static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2355#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2356 , void *accel_priv
2357#endif
2358#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2359 , select_queue_fallback_t fallback
2360#endif
2361)
2362{
2363 return hdd_wmm_select_queue(dev, skb);
2364}
2365
2366static struct net_device_ops wlan_drv_ops = {
2367 .ndo_open = hdd_open,
2368 .ndo_stop = hdd_stop,
2369 .ndo_uninit = hdd_uninit,
2370 .ndo_start_xmit = hdd_hard_start_xmit,
2371 .ndo_tx_timeout = hdd_tx_timeout,
2372 .ndo_get_stats = hdd_get_stats,
2373 .ndo_do_ioctl = hdd_ioctl,
2374 .ndo_set_mac_address = hdd_set_mac_address,
2375 .ndo_select_queue = hdd_select_queue,
2376#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378#endif
2379};
2380
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002381/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2382static struct net_device_ops wlan_mon_drv_ops = {
2383 .ndo_open = hdd_mon_open,
2384 .ndo_stop = hdd_stop,
2385 .ndo_get_stats = hdd_get_stats,
2386};
2387
2388/**
2389 * hdd_set_station_ops() - update net_device ops for monitor mode
2390 * @pWlanDev: Handle to struct net_device to be updated.
2391 * Return: None
2392 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393void hdd_set_station_ops(struct net_device *pWlanDev)
2394{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002395 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2396 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2397 else
2398 pWlanDev->netdev_ops = &wlan_drv_ops;
2399}
2400
Komal Seelama89be8d2016-09-29 11:09:26 +05302401#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302402/**
2403 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2404 * @hdd_ctx: HDD context
2405 *
2406 * Return: None
2407 */
2408static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2409{
2410 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2411
2412 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302413 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302414 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302415}
2416
2417/**
2418 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2419 * @hdd_ctx: HDD Context
2420 *
2421 * Return: None
2422 */
2423static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2424{
2425 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2426
2427 qdf_runtime_lock_deinit(ctx->scan);
2428 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302429 qdf_runtime_lock_deinit(ctx->roc);
2430 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302431 qdf_runtime_lock_deinit(ctx->dfs);
2432 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302433}
2434
Komal Seelama89be8d2016-09-29 11:09:26 +05302435static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2436{
2437 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2438
2439 ctx->connect = qdf_runtime_lock_init("connect");
2440}
2441
2442static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2443{
2444 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2445
2446 qdf_runtime_lock_deinit(ctx->connect);
2447 ctx->connect = NULL;
2448}
2449#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302450static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2451static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302452static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2453static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2454#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002455/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002456 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2457 * @hdd_ctx: global hdd context
2458 * @macAddr: mac address to assign to the interface
2459 * @name: User-visible name of the interface
2460 *
2461 * hdd adapter pointer would point to the netdev->priv space, this function
2462 * would retrive the pointer, and setup the hdd adapter configuration.
2463 *
2464 * Return: the pointer to hdd adapter, otherwise NULL
2465 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2467 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002468 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 const char *name)
2470{
2471 struct net_device *pWlanDev = NULL;
2472 hdd_adapter_t *adapter = NULL;
2473 /*
2474 * cfg80211 initialization and registration....
2475 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002476 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2477#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2478 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002480 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2481 hdd_mon_mode_ether_setup : ether_setup),
2482 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483
2484 if (pWlanDev != NULL) {
2485
2486 /* Save the pointer to the net_device in the HDD adapter */
2487 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2488
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302489 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490
2491 adapter->dev = pWlanDev;
2492 adapter->pHddCtx = hdd_ctx;
2493 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302494 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495
2496 init_completion(&adapter->session_open_comp_var);
2497 init_completion(&adapter->session_close_comp_var);
2498 init_completion(&adapter->disconnect_comp_var);
2499 init_completion(&adapter->linkup_event_var);
2500 init_completion(&adapter->cancel_rem_on_chan_var);
2501 init_completion(&adapter->rem_on_chan_ready_event);
2502 init_completion(&adapter->sta_authorized_event);
2503 init_completion(&adapter->offchannel_tx_event);
2504 init_completion(&adapter->tx_action_cnf_event);
2505#ifdef FEATURE_WLAN_TDLS
2506 init_completion(&adapter->tdls_add_station_comp);
2507 init_completion(&adapter->tdls_del_station_comp);
2508 init_completion(&adapter->tdls_mgmt_comp);
2509 init_completion(&adapter->tdls_link_establish_req_comp);
2510#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002511 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512 init_completion(&adapter->change_country_code);
2513
2514
2515 init_completion(&adapter->scan_info.abortscan_event_var);
2516
2517 adapter->offloads_configured = false;
2518 adapter->isLinkUpSvcNeeded = false;
2519 adapter->higherDtimTransition = true;
2520 /* Init the net_device structure */
2521 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2522
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302523 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302525 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 sizeof(tSirMacAddr));
2527 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528
2529 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2530 pWlanDev->features |=
2531 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2532 pWlanDev->features |= NETIF_F_RXCSUM;
2533
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002534 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 hdd_set_station_ops(adapter->dev);
2537
2538 pWlanDev->destructor = free_netdev;
2539 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002540 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 adapter->wdev.wiphy = hdd_ctx->wiphy;
2542 adapter->wdev.netdev = pWlanDev;
2543 /* set pWlanDev's parent to underlying device */
2544 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2545 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302546 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302548 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 }
2550
2551 return adapter;
2552}
2553
Jeff Johnson590e2012016-10-05 16:16:24 -07002554static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2555 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556{
2557 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002559 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2561 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002562 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302563 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 }
2565 }
2566 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002567 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302568 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 }
2570 } else {
2571 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002572 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302573 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 }
2575 }
2576 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2577
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302578 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579}
2580
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002581QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582{
2583 hdd_adapter_t *adapter = pContext;
2584
2585 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002586 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302587 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002588 }
2589
2590 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002591 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302592 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 }
2594
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002595 /*
2596 * For NAN Data interface, the close session results in the final
2597 * indication to the userspace
2598 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002599 if (adapter->device_mode == QDF_NDI_MODE)
2600 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002601
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2603
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 /*
2605 * We can be blocked while waiting for scheduled work to be
2606 * flushed, and the adapter structure can potentially be freed, in
2607 * which case the magic will have been reset. So make sure the
2608 * magic is still good, and hence the adapter structure is still
2609 * valid, before signaling completion
2610 */
2611 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2612 complete(&adapter->session_close_comp_var);
2613
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302614 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615}
2616
Krunal Soni8c37e322016-02-03 16:08:37 -08002617/**
2618 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2619 * @adapter: pointer to device adapter
2620 * @type: type of interface
2621 *
2622 * This routine will check the mode of adapter and if it is required then it
2623 * will initialize the TDLS operations
2624 *
2625 * Return: QDF_STATUS
2626 */
2627#ifdef FEATURE_WLAN_TDLS
2628static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2629{
2630 if (QDF_IBSS_MODE != type) {
2631 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002632 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002633 return QDF_STATUS_E_FAILURE;
2634 }
2635 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2636 }
2637 return QDF_STATUS_SUCCESS;
2638}
2639#else
2640static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2641{
2642 return QDF_STATUS_SUCCESS;
2643}
2644#endif
2645
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302646QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647{
2648 struct net_device *pWlanDev = adapter->dev;
2649 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2650 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302651 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302652 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002653 uint32_t type, subType;
2654 unsigned long rc;
2655 int ret_val;
2656
2657 INIT_COMPLETION(adapter->session_open_comp_var);
2658 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002659 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002660 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302661 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002662 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 goto error_sme_open;
2664 }
2665 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302666 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2668 (uint8_t *) &adapter->macAddressCurrent,
2669 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302670 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002671 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302672 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302673 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 goto error_sme_open;
2675 }
2676 /* Block on a completion variable. Can't wait forever though. */
2677 rc = wait_for_completion_timeout(
2678 &adapter->session_open_comp_var,
2679 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2680 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002681 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 rc);
Sandeep Puligillae8065992016-11-14 00:23:43 -08002683 adapter->sessionId = HDD_SESSION_ID_INVALID;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302684 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 }
2686
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302687 status = hdd_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
2688 if (QDF_IS_STATUS_ERROR(status))
2689 goto error_vdev_create;
2690
Naveen Rawata410c5a2016-09-19 14:22:33 -07002691 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302693 qdf_ret_status = hdd_register_wext(pWlanDev);
2694 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002695 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302696 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302697 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002698 goto error_register_wext;
2699 }
2700 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002701 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2703
Deepak Dhamdherea2785822016-11-17 01:17:45 -08002704 /* set fast roaming capability in sme session */
2705 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
2706 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002707 /* Set the default operation channel */
2708 pHddStaCtx->conn_info.operationChannel =
2709 hdd_ctx->config->OperatingChannel;
2710
2711 /* Make the default Auth Type as OPEN */
2712 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2713
2714 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302715 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002716 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717 status, status);
2718 goto error_init_txrx;
2719 }
2720
2721 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2722
2723 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302724 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002725 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002726 status, status);
2727 goto error_wmm_init;
2728 }
2729
2730 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2731
2732 ret_val = wma_cli_set_command(adapter->sessionId,
2733 WMI_PDEV_PARAM_BURST_ENABLE,
2734 hdd_ctx->config->enableSifsBurst,
2735 PDEV_CMD);
2736
2737 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002738 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002739 ret_val);
2740 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002741 status = hdd_check_and_init_tdls(adapter, type);
2742 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002744
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302745 status = hdd_lro_enable(hdd_ctx, adapter);
2746 if (status != QDF_STATUS_SUCCESS)
2747 goto error_lro_enable;
2748
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302749 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302751error_lro_enable:
2752 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002753error_tdls_init:
2754 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2755 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756error_wmm_init:
2757 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2758 hdd_deinit_tx_rx(adapter);
2759error_init_txrx:
2760 hdd_unregister_wext(pWlanDev);
2761error_register_wext:
Rajeev Kumarba778852017-01-06 13:23:04 -08002762 status = hdd_release_and_destroy_vdev(adapter);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302763 if (QDF_IS_STATUS_ERROR(status))
2764 hdd_err("vdev delete failed");
2765error_vdev_create:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2767 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302768 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 adapter->sessionId,
2770 hdd_sme_close_session_callback,
2771 adapter)) {
2772 unsigned long rc;
2773
2774 /*
2775 * Block on a completion variable.
2776 * Can't wait forever though.
2777 */
2778 rc = wait_for_completion_timeout(
2779 &adapter->session_close_comp_var,
2780 msecs_to_jiffies
2781 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2782 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002783 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 rc);
2785 }
2786 }
2787error_sme_open:
2788 return status;
2789}
2790
2791void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2792{
2793 hdd_cfg80211_state_t *cfgState;
2794
2795 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2796
2797 if (NULL != cfgState->buf) {
2798 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002799 rc = wait_for_completion_timeout(
2800 &adapter->tx_action_cnf_event,
2801 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2802 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002803 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302804 /*
2805 * Inform tx status as FAILURE to upper layer and free
2806 * cfgState->buf
2807 */
2808 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 }
2810 }
2811 return;
2812}
2813
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302814/**
2815 * hdd_station_adapter_deinit() - De-initialize the station adapter
2816 * @hdd_ctx: global hdd context
2817 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07002818 * @rtnl_held: Used to indicate whether or not the caller is holding
2819 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302820 *
2821 * This function De-initializes the STA/P2P/OCB adapter.
2822 *
2823 * Return: None.
2824 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002825static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2826 hdd_adapter_t *adapter,
2827 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302828{
2829 ENTER_DEV(adapter->dev);
2830
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302831 if (adapter->dev) {
2832 if (rtnl_held)
2833 adapter->dev->wireless_handlers = NULL;
2834 else {
2835 rtnl_lock();
2836 adapter->dev->wireless_handlers = NULL;
2837 rtnl_unlock();
2838 }
2839 }
2840
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302841 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2842 hdd_deinit_tx_rx(adapter);
2843 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2844 }
2845
2846 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2847 hdd_wmm_adapter_close(adapter);
2848 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2849 }
2850
2851 hdd_cleanup_actionframe(hdd_ctx, adapter);
2852 wlan_hdd_tdls_exit(adapter);
2853
2854 EXIT();
2855}
2856
2857/**
2858 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2859 * @hdd_ctx: global hdd context
2860 * @adapter: HDD adapter
2861 * @rtnl_held: the rtnl lock hold flag
2862 * This function De-initializes the AP/P2PGo adapter.
2863 *
2864 * Return: None.
2865 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002866static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
2867 hdd_adapter_t *adapter,
2868 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302869{
2870 ENTER_DEV(adapter->dev);
2871
2872 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2873 hdd_wmm_adapter_close(adapter);
2874 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2875 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002876 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302877
2878 hdd_cleanup_actionframe(hdd_ctx, adapter);
2879
2880 hdd_unregister_hostapd(adapter, rtnl_held);
2881
2882 EXIT();
2883}
2884
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2886 bool rtnl_held)
2887{
2888 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302889
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002890 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002891 case QDF_STA_MODE:
2892 case QDF_P2P_CLIENT_MODE:
2893 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302895 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896 break;
2897 }
2898
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002899 case QDF_SAP_MODE:
2900 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 {
2902
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302903 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904 break;
2905 }
2906
2907 default:
2908 break;
2909 }
2910
2911 EXIT();
2912}
2913
Jeff Johnson590e2012016-10-05 16:16:24 -07002914static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2915 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916{
2917 struct net_device *pWlanDev = NULL;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302918 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919
2920 if (adapter)
2921 pWlanDev = adapter->dev;
2922 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002923 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 return;
2925 }
2926
Rajeev Kumarba778852017-01-06 13:23:04 -08002927 qdf_status = hdd_release_and_destroy_vdev(adapter);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302928 if (QDF_IS_STATUS_ERROR(qdf_status))
2929 hdd_err("vdev delete failed");
2930
Rajeev Kumardca5f812016-02-04 17:28:06 -08002931 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05302932
2933 if (adapter->scan_info.default_scan_ies) {
2934 qdf_mem_free(adapter->scan_info.default_scan_ies);
2935 adapter->scan_info.default_scan_ies = NULL;
2936 }
2937
Komal Seelama89be8d2016-09-29 11:09:26 +05302938 hdd_adapter_runtime_suspend_denit(adapter);
2939
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 /*
2941 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2942 * the driver is almost closed and cannot handle either control
2943 * messages or data. However, unregister_netdevice() call above will
2944 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2945 * to close the active connections (basically excites control path) which
2946 * is not right. Setting this flag helps hdd_stop() to recognize that
2947 * the interface is closed and restricts any operations on that
2948 */
2949 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2950
2951 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2952 if (rtnl_held) {
2953 unregister_netdevice(pWlanDev);
2954 } else {
2955 unregister_netdev(pWlanDev);
2956 }
2957 /*
2958 * Note that the adapter is no longer valid at this point
2959 * since the memory has been reclaimed
2960 */
2961 }
2962}
2963
Jeff Johnson590e2012016-10-05 16:16:24 -07002964static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
2965 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966{
2967 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2968 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302969 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002970 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302971 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002972 adapter = adapterNode->pAdapter;
2973 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302974 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302976 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977 }
2978 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2979 adapterNode = pNext;
2980 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302981 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002983
Arun Khandavalli2358d522016-05-16 18:05:37 +05302984#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2985/**
2986 * hdd_set_fw_log_params() - Set log parameters to FW
2987 * @hdd_ctx: HDD Context
2988 * @adapter: HDD Adapter
2989 *
2990 * This function set the FW Debug log level based on the INI.
2991 *
2992 * Return: None
2993 */
2994static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2995 hdd_adapter_t *adapter)
2996{
2997 uint8_t count = 0, numentries = 0,
2998 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2999 uint32_t value = 0;
3000 int ret;
3001
Arun Khandavallifae92942016-08-01 13:31:08 +05303002 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3003 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303004 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
3005 return;
3006 }
3007
Arun Khandavallifae92942016-08-01 13:31:08 +05303008 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303009 hdd_ctx->fw_log_settings.dl_type =
3010 hdd_ctx->config->enableFwLogType;
3011 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303012 WMI_DBGLOG_TYPE,
3013 hdd_ctx->config->enableFwLogType,
3014 DBG_CMD);
3015 if (ret != 0)
3016 hdd_err("Failed to enable FW log type ret %d",
3017 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303018
3019 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303020 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303021 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303022 WMI_DBGLOG_LOG_LEVEL,
3023 hdd_ctx->config->enableFwLogLevel,
3024 DBG_CMD);
3025 if (ret != 0)
3026 hdd_err("Failed to enable FW log level ret %d",
3027 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303028
3029 hdd_string_to_u8_array(
3030 hdd_ctx->config->enableFwModuleLogLevel,
3031 moduleloglevel,
3032 &numentries,
3033 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3034
3035 while (count < numentries) {
3036 /*
3037 * FW module log level input string looks like
3038 * below:
3039 * gFwDebugModuleLoglevel=<FW Module ID>,
3040 * <Log Level>,...
3041 * For example:
3042 * gFwDebugModuleLoglevel=
3043 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3044 * Above input string means :
3045 * For FW module ID 1 enable log level 0
3046 * For FW module ID 2 enable log level 1
3047 * For FW module ID 3 enable log level 2
3048 * For FW module ID 4 enable log level 3
3049 * For FW module ID 5 enable log level 4
3050 * For FW module ID 6 enable log level 5
3051 * For FW module ID 7 enable log level 6
3052 */
3053
Arun Khandavallifae92942016-08-01 13:31:08 +05303054 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05303055 * Module ID * 10 + Module Log level
3056 */
3057 value = ((moduleloglevel[count] * 10) +
3058 moduleloglevel[count + 1]);
3059 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303060 WMI_DBGLOG_MOD_LOG_LEVEL,
3061 value, DBG_CMD);
3062 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303063 hdd_err("Failed to enable FW module log level %d ret %d",
3064 value, ret);
3065
3066 count += 2;
3067 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303068
Arun Khandavalli2358d522016-05-16 18:05:37 +05303069}
3070#else
3071static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3072 hdd_adapter_t *adapter)
3073{
3074}
3075
3076#endif
3077
3078/**
3079 * hdd_set_fw_params() - Set parameters to firmware
3080 * @adapter: HDD adapter
3081 *
3082 * This function Sets various parameters to fw once the
3083 * adapter is started.
3084 *
3085 * Return: 0 on success or errno on failure
3086 */
3087int hdd_set_fw_params(hdd_adapter_t *adapter)
3088{
3089 int ret;
3090 hdd_context_t *hdd_ctx;
3091
3092 ENTER_DEV(adapter->dev);
3093
3094 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3095 if (!hdd_ctx)
3096 return -EINVAL;
3097
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003098 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303099 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303100#define HDD_DTIM_1CHAIN_RX_ID 0x5
3101#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003102 /*
3103 * Disable DTIM 1 chain Rx when in 1x1,
3104 * we are passing two value
3105 * as param_id << 29 | param_value.
3106 * Below param_value = 0(disable)
3107 */
3108 ret = wma_cli_set_command(adapter->sessionId,
3109 WMI_STA_SMPS_PARAM_CMDID,
3110 HDD_DTIM_1CHAIN_RX_ID <<
3111 HDD_SMPS_PARAM_VALUE_S,
3112 VDEV_CMD);
3113 if (ret) {
3114 hdd_err("DTIM 1 chain set failed %d", ret);
3115 goto error;
3116 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303117
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003118 ret = wma_cli_set_command(adapter->sessionId,
3119 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3120 hdd_ctx->config->txchainmask1x1,
3121 PDEV_CMD);
3122 if (ret) {
3123 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3124 ret);
3125 goto error;
3126 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303127
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003128 ret = wma_cli_set_command(adapter->sessionId,
3129 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3130 hdd_ctx->config->rxchainmask1x1,
3131 PDEV_CMD);
3132 if (ret) {
3133 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3134 ret);
3135 goto error;
3136 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303137#undef HDD_DTIM_1CHAIN_RX_ID
3138#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003139 } else {
3140 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3141 }
3142
Arun Khandavallifae92942016-08-01 13:31:08 +05303143 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3144 ret = wma_cli_set_command(adapter->sessionId,
3145 WMI_PDEV_PARAM_HYST_EN,
3146 hdd_ctx->config->enableMemDeepSleep,
3147 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303148
Arun Khandavallifae92942016-08-01 13:31:08 +05303149 if (ret) {
3150 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3151 ret);
3152 goto error;
3153 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303154
3155 ret = wma_cli_set_command(adapter->sessionId,
3156 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3157 hdd_ctx->config->rts_profile,
3158 VDEV_CMD);
3159 if (ret) {
3160 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3161 goto error;
3162 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303163 }
3164
3165 hdd_set_fw_log_params(hdd_ctx, adapter);
3166
3167 EXIT();
3168 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303169
Arun Khandavalli2358d522016-05-16 18:05:37 +05303170error:
3171 return -EINVAL;
3172}
3173
Ryan Hsu07495ea2016-01-21 15:25:39 -08003174/**
3175 * hdd_open_adapter() - open and setup the hdd adatper
3176 * @hdd_ctx: global hdd context
3177 * @session_type: type of the interface to be created
3178 * @iface_name: User-visible name of the interface
3179 * @macAddr: MAC address to assign to the interface
3180 * @name_assign_type: the name of assign type of the netdev
3181 * @rtnl_held: the rtnl lock hold flag
3182 *
3183 * This function open and setup the hdd adpater according to the device
3184 * type request, assign the name, the mac address assigned, and then prepared
3185 * the hdd related parameters, queue, lock and ready to start.
3186 *
3187 * Return: the pointer of hdd adapter, otherwise NULL.
3188 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3190 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003191 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003192 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193{
3194 hdd_adapter_t *adapter = NULL;
3195 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303196 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198
Arun Khandavallifae92942016-08-01 13:31:08 +05303199 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200
3201 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3202 /*
3203 * Max limit reached on the number of vdevs configured by the
3204 * host. Return error
3205 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303206 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3207 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 return NULL;
3209 }
3210
3211 if (macAddr == NULL) {
3212 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303213 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 return NULL;
3215 }
3216 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303217 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303218 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3219 " already exists",
3220 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221 return NULL;
3222 }
3223
3224 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003225 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003226 /* Reset locally administered bit if the device mode is STA */
3227 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3228 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003229 case QDF_P2P_CLIENT_MODE:
3230 case QDF_P2P_DEVICE_MODE:
3231 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003232 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303233 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003234 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3235 name_assign_type,
3236 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237
3238 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303239 hdd_err("failed to allocate adapter for session %d",
3240 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 return NULL;
3242 }
3243
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003244 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003245 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003246 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303248 else if (QDF_MONITOR_MODE == session_type)
3249 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250 else
3251 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3252
3253 adapter->device_mode = session_type;
3254
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303255 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003256 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303257 if (QDF_STATUS_SUCCESS != status)
3258 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303259 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 /*
3262 * Workqueue which gets scheduled in IPv4 notification
3263 * callback
3264 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3266 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267
3268#ifdef WLAN_NS_OFFLOAD
3269 /*
3270 * Workqueue which gets scheduled in IPv6
3271 * notification callback.
3272 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3274 hdd_ipv6_notifier_work_queue);
3275#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303277 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303279 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 }
3281
3282 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303283 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303285 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3286 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003290 case QDF_P2P_GO_MODE:
3291 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003292 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3293 name_assign_type,
3294 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303296 hdd_alert("failed to allocate adapter for session %d",
3297 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003298 return NULL;
3299 }
3300
3301 adapter->wdev.iftype =
3302 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003303 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 NL80211_IFTYPE_P2P_GO;
3305 adapter->device_mode = session_type;
3306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003307 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303308 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3310 goto err_free_netdev;
3311 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303312 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003313 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303314 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3315 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303317 case QDF_FTM_MODE:
3318 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3319 name_assign_type,
3320 "wlan0");
3321 if (NULL == adapter) {
3322 hdd_err("Failed to allocate adapter for FTM mode");
3323 return NULL;
3324 }
3325 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3326 adapter->device_mode = session_type;
3327 status = hdd_register_interface(adapter, rtnl_held);
3328 if (QDF_STATUS_SUCCESS != status) {
3329 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3330 goto err_free_netdev;
3331 }
3332 /* Stop the Interface TX queue. */
3333 hdd_info("Disabling queues");
3334 wlan_hdd_netif_queue_control(adapter,
3335 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3336 WLAN_CONTROL_PATH);
3337 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303339 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303340 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 return NULL;
3342 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343
3344 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3345 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3346
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303347 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348 /* Add it to the hdd's session list. */
3349 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303350 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303352 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353 } else {
3354 pHddAdapterNode->pAdapter = adapter;
3355 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3356 }
3357 }
3358
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303359 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360 if (NULL != adapter) {
3361 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3362 adapter = NULL;
3363 }
3364 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303365 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003366 }
3367 return NULL;
3368 }
3369
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303370 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003371 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372
3373 /* Initialize the WoWL service */
3374 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003375 hdd_alert("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303376 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 }
3378
3379 /* Adapter successfully added. Increment the vdev count */
3380 hdd_ctx->current_intf_count++;
3381
Jeff Johnson5880d792016-08-15 13:32:30 -07003382 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003383 hdd_ctx->current_intf_count);
3384
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003385 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003386 }
3387
Rajeev Kumardca5f812016-02-04 17:28:06 -08003388 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3389 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003390
3391 return adapter;
3392
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303393err_close_adapter:
3394 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303397 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398
3399 return NULL;
3400}
3401
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303402QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003403 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404{
3405 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303406 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407
3408 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303409 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003410 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003411 status);
3412 return status;
3413 }
3414
3415 while (pCurrent->pAdapter != adapter) {
3416 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303417 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 break;
3419
3420 pCurrent = pNext;
3421 }
3422 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303423 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003424 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3426
3427 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303428 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 adapterNode = NULL;
3430
3431 /* Adapter removed. Decrement vdev count */
3432 if (hdd_ctx->current_intf_count != 0)
3433 hdd_ctx->current_intf_count--;
3434
3435 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303436 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003437 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303438
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303439 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440}
3441
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003442/**
3443 * hdd_close_all_adapters - Close all open adapters
3444 * @hdd_ctx: Hdd context
3445 * rtnl_held: True if RTNL lock held
3446 *
3447 * Close all open adapters.
3448 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303449 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003450 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303451QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003452{
3453 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303454 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455
3456 ENTER();
3457
3458 do {
3459 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303460 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303461 wlan_hdd_release_intf_addr(hdd_ctx,
3462 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003464 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303465 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303466 /* Adapter removed. Decrement vdev count */
3467 if (hdd_ctx->current_intf_count != 0)
3468 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003469 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303470 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471
3472 EXIT();
3473
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303474 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475}
3476
3477void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3478{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303479 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 tSirUpdateIE updateIE;
3481 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003482 case QDF_STA_MODE:
3483 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484 {
3485 hdd_station_ctx_t *pHddStaCtx =
3486 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003487 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488 break;
3489 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003490 case QDF_SAP_MODE:
3491 case QDF_P2P_GO_MODE:
3492 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003494 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495 break;
3496 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003497 case QDF_FTM_MODE:
3498 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003499 default:
3500 /*
3501 * wlan_hdd_reset_prob_rspies should not have been called
3502 * for these kind of devices
3503 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003504 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 pHostapdAdapter->device_mode);
3506 return;
3507 }
3508
Anurag Chouhanc5548422016-02-24 18:33:27 +05303509 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003510 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3511 updateIE.ieBufferlength = 0;
3512 updateIE.pAdditionIEBuffer = NULL;
3513 updateIE.append = true;
3514 updateIE.notify = false;
3515 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3516 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303517 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003518 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 }
3520}
3521
Peng Xu66162de2016-02-11 17:01:20 -08003522/**
3523 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3524 * @hdd_ctx: HDD context which is already NULL validated
3525 * @adapter: HDD adapter which is already NULL validated
3526 *
3527 * Close the SME session and wait for its completion, if needed.
3528 *
3529 * Return: None
3530 */
3531static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3532 hdd_adapter_t *adapter)
3533{
3534 unsigned long rc;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303535 QDF_STATUS qdf_status;
Peng Xu66162de2016-02-11 17:01:20 -08003536
3537 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3538 hdd_err("session is not opened:%d", adapter->sessionId);
3539 return;
3540 }
3541
3542 INIT_COMPLETION(adapter->session_close_comp_var);
3543 if (QDF_STATUS_SUCCESS ==
3544 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3545 hdd_sme_close_session_callback,
3546 adapter)) {
3547 /*
3548 * Block on a completion variable. Can't wait
3549 * forever though.
3550 */
3551 rc = wait_for_completion_timeout(
3552 &adapter->session_close_comp_var,
3553 msecs_to_jiffies
3554 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003555 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003556 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003557 if (adapter->device_mode == QDF_NDI_MODE)
3558 hdd_ndp_session_end_handler(adapter);
3559 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303560 return;
Sandeep Puligillaada72922016-09-29 19:31:21 -07003561 }
Rajeev Kumarba778852017-01-06 13:23:04 -08003562 qdf_status = hdd_release_and_destroy_vdev(adapter);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303563 if (QDF_IS_STATUS_ERROR(qdf_status))
3564 hdd_err("vdev delete failed");
3565
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303566 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003567 }
3568}
3569
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303570QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003571 const bool bCloseSession)
3572{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303573 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3575 union iwreq_data wrqu;
3576 tSirUpdateIE updateIE;
3577 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303578 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003579
3580 ENTER();
3581
Sachin Ahuja988fd102016-09-15 17:16:25 +05303582 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003583 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3585 WLAN_CONTROL_PATH);
3586 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003587 case QDF_STA_MODE:
3588 case QDF_P2P_CLIENT_MODE:
3589 case QDF_IBSS_MODE:
3590 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003591 case QDF_NDI_MODE:
3592 if ((QDF_NDI_MODE == adapter->device_mode) ||
3593 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3595 hdd_is_connecting(
3596 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003597 INIT_COMPLETION(adapter->disconnect_comp_var);
3598 /*
3599 * For NDI do not use pWextState from sta_ctx, if needed
3600 * extract from ndi_ctx.
3601 */
3602 if (QDF_NDI_MODE == adapter->device_mode)
3603 qdf_ret_status = sme_roam_disconnect(
3604 hdd_ctx->hHal,
3605 adapter->sessionId,
3606 eCSR_DISCONNECT_REASON_NDI_DELETE);
3607 else if (pWextState->roamProfile.BSSType ==
3608 eCSR_BSS_TYPE_START_IBSS)
3609 qdf_ret_status = sme_roam_disconnect(
3610 hdd_ctx->hHal,
3611 adapter->sessionId,
3612 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003614 qdf_ret_status = sme_roam_disconnect(
3615 hdd_ctx->hHal,
3616 adapter->sessionId,
3617 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303619 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620 rc = wait_for_completion_timeout(
3621 &adapter->disconnect_comp_var,
3622 msecs_to_jiffies
3623 (WLAN_WAIT_TIME_DISCONNECT));
3624 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003625 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 }
3627 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003628 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629 }
3630 memset(&wrqu, '\0', sizeof(wrqu));
3631 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3632 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3633 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3634 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303635 }
3636 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303637 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303639 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303640 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003641
3642#ifdef WLAN_OPEN_SOURCE
3643 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3644#endif
3645
3646 hdd_deregister_tx_flow_control(adapter);
3647
3648#ifdef WLAN_NS_OFFLOAD
3649#ifdef WLAN_OPEN_SOURCE
3650 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3651#endif
3652#endif
3653
3654 /*
3655 * It is possible that the caller of this function does not
3656 * wish to close the session
3657 */
Peng Xu66162de2016-02-11 17:01:20 -08003658 if (true == bCloseSession)
3659 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003660 break;
3661
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003662 case QDF_SAP_MODE:
3663 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003665 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 /*
3667 * Before stopping the sap adapter, lets make sure there
3668 * is no sap restart work pending.
3669 */
3670 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003671 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003672 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 }
3674 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003675 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003676 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3677
3678 hdd_deregister_tx_flow_control(adapter);
3679
3680 mutex_lock(&hdd_ctx->sap_lock);
3681 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303682 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303683 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003684
3685 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 status = wlansap_stop_bss(
3687 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003688
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303689 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 hdd_hostapd_state_t *hostapd_state =
3691 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303692 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303693 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303694 qdf_status =
3695 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303696 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697 BSS_WAIT_TIMEOUT);
3698
Anurag Chouhance0dc992016-02-16 18:18:03 +05303699 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003700 hdd_err("failure waiting for wlansap_stop_bss %d",
3701 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 }
3703 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003704 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705 }
3706 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003707 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003708 adapter->device_mode,
3709 adapter->sessionId);
3710
Anurag Chouhanc5548422016-02-24 18:33:27 +05303711 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003712 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 updateIE.smeSessionId = adapter->sessionId;
3714 updateIE.ieBufferlength = 0;
3715 updateIE.pAdditionIEBuffer = NULL;
3716 updateIE.append = false;
3717 updateIE.notify = false;
3718 /* Probe bcn reset */
3719 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3720 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303721 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003722 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723 }
3724 /* Assoc resp reset */
3725 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3726 &updateIE,
3727 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303728 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003729 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 }
3731 /* Reset WNI_CFG_PROBE_RSP Flags */
3732 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303733 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 adapter->sessionCtx.ap.beacon = NULL;
3735 }
3736 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003737 if (true == bCloseSession)
3738 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003740 case QDF_OCB_MODE:
Leo Changfdb45c32016-10-28 11:09:23 -07003741 cdp_peer_clear(cds_get_context(QDF_MODULE_ID_SOC),
3742 cds_get_context(QDF_MODULE_ID_TXRX),
3743 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003744 break;
3745 default:
3746 break;
3747 }
3748
3749 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303750 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003751}
3752
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05303753/**
3754 * hdd_deinit_all_adapters - deinit all adapters
3755 * @hdd_ctx: HDD context
3756 * @rtnl_held: True if RTNL lock held
3757 *
3758 */
3759void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
3760{
3761 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3762 QDF_STATUS status;
3763 hdd_adapter_t *adapter;
3764
3765 ENTER();
3766
3767 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
3768
3769 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
3770 adapter = adapter_node->pAdapter;
3771 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3772 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
3773 adapter_node = next;
3774 }
3775
3776 EXIT();
3777}
3778
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303779QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780{
3781 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303782 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 hdd_adapter_t *adapter;
3784
3785 ENTER();
3786
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303787 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3788
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003789 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3790
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303791 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 adapter = adapterNode->pAdapter;
3793 hdd_stop_adapter(hdd_ctx, adapter, true);
3794 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3795 adapterNode = pNext;
3796 }
3797
3798 EXIT();
3799
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303800 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801}
3802
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303803QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804{
3805 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303806 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 hdd_adapter_t *adapter;
3808
3809 ENTER();
3810
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303811 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3812
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3814
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303815 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003817 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818 wlan_hdd_netif_queue_control(adapter,
3819 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3820 WLAN_CONTROL_PATH);
3821
3822 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3823
3824 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003825 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 adapter->sessionId);
3827 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3828 hdd_wmm_adapter_close(adapter);
3829 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3830 }
3831
Wu Gao36717432016-11-21 15:09:48 +08003832 /*
3833 * If adapter is SAP, set session ID to invalid since SAP
3834 * session will be cleanup during SSR.
3835 */
3836 if (adapter->device_mode == QDF_SAP_MODE)
3837 wlansap_set_invalid_session(
3838 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3839
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3841 adapterNode = pNext;
3842 }
3843
3844 EXIT();
3845
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303846 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847}
3848
Arun Khandavallifae92942016-08-01 13:31:08 +05303849/**
3850 * hdd_is_interface_up()- Checkfor interface up before ssr
3851 * @hdd_ctx: HDD context
3852 *
3853 * check if there are any wlan interfaces before SSR accordingly start
3854 * the interface.
3855 *
3856 * Return: 0 if interface was opened else false
3857 */
3858static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3859{
3860 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3861 return true;
3862 else
3863 return false;
3864}
3865
Anurag Chouhanc4092922016-09-08 15:56:11 +05303866#if defined CFG80211_CONNECT_BSS
3867#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
3868 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
Jeff Johnson590e2012016-10-05 16:16:24 -07003869static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303870struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3871 struct ieee80211_channel *channel,
3872 const u8 *bssid, const u8 *ssid,
3873 size_t ssid_len)
3874{
3875 return cfg80211_get_bss(wiphy, channel, bssid,
3876 ssid, ssid_len,
3877 WLAN_CAPABILITY_ESS,
3878 WLAN_CAPABILITY_ESS);
3879}
3880#else
Jeff Johnson590e2012016-10-05 16:16:24 -07003881static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303882struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3883 struct ieee80211_channel *channel,
3884 const u8 *bssid, const u8 *ssid,
3885 size_t ssid_len)
3886{
3887 return cfg80211_get_bss(wiphy, channel, bssid,
3888 ssid, ssid_len,
3889 IEEE80211_BSS_TYPE_ESS,
3890 IEEE80211_PRIVACY_ANY);
3891}
3892#endif
3893#endif
3894
Abhishek Singha84d3952016-09-13 13:45:05 +05303895#if defined CFG80211_CONNECT_BSS
3896/**
3897 * hdd_connect_bss() - API to send connection status to supplicant
3898 * @dev: network device
3899 * @bssid: bssid to which we want to associate
3900 * @req_ie: Request Information Element
3901 * @req_ie_len: len of the req IE
3902 * @resp_ie: Response IE
3903 * @resp_ie_len: len of ht response IE
3904 * @status: status
3905 * @gfp: Kernel Flag
3906 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
3907 *
3908 * The API is a wrapper to send connection status to supplicant
3909 *
3910 * Return: Void
3911 */
3912#if defined CFG80211_CONNECT_TIMEOUT
3913static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3914 struct cfg80211_bss *bss, const u8 *req_ie,
3915 size_t req_ie_len, const u8 *resp_ie,
3916 size_t resp_ie_len, int status, gfp_t gfp,
3917 bool connect_timeout)
3918{
3919 if (connect_timeout)
3920 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
3921 else
3922 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3923 resp_ie, resp_ie_len, status, gfp);
3924}
3925#else
3926static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3927 struct cfg80211_bss *bss, const u8 *req_ie,
3928 size_t req_ie_len, const u8 *resp_ie,
3929 size_t resp_ie_len, int status, gfp_t gfp,
3930 bool connect_timeout)
3931{
3932 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3933 resp_ie, resp_ie_len, status, gfp);
3934}
3935#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303936
3937/**
3938 * hdd_connect_result() - API to send connection status to supplicant
3939 * @dev: network device
3940 * @bssid: bssid to which we want to associate
3941 * @roam_info: information about connected bss
3942 * @req_ie: Request Information Element
3943 * @req_ie_len: len of the req IE
3944 * @resp_ie: Response IE
3945 * @resp_ie_len: len of ht response IE
3946 * @status: status
3947 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05303948 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
Anurag Chouhanc4092922016-09-08 15:56:11 +05303949 *
3950 * The API is a wrapper to send connection status to supplicant
3951 * and allow runtime suspend
3952 *
3953 * Return: Void
3954 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303955void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3956 tCsrRoamInfo *roam_info, const u8 *req_ie,
3957 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303958 size_t resp_ie_len, u16 status, gfp_t gfp,
3959 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303960{
3961 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3962 struct cfg80211_bss *bss = NULL;
3963
3964 if (WLAN_STATUS_SUCCESS == status) {
3965 struct ieee80211_channel *chan;
3966 int freq;
3967 int chan_no = roam_info->pBssDesc->channelId;
3968
3969 if (chan_no <= 14)
3970 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07003971 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303972 else
3973 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07003974 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303975
3976 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
3977 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
3978 roam_info->u.pConnectedProfile->SSID.ssId,
3979 roam_info->u.pConnectedProfile->SSID.length);
3980 }
Komal Seelama89be8d2016-09-29 11:09:26 +05303981
Abhishek Singha84d3952016-09-13 13:45:05 +05303982 hdd_connect_bss(dev, bssid, bss, req_ie,
3983 req_ie_len, resp_ie, resp_ie_len,
3984 status, gfp, connect_timeout);
Komal Seelama89be8d2016-09-29 11:09:26 +05303985
3986 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303987}
3988#else
3989void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3990 tCsrRoamInfo *roam_info, const u8 *req_ie,
3991 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303992 size_t resp_ie_len, u16 status, gfp_t gfp,
3993 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303994{
Komal Seelama89be8d2016-09-29 11:09:26 +05303995 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3996
Anurag Chouhanc4092922016-09-08 15:56:11 +05303997 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
3998 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05303999 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304000}
4001#endif
4002
4003
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304004QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005{
4006 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304007 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 hdd_adapter_t *adapter;
4009#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304010 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011#endif
4012 eConnectionState connState;
4013
4014 ENTER();
4015
4016 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304017 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018 adapter = adapterNode->pAdapter;
4019
Arun Khandavallifae92942016-08-01 13:31:08 +05304020 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304021 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 hdd_wmm_init(adapter);
4024
4025 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004026 case QDF_STA_MODE:
4027 case QDF_P2P_CLIENT_MODE:
4028 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029
4030 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4031 ->conn_info.connState;
4032
4033 hdd_init_station_mode(adapter);
4034 /* Open the gates for HDD to receive Wext commands */
4035 adapter->isLinkUpSvcNeeded = false;
4036 adapter->scan_info.mScanPending = false;
4037
4038 /* Indicate disconnect event to supplicant if associated previously */
4039 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004040 eConnectionState_IbssConnected == connState ||
4041 eConnectionState_NotConnected == connState ||
4042 eConnectionState_IbssDisconnected == connState ||
4043 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004044 union iwreq_data wrqu;
4045 memset(&wrqu, '\0', sizeof(wrqu));
4046 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4047 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4048 wireless_send_event(adapter->dev, SIOCGIWAP,
4049 &wrqu, NULL);
4050 adapter->sessionCtx.station.
4051 hdd_ReassocScenario = false;
4052
4053 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304054 wlan_hdd_cfg80211_indicate_disconnect(
4055 adapter->dev, false,
4056 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 } else if (eConnectionState_Connecting == connState) {
4058 /*
4059 * Indicate connect failure to supplicant if we were in the
4060 * process of connecting
4061 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304062 hdd_connect_result(adapter->dev, NULL, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063 NULL, 0, NULL, 0,
4064 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Abhishek Singha84d3952016-09-13 13:45:05 +05304065 GFP_KERNEL, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 }
4067
4068 hdd_register_tx_flow_control(adapter,
4069 hdd_tx_resume_timer_expired_handler,
4070 hdd_tx_resume_cb);
4071
4072 break;
4073
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004074 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 /* softAP can handle SSR */
4076 break;
4077
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004078 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07004080 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4082#else
Jeff Johnson5880d792016-08-15 13:32:30 -07004083 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 /* event supplicant to restart */
4085 cfg80211_del_sta(adapter->dev,
4086 (const u8 *)&bcastMac.bytes[0],
4087 GFP_KERNEL);
4088#endif
4089 break;
4090
4091 default:
4092 break;
4093 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304094get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004095 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4096 adapterNode = pNext;
4097 }
4098
4099 EXIT();
4100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304101 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102}
4103
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304104QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105 hdd_adapter_list_node_t **padapterNode)
4106{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304107 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004108 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304109 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4110 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004111 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004112 return status;
4113}
4114
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304115QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 hdd_adapter_list_node_t *adapterNode,
4117 hdd_adapter_list_node_t **pNextAdapterNode)
4118{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304119 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004120 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304121 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4122 (qdf_list_node_t *) adapterNode,
4123 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004125 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126 return status;
4127}
4128
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304129QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004130 hdd_adapter_list_node_t *adapterNode)
4131{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304132 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004133 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304134 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004136 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 return status;
4138}
4139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304140QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004141 hdd_adapter_list_node_t **padapterNode)
4142{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304143 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004144 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304145 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4146 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004147 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004148 return status;
4149}
4150
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304151QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152 hdd_adapter_list_node_t *adapterNode)
4153{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304154 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004155 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304156 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4157 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004158 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159 return status;
4160}
4161
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304162QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 hdd_adapter_list_node_t *adapterNode)
4164{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304165 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004166 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304167 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4168 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004169 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 return status;
4171}
4172
4173hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4174 tSirMacAddr macAddr)
4175{
4176 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4177 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304178 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004179
4180 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4181
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304182 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 adapter = adapterNode->pAdapter;
4184
4185 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304186 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 macAddr, sizeof(tSirMacAddr))) {
4188 return adapter;
4189 }
4190 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4191 adapterNode = pNext;
4192 }
4193
4194 return NULL;
4195
4196}
4197
4198hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4199 uint32_t vdev_id)
4200{
4201 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4202 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304203 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304205 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004206
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304207 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004208 adapter = adapterNode->pAdapter;
4209
4210 if (adapter->sessionId == vdev_id)
4211 return adapter;
4212
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304213 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004214 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4215 adapterNode = pNext;
4216 }
4217
Jeff Johnson5880d792016-08-15 13:32:30 -07004218 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219
4220 return NULL;
4221}
4222
Abhishek Singh7996eb72015-12-30 17:24:02 +05304223/**
4224 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4225 * the sessionid
4226 * @hdd_ctx: hdd context.
4227 * @sme_session_id: sme session is for the adapter to get.
4228 *
4229 * This function is used to get the adapter with provided session id
4230 *
4231 * Return: adapter pointer if found
4232 *
4233 */
4234hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4235 uint32_t sme_session_id)
4236{
4237 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4238 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304239 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304240
4241
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304242 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304243
4244 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304245 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304246 adapter = adapter_node->pAdapter;
4247
4248 if (adapter &&
4249 adapter->sessionId == sme_session_id)
4250 return adapter;
4251
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304252 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304253 hdd_get_next_adapter(hdd_ctx,
4254 adapter_node, &next);
4255 adapter_node = next;
4256 }
4257 return NULL;
4258}
4259
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004260/**
4261 * hdd_get_adapter() - to get adapter matching the mode
4262 * @hdd_ctx: hdd context
4263 * @mode: adapter mode
4264 *
4265 * This routine will return the pointer to adapter matching
4266 * with the passed mode.
4267 *
4268 * Return: pointer to adapter or null
4269 */
4270hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4271 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272{
4273 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4274 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304275 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276
4277 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4278
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304279 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 adapter = adapterNode->pAdapter;
4281
4282 if (adapter && (mode == adapter->device_mode))
4283 return adapter;
4284
4285 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4286 adapterNode = pNext;
4287 }
4288
4289 return NULL;
4290
4291}
4292
4293/**
4294 * hdd_get_operating_channel() - return operating channel of the device mode
4295 * @hdd_ctx: Pointer to the HDD context.
4296 * @mode: Device mode for which operating channel is required.
4297 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004298 * QDF_STA_MODE,
4299 * QDF_P2P_CLIENT_MODE,
4300 * QDF_SAP_MODE,
4301 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302 *
4303 * This API returns the operating channel of the requested device mode
4304 *
4305 * Return: channel number. "0" id the requested device is not found OR it is
4306 * not connected.
4307 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004308uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4309 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310{
4311 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304312 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 hdd_adapter_t *adapter;
4314 uint8_t operatingChannel = 0;
4315
4316 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4317
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304318 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004319 adapter = adapterNode->pAdapter;
4320
4321 if (mode == adapter->device_mode) {
4322 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004323 case QDF_STA_MODE:
4324 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 if (hdd_conn_is_connected
4326 (WLAN_HDD_GET_STATION_CTX_PTR
4327 (adapter))) {
4328 operatingChannel =
4329 (WLAN_HDD_GET_STATION_CTX_PTR
4330 (adapter))->conn_info.
4331 operationChannel;
4332 }
4333 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004334 case QDF_SAP_MODE:
4335 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 /* softap connection info */
4337 if (test_bit
4338 (SOFTAP_BSS_STARTED,
4339 &adapter->event_flags))
4340 operatingChannel =
4341 (WLAN_HDD_GET_AP_CTX_PTR
4342 (adapter))->operatingChannel;
4343 break;
4344 default:
4345 break;
4346 }
4347
4348 break; /* Found the device of interest. break the loop */
4349 }
4350
4351 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4352 adapterNode = pNext;
4353 }
4354 return operatingChannel;
4355}
4356
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304357static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 hdd_ctx)
4359{
4360 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304361 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 hdd_adapter_t *adapter;
4363
4364 ENTER();
4365
4366 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4367
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304368 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004370 if ((adapter->device_mode == QDF_STA_MODE) ||
4371 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4372 (adapter->device_mode == QDF_IBSS_MODE) ||
4373 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4374 (adapter->device_mode == QDF_SAP_MODE) ||
4375 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376 wlan_hdd_cfg80211_deregister_frames(adapter);
4377 hdd_unregister_wext(adapter->dev);
4378 }
4379 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4380 adapterNode = pNext;
4381 }
4382
4383 EXIT();
4384
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304385 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386}
4387
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304388QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004389{
4390 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304391 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 hdd_adapter_t *adapter;
4393
4394 ENTER();
4395
4396 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4397
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304398 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004399 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004400 if ((adapter->device_mode == QDF_STA_MODE) ||
4401 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4402 (adapter->device_mode == QDF_IBSS_MODE) ||
4403 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4404 (adapter->device_mode == QDF_SAP_MODE) ||
4405 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4407 eCSR_SCAN_ABORT_DEFAULT);
4408 }
4409 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4410 adapterNode = pNext;
4411 }
4412
4413 EXIT();
4414
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304415 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004416}
4417
Dustin Brownf27bce82016-11-03 12:52:27 -07004418/**
4419 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4420 * adapters
4421 * @hdd_ctx: The HDD context containing the adapters to operate on
4422 *
4423 * return: QDF_STATUS_SUCCESS
4424 */
4425static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4426{
4427 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4428 QDF_STATUS status;
4429 hdd_adapter_t *adapter;
4430 int err;
4431
4432 ENTER();
4433
4434 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4435
4436 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4437 adapter = adapter_node->pAdapter;
4438 if ((adapter->device_mode == QDF_STA_MODE) ||
4439 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4440 (adapter->device_mode == QDF_IBSS_MODE) ||
4441 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4442 (adapter->device_mode == QDF_SAP_MODE) ||
4443 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4444 err = wlan_hdd_sched_scan_stop(adapter->dev);
4445 if (err)
4446 hdd_err("Unable to stop scheduled scan");
4447 }
4448 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node);
4449 adapter_node = next_node;
4450 }
4451
4452 EXIT();
4453
4454 return QDF_STATUS_SUCCESS;
4455}
4456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457#ifdef WLAN_NS_OFFLOAD
4458/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004459 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460 * @hdd_ctx: Pointer to hdd context
4461 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004462 * Unregister for IPv6 address change notifications.
4463 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004464 * Return: None
4465 */
4466static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4467{
4468 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4469
4470 return;
4471}
4472
4473/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004474 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004475 * @hdd_ctx: Pointer to hdd context
4476 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004477 * Register for IPv6 address change notifications.
4478 *
4479 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004481static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482{
4483 int ret;
4484
4485 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4486 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004487 if (ret) {
4488 hdd_err("Failed to register IPv6 notifier: %d", ret);
4489 goto out;
4490 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004492 hdd_info("Registered IPv6 notifier");
4493out:
4494 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495}
4496#else
4497/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004498 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 * @hdd_ctx: Pointer to hdd context
4500 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004501 * Unregister for IPv6 address change notifications.
4502 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 * Return: None
4504 */
4505static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4506{
4507}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004510 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004511 * @hdd_ctx: Pointer to hdd context
4512 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004513 * Register for IPv6 address change notifications.
4514 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004515 * Return: None
4516 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004517static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004518{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004519 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004520}
4521#endif
4522
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304523#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4524/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004525 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304526 * @hdd_ctx: HDD context
4527 *
4528 * Activates the logging service
4529 *
4530 * Return: Zero in case of success, negative value otherwise
4531 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004532static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304533{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004534 int ret;
4535 struct hdd_config *config = hdd_ctx->config;
4536
4537 if (!config->wlanLoggingEnable)
4538 return 0;
4539
4540 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4541 config->wlanLoggingNumBuf);
4542 if (ret)
4543 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4544 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304545}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004546
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304547/**
4548 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4549 * @hdd_ctx: HDD context
4550 *
4551 * Deactivates the logging service
4552 *
4553 * Return: 0 on deactivating the logging service
4554 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004555static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304556{
4557 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4558 return wlan_logging_sock_deactivate_svc();
4559
4560 return 0;
4561}
4562#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004563static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304564{
4565 return 0;
4566}
4567
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004568static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304569{
4570 return 0;
4571}
4572#endif
4573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004575 * hdd_register_notifiers - Register netdev notifiers.
4576 * @hdd_ctx: HDD context
4577 *
4578 * Register netdev notifiers like IPv4 and IPv6.
4579 *
4580 * Return: 0 on success and errno on failure
4581 */
4582static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4583{
4584 int ret;
4585
4586 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4587 if (ret) {
4588 hdd_err("register_netdevice_notifier failed: %d", ret);
4589 goto out;
4590 }
4591
4592 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4593 if (ret)
4594 goto unregister_notifier;
4595
4596 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4597 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4598 if (ret) {
4599 hdd_err("Failed to register IPv4 notifier: %d", ret);
4600 goto unregister_ip6_notifier;
4601 }
4602
4603 return 0;
4604
4605unregister_ip6_notifier:
4606 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4607unregister_notifier:
4608 unregister_netdevice_notifier(&hdd_netdev_notifier);
4609out:
4610 return ret;
4611
4612}
4613
4614/**
4615 * hdd_unregister_notifiers - Unregister netdev notifiers.
4616 * @hdd_ctx: HDD context
4617 *
4618 * Unregister netdev notifiers like IPv4 and IPv6.
4619 *
4620 * Return: None.
4621 */
4622static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4623{
4624 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4625
4626 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4627
4628 unregister_netdevice_notifier(&hdd_netdev_notifier);
4629}
4630
4631/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004632 * hdd_exit_netlink_services - Exit netlink services
4633 * @hdd_ctx: HDD context
4634 *
4635 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4636 * nl service.
4637 *
4638 * Return: None.
4639 */
4640static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4641{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004642 hdd_close_cesium_nl_sock();
4643
4644 ptt_sock_deactivate_svc();
4645
4646 nl_srv_exit();
4647}
4648
4649/**
4650 * hdd_init_netlink_services- Init netlink services
4651 * @hdd_ctx: HDD context
4652 *
4653 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4654 * nl service.
4655 *
4656 * Return: 0 on success and errno on failure.
4657 */
4658static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4659{
4660 int ret;
4661
Ryan Hsuceddceb2016-04-28 10:20:14 -07004662 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004663 if (ret) {
4664 hdd_alert("nl_srv_init failed: %d", ret);
4665 goto out;
4666 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004667 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004668
4669 ret = oem_activate_service(hdd_ctx);
4670 if (ret) {
4671 hdd_alert("oem_activate_service failed: %d", ret);
4672 goto err_nl_srv;
4673 }
4674
4675 ret = ptt_sock_activate_svc();
4676 if (ret) {
4677 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4678 goto err_nl_srv;
4679 }
4680
4681 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004682 if (ret)
4683 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004684
4685 ret = cnss_diag_activate_service();
4686 if (ret) {
4687 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4688 goto err_close_cesium;
4689 }
4690
4691 return 0;
4692
4693err_close_cesium:
4694 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004695 ptt_sock_deactivate_svc();
4696err_nl_srv:
4697 nl_srv_exit();
4698out:
4699 return ret;
4700}
4701
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004702/**
4703 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4704 * @hdd_ctx: HDD context.
4705 *
4706 * Destroy RX wakelock.
4707 *
4708 * Return: None.
4709 */
4710static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4711{
4712 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4713}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004714
4715/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004716 * hdd_rx_wake_lock_create() - Create RX wakelock
4717 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004718 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004719 * Create RX wakelock.
4720 *
4721 * Return: None.
4722 */
4723static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4724{
4725 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4726}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004727
4728/**
4729 * hdd_roc_context_init() - Init ROC context
4730 * @hdd_ctx: HDD context.
4731 *
4732 * Initialize ROC context.
4733 *
4734 * Return: 0 on success and errno on failure.
4735 */
4736static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4737{
4738 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4739 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4740
4741 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4742
4743 return 0;
4744}
4745
4746/**
4747 * hdd_roc_context_destroy() - Destroy ROC context
4748 * @hdd_ctx: HDD context.
4749 *
4750 * Destroy roc list and flush the pending roc work.
4751 *
4752 * Return: None.
4753 */
4754static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4755{
4756 flush_delayed_work(&hdd_ctx->roc_req_work);
4757 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4758}
4759
4760/**
Houston Hoffman160db392016-10-10 17:37:51 -07004761 * hdd_context_deinit() - Deinitialize HDD context
4762 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004763 *
Houston Hoffman160db392016-10-10 17:37:51 -07004764 * Deinitialize HDD context along with all the feature specific contexts but
4765 * do not free hdd context itself. Caller of this API is supposed to free
4766 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004767 *
Houston Hoffman160db392016-10-10 17:37:51 -07004768 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004769 */
Houston Hoffman160db392016-10-10 17:37:51 -07004770static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004771{
Houston Hoffman160db392016-10-10 17:37:51 -07004772 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004773
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004774 hdd_roc_context_destroy(hdd_ctx);
4775
4776 hdd_sap_context_destroy(hdd_ctx);
4777
4778 hdd_rx_wake_lock_destroy(hdd_ctx);
4779
4780 hdd_tdls_context_destroy(hdd_ctx);
4781
4782 hdd_scan_context_destroy(hdd_ctx);
4783
4784 qdf_list_destroy(&hdd_ctx->hddAdapters);
4785
Houston Hoffman160db392016-10-10 17:37:51 -07004786 return 0;
4787}
4788
4789/**
4790 * hdd_context_destroy() - Destroy HDD context
4791 * @hdd_ctx: HDD context to be destroyed.
4792 *
4793 * Free config and HDD context as well as destroy all the resources.
4794 *
4795 * Return: None
4796 */
4797static void hdd_context_destroy(hdd_context_t *hdd_ctx)
4798{
4799 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
4800 hdd_logging_sock_deactivate_svc(hdd_ctx);
4801
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05304802 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
4803
Houston Hoffman160db392016-10-10 17:37:51 -07004804 hdd_context_deinit(hdd_ctx);
4805
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304806 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004807 hdd_ctx->config = NULL;
4808
4809 wiphy_free(hdd_ctx->wiphy);
4810}
4811
4812/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004813 * hdd_wlan_exit() - HDD WLAN exit function
4814 * @hdd_ctx: Pointer to the HDD Context
4815 *
4816 * This is the driver exit point (invoked during rmmod)
4817 *
4818 * Return: None
4819 */
Jeff Johnson590e2012016-10-05 16:16:24 -07004820static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821{
4822 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304823 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304825 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826
4827 ENTER();
4828
Arun Khandavallifae92942016-08-01 13:31:08 +05304829 if (QDF_TIMER_STATE_RUNNING ==
4830 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4831 hdd_info("Stpp interface change timer");
4832 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833 }
4834
Arun Khandavallifae92942016-08-01 13:31:08 +05304835 if (!QDF_IS_STATUS_SUCCESS
4836 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4837 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004838
Arun Khandavallifae92942016-08-01 13:31:08 +05304839
4840 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004841
Nitesh Shah61c10d92016-10-19 19:29:15 +05304842 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
4843
Prashanth Bhattaab004382016-10-11 16:08:11 -07004844 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004845
4846#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304847 if (QDF_TIMER_STATE_RUNNING ==
4848 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4849 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004850 }
4851
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304852 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304853 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004854 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004855 }
Liangwei Dongaef84342016-10-21 05:28:00 -04004856 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4857 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4858 hdd_ctx->last_acs_channel_list = NULL;
4859 hdd_ctx->num_of_channels = 0;
4860 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862
Arun Khandavallifae92942016-08-01 13:31:08 +05304863 mutex_lock(&hdd_ctx->iface_change_lock);
4864 driver_status = hdd_ctx->driver_status;
4865 mutex_unlock(&hdd_ctx->iface_change_lock);
4866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 /*
4868 * Powersave Offload Case
4869 * Disable Idle Power Save Mode
4870 */
4871 hdd_set_idle_ps_config(hdd_ctx, false);
4872
Arun Khandavallifae92942016-08-01 13:31:08 +05304873 if (driver_status != DRIVER_MODULES_CLOSED) {
4874 hdd_unregister_wext_all_adapters(hdd_ctx);
4875 /*
4876 * Cancel any outstanding scan requests. We are about to close
4877 * all of our adapters, but an adapter structure is what SME
4878 * passes back to our callback function. Hence if there
4879 * are any outstanding scan requests then there is a
4880 * race condition between when the adapter is closed and
4881 * when the callback is invoked. We try to resolve that
4882 * race condition here by canceling any outstanding scans
4883 * before we close the adapters.
4884 * Note that the scans may be cancelled in an asynchronous
4885 * manner, so ideally there needs to be some kind of
4886 * synchronization. Rather than introduce a new
4887 * synchronization here, we will utilize the fact that we are
4888 * about to Request Full Power, and since that is synchronized,
4889 * the expectation is that by the time Request Full Power has
4890 * completed, all scans will be cancelled
4891 */
4892 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07004893 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05304894 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 }
4896
4897 /*
4898 * Close the scheduler before calling cds_close to make sure no thread
4899 * is scheduled after the each module close is called i.e after all the
4900 * data structures are freed.
4901 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304902 qdf_status = cds_sched_close(p_cds_context);
4903 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004904 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304905 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05304908 hdd_wlan_stop_modules(hdd_ctx);
4909
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304910 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4911 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4912 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4913
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 /*
4915 * Close CDS
4916 * This frees pMac(HAL) context. There should not be any call
4917 * that requires pMac access after this.
4918 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004919
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07004920 hdd_green_ap_deinit(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921
Komal Seelam8634b772016-09-29 12:12:24 +05304922 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004923 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924
4925 hdd_ipa_cleanup(hdd_ctx);
4926
4927 /* Free up RoC request queue and flush workqueue */
4928 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304930 wlansap_global_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304932 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004933
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07004934 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004935
Arun Khandavallifae92942016-08-01 13:31:08 +05304936 hdd_exit_netlink_services(hdd_ctx);
4937 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004938 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939}
4940
4941void __hdd_wlan_exit(void)
4942{
4943 hdd_context_t *hdd_ctx;
4944
4945 ENTER();
4946
Anurag Chouhan6d760662016-02-20 16:05:43 +05304947 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004949 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004950 EXIT();
4951 return;
4952 }
4953
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004954 /* Check IPA HW Pipe shutdown */
4955 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4956
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004957 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05304958 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004959
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004960 /* Do all the cleanup before deregistering the driver */
4961 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004962
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004963 EXIT();
4964}
4965
4966#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04004967/**
4968 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
4969 * @data: pointer to hdd_context_t
4970 *
4971 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
4972 * Then new ACS request will do a fresh scan without reusing the cached
4973 * scan information.
4974 *
4975 * Return: void
4976 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004977void hdd_skip_acs_scan_timer_handler(void *data)
4978{
4979 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4980
Jeff Johnson760350b2016-08-15 14:01:52 -07004981 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004982 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04004983 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4984 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4985 hdd_ctx->last_acs_channel_list = NULL;
4986 hdd_ctx->num_of_channels = 0;
4987 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004988
4989 if (!hdd_ctx->hHal)
4990 return;
4991 sme_scan_flush_result(hdd_ctx->hHal);
4992}
4993#endif
4994
4995#ifdef QCA_HT_2040_COEX
4996/**
4997 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4998 * @adapter: pointer to adapter
4999 * @staId: station id
5000 * @macAddrSTA: station MAC address
5001 * @channel_type: channel type
5002 *
5003 * This function notifies FW with HT20/HT40 mode
5004 *
5005 * Return: 0 if successful, error number otherwise
5006 */
5007int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305008 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009{
5010 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305011 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012 hdd_context_t *hdd_ctx = NULL;
5013
5014 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5015
5016 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305017 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020 if (!hdd_ctx->hHal)
5021 return -EINVAL;
5022
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305023 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305025 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005026 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 return -EINVAL;
5028 }
5029
5030 return 0;
5031}
5032#endif
5033
5034/**
5035 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5036 * @state: state
5037 *
5038 * This function notifies FW with modem power status
5039 *
5040 * Return: 0 if successful, error number otherwise
5041 */
5042int hdd_wlan_notify_modem_power_state(int state)
5043{
5044 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305045 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005046 hdd_context_t *hdd_ctx;
5047
Anurag Chouhan6d760662016-02-20 16:05:43 +05305048 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005049 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305050 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005051 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305052
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053 if (!hdd_ctx->hHal)
5054 return -EINVAL;
5055
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305056 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5057 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005058 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 state);
5060 return -EINVAL;
5061 }
5062 return 0;
5063}
5064
5065/**
5066 *
5067 * hdd_post_cds_enable_config() - HDD post cds start config helper
5068 * @adapter - Pointer to the HDD
5069 *
5070 * Return: None
5071 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305072QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005073{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305074 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005075
5076 /*
5077 * Send ready indication to the HDD. This will kick off the MAC
5078 * into a 'running' state and should kick off an initial scan.
5079 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305080 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5081 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005082 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5083 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305084 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005085 }
5086
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305087 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005088}
5089
5090/* wake lock APIs for HDD */
5091void hdd_prevent_suspend(uint32_t reason)
5092{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305093 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005094}
5095
5096void hdd_allow_suspend(uint32_t reason)
5097{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305098 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099}
5100
5101void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5102{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305103 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5104 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005105}
5106
5107/**
5108 * hdd_exchange_version_and_caps() - exchange version and capability with target
5109 * @hdd_ctx: Pointer to HDD context
5110 *
5111 * This is the HDD function to exchange version and capability information
5112 * between Host and Target
5113 *
5114 * This function gets reported version of FW.
5115 * It also finds the version of target headers used to compile the host;
5116 * It compares the above two and prints a warning if they are different;
5117 * It gets the SW and HW version string;
5118 * Finally, it exchanges capabilities between host and target i.e. host
5119 * and target exchange a msg indicating the features they support through a
5120 * bitmap
5121 *
5122 * Return: None
5123 */
5124void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5125{
5126
5127 tSirVersionType versionCompiled;
5128 tSirVersionType versionReported;
5129 tSirVersionString versionString;
5130 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305131 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005132
5133 memset(&versionCompiled, 0, sizeof(versionCompiled));
5134 memset(&versionReported, 0, sizeof(versionReported));
5135
5136 /* retrieve and display WCNSS version information */
5137 do {
5138
5139 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5140 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305141 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005142 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143 break;
5144 }
5145
5146 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5147 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305148 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005149 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 break;
5151 }
5152
5153 if ((versionCompiled.major != versionReported.major) ||
5154 (versionCompiled.minor != versionReported.minor) ||
5155 (versionCompiled.version != versionReported.version) ||
5156 (versionCompiled.revision != versionReported.revision)) {
5157 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5158 "Host expected %u.%u.%u.%u\n",
5159 WLAN_MODULE_NAME,
5160 (int)versionReported.major,
5161 (int)versionReported.minor,
5162 (int)versionReported.version,
5163 (int)versionReported.revision,
5164 (int)versionCompiled.major,
5165 (int)versionCompiled.minor,
5166 (int)versionCompiled.version,
5167 (int)versionCompiled.revision);
5168 } else {
5169 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5170 WLAN_MODULE_NAME,
5171 (int)versionReported.major,
5172 (int)versionReported.minor,
5173 (int)versionReported.version,
5174 (int)versionReported.revision);
5175 }
5176
5177 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5178 versionString,
5179 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305180 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005181 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005182 break;
5183 }
5184
5185 pr_info("%s: WCNSS software version %s\n",
5186 WLAN_MODULE_NAME, versionString);
5187
5188 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5189 versionString,
5190 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305191 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005192 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005193 break;
5194 }
5195
5196 pr_info("%s: WCNSS hardware version %s\n",
5197 WLAN_MODULE_NAME, versionString);
5198
5199 /*
5200 * 1.Check if FW version is greater than 0.1.1.0. Only then
5201 * send host-FW capability exchange message
5202 * 2.Host-FW capability exchange message is only present on
5203 * target 1.1 so send the message only if it the target is 1.1
5204 * minor numbers for different target branches:
5205 * 0 -> (1.0)Mainline Build
5206 * 1 -> (1.1)Mainline Build
5207 * 2->(1.04) Stability Build
5208 */
5209 if (((versionReported.major > 0) || (versionReported.minor > 1)
5210 || ((versionReported.minor >= 1)
5211 && (versionReported.version >= 1)))
5212 && ((versionReported.major == 1)
5213 && (versionReported.minor >= 1)))
5214 fwFeatCapsMsgSupported = 1;
5215
5216 if (fwFeatCapsMsgSupported) {
5217 /*
5218 * Indicate if IBSS heartbeat monitoring needs to be
5219 * offloaded
5220 */
5221 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5222 sme_disable_feature_capablity
5223 (IBSS_HEARTBEAT_OFFLOAD);
5224 }
5225
5226 sme_feature_caps_exchange(hdd_ctx->hHal);
5227 }
5228
5229 } while (0);
5230
5231}
5232
5233/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305234QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235{
5236 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5237 hdd_ctx->reg.cc_src);
5238}
5239
5240/**
5241 * hdd_is_5g_supported() - check if hardware supports 5GHz
5242 * @hdd_ctx: Pointer to the hdd context
5243 *
5244 * HDD function to know if hardware supports 5GHz
5245 *
5246 * Return: true if hardware supports 5GHz
5247 */
5248bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5249{
zdingf54169a2016-10-12 17:08:45 +08005250 if (!hdd_ctx || !hdd_ctx->config)
5251 return true;
5252
5253 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5254 return true;
5255 else
5256 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257}
5258
Amar Singhale4f28ee2015-10-21 14:36:56 -07005259static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260{
5261 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005262 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263
5264 wiphy = hdd_ctx->wiphy;
5265
5266 /*
5267 * The channel information in
5268 * wiphy needs to be initialized before wiphy registration
5269 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005270 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5271 if (ret_val) {
5272 hdd_alert("regulatory init failed");
5273 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005274 }
5275
5276#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5277 wiphy->wowlan = &wowlan_support_reg_init;
5278#else
5279 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5280 WIPHY_WOWLAN_MAGIC_PKT |
5281 WIPHY_WOWLAN_DISCONNECT |
5282 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5283 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5284 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5285 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5286 WIPHY_WOWLAN_RFKILL_RELEASE;
5287
5288 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5289 WOW_MAX_FILTERS_PER_LIST);
5290 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5291 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5292#endif
5293
5294 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005295 ret_val = wlan_hdd_cfg80211_register(wiphy);
5296 if (0 > ret_val)
5297 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005298
Amar Singhale4f28ee2015-10-21 14:36:56 -07005299 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300}
5301
Ravi Joshie2331e82015-07-01 18:18:54 -07005302/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005303 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005304 * @hdd_ctx - handle to hdd context
5305 * @tx_packets - transmit packet count
5306 * @rx_packets - receive packet count
5307 *
5308 * The function controls the bus bandwidth and dynamic control of
5309 * tcp delayed ack configuration
5310 *
5311 * Returns: None
5312 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005314static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5315 const uint64_t tx_packets,
5316 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005318 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005319 uint64_t temp_rx = 0;
5320 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005321 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005322 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5323 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005324 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005326 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005327 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005329 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005330 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005331 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005332 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005333 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334
Mohit Khannae71e2262015-11-10 09:37:24 -08005335 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5336 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005337
5338 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005339 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5340 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005342 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305343 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305344 if (hdd_ctx->hbw_requested) {
5345 pld_remove_pm_qos(hdd_ctx->parent_dev);
5346 hdd_ctx->hbw_requested = false;
5347 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305348 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005349 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305350 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305351 if (!hdd_ctx->hbw_requested) {
5352 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5353 hdd_ctx->hbw_requested = true;
5354 }
5355
Nirav Shah3bbfa512016-05-12 16:43:49 +05305356 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005357 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305358 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005359 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005360 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005361
5362 /* fine-tuning parameters for RX Flows */
5363 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005365 hdd_ctx->prev_rx = rx_packets;
Ravi Joshifed83572016-10-07 16:20:37 -07005366 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5367 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5368 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5369 next_rx_level = WLAN_SVC_TP_HIGH;
5370 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005371 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005372 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005373 hdd_ctx->rx_high_ind_cnt = 0;
5374 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375
Mohit Khannae71e2262015-11-10 09:37:24 -08005376 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5377 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378
5379 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005380 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381 next_rx_level, temp_rx);
5382 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005383 /* Send throughput indication only if it is enabled.
5384 * Disabling tcp_del_ack will revert the tcp stack behavior
5385 * to default delayed ack. Note that this will disable the
5386 * dynamic delayed ack mechanism across the system
5387 */
5388 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305389 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5390 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391 &next_rx_level,
5392 sizeof(next_rx_level));
5393 }
5394
Mohit Khannae71e2262015-11-10 09:37:24 -08005395 /* fine-tuning parameters for TX Flows */
5396 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5397 hdd_ctx->prev_tx = tx_packets;
5398 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5399 next_tx_level = WLAN_SVC_TP_HIGH;
5400 else
5401 next_tx_level = WLAN_SVC_TP_LOW;
5402
5403 if (hdd_ctx->cur_tx_level != next_tx_level) {
5404 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5405 next_tx_level, temp_tx);
5406 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305407 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5408 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005409 &next_tx_level,
5410 sizeof(next_tx_level));
5411 }
5412
5413 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5414 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 hdd_ctx->hdd_txrx_hist_idx++;
5416 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417}
5418
5419#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
5420static void hdd_bus_bw_compute_cbk(void *priv)
5421{
5422 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
5423 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305424 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305425 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5426 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427 uint64_t total_tx = 0, total_rx = 0;
5428 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305429 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305430 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 bool connected = false;
5432 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5433
Prashanth Bhattaab004382016-10-11 16:08:11 -07005434 if (wlan_hdd_validate_context(hdd_ctx))
5435 return;
5436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305438 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 status =
5440 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5441
5442 if (adapterNode->pAdapter == NULL)
5443 continue;
5444 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305445 /*
5446 * Validate magic so we don't end up accessing
5447 * an invalid adapter.
5448 */
5449 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5450 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005451
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005452 if ((adapter->device_mode == QDF_STA_MODE ||
5453 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5455 != eConnectionState_Associated) {
5456
5457 continue;
5458 }
5459
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005460 if ((adapter->device_mode == QDF_SAP_MODE ||
5461 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005462 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5463
5464 continue;
5465 }
5466
5467 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5468 adapter->prev_tx_packets);
5469 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5470 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305471
5472 if (adapter->device_mode == QDF_SAP_MODE ||
5473 adapter->device_mode == QDF_P2P_GO_MODE ||
5474 adapter->device_mode == QDF_IBSS_MODE) {
5475
5476 ret = ol_get_intra_bss_fwd_pkts_count(
5477 adapter->sessionId,
5478 &fwd_tx_packets, &fwd_rx_packets);
5479 if (ret == A_OK) {
5480 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5481 fwd_tx_packets,
5482 adapter->prev_fwd_tx_packets);
5483 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5484 fwd_tx_packets,
5485 adapter->prev_fwd_rx_packets);
5486 }
5487 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488
5489 total_rx += adapter->stats.rx_packets;
5490 total_tx += adapter->stats.tx_packets;
5491
5492 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5493 adapter->prev_tx_packets = adapter->stats.tx_packets;
5494 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305495 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5496 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5498 connected = true;
5499 }
5500
5501 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5502 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5503 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5504 rx_packets;
5505 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5506 tx_packets;
5507
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305508 /* add intra bss forwarded tx and rx packets */
5509 tx_packets += fwd_tx_packets_diff;
5510 rx_packets += fwd_rx_packets_diff;
5511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005512 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5513 tx_packets += (uint64_t)ipa_tx_packets;
5514 rx_packets += (uint64_t)ipa_rx_packets;
5515
5516 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005517 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 return;
5519 }
5520
Yuanyuan Liu13738502016-04-06 17:41:37 -07005521 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522
5523 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5524 hdd_ipa_uc_stat_request(adapter, 2);
5525
Anurag Chouhan210db072016-02-22 18:42:15 +05305526 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527 hdd_ctx->config->busBandwidthComputeInterval);
5528}
Prashanth Bhattaab004382016-10-11 16:08:11 -07005529
5530int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
5531{
5532 spin_lock_init(&hdd_ctx->bus_bw_lock);
5533
5534 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
5535 QDF_TIMER_TYPE_SW,
5536 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5537
5538 return 0;
5539}
5540
5541void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
5542{
5543 if (qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer) ==
5544 QDF_TIMER_STATE_RUNNING)
5545 hdd_reset_tcp_delack(hdd_ctx);
5546
5547 qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer);
5548}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549#endif
5550
5551/**
Nirav Shahed34b212016-04-25 10:59:16 +05305552 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5553 * @hdd_ctx: hdd context
5554 *
5555 * Return: 0 for success or error code
5556 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005557static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305558{
5559 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5560 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5561 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005562 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305563 return -ENOMEM;
5564 }
5565 return 0;
5566}
5567
5568/**
5569 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5570 * @hdd_ctx: hdd context
5571 *
5572 * Return: none
5573 */
5574void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5575{
5576 if (hdd_ctx->hdd_txrx_hist) {
5577 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5578 hdd_ctx->hdd_txrx_hist = NULL;
5579 }
5580}
5581
Nirav Shahda008342016-05-17 18:50:40 +05305582static uint8_t *convert_level_to_string(uint32_t level)
5583{
5584 switch (level) {
5585 /* initialize the wlan sub system */
5586 case WLAN_SVC_TP_NONE:
5587 return "NONE";
5588 case WLAN_SVC_TP_LOW:
5589 return "LOW";
5590 case WLAN_SVC_TP_MEDIUM:
5591 return "MED";
5592 case WLAN_SVC_TP_HIGH:
5593 return "HIGH";
5594 default:
5595 return "INVAL";
5596 }
5597}
5598
Nirav Shahed34b212016-04-25 10:59:16 +05305599
5600/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005601 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5602 * @hdd_ctx: hdd context
5603 *
5604 * Return: none
5605 */
5606void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5607{
5608 int i;
5609
5610#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005611 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305612 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005613 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614 hdd_ctx->config->busBandwidthHighThreshold,
5615 hdd_ctx->config->busBandwidthMediumThreshold,
5616 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005617 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305618 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005619 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005620 hdd_ctx->config->tcpDelackThresholdHigh,
5621 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005622 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305623 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624#endif
5625
Jeff Johnson760350b2016-08-15 14:01:52 -07005626 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305627 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5628
Jeff Johnson760350b2016-08-15 14:01:52 -07005629 hdd_err("index, total_rx, interval_rx, total_tx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630
5631 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005632 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005633 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5634 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5635 hdd_ctx->hdd_txrx_hist[i].total_tx,
5636 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305637 convert_level_to_string(
5638 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5639 convert_level_to_string(
5640 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5641 convert_level_to_string(
5642 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005643 }
5644 return;
5645}
5646
5647/**
5648 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5649 * @hdd_ctx: hdd context
5650 *
5651 * Return: none
5652 */
5653void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5654{
5655 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305656 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5657 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005658}
5659
5660/**
5661 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5662 * @pHddCtx: hdd context
5663 *
5664 * Return: none
5665 */
5666void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5667{
5668
5669 hdd_adapter_t *adapter = NULL;
5670 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305671 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305673 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005674
5675 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305676 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005677 adapter = adapter_node->pAdapter;
5678
Jeff Johnson760350b2016-08-15 14:01:52 -07005679 hdd_err("\nNetif queue operation statistics:");
5680 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305681 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005682 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305683 curr_time = qdf_system_ticks();
5684 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305685 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305686 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305687 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305688 unpause = adapter->total_unpause_time;
5689 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305690 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305691 pause = adapter->total_pause_time;
5692 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005693 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305694 qdf_system_ticks_to_msecs(total),
5695 qdf_system_ticks_to_msecs(pause),
5696 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005697 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005698
Nirav Shahda008342016-05-17 18:50:40 +05305699 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5700 qdf_time_t pause_delta = 0;
5701
5702 if (adapter->pause_map & (1 << i))
5703 pause_delta = delta;
5704
Jeff Johnson760350b2016-08-15 14:01:52 -07005705 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005706 hdd_reason_type_to_string(i),
5707 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305708 adapter->queue_oper_stats[i].unpause_count,
5709 qdf_system_ticks_to_msecs(
5710 adapter->queue_oper_stats[i].total_pause_time +
5711 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712 }
5713
Jeff Johnson760350b2016-08-15 14:01:52 -07005714 hdd_err("\nNetif queue operation history:");
5715 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305716 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5717
Jeff Johnson760350b2016-08-15 14:01:52 -07005718 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005719
5720 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005721 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305722 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723 adapter->queue_oper_history[i].time),
5724 hdd_action_type_to_string(
5725 adapter->queue_oper_history[i].netif_action),
5726 hdd_reason_type_to_string(
5727 adapter->queue_oper_history[i].netif_reason),
5728 adapter->queue_oper_history[i].pause_map);
5729 }
5730
5731 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5732 adapter_node = next;
5733 }
5734
5735
5736}
5737
5738/**
5739 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5740 * @hdd_ctx: hdd context
5741 *
5742 * Return: none
5743 */
5744void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5745{
5746 hdd_adapter_t *adapter = NULL;
5747 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305748 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005749
5750 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305751 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005752 adapter = adapter_node->pAdapter;
5753
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305754 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005755 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305756 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305758 adapter->history_index = 0;
5759 adapter->start_time = adapter->last_time = qdf_system_ticks();
5760 adapter->total_pause_time = 0;
5761 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5763 adapter_node = next;
5764 }
5765}
5766
5767/**
5768 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5769 * @halHandle: Hal handle
5770 * @pContext: Pointer to the context
5771 * @sessionId: Session ID
5772 * @scanId: Scan ID
5773 * @status: Status
5774 *
5775 * This is the callback to be executed when 11d scan is completed to flush out
5776 * the scan results
5777 *
5778 * 11d scan is done during driver load and is a passive scan on all
5779 * channels supported by the device, 11d scans may find some APs on
5780 * frequencies which are forbidden to be used in the regulatory domain
5781 * the device is operating in. If these APs are notified to the supplicant
5782 * it may try to connect to these APs, thus flush out all the scan results
5783 * which are present in SME after 11d scan is done.
5784 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305785 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005786 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305787static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788 uint8_t sessionId, uint32_t scanId,
5789 eCsrScanStatus status)
5790{
5791 ENTER();
5792
5793 sme_scan_flush_result(halHandle);
5794
5795 EXIT();
5796
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305797 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798}
5799
5800#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5801/**
5802 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5803 * @hdd_ctx: hdd global context
5804 *
5805 * Return: none
5806 */
5807static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5808{
5809 uint8_t i;
5810
5811 mutex_init(&hdd_ctx->op_ctx.op_lock);
5812 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5813 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5814 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5815 }
5816}
5817#else
5818static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5819{
5820}
5821#endif
5822
Yingying Tang95409972016-10-20 15:16:15 +08005823#ifdef WLAN_FEATURE_WOW_PULSE
5824/**
5825 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
5826 * @phddctx: hdd_context_t structure pointer
5827 * @enable: enable or disable this behaviour
5828 *
5829 * Return: int
5830 */
5831static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
5832{
5833 struct hdd_config *pcfg_ini = phddctx->config;
5834 struct wow_pulse_mode wow_pulse_set_info;
5835 QDF_STATUS status;
5836
5837 hdd_notice("wow pulse enable flag is %d", enable);
5838
5839 if (false == phddctx->config->wow_pulse_support)
5840 return 0;
5841
5842 /* prepare the request to send to SME */
5843 if (enable == true) {
5844 wow_pulse_set_info.wow_pulse_enable = true;
5845 wow_pulse_set_info.wow_pulse_pin =
5846 pcfg_ini->wow_pulse_pin;
5847 wow_pulse_set_info.wow_pulse_interval_low =
5848 pcfg_ini->wow_pulse_interval_low;
5849 wow_pulse_set_info.wow_pulse_interval_high =
5850 pcfg_ini->wow_pulse_interval_high;
5851 } else {
5852 wow_pulse_set_info.wow_pulse_enable = false;
5853 wow_pulse_set_info.wow_pulse_pin = 0;
5854 wow_pulse_set_info.wow_pulse_interval_low = 0;
5855 wow_pulse_set_info.wow_pulse_interval_high = 0;
5856 }
5857 hdd_notice("enable %d pin %d low %d high %d",
5858 wow_pulse_set_info.wow_pulse_enable,
5859 wow_pulse_set_info.wow_pulse_pin,
5860 wow_pulse_set_info.wow_pulse_interval_low,
5861 wow_pulse_set_info.wow_pulse_interval_high);
5862
5863 status = sme_set_wow_pulse(&wow_pulse_set_info);
5864 if (QDF_STATUS_E_FAILURE == status) {
5865 hdd_notice("sme_set_wow_pulse failure!");
5866 return -EIO;
5867 }
5868 hdd_notice("sme_set_wow_pulse success!");
5869 return 0;
5870}
5871#else
5872static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
5873{
5874 return 0;
5875}
5876#endif
5877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005878#ifdef WLAN_FEATURE_FASTPATH
5879/**
5880 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5881 * @hdd_cfg: hdd config
5882 * @context: lower layer context
5883 *
5884 * Return: none
5885 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305886void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005887 void *context)
5888{
5889 if (hdd_cfg->fastpath_enable)
5890 hif_enable_fastpath(context);
5891}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005892#endif
5893
Yuanyuan Liu13738502016-04-06 17:41:37 -07005894#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895/**
5896 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005897 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898 * @level: thermal level
5899 *
5900 * Change IPA data path to SW path when the thermal throttle level greater
5901 * than 0, and restore the original data path when throttle level is 0
5902 *
5903 * Return: none
5904 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005905static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005906{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005907 hdd_context_t *hdd_ctx = context;
5908
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909 /* Change IPA to SW path when throttle level greater than 0 */
5910 if (level > THROTTLE_LEVEL_0)
5911 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5912 else
5913 /* restore original concurrency mode */
5914 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5915}
5916
5917/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305918 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5919 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305920 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305922 * Get a safe channel to restart SAP. PCL already takes into account the
5923 * unsafe channels. So, the PCL is validated with the ACS range to provide
5924 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005925 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305926 * Return: Channel number to restart SAP in case of success. In case of any
5927 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305929static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5930 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305932 struct sir_pcl_list pcl;
5933 QDF_STATUS status;
5934 uint32_t i, j;
5935 tHalHandle *hal_handle;
5936 hdd_context_t *hdd_ctx;
5937 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005938
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305939 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5940 if (!hdd_ctx) {
5941 hdd_err("invalid HDD context");
5942 return INVALID_CHANNEL_ID;
5943 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005944
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305945 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5946 if (!hal_handle) {
5947 hdd_err("invalid HAL handle");
5948 return INVALID_CHANNEL_ID;
5949 }
5950
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305951 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5952 pcl.pcl_list, &pcl.pcl_len,
5953 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5954 if (QDF_IS_STATUS_ERROR(status)) {
5955 hdd_err("Get PCL failed");
5956 return INVALID_CHANNEL_ID;
5957 }
5958
5959 if (!pcl.pcl_len) {
5960 hdd_alert("pcl length is zero. this is not expected");
5961 return INVALID_CHANNEL_ID;
5962 }
5963
5964 hdd_info("start:%d end:%d",
5965 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5966 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5967
5968 /* PCL already takes unsafe channel into account */
5969 for (i = 0; i < pcl.pcl_len; i++) {
5970 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5971 if ((pcl.pcl_list[i] >=
5972 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5973 (pcl.pcl_list[i] <=
5974 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5975 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5976 return pcl.pcl_list[i];
5977 }
5978 }
5979
5980 hdd_info("no safe channel from PCL found in ACS range");
5981
5982 /* Try for safe channel from all valid channel */
5983 pcl.pcl_len = MAX_NUM_CHAN;
5984 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5985 &pcl.pcl_len);
5986 if (QDF_IS_STATUS_ERROR(status)) {
5987 hdd_err("error in getting valid channel list");
5988 return INVALID_CHANNEL_ID;
5989 }
5990
5991 for (i = 0; i < pcl.pcl_len; i++) {
5992 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5993 found = false;
5994 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07005995 if (pcl.pcl_list[i] ==
5996 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305997 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5998 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005999 break;
6000 }
6001 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306002
6003 if (found)
6004 continue;
6005
6006 if ((pcl.pcl_list[i] >=
6007 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6008 (pcl.pcl_list[i] <=
6009 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6010 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
6011 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012 }
6013 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306014
6015 return INVALID_CHANNEL_ID;
6016}
6017
6018/**
6019 * hdd_restart_sap() - Restarts SAP on the given channel
6020 * @adapter: AP adapter
6021 * @channel: Channel
6022 *
6023 * Restarts the SAP interface by invoking the function which executes the
6024 * callback to perform channel switch using (E)CSA.
6025 *
6026 * Return: None
6027 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006028static void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306029{
6030 hdd_ap_ctx_t *hdd_ap_ctx;
6031 tHalHandle *hal_handle;
6032
6033 if (!adapter) {
6034 hdd_err("invalid adapter");
6035 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006036 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306037
6038 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6039
6040 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6041 if (!hal_handle) {
6042 hdd_err("invalid HAL handle");
6043 return;
6044 }
6045
6046 hdd_ap_ctx->sapConfig.channel = channel;
6047 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6048 hdd_ap_ctx->sapConfig.ch_width_orig;
6049
6050 hdd_info("chan:%d width:%d",
6051 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6052
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006053 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306054 hdd_ap_ctx->sapConfig.sec_ch,
6055 &hdd_ap_ctx->sapConfig.ch_params);
6056
6057 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058}
Agrawal Ashish467dde42016-09-08 18:44:22 +05306059/**
6060 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6061 * @hdd_ctx: hdd context pointer
6062 *
6063 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6064 * and if ACS is enabled, driver will ask userspace to restart the
6065 * sap. User space on LTE coex indication restart driver.
6066 *
6067 * Return - none
6068 */
6069void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6070{
6071 QDF_STATUS status;
6072 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6073 hdd_adapter_t *adapter_temp;
6074 uint32_t i;
6075 bool found = false;
6076 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006077
Agrawal Ashish467dde42016-09-08 18:44:22 +05306078 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6079 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6080 adapter_temp = adapter_node->pAdapter;
6081
6082 if (!adapter_temp) {
6083 hdd_err("adapter is NULL, moving to next one");
6084 goto next_adapater;
6085 }
6086
6087 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6088 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
6089 hdd_info("skip device mode:%d acs:%d",
6090 adapter_temp->device_mode,
6091 adapter_temp->sessionCtx.ap.sapConfig.
6092 acs_cfg.acs_mode);
6093 goto next_adapater;
6094 }
6095
6096 found = false;
6097 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006098 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306099 hdd_ctxt->unsafe_channel_list[i]) {
6100 found = true;
6101 hdd_info("operating ch:%d is unsafe",
6102 adapter_temp->sessionCtx.ap.operatingChannel);
6103 break;
6104 }
6105 }
6106
6107 if (!found) {
6108 hdd_info("ch:%d is safe. no need to change channel",
6109 adapter_temp->sessionCtx.ap.operatingChannel);
6110 goto next_adapater;
6111 }
6112
6113 restart_chan =
6114 hdd_get_safe_channel_from_pcl_and_acs_range(
6115 adapter_temp);
6116 if (!restart_chan) {
6117 hdd_alert("fail to restart SAP");
6118 } else {
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306119 /* SAP restart due to unsafe channel. While restarting
6120 * the SAP, make sure to clear acs_channel, channel to
6121 * reset to 0. Otherwise these settings will override
6122 * the ACS while restart.
6123 */
6124 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6125 adapter_temp->sessionCtx.ap.sapConfig.channel =
6126 AUTO_CHANNEL_SELECT;
Agrawal Ashish467dde42016-09-08 18:44:22 +05306127 hdd_info("sending coex indication");
6128 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6129 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6130 hdd_restart_sap(adapter_temp, restart_chan);
6131 }
6132
6133next_adapater:
6134 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6135 adapter_node = next;
6136 }
6137}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006138/**
6139 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6140 * @adapter: HDD adapter pointer
6141 * @indParam: Channel avoid notification parameter
6142 *
6143 * Avoid channel notification from FW handler.
6144 * FW will send un-safe channel list to avoid over wrapping.
6145 * hostapd should not use notified channel
6146 *
6147 * Return: None
6148 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306149void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006150{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006151 hdd_context_t *hdd_ctxt;
6152 tSirChAvoidIndType *ch_avoid_indi;
6153 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006154 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6155 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006156 uint16_t start_channel;
6157 uint16_t end_channel;
6158 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159 tHddAvoidFreqList hdd_avoid_freq_list;
6160 uint32_t i;
6161
6162 /* Basic sanity */
6163 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006164 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006165 return;
6166 }
6167
6168 hdd_ctxt = (hdd_context_t *) hdd_context;
6169 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6170 cds_context = hdd_ctxt->pcds_context;
6171
6172 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006173 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174 ch_avoid_indi->avoid_range_count);
6175
6176 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306177 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006178 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6179 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6180 ch_avoid_indi->avoid_freq_range[i].start_freq;
6181 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6182 ch_avoid_indi->avoid_freq_range[i].end_freq;
6183 }
6184 hdd_avoid_freq_list.avoidFreqRangeCount =
6185 ch_avoid_indi->avoid_range_count;
6186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006187 /* clear existing unsafe channel cache */
6188 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306189 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006190 sizeof(hdd_ctxt->unsafe_channel_list));
6191
6192 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6193 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006194 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006195 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006196 break;
6197 }
6198
6199 start_channel = ieee80211_frequency_to_channel(
6200 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6201 end_channel = ieee80211_frequency_to_channel(
6202 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006203 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006204 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6205 start_channel,
6206 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6207 end_channel);
6208
6209 /* do not process frequency bands that are not mapped to
6210 * predefined channels
6211 */
6212 if (start_channel == 0 || end_channel == 0)
6213 continue;
6214
Amar Singhalb8d4f152016-02-10 10:21:43 -08006215 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6216 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006217 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006218 ch_avoid_indi->avoid_freq_range[
6219 range_loop].start_freq) {
6220 start_channel_idx = channel_loop;
6221 break;
6222 }
6223 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006224 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6225 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006226 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006227 ch_avoid_indi->avoid_freq_range[
6228 range_loop].end_freq) {
6229 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006230 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006231 ch_avoid_indi->avoid_freq_range[
6232 range_loop].end_freq)
6233 end_channel_idx--;
6234 break;
6235 }
6236 }
6237
Amar Singhalb8d4f152016-02-10 10:21:43 -08006238 if (start_channel_idx == INVALID_CHANNEL ||
6239 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006240 continue;
6241
6242 for (channel_loop = start_channel_idx; channel_loop <=
6243 end_channel_idx; channel_loop++) {
6244 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006245 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006246 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006247 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006248 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006249 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006250 break;
6251 }
6252 }
6253 }
6254
Jeff Johnson34c88b72016-08-15 14:27:11 -07006255 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006256 hdd_ctxt->unsafe_channel_count);
6257
Yuanyuan Liu13738502016-04-06 17:41:37 -07006258 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6259 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006260 hdd_ctxt->unsafe_channel_count)) {
6261 hdd_err("Failed to set unsafe channel");
6262
6263 /* clear existing unsafe channel cache */
6264 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306265 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006266 sizeof(hdd_ctxt->unsafe_channel_list));
6267
6268 return;
6269 }
6270
6271 for (channel_loop = 0;
6272 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006273 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006274 hdd_ctxt->unsafe_channel_list[channel_loop]);
6275 }
6276
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306277 /*
6278 * first update the unsafe channel list to the platform driver and
6279 * send the avoid freq event to the application
6280 */
6281 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6282
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306283 if (!hdd_ctxt->unsafe_channel_count) {
6284 hdd_info("no unsafe channels - not restarting SAP");
6285 return;
6286 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306287 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006288 return;
6289}
6290
6291/**
6292 * hdd_init_channel_avoidance() - Initialize channel avoidance
6293 * @hdd_ctx: HDD global context
6294 *
6295 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006296 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006297 * down to the lower layers. Then subscribe to subsequent channel
6298 * avoidance events.
6299 *
6300 * Return: None
6301 */
6302static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6303{
6304 uint16_t unsafe_channel_count;
6305 int index;
6306
Yuanyuan Liu13738502016-04-06 17:41:37 -07006307 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6308 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006309 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006310 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006311
Jeff Johnson34c88b72016-08-15 14:27:11 -07006312 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006313 hdd_ctx->unsafe_channel_count);
6314
Anurag Chouhan6d760662016-02-20 16:05:43 +05306315 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006316 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006317
6318 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006319 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006320 hdd_ctx->unsafe_channel_list[index]);
6321
6322 }
6323
6324 /* Plug in avoid channel notification callback */
6325 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6326}
6327#else
6328static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6329{
6330}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006331static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006332{
6333}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006334#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006335
6336/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006337 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6338 * user space
6339 * @frame_ind: Management frame data to be informed.
6340 *
6341 * This function is used to indicate management frame to
6342 * user space
6343 *
6344 * Return: None
6345 *
6346 */
6347void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6348{
6349 hdd_context_t *hdd_ctx = NULL;
6350 hdd_adapter_t *adapter = NULL;
6351 void *cds_context = NULL;
6352 int i;
6353
6354 /* Get the global VOSS context.*/
6355 cds_context = cds_get_global_context();
6356 if (!cds_context) {
6357 hdd_err("Global CDS context is Null");
6358 return;
6359 }
6360 /* Get the HDD context.*/
6361 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6362
6363 if (0 != wlan_hdd_validate_context(hdd_ctx))
6364 return;
6365
6366 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6367 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6368 adapter =
6369 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6370 if (adapter)
6371 break;
6372 }
6373 } else {
6374 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6375 frame_ind->sessionId);
6376 }
6377
6378 if ((NULL != adapter) &&
6379 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6380 __hdd_indicate_mgmt_frame(adapter,
6381 frame_ind->frame_len,
6382 frame_ind->frameBuf,
6383 frame_ind->frameType,
6384 frame_ind->rxChan,
6385 frame_ind->rxRssi);
6386 return;
6387}
6388
6389/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006390 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6391 * @hdd_ctx: HDD context
6392 *
6393 * Disables all the dual mac features like DBS, Agile DFS etc.
6394 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306395 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006396 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306397static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006398{
6399 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306400 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006401
6402 if (!hdd_ctx) {
6403 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306404 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006405 }
6406
6407 cfg.scan_config = 0;
6408 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306409 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006410
6411 hdd_debug("Disabling all dual mac features...");
6412
6413 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306414 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006415 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6416 return status;
6417 }
6418
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306419 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006420}
6421
6422/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006423 * hdd_override_ini_config - Override INI config
6424 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006425 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006426 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006427 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006428 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006429 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006430static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006431{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006432
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006433 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6434 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6435 hdd_notice("Module enable_dfs_chan_scan set to %d",
6436 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006437 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006438 if (0 == enable_11d || 1 == enable_11d) {
6439 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6440 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006441 }
Leo Chang11545d62016-10-17 14:53:50 -07006442
6443 if (!hdd_ipa_is_present(hdd_ctx))
6444 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006445}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006446
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006447/**
6448 * hdd_set_trace_level_for_each - Set trace level for each INI config
6449 * @hdd_ctx - HDD context
6450 *
6451 * Set trace level for each module based on INI config.
6452 *
6453 * Return: None
6454 */
6455static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6456{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306457 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6458 hdd_ctx->config->qdf_trace_enable_wdi);
6459 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6460 hdd_ctx->config->qdf_trace_enable_hdd);
6461 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6462 hdd_ctx->config->qdf_trace_enable_sme);
6463 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6464 hdd_ctx->config->qdf_trace_enable_pe);
6465 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6466 hdd_ctx->config->qdf_trace_enable_wma);
6467 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6468 hdd_ctx->config->qdf_trace_enable_sys);
6469 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6470 hdd_ctx->config->qdf_trace_enable_qdf);
6471 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6472 hdd_ctx->config->qdf_trace_enable_sap);
6473 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6474 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6475 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6476 hdd_ctx->config->qdf_trace_enable_bmi);
6477 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6478 hdd_ctx->config->qdf_trace_enable_cfg);
6479 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6480 hdd_ctx->config->qdf_trace_enable_epping);
6481 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6482 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6483 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306484 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306485 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6486 hdd_ctx->config->qdf_trace_enable_htc);
6487 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6488 hdd_ctx->config->qdf_trace_enable_hif);
6489 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6490 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6491 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6492 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306493
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006494 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006495}
6496
6497/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006498 * hdd_context_init() - Initialize HDD context
6499 * @hdd_ctx: HDD context.
6500 *
6501 * Initialize HDD context along with all the feature specific contexts.
6502 *
6503 * return: 0 on success and errno on failure.
6504 */
6505static int hdd_context_init(hdd_context_t *hdd_ctx)
6506{
6507 int ret;
6508
6509 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6510 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6511
6512 hdd_init_ll_stats_ctx();
6513
6514 init_completion(&hdd_ctx->mc_sus_event_var);
6515 init_completion(&hdd_ctx->ready_to_suspend);
6516
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306517 hdd_init_bpf_completion();
6518
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006519 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306520 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006521 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306522
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006523 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6524
6525 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6526
6527 ret = hdd_scan_context_init(hdd_ctx);
6528 if (ret)
6529 goto list_destroy;
6530
6531 hdd_tdls_context_init(hdd_ctx);
6532
6533 hdd_rx_wake_lock_create(hdd_ctx);
6534
6535 ret = hdd_sap_context_init(hdd_ctx);
6536 if (ret)
6537 goto scan_destroy;
6538
6539 ret = hdd_roc_context_init(hdd_ctx);
6540 if (ret)
6541 goto sap_destroy;
6542
6543 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6544
6545 hdd_init_offloaded_packets_ctx(hdd_ctx);
6546
6547 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6548 hdd_ctx->config);
6549 if (ret)
6550 goto roc_destroy;
6551
6552 return 0;
6553
6554roc_destroy:
6555 hdd_roc_context_destroy(hdd_ctx);
6556
6557sap_destroy:
6558 hdd_sap_context_destroy(hdd_ctx);
6559
6560scan_destroy:
6561 hdd_scan_context_destroy(hdd_ctx);
6562 hdd_rx_wake_lock_destroy(hdd_ctx);
6563 hdd_tdls_context_destroy(hdd_ctx);
6564
6565list_destroy:
6566 qdf_list_destroy(&hdd_ctx->hddAdapters);
6567 return ret;
6568}
6569
6570/**
6571 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306572 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006573 *
6574 * Allocate and initialize HDD context. HDD context is allocated as part of
6575 * wiphy allocation and then context is initialized.
6576 *
6577 * Return: HDD context on success and ERR_PTR on failure
6578 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006579static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006580{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306581 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006582 int ret = 0;
6583 hdd_context_t *hdd_ctx;
6584 v_CONTEXT_t p_cds_context;
6585
6586 ENTER();
6587
6588 p_cds_context = cds_get_global_context();
6589 if (p_cds_context == NULL) {
6590 hdd_alert("Failed to get CDS global context");
6591 ret = -EINVAL;
6592 goto err_out;
6593 }
6594
6595 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6596
6597 if (hdd_ctx == NULL) {
6598 ret = -ENOMEM;
6599 goto err_out;
6600 }
6601
6602 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006603 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006604
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306605 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006606 if (hdd_ctx->config == NULL) {
6607 hdd_alert("Failed to alloc memory for HDD config!");
6608 ret = -ENOMEM;
6609 goto err_free_hdd_context;
6610 }
6611
6612 /* Read and parse the qcom_cfg.ini file */
6613 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306614 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306615 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006616 WLAN_INI_FILE);
6617 ret = -EINVAL;
6618 goto err_free_config;
6619 }
6620
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006621 hdd_ctx->configuredMcastBcastFilter =
6622 hdd_ctx->config->mcastBcastFilterSetting;
6623
6624 hdd_notice("Setting configuredMcastBcastFilter: %d",
6625 hdd_ctx->config->mcastBcastFilterSetting);
6626
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306627 if (hdd_ctx->config->fhostNSOffload)
6628 hdd_ctx->ns_offload_enable = true;
6629
Abhishek Singh5ea86532016-04-27 14:10:53 +05306630 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6631
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006632 hdd_override_ini_config(hdd_ctx);
6633
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006634 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006635
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006636 ret = hdd_context_init(hdd_ctx);
6637
6638 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006639 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006640
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006641
Yuanyuan Liu13738502016-04-06 17:41:37 -07006642 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6643 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006644
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006645
6646 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306647 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006648
Anurag Chouhan6d760662016-02-20 16:05:43 +05306649 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006650 goto skip_multicast_logging;
6651
6652 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6653
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006654 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6655 if (ret)
6656 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05306657
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006658 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6659 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306660 goto err_free_histogram;
6661
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006662
6663 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306664 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006665 * levels of the code need not be set when the logger thread
6666 * is not enabled.
6667 */
6668 if (cds_is_multicast_logging())
6669 wlan_logging_set_log_level();
6670
6671skip_multicast_logging:
6672 hdd_set_trace_level_for_each(hdd_ctx);
6673
6674 return hdd_ctx;
6675
Nirav Shahed34b212016-04-25 10:59:16 +05306676err_free_histogram:
6677 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6678
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006679err_deinit_hdd_context:
6680 hdd_context_deinit(hdd_ctx);
6681
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006682err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306683 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006684
6685err_free_hdd_context:
6686 wiphy_free(hdd_ctx->wiphy);
6687
6688err_out:
6689 return ERR_PTR(ret);
6690}
6691
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006692#ifdef WLAN_OPEN_P2P_INTERFACE
6693/**
6694 * hdd_open_p2p_interface - Open P2P interface
6695 * @hdd_ctx: HDD context
6696 * @rtnl_held: True if RTNL lock held
6697 *
6698 * Open P2P interface during probe. This function called to open the P2P
6699 * interface at probe along with STA interface.
6700 *
6701 * Return: 0 on success and errno on failure
6702 */
6703static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6704{
6705 hdd_adapter_t *adapter;
6706 uint8_t *p2p_dev_addr;
6707
6708 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6709 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306710 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006711 hdd_ctx->config->intfMacAddr[0].bytes,
6712 sizeof(tSirMacAddr));
6713
6714 /*
6715 * Generate the P2P Device Address. This consists of
6716 * the device's primary MAC address with the locally
6717 * administered bit set.
6718 */
6719 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6720 } else {
6721 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6722 if (p2p_dev_addr == NULL) {
6723 hdd_alert("Failed to allocate mac_address for p2p_device");
6724 return -ENOSPC;
6725 }
6726
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306727 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306728 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006729 }
6730
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006731 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006732 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006733 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006734
6735 if (NULL == adapter) {
6736 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6737 return -ENOSPC;
6738 }
6739
6740 return 0;
6741}
6742#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306743static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006744 bool rtnl_held)
6745{
6746 return 0;
6747}
6748#endif
6749
6750/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306751 * hdd_start_station_adapter()- Start the Station Adapter
6752 * @adapter: HDD adapter
6753 *
6754 * This function initializes the adapter for the station mode.
6755 *
6756 * Return: 0 on success or errno on failure.
6757 */
6758int hdd_start_station_adapter(hdd_adapter_t *adapter)
6759{
6760 QDF_STATUS status;
6761
6762 ENTER_DEV(adapter->dev);
6763
6764 status = hdd_init_station_mode(adapter);
6765
6766 if (QDF_STATUS_SUCCESS != status) {
6767 hdd_err("Error Initializing station mode: %d", status);
6768 return qdf_status_to_os_return(status);
6769 }
6770
Arun Khandavallifae92942016-08-01 13:31:08 +05306771 hdd_register_tx_flow_control(adapter,
6772 hdd_tx_resume_timer_expired_handler,
6773 hdd_tx_resume_cb);
6774
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306775 EXIT();
6776 return 0;
6777}
6778
6779/**
6780 * hdd_start_ap_adapter()- Start AP Adapter
6781 * @adapter: HDD adapter
6782 *
6783 * This function initializes the adapter for the AP mode.
6784 *
6785 * Return: 0 on success errno on failure.
6786 */
6787int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6788{
6789 QDF_STATUS status;
6790
6791 ENTER();
6792
6793 status = hdd_init_ap_mode(adapter);
6794
6795 if (QDF_STATUS_SUCCESS != status) {
6796 hdd_err("Error Initializing the AP mode: %d", status);
6797 return qdf_status_to_os_return(status);
6798 }
6799
Arun Khandavallifae92942016-08-01 13:31:08 +05306800 hdd_register_tx_flow_control(adapter,
6801 hdd_softap_tx_resume_timer_expired_handler,
6802 hdd_softap_tx_resume_cb);
6803
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306804 EXIT();
6805 return 0;
6806}
6807
6808/**
6809 * hdd_start_ftm_adapter()- Start FTM adapter
6810 * @adapter: HDD adapter
6811 *
6812 * This function initializes the adapter for the FTM mode.
6813 *
6814 * Return: 0 on success or errno on failure.
6815 */
6816int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6817{
6818 QDF_STATUS qdf_status;
6819
6820 ENTER_DEV(adapter->dev);
6821
6822 qdf_status = hdd_init_tx_rx(adapter);
6823
6824 if (QDF_STATUS_SUCCESS != qdf_status) {
6825 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6826 return qdf_status_to_os_return(qdf_status);
6827 }
6828
6829 return 0;
6830 EXIT();
6831}
6832
6833/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006834 * hdd_open_interfaces - Open all required interfaces
6835 * hdd_ctx: HDD context
6836 * rtnl_held: True if RTNL lock is held
6837 *
6838 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6839 *
6840 * Return: Primary adapter on success and PTR_ERR on failure
6841 */
6842static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6843 bool rtnl_held)
6844{
6845 hdd_adapter_t *adapter = NULL;
6846 hdd_adapter_t *adapter_11p = NULL;
6847 int ret;
6848
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006849 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306850 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006851 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006852 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006853 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006854
6855 if (adapter == NULL)
6856 return ERR_PTR(-ENOSPC);
6857
6858 return adapter;
6859 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006860 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006861 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006862 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006863
6864 if (adapter == NULL)
6865 return ERR_PTR(-ENOSPC);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08006866 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
6867 adapter->fast_roaming_allowed = true;
6868
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006869 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6870 if (ret)
6871 goto err_close_adapter;
6872
6873 /* Open 802.11p Interface */
6874 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006875 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006876 "wlanocb%d",
6877 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006878 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006879 if (adapter_11p == NULL) {
6880 hdd_err("Failed to open 802.11p interface");
6881 goto err_close_adapter;
6882 }
6883 }
6884
6885 return adapter;
6886
6887err_close_adapter:
6888 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6889 return ERR_PTR(ret);
6890}
6891
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006892/**
6893 * hdd_update_country_code - Update country code
6894 * @hdd_ctx: HDD context
6895 * @adapter: Primary adapter context
6896 *
6897 * Update country code based on module parameter country_code at SME and wait
6898 * for the settings to take effect.
6899 *
6900 * Return: 0 on success and errno on failure
6901 */
6902static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6903 hdd_adapter_t *adapter)
6904{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306905 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006906 int ret = 0;
6907 unsigned long rc;
6908
6909 if (country_code == NULL)
6910 return 0;
6911
6912 INIT_COMPLETION(adapter->change_country_code);
6913
6914 status = sme_change_country_code(hdd_ctx->hHal,
6915 wlan_hdd_change_country_code_callback,
6916 country_code, adapter,
6917 hdd_ctx->pcds_context, eSIR_TRUE,
6918 eSIR_TRUE);
6919
6920
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306921 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006922 hdd_err("SME Change Country code from module param fail ret=%d",
6923 ret);
6924 return -EINVAL;
6925 }
6926
6927 rc = wait_for_completion_timeout(&adapter->change_country_code,
6928 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6929 if (!rc) {
6930 hdd_err("SME while setting country code timed out");
6931 ret = -ETIMEDOUT;
6932 }
6933
6934 return ret;
6935}
6936
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306937#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6938/**
6939 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6940 * @cds_cfg: CDS Configuration
6941 * @hdd_ctx: Pointer to hdd context
6942 *
6943 * Return: none
6944 */
6945static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6946 *cds_cfg,
6947 hdd_context_t *hdd_ctx)
6948{
6949 cds_cfg->tx_flow_stop_queue_th =
6950 hdd_ctx->config->TxFlowStopQueueThreshold;
6951 cds_cfg->tx_flow_start_queue_offset =
6952 hdd_ctx->config->TxFlowStartQueueOffset;
6953}
6954#else
6955static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6956 *cds_cfg,
6957 hdd_context_t *hdd_ctx)
6958{
6959}
6960#endif
6961
6962#ifdef FEATURE_WLAN_RA_FILTERING
6963/**
6964 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6965 * @cds_cfg: CDS Configuration
6966 * @hdd_ctx: Pointer to hdd context
6967 *
6968 * Return: none
6969 */
Anand Kumar3b92a912016-12-05 12:01:26 +05306970static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306971 hdd_context_t *hdd_ctx)
6972{
6973 cds_cfg->ra_ratelimit_interval =
6974 hdd_ctx->config->RArateLimitInterval;
6975 cds_cfg->is_ra_ratelimit_enabled =
6976 hdd_ctx->config->IsRArateLimitEnabled;
6977}
6978#else
Anand Kumar3b92a912016-12-05 12:01:26 +05306979static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306980 hdd_context_t *hdd_ctx)
6981{
6982}
6983#endif
6984
6985/**
6986 * hdd_update_cds_config() - API to update cds configuration parameters
6987 * @hdd_ctx: HDD Context
6988 *
6989 * Return: 0 for Success, errno on failure
6990 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006991static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306992{
6993 struct cds_config_info *cds_cfg;
6994
6995 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6996 if (!cds_cfg) {
6997 hdd_err("failed to allocate cds config");
6998 return -ENOMEM;
6999 }
7000
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307001 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
7002 cds_cfg->powersave_offload_enabled =
7003 hdd_ctx->config->enablePowersaveOffload;
7004 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7005 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7006 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7007 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7008 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7009
7010 /* Here ol_ini_info is used to store ini status of arp offload
7011 * ns offload and others. Currently 1st bit is used for arp
7012 * off load and 2nd bit for ns offload currently, rest bits are unused
7013 */
7014 if (hdd_ctx->config->fhostArpOffload)
7015 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7016 if (hdd_ctx->config->fhostNSOffload)
7017 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7018
7019 /*
7020 * Copy the DFS Phyerr Filtering Offload status.
7021 * This parameter reflects the value of the
7022 * dfs_phyerr_filter_offload flag as set in the ini.
7023 */
7024 cds_cfg->dfs_phyerr_filter_offload =
7025 hdd_ctx->config->fDfsPhyerrFilterOffload;
7026 if (hdd_ctx->config->ssdp)
7027 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7028
7029 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7030 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7031
7032 cds_cfg->ap_maxoffload_reorderbuffs =
7033 hdd_ctx->config->apMaxOffloadReorderBuffs;
7034
7035 cds_cfg->ap_disable_intrabss_fwd =
7036 hdd_ctx->config->apDisableIntraBssFwd;
7037
7038 cds_cfg->dfs_pri_multiplier =
7039 hdd_ctx->config->dfsRadarPriMultiplier;
7040 cds_cfg->reorder_offload =
7041 hdd_ctx->config->reorderOffloadSupport;
7042
7043 /* IPA micro controller data path offload resource config item */
7044 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007045 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7046 /* IpaUcTxBufCount should be power of 2 */
7047 hdd_err("Round down IpaUcTxBufCount %d to nearest power of 2",
7048 hdd_ctx->config->IpaUcTxBufCount);
7049 hdd_ctx->config->IpaUcTxBufCount =
7050 rounddown_pow_of_two(
7051 hdd_ctx->config->IpaUcTxBufCount);
7052 if (!hdd_ctx->config->IpaUcTxBufCount) {
7053 hdd_err("Failed to round down IpaUcTxBufCount");
7054 return -EINVAL;
7055 }
7056 hdd_err("IpaUcTxBufCount rounded down to %d",
7057 hdd_ctx->config->IpaUcTxBufCount);
7058 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307059 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7060 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007061 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7062 /* IpaUcRxIndRingCount should be power of 2 */
7063 hdd_err("Round down IpaUcRxIndRingCount %d to nearest power of 2",
7064 hdd_ctx->config->IpaUcRxIndRingCount);
7065 hdd_ctx->config->IpaUcRxIndRingCount =
7066 rounddown_pow_of_two(
7067 hdd_ctx->config->IpaUcRxIndRingCount);
7068 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7069 hdd_err("Failed to round down IpaUcRxIndRingCount");
7070 return -EINVAL;
7071 }
7072 hdd_err("IpaUcRxIndRingCount rounded down to %d",
7073 hdd_ctx->config->IpaUcRxIndRingCount);
7074 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307075 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007076 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307077 cds_cfg->uc_tx_partition_base =
7078 hdd_ctx->config->IpaUcTxPartitionBase;
7079 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7080
7081 cds_cfg->ip_tcp_udp_checksum_offload =
7082 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307083 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307084 cds_cfg->ce_classify_enabled =
7085 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007086 cds_cfg->bpf_packet_filter_enable =
7087 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307088 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7089 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7090 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007091 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007092 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007093 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007094 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307095
7096 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7097 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7098 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007099 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307100 cds_init_ini_config(cds_cfg);
7101 return 0;
7102}
7103
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007104/**
7105 * hdd_init_thermal_info - Initialize thermal level
7106 * @hdd_ctx: HDD context
7107 *
7108 * Initialize thermal level at SME layer and set the thermal level callback
7109 * which would be called when a configured thermal threshold is hit.
7110 *
7111 * Return: 0 on success and errno on failure
7112 */
7113static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7114{
7115 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307116 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007117
7118 thermal_param.smeThermalMgmtEnabled =
7119 hdd_ctx->config->thermalMitigationEnable;
7120 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7121
Poddar, Siddarth83905022016-04-16 17:56:08 -07007122 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7123 hdd_ctx->config->throttle_dutycycle_level0;
7124 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7125 hdd_ctx->config->throttle_dutycycle_level1;
7126 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7127 hdd_ctx->config->throttle_dutycycle_level2;
7128 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7129 hdd_ctx->config->throttle_dutycycle_level3;
7130
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007131 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7132 hdd_ctx->config->thermalTempMinLevel0;
7133 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7134 hdd_ctx->config->thermalTempMaxLevel0;
7135 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7136 hdd_ctx->config->thermalTempMinLevel1;
7137 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7138 hdd_ctx->config->thermalTempMaxLevel1;
7139 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7140 hdd_ctx->config->thermalTempMinLevel2;
7141 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7142 hdd_ctx->config->thermalTempMaxLevel2;
7143 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7144 hdd_ctx->config->thermalTempMinLevel3;
7145 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7146 hdd_ctx->config->thermalTempMaxLevel3;
7147
7148 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7149
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307150 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307151 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007152
7153 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7154 hdd_set_thermal_level_cb);
7155
7156 return 0;
7157
7158}
7159
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007160#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7161/**
7162 * hdd_hold_rtnl_lock - Hold RTNL lock
7163 *
7164 * Hold RTNL lock
7165 *
7166 * Return: True if held and false otherwise
7167 */
7168static inline bool hdd_hold_rtnl_lock(void)
7169{
7170 rtnl_lock();
7171 return true;
7172}
7173
7174/**
7175 * hdd_release_rtnl_lock - Release RTNL lock
7176 *
7177 * Release RTNL lock
7178 *
7179 * Return: None
7180 */
7181static inline void hdd_release_rtnl_lock(void)
7182{
7183 rtnl_unlock();
7184}
7185#else
7186static inline bool hdd_hold_rtnl_lock(void) { return false; }
7187static inline void hdd_release_rtnl_lock(void) { }
7188#endif
7189
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007190#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007191
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307192/* MAX iwpriv command support */
7193#define PKTLOG_SET_BUFF_SIZE 3
7194#define MAX_PKTLOG_SIZE 16
7195
7196/**
7197 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7198 * @hdd_ctx: hdd context
7199 * @set_value2: pktlog buffer size value
7200 *
7201 *
7202 * Return: 0 for success or error.
7203 */
7204static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7205{
7206 struct sir_wifi_start_log start_log = { 0 };
7207 QDF_STATUS status;
7208
7209 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7210 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7211 start_log.ini_triggered = cds_is_packet_log_enabled();
7212 start_log.user_triggered = 1;
7213 start_log.size = set_value2;
7214
7215 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7216 if (!QDF_IS_STATUS_SUCCESS(status)) {
7217 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7218 EXIT();
7219 return -EINVAL;
7220 }
7221
7222 return 0;
7223}
7224
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007225/**
7226 * hdd_process_pktlog_command() - process pktlog command
7227 * @hdd_ctx: hdd context
7228 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307229 * @set_value2: pktlog buffer size value
7230 *
7231 * This function process pktlog command.
7232 * set_value2 only matters when set_value is 3 (set buff size)
7233 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007234 *
7235 * Return: 0 for success or error.
7236 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307237int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
7238 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007239{
7240 int ret;
7241 bool enable;
7242 uint8_t user_triggered = 0;
7243
7244 ret = wlan_hdd_validate_context(hdd_ctx);
7245 if (0 != ret)
7246 return ret;
7247
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307248 hdd_info("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007249
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307250 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007251 hdd_err("invalid pktlog value %d", set_value);
7252 return -EINVAL;
7253 }
7254
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307255 if (set_value == PKTLOG_SET_BUFF_SIZE) {
7256 if (set_value2 <= 0) {
7257 hdd_err("invalid pktlog size %d", set_value2);
7258 return -EINVAL;
7259 } else if (set_value2 > MAX_PKTLOG_SIZE) {
7260 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
7261 return -EINVAL;
7262 }
7263 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
7264 }
7265
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007266 /*
7267 * set_value = 0 then disable packetlog
7268 * set_value = 1 enable packetlog forcefully
7269 * set_vlaue = 2 then disable packetlog if disabled through ini or
7270 * enable packetlog with AUTO type.
7271 */
7272 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
7273 true : false;
7274
7275 if (1 == set_value) {
7276 enable = true;
7277 user_triggered = 1;
7278 }
7279
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307280 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007281}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007282/**
7283 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
7284 * @hdd_ctx: HDD context
7285 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307286 * @user_triggered: triggered through iwpriv
7287 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007288 *
7289 * Return: 0 on success; error number otherwise
7290 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007291int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307292 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007293{
7294 struct sir_wifi_start_log start_log;
7295 QDF_STATUS status;
7296
7297 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7298 start_log.verbose_level =
7299 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007300 start_log.ini_triggered = cds_is_packet_log_enabled();
7301 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307302 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307303 /*
7304 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7305 * commands. Host uses this flag to decide whether to send pktlog
7306 * disable command to fw without sending pktlog enable command
7307 * previously. For eg, If vendor sends pktlog disable command without
7308 * sending pktlog enable command, then host discards the packet
7309 * but for iwpriv command, host will send it to fw.
7310 */
7311 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007312 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7313 if (!QDF_IS_STATUS_SUCCESS(status)) {
7314 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7315 EXIT();
7316 return -EINVAL;
7317 }
7318
7319 return 0;
7320}
7321#endif /* REMOVE_PKT_LOG */
7322
7323
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307324#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7325/**
7326 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7327 * switch without restart
7328 *
7329 * Registers callback function to change the operating channel of SAP by using
7330 * channel switch announcements instead of restarting SAP.
7331 *
7332 * Return: QDF_STATUS
7333 */
7334QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7335{
7336 QDF_STATUS status;
7337
7338 status = cds_register_sap_restart_channel_switch_cb(
7339 (void *)hdd_sap_restart_with_channel_switch);
7340 if (!QDF_IS_STATUS_SUCCESS(status))
7341 hdd_err("restart cb registration failed");
7342
7343 return status;
7344}
7345#endif
7346
Komal Seelam92fff912016-03-24 11:51:41 +05307347/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007348 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
7349 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05307350 * @dev: Device Pointer
7351 * @num: Number of Valid Mac address
7352 *
7353 * Return: Pointer to MAC address buffer
7354 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007355static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
7356 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05307357{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007358 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05307359}
Komal Seelam92fff912016-03-24 11:51:41 +05307360
7361/**
7362 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7363 * @hdd_ctx: HDD Context
7364 * @num: Number of random mac addresses needed
7365 *
7366 * Generate random addresses using bit manipulation on the base mac address
7367 *
7368 * Return: None
7369 */
7370static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7371{
7372 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7373 uint32_t iter;
7374 struct hdd_config *ini = hdd_ctx->config;
7375 uint8_t *buf = NULL;
7376 uint8_t macaddr_b3, tmp_br3;
7377 uint8_t *src = ini->intfMacAddr[0].bytes;
7378
7379 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
7380 buf = ini->intfMacAddr[iter].bytes;
7381 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7382 macaddr_b3 = buf[3];
7383 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7384 INTF_MACADDR_MASK;
7385 macaddr_b3 += tmp_br3;
7386 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7387 buf[0] |= 0x02;
7388 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007389 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307390 }
7391}
7392
7393/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007394 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05307395 * @hdd_ctx: HDD Context
7396 *
7397 * API to get mac addresses from platform driver and update the driver
7398 * structures and configure FW with the base mac address.
7399 * Return: int
7400 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007401static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05307402{
7403 uint32_t no_of_mac_addr, iter;
7404 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7405 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7406 uint8_t *addr, *buf;
7407 struct device *dev = hdd_ctx->parent_dev;
7408 struct hdd_config *ini = hdd_ctx->config;
7409 tSirMacAddr mac_addr;
7410 QDF_STATUS status;
7411
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007412 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05307413
7414 if (no_of_mac_addr == 0 || !addr) {
7415 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7416 return -EINVAL;
7417 }
7418
7419 if (no_of_mac_addr > max_mac_addr)
7420 no_of_mac_addr = max_mac_addr;
7421
7422 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7423
7424 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7425 buf = ini->intfMacAddr[iter].bytes;
7426 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007427 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307428 }
7429
7430 status = sme_set_custom_mac_addr(mac_addr);
7431
7432 if (!QDF_IS_STATUS_SUCCESS(status))
7433 return -EAGAIN;
7434 if (no_of_mac_addr < max_mac_addr)
7435 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7436 no_of_mac_addr);
7437 return 0;
7438}
7439
7440/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007441 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7442 * @hdd_ctx: HDD Context
7443 *
7444 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7445 * will generate its own MAC and update it to FW.
7446 *
7447 * Return: 0 for success
7448 * Non-zero error code for failure
7449 */
7450static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7451{
7452 tSirMacAddr customMacAddr;
7453 QDF_STATUS status;
7454
7455 qdf_mem_copy(&customMacAddr,
7456 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7457 sizeof(tSirMacAddr));
7458 status = sme_set_custom_mac_addr(customMacAddr);
7459 if (!QDF_IS_STATUS_SUCCESS(status))
7460 return -EAGAIN;
7461 return 0;
7462}
7463
7464/**
Komal Seelam92fff912016-03-24 11:51:41 +05307465 * hdd_initialize_mac_address() - API to get wlan mac addresses
7466 * @hdd_ctx: HDD Context
7467 *
7468 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
7469 * is provisioned with mac addresses, driver uses it, else it will use
7470 * wlan_mac.bin to update HW MAC addresses.
7471 *
7472 * Return: None
7473 */
7474static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
7475{
7476 QDF_STATUS status;
7477 int ret;
7478
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007479 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05307480 if (ret == 0)
7481 return;
7482
7483 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7484
7485 status = hdd_update_mac_config(hdd_ctx);
7486
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007487 if (QDF_IS_STATUS_SUCCESS(status))
7488 return;
7489
7490 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
7491
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007492 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007493 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007494 if (ret != 0) {
7495 hdd_err("MAC address out-of-sync, ret:%d", ret);
7496 QDF_ASSERT(ret);
7497 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007498 }
Komal Seelam92fff912016-03-24 11:51:41 +05307499}
7500
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007501/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007502 * hdd_tsf_init() - Initialize the TSF synchronization interface
7503 * @hdd_ctx: HDD global context
7504 *
7505 * When TSF synchronization via GPIO is supported by the driver and
7506 * has been enabled in the configuration file, this function plumbs
7507 * the GPIO value down to firmware via SME.
7508 *
7509 * Return: None
7510 */
7511#ifdef WLAN_FEATURE_TSF
7512static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7513{
7514 QDF_STATUS status;
7515
7516 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7517 return;
7518
7519 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7520 hdd_ctx->config->tsf_gpio_pin);
7521 if (!QDF_IS_STATUS_SUCCESS(status))
7522 hdd_err("Set tsf GPIO failed, status: %d", status);
7523}
7524#else
7525static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7526{
7527}
7528#endif
7529
7530/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007531 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7532 * @hdd_ctx: HDD context
7533 *
7534 * Pre configurations to be done at lower layer before calling cds enable.
7535 *
7536 * Return: 0 on success and errno on failure.
7537 */
7538static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7539{
7540 int ret;
7541 QDF_STATUS status;
7542 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07007543 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007544
Leo Changfdb45c32016-10-28 11:09:23 -07007545 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007546 /*
7547 * Set 802.11p config
7548 * TODO-OCB: This has been temporarily added here to ensure this
7549 * parameter is set in CSR when we init the channel list. This should
7550 * be removed once the 5.9 GHz channels are added to the regulatory
7551 * domain.
7552 */
7553 hdd_set_dot11p_config(hdd_ctx);
7554
7555 /*
7556 * Note that the cds_pre_enable() sequence triggers the cfg download.
7557 * The cfg download must occur before we update the SME config
7558 * since the SME config operation must access the cfg database
7559 */
7560 status = hdd_set_sme_config(hdd_ctx);
7561
7562 if (QDF_STATUS_SUCCESS != status) {
7563 hdd_alert("Failed hdd_set_sme_config: %d", status);
7564 ret = qdf_status_to_os_return(status);
7565 goto out;
7566 }
7567
7568 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7569 hdd_ctx->config->tx_chain_mask_1ss,
7570 PDEV_CMD);
7571 if (0 != ret) {
7572 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7573 goto out;
7574 }
7575
7576 hdd_program_country_code(hdd_ctx);
7577
7578 status = hdd_set_sme_chan_list(hdd_ctx);
7579 if (status != QDF_STATUS_SUCCESS) {
7580 hdd_alert("Failed to init channel list: %d", status);
7581 ret = qdf_status_to_os_return(status);
7582 goto out;
7583 }
7584
7585 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07007586 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07007587 hdd_alert("config update failed");
7588 ret = -EINVAL;
7589 goto out;
7590 }
7591
Prashanth Bhatta07998752016-04-28 12:35:33 -07007592 /*
7593 * Set the MAC Address Currently this is used by HAL to add self sta.
7594 * Remove this once self sta is added as part of session open.
7595 */
7596 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7597 hdd_ctx->config->intfMacAddr[0].bytes,
7598 sizeof(hdd_ctx->config->intfMacAddr[0]));
7599
7600 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7601 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7602 hal_status, hal_status);
7603 ret = -EINVAL;
7604 goto out;
7605 }
7606
7607 hdd_init_channel_avoidance(hdd_ctx);
7608
7609out:
7610 return ret;
7611}
7612
7613/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007614 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7615 * @context_ptr - hdd context pointer
7616 * @event_ptr - event structure pointer
7617 *
7618 * This is the p2p listen offload stop event handler, it sends vendor
7619 * event back to supplicant to notify the stop reason.
7620 *
7621 * Return: None
7622 */
7623static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7624 void *event_ptr)
7625{
7626 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7627 struct sir_p2p_lo_event *evt = event_ptr;
7628 struct sk_buff *vendor_event;
7629
7630 ENTER();
7631
7632 if (hdd_ctx == NULL) {
7633 hdd_err("Invalid HDD context pointer");
7634 return;
7635 }
7636
7637 vendor_event =
7638 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7639 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7640 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7641 GFP_KERNEL);
7642
7643 if (!vendor_event) {
7644 hdd_err("cfg80211_vendor_event_alloc failed");
7645 return;
7646 }
7647
7648 if (nla_put_u32(vendor_event,
7649 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7650 evt->reason_code)) {
7651 hdd_err("nla put failed");
7652 kfree_skb(vendor_event);
7653 return;
7654 }
7655
7656 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7657}
7658
7659/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307660 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7661 * @hdd_ctx: HDD context
7662 *
7663 * This function sends the adaptive dwell time config configuration to the
7664 * firmware via WMA
7665 *
7666 * Return: 0 - success, < 0 - failure
7667 */
7668static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7669{
7670 QDF_STATUS status;
7671 struct adaptive_dwelltime_params dwelltime_params;
7672
7673 dwelltime_params.is_enabled =
7674 hdd_ctx->config->adaptive_dwell_mode_enabled;
7675 dwelltime_params.dwelltime_mode =
7676 hdd_ctx->config->global_adapt_dwelltime_mode;
7677 dwelltime_params.lpf_weight =
7678 hdd_ctx->config->adapt_dwell_lpf_weight;
7679 dwelltime_params.passive_mon_intval =
7680 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7681 dwelltime_params.wifi_act_threshold =
7682 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7683
7684 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7685 &dwelltime_params);
7686
7687 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7688 if (!QDF_IS_STATUS_SUCCESS(status)) {
7689 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7690 return -EAGAIN;
7691 }
7692 return 0;
7693}
7694
Arun Khandavallid4349a92016-07-25 11:10:43 +05307695#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7696/**
7697 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7698 * @hdd_ctx: HDD context
7699 *
7700 * Set auto shutdown callback to get indications from firmware to indicate
7701 * userspace to shutdown WLAN after a configured amount of inactivity.
7702 *
7703 * Return: 0 on success and errno on failure.
7704 */
7705static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7706{
7707 QDF_STATUS status;
7708
7709 if (!hdd_ctx->config->WlanAutoShutdown)
7710 return 0;
7711
7712 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7713 wlan_hdd_auto_shutdown_cb);
7714 if (status != QDF_STATUS_SUCCESS)
7715 hdd_err("Auto shutdown feature could not be enabled: %d",
7716 status);
7717
7718 return qdf_status_to_os_return(status);
7719}
7720#else
7721static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7722{
7723 return 0;
7724}
7725#endif
7726
7727/**
7728 * hdd_features_init() - Init features
7729 * @hdd_ctx: HDD context
7730 * @adapter: Primary adapter context
7731 *
7732 * Initialize features and their feature context after WLAN firmware is up.
7733 *
7734 * Return: 0 on success and errno on failure.
7735 */
7736static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7737{
7738 tSirTxPowerLimit hddtxlimit;
7739 QDF_STATUS status;
7740 int ret;
7741
7742 ENTER();
7743
7744 ret = hdd_update_country_code(hdd_ctx, adapter);
7745 if (ret) {
7746 hdd_err("Failed to update country code: %d", ret);
7747 goto out;
7748 }
7749
7750 /* FW capabilities received, Set the Dot11 mode */
7751 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07007752 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
7753 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307754
Arun Khandavallid4349a92016-07-25 11:10:43 +05307755
7756 if (hdd_ctx->config->fIsImpsEnabled)
7757 hdd_set_idle_ps_config(hdd_ctx, true);
7758 else
7759 hdd_set_idle_ps_config(hdd_ctx, false);
7760
7761 if (hdd_lro_init(hdd_ctx))
7762 hdd_err("Unable to initialize LRO in fw");
7763
7764 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7765 hdd_err("Unable to send adaptive dwelltime setting to FW");
7766
7767 ret = hdd_init_thermal_info(hdd_ctx);
7768 if (ret) {
7769 hdd_err("Error while initializing thermal information");
7770 goto deregister_frames;
7771 }
7772
7773 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7774 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7775 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7776 if (!QDF_IS_STATUS_SUCCESS(status))
7777 hdd_err("Error setting txlimit in sme: %d", status);
7778
7779 hdd_tsf_init(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307780 hdd_encrypt_decrypt_init(hdd_ctx);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307781
Arun Khandavallid4349a92016-07-25 11:10:43 +05307782 ret = hdd_register_cb(hdd_ctx);
7783 if (ret) {
7784 hdd_err("Failed to register HDD callbacks!");
7785 goto deregister_frames;
7786 }
7787
7788 if (hdd_ctx->config->dual_mac_feature_disable) {
7789 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7790 if (status != QDF_STATUS_SUCCESS) {
7791 hdd_err("Failed to disable dual mac features");
7792 goto deregister_cb;
7793 }
7794 }
7795
7796 /* register P2P Listen Offload event callback */
7797 if (wma_is_p2p_lo_capable())
7798 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7799 wlan_hdd_p2p_lo_event_callback);
7800
7801 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7802
7803 if (ret)
7804 goto deregister_cb;
7805
7806 EXIT();
7807 return 0;
7808
7809deregister_cb:
7810 hdd_deregister_cb(hdd_ctx);
7811deregister_frames:
7812 wlan_hdd_cfg80211_deregister_frames(adapter);
7813out:
7814 return -EINVAL;
7815
7816}
7817
7818
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307819/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307820 * hdd_configure_cds() - Configure cds modules
7821 * @hdd_ctx: HDD context
7822 * @adapter: Primary adapter context
7823 *
7824 * Enable Cds modules after WLAN firmware is up.
7825 *
7826 * Return: 0 on success and errno on failure.
7827 */
7828int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7829{
7830 int ret;
7831 QDF_STATUS status;
7832 /* structure of function pointers to be used by CDS */
7833 struct cds_sme_cbacks sme_cbacks;
7834
7835 ret = hdd_pre_enable_configure(hdd_ctx);
7836 if (ret) {
7837 hdd_err("Failed to pre-configure cds");
7838 goto out;
7839 }
7840
7841 /*
7842 * Start CDS which starts up the SME/MAC/HAL modules and everything
7843 * else
7844 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307845 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307846
7847 if (!QDF_IS_STATUS_SUCCESS(status)) {
7848 hdd_alert("cds_enable failed");
7849 goto out;
7850 }
7851
7852 status = hdd_post_cds_enable_config(hdd_ctx);
7853 if (!QDF_IS_STATUS_SUCCESS(status)) {
7854 hdd_alert("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007855 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307856 }
7857
7858 ret = hdd_features_init(hdd_ctx, adapter);
7859 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007860 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307861
7862 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7863 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7864 status = cds_init_policy_mgr(&sme_cbacks);
7865 if (!QDF_IS_STATUS_SUCCESS(status)) {
7866 hdd_err("Policy manager initialization failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007867 goto hdd_features_deinit;
Arun Khandavallifae92942016-08-01 13:31:08 +05307868 }
7869
7870 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007871
7872hdd_features_deinit:
7873 hdd_deregister_cb(hdd_ctx);
7874 wlan_hdd_cfg80211_deregister_frames(adapter);
7875cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307876 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007877
Arun Khandavallifae92942016-08-01 13:31:08 +05307878out:
7879 return -EINVAL;
7880}
7881
7882/**
7883 * hdd_deconfigure_cds() -De-Configure cds
7884 * @hdd_ctx: HDD context
7885 *
7886 * Deconfigure Cds modules before WLAN firmware is down.
7887 *
7888 * Return: 0 on success and errno on failure.
7889 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007890static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307891{
7892 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07007893 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307894
7895 ENTER();
7896 /* De-register the SME callbacks */
7897 hdd_deregister_cb(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307898 hdd_encrypt_decrypt_deinit(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307899
7900 /* De-init Policy Manager */
7901 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7902 hdd_err("Failed to deinit policy manager");
7903 /* Proceed and complete the clean up */
Houston Hoffman6640cf32016-10-10 16:44:29 -07007904 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307905 }
7906
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307907 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307908 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7909 hdd_err("Failed to Disable the CDS Modules! :%d",
7910 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07007911 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307912 }
7913
7914 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07007915 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307916}
7917
7918
7919/**
7920 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7921 * @hdd_ctx: HDD context
Arun Khandavallifae92942016-08-01 13:31:08 +05307922 *
7923 * This function maintains the driver state machine it will be invoked from
7924 * exit, shutdown and con_mode change handler. Depending on the driver state
7925 * shall perform the stopping/closing of the modules.
7926 *
7927 * Return: 0 for success; non-zero for failure
7928 */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007929int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307930{
7931 void *hif_ctx;
7932 qdf_device_t qdf_ctx;
7933 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307934 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307935 p_cds_sched_context cds_sched_context = NULL;
7936
7937 ENTER();
7938
7939 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7940 if (!qdf_ctx) {
7941 hdd_err("QDF device context NULL");
7942 return -EINVAL;
7943 }
7944
7945 cds_sched_context = get_cds_sched_ctxt();
7946 if (!cds_sched_context) {
7947 hdd_err("cds scheduler context NULL");
7948 return -EINVAL;
7949 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307950 mutex_lock(&hdd_ctx->iface_change_lock);
7951 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307952
7953 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7954
7955 switch (hdd_ctx->driver_status) {
7956 case DRIVER_MODULES_UNINITIALIZED:
7957 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307958 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307959 case DRIVER_MODULES_CLOSED:
7960 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307961 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307962 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05307963 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05307964 if (hdd_deconfigure_cds(hdd_ctx)) {
7965 hdd_alert("Failed to de-configure CDS");
7966 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307967 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307968 }
7969 hdd_info("successfully Disabled the CDS modules!");
7970 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7971 break;
7972 case DRIVER_MODULES_OPENED:
7973 hdd_info("Closing CDS modules!");
7974 break;
7975 default:
7976 hdd_err("Trying to stop wlan in a wrong state: %d",
7977 hdd_ctx->driver_status);
7978 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307979 ret = -EINVAL;
7980 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307981 }
7982
Govind Singhb048e872016-09-27 22:07:43 +05307983 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
7984 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7985 hdd_err("Failed to process post CDS disable Modules! :%d",
7986 qdf_status);
7987 ret = -EINVAL;
7988 QDF_ASSERT(0);
7989 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307990 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307991 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7992 hdd_warn("Failed to stop CDS:%d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05307993 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307994 QDF_ASSERT(0);
7995 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07007996
Rajeev Kumar3a6c13c2017-01-06 13:01:08 -08007997 qdf_status = hdd_release_and_destroy_pdev(hdd_ctx);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307998 if (QDF_IS_STATUS_ERROR(qdf_status))
7999 hdd_err("Pdev delete failed");
8000
Rajeev Kumar1cba9d02017-01-06 11:36:14 -08008001 qdf_status = hdd_release_and_destroy_psoc(hdd_ctx);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308002 if (QDF_IS_STATUS_ERROR(qdf_status))
8003 hdd_err("Psoc delete failed");
8004
Arun Khandavallifae92942016-08-01 13:31:08 +05308005 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8006 if (!hif_ctx) {
8007 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308008 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308009 }
8010
8011 hdd_hif_close(hif_ctx);
8012
8013 ol_cds_free();
8014
Arunk Khandavalli649c0092016-11-22 21:20:43 +05308015 if (!cds_is_driver_recovering() && !cds_is_driver_unloading()) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308016 ret = pld_power_off(qdf_ctx->dev);
8017 if (ret)
8018 hdd_err("CNSS power down failed put device into Low power mode:%d",
8019 ret);
8020 }
8021 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
8022
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308023done:
8024 hdd_ctx->stop_modules_in_progress = false;
8025 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308026 EXIT();
8027
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308028 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308029
8030}
8031
8032/**
8033 * hdd_iface_change_callback() - Function invoked when stop modules expires
8034 * @priv: pointer to hdd context
8035 *
8036 * This function is invoked when the timer waiting for the interface change
8037 * expires, it shall cut-down the power to wlan and stop all the modules.
8038 *
8039 * Return: void
8040 */
8041static void hdd_iface_change_callback(void *priv)
8042{
8043 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
8044 int ret;
8045 int status = wlan_hdd_validate_context(hdd_ctx);
8046
8047 if (status)
8048 return;
8049
8050 ENTER();
8051 hdd_info("Interface change timer expired close the modules!");
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008052 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308053 if (ret)
8054 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05308055 EXIT();
8056}
8057
8058/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308059 * hdd_state_info_dump() - prints state information of hdd layer
8060 * @buf: buffer pointer
8061 * @size: size of buffer to be filled
8062 *
8063 * This function is used to dump state information of hdd layer
8064 *
8065 * Return: None
8066 */
8067static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
8068{
8069 hdd_context_t *hdd_ctx;
8070 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8071 QDF_STATUS status;
8072 hdd_station_ctx_t *hdd_sta_ctx;
8073 hdd_adapter_t *adapter;
8074 uint16_t len = 0;
8075 char *buf = *buf_ptr;
8076
8077 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8078 if (!hdd_ctx) {
8079 hdd_err("Failed to get hdd context ");
8080 return;
8081 }
8082
8083 hdd_notice("size of buffer: %d", *size);
8084
8085 len += scnprintf(buf + len, *size - len,
8086 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8087 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008088 "\n is_scheduler_suspended %d",
8089 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308090
8091 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8092
8093 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8094 adapter = adapter_node->pAdapter;
8095 if (adapter->dev)
8096 len += scnprintf(buf + len, *size - len,
8097 "\n device name: %s", adapter->dev->name);
8098 len += scnprintf(buf + len, *size - len,
8099 "\n device_mode: %d", adapter->device_mode);
8100 switch (adapter->device_mode) {
8101 case QDF_STA_MODE:
8102 case QDF_P2P_CLIENT_MODE:
8103 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8104 len += scnprintf(buf + len, *size - len,
8105 "\n connState: %d",
8106 hdd_sta_ctx->conn_info.connState);
8107 break;
8108
8109 default:
8110 break;
8111 }
8112 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
8113 adapter_node = next;
8114 }
8115
8116 *size -= len;
8117 *buf_ptr += len;
8118}
8119
8120/**
8121 * hdd_register_debug_callback() - registration function for hdd layer
8122 * to print hdd state information
8123 *
8124 * Return: None
8125 */
8126static void hdd_register_debug_callback(void)
8127{
8128 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
8129}
8130
8131/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008132 * hdd_wlan_startup() - HDD init function
8133 * @dev: Pointer to the underlying device
8134 *
8135 * This is the driver startup code executed once a WLAN device has been detected
8136 *
8137 * Return: 0 for success, < 0 for failure
8138 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308139int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008140{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308141 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008142 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008143 hdd_context_t *hdd_ctx = NULL;
8144 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308145 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008146 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308147 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008148
8149 ENTER();
8150
Arun Khandavallifae92942016-08-01 13:31:08 +05308151 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008152
8153 if (IS_ERR(hdd_ctx))
8154 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008155
Arun Khandavallifae92942016-08-01 13:31:08 +05308156 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
8157 hdd_iface_change_callback, (void *)hdd_ctx);
8158
8159 mutex_init(&hdd_ctx->iface_change_lock);
8160
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008161 ret = hdd_init_netlink_services(hdd_ctx);
8162 if (ret)
8163 goto err_hdd_free_context;
8164
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07008165 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308166
Arun Khandavallifae92942016-08-01 13:31:08 +05308167 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
8168 if (ret) {
8169 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008170 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008171 }
8172
Yingying Tang80e15f32016-09-27 18:23:01 +08008173 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008174
Yingying Tang95409972016-10-20 15:16:15 +08008175 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
8176 hdd_notice("Failed to set wow pulse");
8177
Anurag Chouhan6d760662016-02-20 16:05:43 +05308178 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008179
8180 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008181 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05308182 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008183 }
8184
Prashanth Bhatta07998752016-04-28 12:35:33 -07008185 ret = hdd_wiphy_init(hdd_ctx);
8186 if (ret) {
8187 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05308188 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008189 }
8190
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05308191 if (hdd_ctx->config->enable_dp_trace)
8192 qdf_dp_trace_init();
8193
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308194 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008195 goto err_wiphy_unregister;
8196
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07008197 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08008198
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008199 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008200
Arun Khandavallifae92942016-08-01 13:31:08 +05308201 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008202
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008203 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008204 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008205 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05308206 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008207 }
8208
Arun Khandavallifae92942016-08-01 13:31:08 +05308209 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308210 if (!hif_sc) {
8211 hdd_err("HIF context is NULL");
8212 goto err_close_adapter;
8213 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008214 /*
8215 * target hw version/revision would only be retrieved after firmware
8216 * donwload
8217 */
8218 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
8219 &hdd_ctx->target_hw_revision,
8220 &hdd_ctx->target_hw_name);
8221
8222 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05308223 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008224
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008225 hdd_release_rtnl_lock();
8226 rtnl_held = false;
8227
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05308228 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8229 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08008230
8231 wlan_hdd_update_11n_mode(hdd_ctx->config);
8232
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008233#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05308234 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308235 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008236 hdd_skip_acs_scan_timer_handler,
8237 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308238 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07008239 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04008240 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008241#endif
8242
Nitesh Shah61c10d92016-10-19 19:29:15 +05308243 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
8244 QDF_TIMER_TYPE_SW,
8245 wlan_hdd_change_tdls_mode,
8246 hdd_ctx);
8247
Prashanth Bhattaab004382016-10-11 16:08:11 -07008248 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008249
Jeff Johnson9afc5012016-09-23 13:56:27 -07008250 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008251
Nirav Shahbd36b062016-07-18 11:12:59 +05308252 if (hdd_ctx->rps)
8253 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07008254
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008255
8256 if (cds_is_packet_log_enabled())
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308257 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008258
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008259 ret = hdd_register_notifiers(hdd_ctx);
8260 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05308261 goto err_debugfs_exit;
8262
8263 status = wlansap_global_init();
8264 if (QDF_IS_STATUS_ERROR(status))
8265 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008266
Komal Seelam8634b772016-09-29 12:12:24 +05308267 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008268 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308269 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008270
bings612b9c42016-11-07 10:52:03 +08008271 if (hdd_enable_egap(hdd_ctx))
8272 hdd_err("enhance green ap is not enabled");
8273
Arun Khandavallifae92942016-08-01 13:31:08 +05308274 if (hdd_ctx->config->fIsImpsEnabled)
8275 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308276
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308277 if (hdd_ctx->config->sifs_burst_duration) {
8278 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
8279 hdd_ctx->config->sifs_burst_duration;
8280
8281 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
8282 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
8283 set_value, PDEV_CMD);
8284 }
8285
Arun Khandavallifae92942016-08-01 13:31:08 +05308286 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
8287 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308288
8289 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8290 status = sme_enable_disable_chanavoidind_event(
8291 hdd_ctx->hHal, 0);
8292 if (!QDF_IS_STATUS_SUCCESS(status))
8293 hdd_err("Failed to disable Chan Avoidance Indication");
8294 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008295 goto success;
8296
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008297err_debugfs_exit:
8298 hdd_debugfs_exit(adapter);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308299
8300err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008301 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008302
Arun Khandavallid4349a92016-07-25 11:10:43 +05308303 if (rtnl_held)
8304 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008305
Anurag Chouhance6a4052016-09-14 18:20:42 +05308306err_ipa_cleanup:
8307 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08008308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008309err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008310 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008311
Arun Khandavallifae92942016-08-01 13:31:08 +05308312err_stop_modules:
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008313 hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308314
8315
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008316 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308317 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008318 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308319 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008320 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008321
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008322err_exit_nl_srv:
Houston Hoffman47a4a052016-11-14 23:22:44 -08008323 hdd_green_ap_deinit(hdd_ctx);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008324 hdd_exit_netlink_services(hdd_ctx);
8325
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308326 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008327err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05308328 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
8329 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07008330 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308331 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008333 return -EIO;
8334
8335success:
8336 EXIT();
8337 return 0;
8338}
8339
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008340/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308341 * hdd_wlan_update_target_info() - update target type info
8342 * @hdd_ctx: HDD context
8343 * @context: hif context
8344 *
8345 * Update target info received from firmware in hdd context
8346 * Return:None
8347 */
8348
8349void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
8350{
8351 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
8352
8353 if (!tgt_info) {
8354 hdd_err("Target info is Null");
8355 return;
8356 }
8357
8358 hdd_ctx->target_type = tgt_info->target_type;
8359}
8360
8361/**
8362 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308363 * @hdd_ctx: HDD context
8364 *
8365 * Register the HDD callbacks to CDS/SME.
8366 *
8367 * Return: 0 for success or Error code for failure
8368 */
8369int hdd_register_cb(hdd_context_t *hdd_ctx)
8370{
8371 QDF_STATUS status;
8372 int ret = 0;
8373
8374 ENTER();
8375
8376 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
8377
8378 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
8379 hdd_send_oem_data_rsp_msg);
8380
8381 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
8382 wlan_hdd_cfg80211_fw_mem_dump_cb);
8383 if (!QDF_IS_STATUS_SUCCESS(status)) {
8384 hdd_err("Failed to register memdump callback");
8385 ret = -EINVAL;
8386 return ret;
8387 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05308388 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
8389 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308390 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
8391 sme_nan_register_callback(hdd_ctx->hHal,
8392 wlan_hdd_cfg80211_nan_callback);
8393 sme_stats_ext_register_callback(hdd_ctx->hHal,
8394 wlan_hdd_cfg80211_stats_ext_callback);
8395
8396 sme_ext_scan_register_callback(hdd_ctx->hHal,
8397 wlan_hdd_cfg80211_extscan_callback);
8398
8399 status = cds_register_sap_restart_channel_switch_cb(
8400 (void *)hdd_sap_restart_with_channel_switch);
8401 if (!QDF_IS_STATUS_SUCCESS(status)) {
8402 hdd_err("restart cb registration failed");
8403 ret = -EINVAL;
8404 return ret;
8405 }
8406
8407 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
8408 hdd_rssi_threshold_breached);
8409
8410 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
8411 hdd_get_bpf_offload_cb);
8412 if (!QDF_IS_STATUS_SUCCESS(status)) {
8413 hdd_err("set bpf offload callback failed");
8414 ret = -EINVAL;
8415 return ret;
8416 }
8417
8418 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
8419 wlan_hdd_cfg80211_link_layer_stats_callback);
8420
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05308421 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
8422 hdd_lost_link_info_cb);
8423 /* print error and not block the startup process */
8424 if (!QDF_IS_STATUS_SUCCESS(status))
8425 hdd_err("set lost link info callback failed");
8426
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308427 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
8428
8429 EXIT();
8430
8431 return ret;
8432}
8433
8434/**
8435 * hdd_deregister_cb() - De-Register HDD callbacks.
8436 * @hdd_ctx: HDD context
8437 *
8438 * De-Register the HDD callbacks to CDS/SME.
8439 *
8440 * Return: void
8441 */
8442void hdd_deregister_cb(hdd_context_t *hdd_ctx)
8443{
8444 QDF_STATUS status;
8445
8446 ENTER();
8447
8448 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
8449 if (!QDF_IS_STATUS_SUCCESS(status))
8450 hdd_err("De-register of dcc stats callback failed: %d",
8451 status);
8452
8453 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
8454 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
8455 if (!QDF_IS_STATUS_SUCCESS(status))
8456 hdd_err("De-register bpf offload callback failed: %d",
8457 status);
8458 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
8459
8460 status = cds_deregister_sap_restart_channel_switch_cb();
8461 if (!QDF_IS_STATUS_SUCCESS(status))
8462 hdd_err("De-register restart cb registration failed: %d",
8463 status);
8464
8465 sme_stats_ext_register_callback(hdd_ctx->hHal,
8466 wlan_hdd_cfg80211_stats_ext_callback);
8467
8468 sme_nan_deregister_callback(hdd_ctx->hHal);
8469 status = sme_reset_tsfcb(hdd_ctx->hHal);
8470 if (!QDF_IS_STATUS_SUCCESS(status))
8471 hdd_err("Failed to de-register tsfcb the callback:%d",
8472 status);
8473 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
8474 if (!QDF_IS_STATUS_SUCCESS(status))
8475 hdd_err("Failed to de-register the fw mem dump callback: %d",
8476 status);
8477
8478 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
8479 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
8480
8481 EXIT();
8482}
8483
8484/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008485 * hdd_softap_sta_deauth() - handle deauth req from HDD
8486 * @adapter: Pointer to the HDD
8487 * @enable: bool value
8488 *
8489 * This to take counter measure to handle deauth req from HDD
8490 *
8491 * Return: None
8492 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308493QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008494 struct tagCsrDelStaParams *pDelStaParams)
8495{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308496 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008497
8498 ENTER();
8499
Jeff Johnson34c88b72016-08-15 14:27:11 -07008500 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008501 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8502
8503 /* Ignore request to deauth bcmc station */
8504 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308505 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008506
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308507 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008508 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8509 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008510
8511 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308512 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008513}
8514
8515/**
8516 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
8517 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308518 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008519 *
8520 * This to take counter measure to handle deauth req from HDD
8521 *
8522 * Return: None
8523 */
8524void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308525 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008526{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008527 ENTER();
8528
Jeff Johnson34c88b72016-08-15 14:27:11 -07008529 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008530 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8531
8532 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308533 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008534 return;
8535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008536 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308537 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008538}
8539
8540void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
8541 bool enable)
8542{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008543 ENTER();
8544
Jeff Johnson34c88b72016-08-15 14:27:11 -07008545 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008546 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8547
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008548 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8549 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008550}
8551
8552/**
8553 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
8554 * @hdd_ctx: HDD Context
8555 *
8556 * API to find if there is any STA or P2P-Client is connected
8557 *
8558 * Return: true if connected; false otherwise
8559 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308560QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008561{
8562 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
8563}
8564
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008565/**
8566 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
8567 * @adapter: HDD adapter pointer
8568 *
8569 * This function loop through each adapter and disable roaming on each STA
8570 * device mode except the input adapter.
8571 *
8572 * Note: On the input adapter roaming is not enabled yet hence no need to
8573 * disable.
8574 *
8575 * Return: None
8576 */
8577void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8578{
8579 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8580 hdd_adapter_t *adapterIdx = NULL;
8581 hdd_adapter_list_node_t *adapterNode = NULL;
8582 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308583 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008584
8585 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8586 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008587 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008588 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008589 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008590 adapter->sessionId);
8591 /*
8592 * Loop through adapter and disable roaming for each STA device
8593 * mode except the input adapter.
8594 */
8595 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8596
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308597 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008598 adapterIdx = adapterNode->pAdapter;
8599
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008600 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008601 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008602 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008603 adapterIdx->sessionId);
8604 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8605 (adapterIdx),
8606 adapterIdx->sessionId, 0);
8607 }
8608
8609 status = hdd_get_next_adapter(hdd_ctx,
8610 adapterNode,
8611 &pNext);
8612 adapterNode = pNext;
8613 }
8614 }
8615}
8616
8617/**
8618 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8619 * @adapter: HDD adapter pointer
8620 *
8621 * This function loop through each adapter and enable roaming on each STA
8622 * device mode except the input adapter.
8623 * Note: On the input adapter no need to enable roaming because link got
8624 * disconnected on this.
8625 *
8626 * Return: None
8627 */
8628void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8629{
8630 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8631 hdd_adapter_t *adapterIdx = NULL;
8632 hdd_adapter_list_node_t *adapterNode = NULL;
8633 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308634 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008635
8636 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8637 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008638 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008639 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008640 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008641 adapter->sessionId);
8642 /*
8643 * Loop through adapter and enable roaming for each STA device
8644 * mode except the input adapter.
8645 */
8646 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8647
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308648 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008649 adapterIdx = adapterNode->pAdapter;
8650
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008651 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008652 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008653 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008654 adapterIdx->sessionId);
8655 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8656 (adapterIdx),
8657 adapterIdx->sessionId,
8658 REASON_CONNECT);
8659 }
8660
8661 status = hdd_get_next_adapter(hdd_ctx,
8662 adapterNode,
8663 &pNext);
8664 adapterNode = pNext;
8665 }
8666 }
8667}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008668
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308669void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008670{
8671 struct sk_buff *skb;
8672 struct nlmsghdr *nlh;
8673 tAniMsgHdr *ani_hdr;
8674 void *nl_data = NULL;
8675 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308676 struct radio_index_tlv *radio_info;
8677 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008678
8679 if (in_interrupt() || irqs_disabled() || in_atomic())
8680 flags = GFP_ATOMIC;
8681
8682 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8683
8684 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008685 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008686 return;
8687 }
8688
8689 nlh = (struct nlmsghdr *)skb->data;
8690 nlh->nlmsg_pid = 0; /* from kernel */
8691 nlh->nlmsg_flags = 0;
8692 nlh->nlmsg_seq = 0;
8693 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8694
8695 ani_hdr = NLMSG_DATA(nlh);
8696 ani_hdr->type = type;
8697
8698 switch (type) {
8699 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05308700 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008701 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008702 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008703 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008704 ani_hdr->length = 0;
8705 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8706 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8707 break;
8708 case WLAN_SVC_WLAN_STATUS_IND:
8709 case WLAN_SVC_WLAN_VERSION_IND:
8710 case WLAN_SVC_DFS_CAC_START_IND:
8711 case WLAN_SVC_DFS_CAC_END_IND:
8712 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8713 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8714 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008715 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308716 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008717 ani_hdr->length = len;
8718 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8719 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8720 memcpy(nl_data, data, len);
8721 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
8722 break;
8723
8724 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008725 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726 type);
8727 kfree_skb(skb);
8728 return;
8729 }
8730
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308731 /*
8732 * Add radio index at the end of the svc event in TLV format to maintain
8733 * the backward compatibility with userspace applications.
8734 */
8735
8736 tlv_len = 0;
8737
8738 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8739 < WLAN_NL_MAX_PAYLOAD) {
8740 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8741 sizeof(*ani_hdr) + len);
8742 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8743 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8744 radio_info->radio = radio;
8745 tlv_len = sizeof(*radio_info);
8746 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8747 "Added radio index tlv - radio index %d",
8748 radio_info->radio);
8749 }
8750
8751 nlh->nlmsg_len += tlv_len;
8752 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8753
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008754 nl_srv_bcast(skb);
8755
8756 return;
8757}
8758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008759#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8760void wlan_hdd_auto_shutdown_cb(void)
8761{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008762 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308763
8764 if (!hdd_ctx)
8765 return;
8766
Jeff Johnson28f8a772016-08-15 15:30:36 -07008767 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308768 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8769 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008770}
8771
8772void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8773{
8774 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308775 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008776 hdd_adapter_t *adapter;
8777 bool ap_connected = false, sta_connected = false;
8778 tHalHandle hal_handle;
8779
8780 hal_handle = hdd_ctx->hHal;
8781 if (hal_handle == NULL)
8782 return;
8783
8784 if (hdd_ctx->config->WlanAutoShutdown == 0)
8785 return;
8786
8787 if (enable == false) {
8788 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308789 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008790 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008791 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308792 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008793 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008794 return;
8795 }
8796
8797 /* To enable shutdown timer check conncurrency */
8798 if (cds_concurrent_open_sessions_running()) {
8799 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8800
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308801 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008802 adapter = adapterNode->pAdapter;
8803 if (adapter
8804 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008805 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008806 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8807 conn_info.connState ==
8808 eConnectionState_Associated) {
8809 sta_connected = true;
8810 break;
8811 }
8812 }
8813 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008814 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008815 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8816 bApActive == true) {
8817 ap_connected = true;
8818 break;
8819 }
8820 }
8821 status = hdd_get_next_adapter(hdd_ctx,
8822 adapterNode,
8823 &pNext);
8824 adapterNode = pNext;
8825 }
8826 }
8827
8828 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008829 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008830 return;
8831 } else {
8832 if (sme_set_auto_shutdown_timer(hal_handle,
8833 hdd_ctx->config->
8834 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308835 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008836 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008837 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008838 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008839 hdd_ctx->config->WlanAutoShutdown);
8840
8841 }
8842}
8843#endif
8844
8845hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8846 bool check_start_bss)
8847{
8848 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8849 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308850 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008851 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8852
8853 con_sap_adapter = NULL;
8854
8855 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308856 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008857 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008858 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8859 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008860 adapter != this_sap_adapter) {
8861 if (check_start_bss) {
8862 if (test_bit(SOFTAP_BSS_STARTED,
8863 &adapter->event_flags)) {
8864 con_sap_adapter = adapter;
8865 break;
8866 }
8867 } else {
8868 con_sap_adapter = adapter;
8869 break;
8870 }
8871 }
8872 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8873 adapterNode = pNext;
8874 }
8875
8876 return con_sap_adapter;
8877}
8878
8879#ifdef MSM_PLATFORM
8880void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8881{
8882 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8883
Anurag Chouhan210db072016-02-22 18:42:15 +05308884 if (QDF_TIMER_STATE_RUNNING ==
8885 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008886 return;
8887
Anurag Chouhan210db072016-02-22 18:42:15 +05308888 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008889 hdd_ctx->config->busBandwidthComputeInterval);
8890}
8891
8892void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8893{
8894 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308895 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008896 bool can_stop = true;
8897 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8898
Anurag Chouhan210db072016-02-22 18:42:15 +05308899 if (QDF_TIMER_STATE_RUNNING !=
8900 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008901 /* trying to stop timer, when not running is not good */
Srinivas Girigowda0ee96442016-08-17 19:10:56 -07008902 hdd_info("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008903 return;
8904 }
8905
8906 if (cds_concurrent_open_sessions_running()) {
8907 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8908
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308909 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008910 adapter = adapterNode->pAdapter;
8911 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008912 && (adapter->device_mode == QDF_STA_MODE
8913 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008914 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8915 conn_info.connState ==
8916 eConnectionState_Associated) {
8917 can_stop = false;
8918 break;
8919 }
8920 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008921 && (adapter->device_mode == QDF_SAP_MODE
8922 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008923 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8924 true) {
8925 can_stop = false;
8926 break;
8927 }
8928 status = hdd_get_next_adapter(hdd_ctx,
8929 adapterNode,
8930 &pNext);
8931 adapterNode = pNext;
8932 }
8933 }
8934
Ravi Joshib89e7f72016-09-07 13:43:15 -07008935 if (can_stop == true) {
Chris Guoc0c95bf2016-11-10 14:28:25 +08008936 /* reset the ipa perf level */
8937 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
Anurag Chouhan210db072016-02-22 18:42:15 +05308938 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Ravi Joshib89e7f72016-09-07 13:43:15 -07008939 hdd_reset_tcp_delack(hdd_ctx);
8940 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008941}
8942#endif
8943
8944/**
8945 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8946 * and sta's operating channel.
8947 * @sta_adapter: Describe the first argument to foobar.
8948 * @ap_adapter: Describe the second argument to foobar.
8949 * @roam_profile: Roam profile of AP to which STA wants to connect.
8950 * @concurrent_chnl_same: If both SAP and STA channels are same then
8951 * set this flag to true else false.
8952 *
8953 * This function checks the sap's operating channel and sta's operating channel.
8954 * if both are same then it will return false else it will restart the sap in
8955 * sta's channel and return true.
8956 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308957 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008958 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308959QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008960 hdd_adapter_t *ap_adapter,
8961 tCsrRoamProfile *roam_profile,
8962 tScanResultHandle *scan_cache,
8963 bool *concurrent_chnl_same)
8964{
8965 hdd_ap_ctx_t *hdd_ap_ctx;
8966 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308967 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008968 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008969 *concurrent_chnl_same = true;
8970
8971 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8972 status =
8973 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8974 roam_profile,
8975 scan_cache,
8976 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308977 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008978 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008979 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8980 if (hdd_ap_ctx->operatingChannel != channel_id) {
8981 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008982 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008983 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008984 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008985 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8986 if (hdd_ap_ctx->operatingChannel != channel_id) {
8987 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008988 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008989 }
8990 }
8991 } else {
8992 /*
8993 * Lets handle worst case scenario here, Scan cache lookup is
8994 * failed so we have to stop the SAP to avoid any channel
8995 * discrepancy between SAP's channel and STA's channel.
8996 * Return the status as failure so caller function could know
8997 * that scan look up is failed.
8998 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008999 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309000 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009001 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309002 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009003}
9004
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009005/**
9006 * wlan_hdd_stop_sap() - This function stops bss of SAP.
9007 * @ap_adapter: SAP adapter
9008 *
9009 * This function will process the stopping of sap adapter.
9010 *
9011 * Return: None
9012 */
9013void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
9014{
9015 hdd_ap_ctx_t *hdd_ap_ctx;
9016 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309017 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009018 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009019
9020 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009021 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009022 return;
9023 }
9024
9025 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9026 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309027 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009028 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309029
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009030 mutex_lock(&hdd_ctx->sap_lock);
9031 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08009032 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009033 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
9034 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009035 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309036 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309037 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009038 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309039 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309040 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009041 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309042 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009043 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009044 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009045 return;
9046 }
9047 }
9048 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08009049 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009050 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009051 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009052 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009053 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009054 }
9055 mutex_unlock(&hdd_ctx->sap_lock);
9056 return;
9057}
9058
9059/**
9060 * wlan_hdd_start_sap() - this function starts bss of SAP.
9061 * @ap_adapter: SAP adapter
9062 *
9063 * This function will process the starting of sap adapter.
9064 *
9065 * Return: None
9066 */
9067void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
9068{
9069 hdd_ap_ctx_t *hdd_ap_ctx;
9070 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309071 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009072 hdd_context_t *hdd_ctx;
9073 tsap_Config_t *sap_config;
9074
9075 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009076 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009077 return;
9078 }
9079
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009080 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07009081 hdd_err("SoftAp role has not been enabled");
9082 return;
9083 }
9084
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009085 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
9086 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9087 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9088 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
9089
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309090 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009091 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009093 mutex_lock(&hdd_ctx->sap_lock);
9094 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
9095 goto end;
9096
9097 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009098 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009099 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9100 goto end;
9101 }
9102
Wei Song2f76f642016-11-18 16:32:53 +08009103 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009104 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
9105 &hdd_ap_ctx->sapConfig,
9106 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309107 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009108 goto end;
9109
Jeff Johnson28f8a772016-08-15 15:30:36 -07009110 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309111 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009112 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309113 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009114 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009115 goto end;
9116 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07009117 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009118 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -08009119 if (hostapd_state->bssState == BSS_START)
9120 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009121 ap_adapter->sessionId);
9122 hostapd_state->bCommit = true;
9123
9124end:
9125 mutex_unlock(&hdd_ctx->sap_lock);
9126 return;
9127}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009128
9129/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08009130 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
9131 * mac scan config
9132 * @status: Status of set antenna mode
9133 *
9134 * Callback on setting the dual mac configuration
9135 *
9136 * Return: None
9137 */
9138void wlan_hdd_soc_set_antenna_mode_cb(
9139 enum set_antenna_mode_status status)
9140{
9141 hdd_context_t *hdd_ctx;
9142
9143 hdd_info("Status: %d", status);
9144
9145 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9146 if (0 != wlan_hdd_validate_context(hdd_ctx))
9147 return;
9148
9149 /* Signal the completion of set dual mac config */
9150 complete(&hdd_ctx->set_antenna_mode_cmpl);
9151}
9152
9153/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009154 * hdd_get_fw_version() - Get FW version
9155 * @hdd_ctx: pointer to HDD context.
9156 * @major_spid: FW version - major spid.
9157 * @minor_spid: FW version - minor spid
9158 * @ssid: FW version - ssid
9159 * @crmid: FW version - crmid
9160 *
9161 * This function is called to get the firmware build version stored
9162 * as part of the HDD context
9163 *
9164 * Return: None
9165 */
9166void hdd_get_fw_version(hdd_context_t *hdd_ctx,
9167 uint32_t *major_spid, uint32_t *minor_spid,
9168 uint32_t *siid, uint32_t *crmid)
9169{
9170 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
9171 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
9172 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
9173 *crmid = hdd_ctx->target_fw_version & 0x7fff;
9174}
9175
9176#ifdef QCA_CONFIG_SMP
9177/**
9178 * wlan_hdd_get_cpu() - get cpu_index
9179 *
9180 * Return: cpu_index
9181 */
9182int wlan_hdd_get_cpu(void)
9183{
9184 int cpu_index = get_cpu();
9185 put_cpu();
9186 return cpu_index;
9187}
9188#endif
9189
9190/**
9191 * hdd_get_fwpath() - get framework path
9192 *
9193 * This function is used to get the string written by
9194 * userspace to start the wlan driver
9195 *
9196 * Return: string
9197 */
9198const char *hdd_get_fwpath(void)
9199{
9200 return fwpath.string;
9201}
9202
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009203/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009204 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009205 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009206 * This function initilizes CDS global context with the help of cds_init. This
9207 * has to be the first function called after probe to get a valid global
9208 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009209 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009210 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009211 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009212int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009213{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009214 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009215 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009216
9217#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9218 wlan_logging_sock_init_svc();
9219#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009220 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009221
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009222 if (p_cds_context == NULL) {
9223 hdd_alert("Failed to allocate CDS context");
9224 ret = -ENOMEM;
9225 goto err_out;
9226 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009227
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009228 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309229 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009230
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009231err_out:
9232 return ret;
9233}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009234
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009235/**
9236 * hdd_deinit() - Deinitialize Driver
9237 *
9238 * This function frees CDS global context with the help of cds_deinit. This
9239 * has to be the last function call in remove callback to free the global
9240 * context.
9241 */
9242void hdd_deinit(void)
9243{
9244 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009245
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009246#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9247 wlan_logging_sock_deinit_svc();
9248#endif
9249}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009250
9251#ifdef QCA_WIFI_3_0_ADRASTEA
9252#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
9253#else
9254#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
9255#endif
9256
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009257/**
9258 * __hdd_module_init - Module init helper
9259 *
9260 * Module init helper function used by both module and static driver.
9261 *
9262 * Return: 0 for success, errno on failure
9263 */
9264static int __hdd_module_init(void)
9265{
9266 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009267
Arun Khandavallifae92942016-08-01 13:31:08 +05309268 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009269 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009270
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009271 pld_init();
9272
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309273 ret = hdd_init();
9274 if (ret) {
9275 pr_err("hdd_init failed %x\n", ret);
9276 goto err_hdd_init;
9277 }
9278
Rajeev Kumar97767a02016-11-30 11:20:40 -08009279 dispatcher_init();
9280
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309281 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009282
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009283 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009284
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009285 ret = wlan_hdd_register_driver();
9286 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07009287 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
9288 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009289 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009290 }
9291
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309292 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009293
9294 return 0;
9295out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309296 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -08009297 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309298 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009299
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309300err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009301 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009302
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009303 return ret;
9304}
9305
9306/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309307 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
9308 *
9309 * Block the unloading of the driver until the cds recovery is completed
9310 *
9311 * Return: None
9312 */
9313static void hdd_wait_for_recovery_completion(void)
9314{
9315 int retry = 0;
9316
9317 /* Wait for recovery to complete */
9318 while (cds_is_driver_recovering()) {
9319 hdd_alert("Recovery in progress; wait here!!!");
9320 msleep(1000);
9321 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
9322 hdd_alert("SSR never completed, fatal error");
9323 QDF_BUG(0);
9324 }
9325 }
9326}
9327
9328/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009329 * __hdd_module_exit - Module exit helper
9330 *
9331 * Module exit helper function used by both module and static driver.
9332 */
9333static void __hdd_module_exit(void)
9334{
9335 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
9336 QWLAN_VERSIONSTR);
9337
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309338 hdd_wait_for_recovery_completion();
9339
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009340 wlan_hdd_unregister_driver();
9341
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309342 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009343
Rajeev Kumar97767a02016-11-30 11:20:40 -08009344 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309345 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009346 pld_deinit();
9347
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009348 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009349}
9350
Arun Khandavallifae92942016-08-01 13:31:08 +05309351#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009352/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309353 * wlan_boot_cb() - Wlan boot callback
9354 * @kobj: object whose directory we're creating the link in.
9355 * @attr: attribute the user is interacting with
9356 * @buff: the buffer containing the user data
9357 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009358 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309359 * This callback is invoked when the fs is ready to start the
9360 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009361 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309362 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009363 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309364static ssize_t wlan_boot_cb(struct kobject *kobj,
9365 struct kobj_attribute *attr,
9366 const char *buf,
9367 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009368{
Arun Khandavallifae92942016-08-01 13:31:08 +05309369
9370 int ret = 0;
9371
9372 if (wlan_loader->loaded_state) {
9373 pr_info("Wlan driver already initialized");
9374 return 0;
9375 }
9376
9377
9378 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9379 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9380
9381 if (__hdd_module_init()) {
9382 pr_err("%s: Failed to register handler\n", __func__);
9383 ret = -EINVAL;
9384 } else
9385 wlan_loader->loaded_state = MODULE_INITIALIZED;
9386
9387 return count;
9388
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009389}
Arun Khandavallifae92942016-08-01 13:31:08 +05309390
9391/**
9392 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
9393 * ready
9394 *
9395 * This is creates the syfs entry boot_wlan. Which shall be invoked
9396 * when the filesystem is ready.
9397 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009398 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +05309399 */
9400static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009401{
Arun Khandavallifae92942016-08-01 13:31:08 +05309402 int ret = -EINVAL;
9403
9404 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
9405 if (!wlan_loader) {
9406 pr_err("%s: memory alloc failed\n", __func__);
9407 ret = -ENOMEM;
9408 return ret;
9409 }
9410
9411 wlan_loader->boot_wlan_obj = NULL;
9412 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
9413 GFP_KERNEL);
9414 if (!wlan_loader->attr_group) {
9415 pr_err("%s: malloc attr_group failed\n", __func__);
9416 ret = -ENOMEM;
9417 goto error_return;
9418 }
9419
9420 wlan_loader->loaded_state = 0;
9421 wlan_loader->attr_group->attrs = attrs;
9422
9423 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
9424 kernel_kobj);
9425 if (!wlan_loader->boot_wlan_obj) {
9426 pr_err("%s: sysfs create and add failed\n", __func__);
9427 ret = -ENOMEM;
9428 goto error_return;
9429 }
9430
9431 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
9432 wlan_loader->attr_group);
9433 if (ret) {
9434 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
9435 goto error_return;
9436 }
9437
9438 return 0;
9439
9440error_return:
9441
9442 if (wlan_loader->boot_wlan_obj) {
9443 kobject_del(wlan_loader->boot_wlan_obj);
9444 wlan_loader->boot_wlan_obj = NULL;
9445 }
9446
9447 return ret;
9448}
9449
9450/**
9451 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
9452 *
9453 * Return: 0 on success or errno on failure
9454 */
9455static int wlan_deinit_sysfs(void)
9456{
9457
9458 if (!wlan_loader) {
9459 hdd_alert("wlan loader context is Null!");
9460 return -EINVAL;
9461 }
9462
9463 if (wlan_loader->boot_wlan_obj) {
9464 sysfs_remove_group(wlan_loader->boot_wlan_obj,
9465 wlan_loader->attr_group);
9466 kobject_del(wlan_loader->boot_wlan_obj);
9467 wlan_loader->boot_wlan_obj = NULL;
9468 }
9469
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009470 return 0;
9471}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009472
Arun Khandavallifae92942016-08-01 13:31:08 +05309473#endif
9474
9475#ifdef MODULE
9476/**
9477 * __hdd_module_init - Module init helper
9478 *
9479 * Module init helper function used by both module and static driver.
9480 *
9481 * Return: 0 for success, errno on failure
9482 */
9483static int hdd_module_init(void)
9484{
9485 int ret = 0;
9486
9487 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9488 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9489
9490 if (__hdd_module_init()) {
9491 pr_err("%s: Failed to register handler\n", __func__);
9492 ret = -EINVAL;
9493 }
9494
9495 return ret;
9496}
9497#else
9498static int __init hdd_module_init(void)
9499{
9500 int ret = -EINVAL;
9501
9502 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009503 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +05309504 pr_err("Failed to create sysfs entry for loading wlan");
9505
9506 return ret;
9507}
9508#endif
9509
9510
9511#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009512/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009513 * hdd_module_exit() - Exit function
9514 *
9515 * This is the driver exit point (invoked when module is unloaded using rmmod)
9516 *
9517 * Return: None
9518 */
9519static void __exit hdd_module_exit(void)
9520{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009521 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009522}
Arun Khandavallifae92942016-08-01 13:31:08 +05309523#else
9524static void __exit hdd_module_exit(void)
9525{
9526 __hdd_module_exit();
9527 wlan_deinit_sysfs();
9528}
9529#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009530
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009531static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
9532{
9533 return param_set_copystring(kmessage, kp);
9534}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009535
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309536/**
9537 * is_con_mode_valid() check con mode is valid or not
9538 * @mode: global con mode
9539 *
9540 * Return: TRUE on success FALSE on failure
9541 */
9542static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
9543{
9544 switch (mode) {
9545 case QDF_GLOBAL_MONITOR_MODE:
9546 case QDF_GLOBAL_FTM_MODE:
9547 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309548 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309549 return true;
9550 default:
9551 return false;
9552 }
9553}
9554
9555/**
9556 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
9557 * @mode: global con mode
9558 *
9559 * Return: adapter mode
9560 */
9561static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
9562 enum tQDF_GLOBAL_CON_MODE mode)
9563{
9564
9565 switch (mode) {
9566 case QDF_GLOBAL_MISSION_MODE:
9567 return QDF_STA_MODE;
9568 case QDF_GLOBAL_MONITOR_MODE:
9569 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309570 case QDF_GLOBAL_EPPING_MODE:
9571 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309572 case QDF_GLOBAL_FTM_MODE:
9573 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309574 case QDF_GLOBAL_QVIT_MODE:
9575 return QDF_QVIT_MODE;
9576 default:
9577 return QDF_MAX_NO_OF_MODE;
9578 }
9579}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009580
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309581static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
9582 enum tQDF_GLOBAL_CON_MODE curr_mode)
9583{
9584 switch (curr_mode) {
9585 case QDF_GLOBAL_MISSION_MODE:
9586 case QDF_GLOBAL_MONITOR_MODE:
9587 case QDF_GLOBAL_FTM_MODE:
9588 hdd_abort_mac_scan_all_adapters(hdd_ctx);
9589 hdd_stop_all_adapters(hdd_ctx);
9590 hdd_deinit_all_adapters(hdd_ctx, false);
9591 hdd_close_all_adapters(hdd_ctx, false);
9592 break;
9593 case QDF_GLOBAL_EPPING_MODE:
9594 epping_disable();
9595 epping_close();
9596 break;
9597 default:
9598 return;
9599 }
9600}
9601
9602static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
9603 enum tQDF_GLOBAL_CON_MODE mode)
9604{
9605 hdd_adapter_t *adapter;
9606 int ret = 0;
9607 bool rtnl_held;
9608 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
9609 QDF_STATUS status;
9610
9611 if (!qdf_dev) {
9612 hdd_err("qdf device context is Null return!");
9613 return -EINVAL;
9614 }
9615
9616 rtnl_held = hdd_hold_rtnl_lock();
9617 switch (mode) {
9618 case QDF_GLOBAL_MISSION_MODE:
9619 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
9620 if (IS_ERR(adapter)) {
9621 hdd_alert("Failed to open interface, adapter is NULL");
9622 ret = -EINVAL;
9623 }
9624 break;
9625 case QDF_GLOBAL_FTM_MODE:
9626 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
9627 wlan_hdd_get_intf_addr(hdd_ctx),
9628 NET_NAME_UNKNOWN, rtnl_held);
9629 if (adapter == NULL)
9630 ret = -EINVAL;
9631 break;
9632 case QDF_GLOBAL_MONITOR_MODE:
9633 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
9634 wlan_hdd_get_intf_addr(hdd_ctx),
9635 NET_NAME_UNKNOWN, rtnl_held);
9636 if (adapter == NULL)
9637 ret = -EINVAL;
9638 break;
9639 case QDF_GLOBAL_EPPING_MODE:
9640 status = epping_open();
9641 if (status != QDF_STATUS_SUCCESS) {
9642 hdd_err("Failed to open in eeping mode: %d", status);
9643 ret = -EINVAL;
9644 break;
9645 }
9646 ret = epping_enable(qdf_dev->dev);
9647 if (ret) {
9648 hdd_err("Failed to enable in epping mode : %d", ret);
9649 epping_close();
9650 }
9651 break;
9652 default:
9653 hdd_info("Mode not supported");
9654 ret = -ENOTSUPP;
9655 break;
9656 }
9657 hdd_release_rtnl_lock();
9658 rtnl_held = false;
9659 return ret;
9660}
9661
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009662/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309663 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309664 * @kmessage: con mode name on which driver to be bring up
9665 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309666 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009667 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309668 * This function is invoked when user updates con mode using sys entry,
9669 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009670 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309671 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009672 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309673static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
9674 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009675{
9676 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309677 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309678 enum tQDF_GLOBAL_CON_MODE curr_mode;
9679 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309680
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309681 ret = wlan_hdd_validate_context(hdd_ctx);
9682 if (ret)
9683 return ret;
9684
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309685 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009686
Arun Khandavallifae92942016-08-01 13:31:08 +05309687 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009688 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05309689
Arun Khandavallifae92942016-08-01 13:31:08 +05309690
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309691
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309692 if (!(is_con_mode_valid(con_mode))) {
9693 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309694 ret = -EINVAL;
9695 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309696 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309697
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309698 curr_mode = hdd_get_conparam();
9699 if (curr_mode == con_mode) {
9700 hdd_err("curr mode: %d is same as user triggered mode %d",
9701 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309702 ret = 0;
9703 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309704 }
9705
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309706 /* Cleanup present mode before switching to new mode */
9707 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05309708
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07009709 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309710 if (ret) {
9711 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309712 goto reset_flags;
9713 }
9714
9715 hdd_set_conparam(con_mode);
9716
9717 /* Register for new con_mode & then kick_start modules again */
9718 ret = hdd_register_req_mode(hdd_ctx, con_mode);
9719 if (ret) {
9720 hdd_err("Failed to register for new mode");
9721 goto reset_flags;
9722 }
9723
9724 adapter_mode = hdd_get_adpter_mode(con_mode);
9725 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
9726 hdd_err("invalid adapter");
9727 ret = -EINVAL;
9728 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309729 }
9730
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309731 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309732 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309733 hdd_err("Failed to get adapter:%d", adapter_mode);
9734 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309735 }
9736
9737 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
9738 if (ret) {
9739 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309740 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309741 }
9742
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309743 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
9744 con_mode == QDF_GLOBAL_FTM_MODE) {
9745 if (hdd_start_adapter(adapter)) {
9746 hdd_err("Failed to start %s adapter", kmessage);
9747 ret = -EINVAL;
9748 goto reset_flags;
9749 }
Arun Khandavallifae92942016-08-01 13:31:08 +05309750 }
9751
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309752 hdd_info("Mode successfully changed to %s", kmessage);
9753 ret = 0;
9754
9755reset_flags:
9756 cds_set_load_in_progress(false);
9757 return ret;
9758}
9759
9760
9761static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
9762{
9763 int ret;
9764 hdd_context_t *hdd_ctx;
9765
9766 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9767 ret = wlan_hdd_validate_context(hdd_ctx);
9768 if (ret)
9769 return ret;
9770
9771 cds_ssr_protect(__func__);
9772 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
9773 cds_ssr_unprotect(__func__);
9774
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009775 return ret;
9776}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009777
9778/**
9779 * hdd_get_conparam() - driver exit point
9780 *
9781 * This is the driver exit point (invoked when module is unloaded using rmmod)
9782 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309783 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009784 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309785enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009786{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309787 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009788}
9789
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009790void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009791{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009792 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009793}
9794
Komal Seelamc11bb222016-01-27 18:57:10 +05309795/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309796 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9797 * @hdd_ctx: HDD context
9798 *
9799 * Cleans up the pre cac interface, if it exists
9800 *
9801 * Return: None
9802 */
9803void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9804{
9805 uint8_t session_id;
9806 QDF_STATUS status;
9807 struct hdd_adapter_s *precac_adapter;
9808
9809 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9810 if (QDF_IS_STATUS_ERROR(status)) {
9811 hdd_err("failed to get pre cac vdev id");
9812 return;
9813 }
9814
9815 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9816 if (!precac_adapter) {
9817 hdd_err("invalid pre cac adapater");
9818 return;
9819 }
9820
9821 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9822 wlan_hdd_sap_pre_cac_failure,
9823 (void *)precac_adapter);
9824 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9825
9826}
9827
9828/**
Komal Seelamec702b02016-02-24 18:42:16 +05309829 * hdd_update_ol_config - API to update ol configuration parameters
9830 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309831 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309832 * Return: void
9833 */
Komal Seelamec702b02016-02-24 18:42:16 +05309834static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309835{
Komal Seelamec702b02016-02-24 18:42:16 +05309836 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309837 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309838
Komal Seelamec702b02016-02-24 18:42:16 +05309839 if (!ol_ctx)
9840 return;
9841
9842 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9843 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9844 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9845 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -07009846 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +05309847
9848 ol_init_ini_config(ol_ctx, &cfg);
9849}
9850
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009851#ifdef FEATURE_RUNTIME_PM
9852/**
9853 * hdd_populate_runtime_cfg() - populate runtime configuration
9854 * @hdd_ctx: hdd context
9855 * @cfg: pointer to the configuration memory being populated
9856 *
9857 * Return: void
9858 */
9859static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9860 struct hif_config_info *cfg)
9861{
9862 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9863 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9864}
9865#else
9866static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9867 struct hif_config_info *cfg)
9868{
9869}
9870#endif
9871
Komal Seelamec702b02016-02-24 18:42:16 +05309872/**
9873 * hdd_update_hif_config - API to update HIF configuration parameters
9874 * @hdd_ctx: HDD Context
9875 *
9876 * Return: void
9877 */
9878static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9879{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309880 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309881 struct hif_config_info cfg;
9882
9883 if (!scn)
9884 return;
9885
9886 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009887 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05309888 hif_init_ini_config(scn, &cfg);
9889}
9890
9891/**
9892 * hdd_update_config() - Initialize driver per module ini parameters
9893 * @hdd_ctx: HDD Context
9894 *
9895 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309896 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05309897 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309898int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05309899{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309900 int ret;
9901
Komal Seelamec702b02016-02-24 18:42:16 +05309902 hdd_update_ol_config(hdd_ctx);
9903 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309904 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
9905 ret = hdd_update_cds_config_ftm(hdd_ctx);
9906 else
9907 ret = hdd_update_cds_config(hdd_ctx);
9908
9909 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05309910}
9911
Agrawal Ashish65634612016-08-18 13:24:32 +05309912/**
9913 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
9914 * @mode : cfg80211 DFS mode
9915 *
9916 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
9917 */
9918enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
9919{
9920 switch (mode) {
9921 case DFS_MODE_ENABLE:
9922 return ACS_DFS_MODE_ENABLE;
9923 break;
9924 case DFS_MODE_DISABLE:
9925 return ACS_DFS_MODE_DISABLE;
9926 break;
9927 case DFS_MODE_DEPRIORITIZE:
9928 return ACS_DFS_MODE_DEPRIORITIZE;
9929 break;
9930 default:
9931 hdd_err("ACS dfs mode is NONE");
9932 return ACS_DFS_MODE_NONE;
9933 }
9934}
9935
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309936/**
9937 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
9938 * @hddctx: pointer to hdd context
9939 * @set_value: enable/disable
9940 *
9941 * When Host sends vendor command enable, FW will send *ONE* CA ind to
9942 * Host(even though it is duplicate). When Host send vendor command
9943 * disable,FW doesn't perform any action. Whenever any change in
9944 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
9945 *
9946 * return - 0 on success, appropriate error values on failure.
9947 */
9948int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
9949{
9950 QDF_STATUS status;
9951
9952 if (0 != wlan_hdd_validate_context(hddctx)) {
9953 return -EAGAIN;
9954 }
9955
9956 if (!hddctx->config->goptimize_chan_avoid_event) {
9957 hdd_warn("goptimize_chan_avoid_event ini param disabled");
9958 return -EINVAL;
9959 }
9960
9961 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
9962 if (!QDF_IS_STATUS_SUCCESS(status)) {
9963 hdd_err("Failed to send chan avoid command to SME");
9964 return -EINVAL;
9965 }
9966 return 0;
9967}
Agrawal Ashish65634612016-08-18 13:24:32 +05309968
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -08009969/**
9970 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
9971 * @value: value to set
9972 *
9973 * This function will set the passed value to roaming in progress flag.
9974 *
9975 * Return: None
9976 */
9977void hdd_set_roaming_in_progress(bool value)
9978{
9979 hdd_context_t *hdd_ctx;
9980
9981 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9982 if (!hdd_ctx) {
9983 hdd_err("HDD context is NULL");
9984 return;
9985 }
9986
9987 hdd_ctx->roaming_in_progress = value;
9988 hdd_info("Roaming in Progress set to %d", value);
9989}
9990
9991/**
9992 * hdd_is_roaming_in_progress() - check if roaming is in progress
9993 * @hdd_ctx - HDD context
9994 *
9995 * Return: true if roaming is in progress else false
9996 */
9997bool hdd_is_roaming_in_progress(void)
9998{
9999 hdd_context_t *hdd_ctx;
10000
10001 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10002 if (!hdd_ctx) {
10003 hdd_err("HDD context is NULL");
10004 return false;
10005 }
10006 return hdd_ctx->roaming_in_progress;
10007}
10008
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +053010009QDF_STATUS hdd_create_and_store_psoc(hdd_context_t *hdd_ctx, uint8_t psoc_id)
10010{
10011 struct wlan_objmgr_psoc *psoc;
10012
10013 psoc = wlan_objmgr_psoc_obj_create(psoc_id, WLAN_DEV_OL);
10014 if (!psoc)
10015 return QDF_STATUS_E_FAILURE;
10016
10017 hdd_ctx->hdd_psoc = psoc;
10018
10019 return QDF_STATUS_SUCCESS;
10020}
10021
Rajeev Kumar1cba9d02017-01-06 11:36:14 -080010022QDF_STATUS hdd_release_and_destroy_psoc(hdd_context_t *hdd_ctx)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +053010023{
10024 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10025
10026 hdd_ctx->hdd_psoc = NULL;
10027 if (psoc) {
10028 wlan_objmgr_psoc_obj_delete(psoc);
10029 return QDF_STATUS_SUCCESS;
10030 } else
10031 return QDF_STATUS_E_FAILURE;
10032}
10033
10034QDF_STATUS hdd_create_and_store_pdev(hdd_context_t *hdd_ctx)
10035{
10036 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10037 struct wlan_objmgr_pdev *pdev;
10038
10039 if (!psoc) {
10040 hdd_err("Psoc NULL");
10041 return QDF_STATUS_E_FAILURE;
10042 }
10043
10044 pdev = wlan_objmgr_pdev_obj_create(psoc, NULL);
10045 if (!pdev) {
10046 hdd_err("pdev obj create failed");
10047 return QDF_STATUS_E_FAILURE;
10048 }
10049 hdd_ctx->hdd_pdev = pdev;
10050
10051 return QDF_STATUS_SUCCESS;
10052}
10053
Rajeev Kumar3a6c13c2017-01-06 13:01:08 -080010054QDF_STATUS hdd_release_and_destroy_pdev(hdd_context_t *hdd_ctx)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +053010055{
10056 struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
10057
10058 hdd_ctx->hdd_pdev = NULL;
10059 if (pdev) {
10060 wlan_objmgr_pdev_obj_delete(pdev);
10061 return QDF_STATUS_SUCCESS;
10062 } else
10063 return QDF_STATUS_E_FAILURE;
10064}
10065
10066QDF_STATUS hdd_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
10067 hdd_adapter_t *adapter)
10068{
10069 struct wlan_objmgr_vdev *vdev;
10070 struct wlan_objmgr_peer *peer;
10071 struct wlan_vdev_create_params vdev_params;
10072
10073 vdev_params.opmode = adapter->device_mode;
10074 qdf_mem_copy(vdev_params.macaddr, adapter->macAddressCurrent.bytes,
10075 QDF_NET_MAC_ADDR_MAX_LEN);
10076 if (!pdev) {
10077 hdd_err("pdev NULL");
10078 return QDF_STATUS_E_FAILURE;
10079 }
10080
10081 vdev = wlan_objmgr_vdev_obj_create(pdev, &vdev_params);
10082 if (!vdev) {
10083 hdd_err("vdev obj create fails");
10084 return QDF_STATUS_E_FAILURE;
10085 }
10086
10087 if (adapter->sessionId != wlan_vdev_get_id(vdev)) {
10088 hdd_err("session id and vdev id mismatch");
10089 wlan_objmgr_vdev_obj_delete(vdev);
10090 QDF_ASSERT(0);
10091 return QDF_STATUS_E_FAILURE;
10092 }
10093
10094 peer = wlan_objmgr_peer_obj_create(vdev, WLAN_PEER_SELF,
10095 vdev_params.macaddr);
10096 if (!peer) {
10097 hdd_err("obj manager self peer create fails for adapter %d",
10098 adapter->device_mode);
10099 wlan_objmgr_vdev_obj_delete(vdev);
10100 return QDF_STATUS_E_FAILURE;
10101 }
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +053010102 wlan_objmgr_peer_ref_peer(peer);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +053010103 adapter->hdd_vdev = vdev;
10104
10105 return QDF_STATUS_SUCCESS;
10106}
10107
Rajeev Kumarba778852017-01-06 13:23:04 -080010108QDF_STATUS hdd_release_and_destroy_vdev(hdd_adapter_t *adapter)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +053010109{
10110 struct wlan_objmgr_vdev *vdev = adapter->hdd_vdev;
10111
10112 adapter->hdd_vdev = NULL;
10113 if (vdev) {
10114 if (hdd_remove_peer_object(vdev,
10115 wlan_vdev_mlme_get_macaddr(vdev))) {
10116 hdd_err("Self peer delete fails");
10117 return QDF_STATUS_E_FAILURE;
10118 }
10119
10120 wlan_objmgr_vdev_obj_delete(vdev);
10121 return QDF_STATUS_SUCCESS;
10122 } else
10123 return QDF_STATUS_E_FAILURE;
10124}
10125
10126QDF_STATUS hdd_add_peer_object(struct wlan_objmgr_vdev *vdev,
10127 enum tQDF_ADAPTER_MODE adapter_mode,
10128 uint8_t *mac_addr)
10129{
10130 enum wlan_peer_type peer_type;
10131
10132 if ((adapter_mode == QDF_STA_MODE) ||
10133 (adapter_mode == QDF_P2P_CLIENT_MODE))
10134 peer_type = WLAN_PEER_AP;
10135 else if ((adapter_mode == QDF_SAP_MODE) ||
10136 (adapter_mode == QDF_P2P_GO_MODE))
10137 peer_type = WLAN_PEER_STA;
10138 else if (adapter_mode == QDF_IBSS_MODE)
10139 peer_type = WLAN_PEER_IBSS;
10140 else {
10141 hdd_err("Unsupported device mode %d", adapter_mode);
10142 return QDF_STATUS_E_FAILURE;
10143 }
10144
10145 if (!vdev) {
10146 hdd_err("vdev NULL");
10147 QDF_ASSERT(0);
10148 return QDF_STATUS_E_FAILURE;
10149 }
10150
10151 if (!wlan_objmgr_peer_obj_create(vdev, peer_type, mac_addr))
10152 return QDF_STATUS_E_FAILURE;
10153
10154 hdd_info("Peer object "MAC_ADDRESS_STR" add success!",
10155 MAC_ADDR_ARRAY(mac_addr));
10156
10157 return QDF_STATUS_SUCCESS;
10158}
10159
10160QDF_STATUS hdd_remove_peer_object(struct wlan_objmgr_vdev *vdev,
10161 uint8_t *mac_addr)
10162{
10163 struct wlan_objmgr_psoc *psoc;
10164 struct wlan_objmgr_peer *peer;
10165
10166 if (!vdev) {
10167 hdd_err("vdev NULL");
10168 QDF_ASSERT(0);
10169 return QDF_STATUS_E_FAILURE;
10170 }
10171
10172 psoc = wlan_vdev_get_psoc(vdev);
10173 if (!psoc) {
10174 hdd_err("Psoc NUll");
10175 QDF_ASSERT(0);
10176 return QDF_STATUS_E_FAILURE;
10177 }
10178
10179 peer = wlan_objmgr_find_peer(psoc, mac_addr);
10180 if (peer) {
10181 if (wlan_objmgr_peer_obj_delete(peer))
10182 return QDF_STATUS_E_FAILURE;
10183
10184 hdd_info("Peer obj "MAC_ADDRESS_STR" deleted",
10185 MAC_ADDR_ARRAY(mac_addr));
10186 return QDF_STATUS_SUCCESS;
10187 }
10188
10189 hdd_err("Peer obj "MAC_ADDRESS_STR" not found",
10190 MAC_ADDR_ARRAY(mac_addr));
10191
10192 return QDF_STATUS_E_FAILURE;
10193}
10194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010195/* Register the module init/exit functions */
10196module_init(hdd_module_init);
10197module_exit(hdd_module_exit);
10198
10199MODULE_LICENSE("Dual BSD/GPL");
10200MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10201MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10204 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010205
10206module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
10207 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
10208
10209module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
10210
10211module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
10212
10213module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);