blob: 39e21598a99a7a417054c0572e0c31905f845cbd [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
Jeff Johnson94be11c2016-08-15 15:39:25 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038/* Include Files */
39#include <wlan_hdd_includes.h>
40#include <cds_api.h>
41#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053042#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#include <linux/etherdevice.h>
44#include <linux/firmware.h>
45#include <wlan_hdd_tx_rx.h>
46#include <wni_api.h>
47#include <wlan_hdd_cfg.h>
48#include <wlan_ptt_sock_svc.h>
49#include <dbglog_host.h>
50#include <wlan_logging_sock_svc.h>
51#include <wlan_hdd_wowl.h>
52#include <wlan_hdd_misc.h>
53#include <wlan_hdd_wext.h>
54#include "wlan_hdd_trace.h"
55#include "wlan_hdd_ioctl.h"
56#include "wlan_hdd_ftm.h"
57#include "wlan_hdd_power.h"
58#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070059#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070062#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063
64#include <net/addrconf.h>
65#include <linux/wireless.h>
66#include <net/cfg80211.h>
67#include <linux/inetdevice.h>
68#include <net/addrconf.h>
69#include "wlan_hdd_cfg80211.h"
70#include "wlan_hdd_ext_scan.h"
71#include "wlan_hdd_p2p.h"
72#include <linux/rtnetlink.h>
73#include "sap_api.h"
74#include <linux/semaphore.h>
75#include <linux/ctype.h>
76#include <linux/compat.h>
77#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078#include <soc/qcom/subsystem_restart.h>
79#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080#include <wlan_hdd_hostapd.h>
81#include <wlan_hdd_softap_tx_rx.h>
82#include "cfg_api.h"
83#include "qwlan_version.h"
84#include "wma_types.h"
85#include "wlan_hdd_tdls.h"
86#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053087#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080088#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070090#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080091#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#include "wlan_hdd_nan.h"
93#include "wlan_hdd_debugfs.h"
94#include "wlan_hdd_driver_ops.h"
95#include "epping_main.h"
96#include "wlan_hdd_memdump.h"
97
98#include <wlan_hdd_ipa.h>
99#include "hif.h"
100#include "wma.h"
101#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700102#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530104#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700105#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530106#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700107#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530108#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700109#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530110#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800111#include <dispatcher_init_deinit.h>
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +0530112#include <wlan_objmgr_cmn.h>
113#include <wlan_objmgr_global_obj.h>
114#include <wlan_objmgr_psoc_obj.h>
115#include <wlan_objmgr_pdev_obj.h>
116#include <wlan_objmgr_vdev_obj.h>
117#include <wlan_objmgr_peer_obj.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800118
119#ifdef MODULE
120#define WLAN_MODULE_NAME module_name(THIS_MODULE)
121#else
122#define WLAN_MODULE_NAME "wlan"
123#endif
124
125#ifdef TIMER_MANAGER
126#define TIMER_MANAGER_STR " +TIMER_MANAGER"
127#else
128#define TIMER_MANAGER_STR ""
129#endif
130
131#ifdef MEMORY_DEBUG
132#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
133#else
134#define MEMORY_DEBUG_STR ""
135#endif
136
Arun Khandavallifae92942016-08-01 13:31:08 +0530137#ifndef MODULE
138static struct gwlan_loader *wlan_loader;
139static ssize_t wlan_boot_cb(struct kobject *kobj,
140 struct kobj_attribute *attr,
141 const char *buf, size_t count);
142struct gwlan_loader {
143 bool loaded_state;
144 struct kobject *boot_wlan_obj;
145 struct attribute_group *attr_group;
146};
147
148static struct kobj_attribute wlan_boot_attribute =
149 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
150
151static struct attribute *attrs[] = {
152 &wlan_boot_attribute.attr,
153 NULL,
154};
155
156#define MODULE_INITIALIZED 1
157#endif
158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159/* the Android framework expects this param even though we don't use it */
160#define BUF_LEN 20
161static char fwpath_buffer[BUF_LEN];
162static struct kparam_string fwpath = {
163 .string = fwpath_buffer,
164 .maxlen = BUF_LEN,
165};
166
167static char *country_code;
168static int enable_11d = -1;
169static int enable_dfs_chan_scan = -1;
170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800171/*
172 * spinlock for synchronizing asynchronous request/response
173 * (full description of use in wlan_hdd_main.h)
174 */
175DEFINE_SPINLOCK(hdd_context_lock);
176
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800177#define WLAN_NLINK_CESIUM 30
178
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530179static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180
181#define WOW_MAX_FILTER_LISTS 1
182#define WOW_MAX_FILTERS_PER_LIST 4
183#define WOW_MIN_PATTERN_SIZE 6
184#define WOW_MAX_PATTERN_SIZE 64
185
186#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
187static const struct wiphy_wowlan_support wowlan_support_reg_init = {
188 .flags = WIPHY_WOWLAN_ANY |
189 WIPHY_WOWLAN_MAGIC_PKT |
190 WIPHY_WOWLAN_DISCONNECT |
191 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
192 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
193 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
194 WIPHY_WOWLAN_4WAY_HANDSHAKE |
195 WIPHY_WOWLAN_RFKILL_RELEASE,
196 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
197 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
198 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
199};
200#endif
201
202/* internal function declaration */
203
204struct sock *cesium_nl_srv_sock;
205
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
207void wlan_hdd_auto_shutdown_cb(void);
208#endif
209
210/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530211 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
212 * @hdd_ctx: pointer to hdd_context_t
213 *
214 * Return: none
215 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700216static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530217{
218 hdd_adapter_t *adapter;
219 hdd_adapter_list_node_t *adapter_node, *next;
220 QDF_STATUS status = QDF_STATUS_SUCCESS;
221
222 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
223 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
224 adapter = adapter_node->pAdapter;
225 if (NULL != adapter)
226 hdd_send_rps_ind(adapter);
227 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
228 adapter_node = next;
229 }
230}
231
232/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
234 * @vdev_id: vdev_id
235 * @action: action type
236 * @reason: reason type
237 *
238 * Return: none
239 */
240void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
241 enum netif_action_type action, enum netif_reason_type reason)
242{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530243 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800244 hdd_adapter_t *adapter;
245
246 if (!hdd_ctx) {
247 hdd_err("hdd ctx is NULL");
248 return;
249 }
250 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
251
252 wlan_hdd_netif_queue_control(adapter, action, reason);
253 return;
254}
255
256/*
257 * Store WLAN driver version info in a global variable such that crash debugger
258 * can extract it from driver debug symbol and crashdump for post processing
259 */
260uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
261
262/**
263 * hdd_device_mode_to_string() - return string conversion of device mode
264 * @device_mode: device mode
265 *
266 * This utility function helps log string conversion of device mode.
267 *
268 * Return: string conversion of device mode, if match found;
269 * "Unknown" otherwise.
270 */
271const char *hdd_device_mode_to_string(uint8_t device_mode)
272{
273 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800274 CASE_RETURN_STRING(QDF_STA_MODE);
275 CASE_RETURN_STRING(QDF_SAP_MODE);
276 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
277 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
278 CASE_RETURN_STRING(QDF_FTM_MODE);
279 CASE_RETURN_STRING(QDF_IBSS_MODE);
280 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
281 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700282 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800283 default:
284 return "Unknown";
285 }
286}
287
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530288/**
289 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
290 * @adapter: HDD adapter
291 * @chan_number: Channel number
292 * @chan_bw: Bandwidth
293 *
294 * Checks if the given bandwidth is valid for the given channel number.
295 *
296 * Return: 0 for success, non-zero for failure
297 */
298int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
299 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800300 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530301{
302 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
303 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
304 bool found = false;
305 tHalHandle hal;
306
307 hal = WLAN_HDD_GET_HAL_CTX(adapter);
308 if (!hal) {
309 hdd_err("Invalid HAL context");
310 return -EINVAL;
311 }
312
313 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
314 hdd_err("No valid channel list");
315 return -EOPNOTSUPP;
316 }
317
318 for (i = 0; i < len; i++) {
319 if (chan[i] == chan_number) {
320 found = true;
321 break;
322 }
323 }
324
325 if (found == false) {
326 hdd_err("Channel not in driver's valid channel list");
327 return -EOPNOTSUPP;
328 }
329
330 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
331 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
332 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
333 return -EINVAL;
334 }
335
336 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
337 if (chan_bw == CH_WIDTH_80MHZ) {
338 hdd_err("BW80 not possible in 2.4GHz band");
339 return -EINVAL;
340 }
341 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
342 (chan_bw != CH_WIDTH_MAX)) {
343 hdd_err("Only BW20 possible on channel 14");
344 return -EINVAL;
345 }
346 }
347
348 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
349 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
350 (chan_bw != CH_WIDTH_MAX)) {
351 hdd_err("Only BW20 possible on channel 165");
352 return -EINVAL;
353 }
354 }
355
356 return 0;
357}
358
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800359static int __hdd_netdev_notifier_call(struct notifier_block *nb,
360 unsigned long state, void *data)
361{
362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
363 struct netdev_notifier_info *dev_notif_info = data;
364 struct net_device *dev = dev_notif_info->dev;
365#else
366 struct net_device *dev = data;
367#endif
368 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
369 hdd_context_t *hdd_ctx;
370
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800371 ENTER_DEV(dev);
372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 /* Make sure that this callback corresponds to our device. */
374 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
375 return NOTIFY_DONE;
376
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530377 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700379 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 return NOTIFY_DONE;
381 }
382
383 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700384 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 return NOTIFY_DONE;
386 }
387
388 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
389 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700390 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530391 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800392 return NOTIFY_DONE;
393 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800394 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800395 return NOTIFY_DONE;
396
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700397 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 dev->name, state);
399
400 switch (state) {
401 case NETDEV_REGISTER:
402 break;
403
404 case NETDEV_UNREGISTER:
405 break;
406
407 case NETDEV_UP:
408 sme_ch_avoid_update_req(hdd_ctx->hHal);
409 break;
410
411 case NETDEV_DOWN:
412 break;
413
414 case NETDEV_CHANGE:
415 if (true == adapter->isLinkUpSvcNeeded)
416 complete(&adapter->linkup_event_var);
417 break;
418
419 case NETDEV_GOING_DOWN:
420 if (adapter->scan_info.mScanPending != false) {
421 unsigned long rc;
422 INIT_COMPLETION(adapter->scan_info.
423 abortscan_event_var);
424 hdd_abort_mac_scan(adapter->pHddCtx,
425 adapter->sessionId,
426 eCSR_SCAN_ABORT_DEFAULT);
427 rc = wait_for_completion_timeout(
428 &adapter->scan_info.abortscan_event_var,
429 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
430 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700431 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432 }
433 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700434 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435 }
436 break;
437
438 default:
439 break;
440 }
441
442 return NOTIFY_DONE;
443}
444
445/**
446 * hdd_netdev_notifier_call() - netdev notifier callback function
447 * @nb: pointer to notifier block
448 * @state: state
449 * @ndev: ndev pointer
450 *
451 * Return: 0 on success, error number otherwise.
452 */
453static int hdd_netdev_notifier_call(struct notifier_block *nb,
454 unsigned long state,
455 void *ndev)
456{
457 int ret;
458
459 cds_ssr_protect(__func__);
460 ret = __hdd_netdev_notifier_call(nb, state, ndev);
461 cds_ssr_unprotect(__func__);
462
463 return ret;
464}
465
466struct notifier_block hdd_netdev_notifier = {
467 .notifier_call = hdd_netdev_notifier_call,
468};
469
470/* variable to hold the insmod parameters */
471static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800472
473/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530476/**
477 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
478 * @ch_width: NL channel width
479 *
480 * Converts the NL channel width to the driver's internal representation
481 *
482 * Return: Converted channel width. In case of non matching NL channel width,
483 * CH_WIDTH_MAX will be returned.
484 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800485enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530486{
487 switch (ch_width) {
488 case NL80211_CHAN_WIDTH_20_NOHT:
489 case NL80211_CHAN_WIDTH_20:
490 return CH_WIDTH_20MHZ;
491 case NL80211_CHAN_WIDTH_40:
492 return CH_WIDTH_40MHZ;
493 break;
494 case NL80211_CHAN_WIDTH_80:
495 return CH_WIDTH_80MHZ;
496 case NL80211_CHAN_WIDTH_80P80:
497 return CH_WIDTH_80P80MHZ;
498 case NL80211_CHAN_WIDTH_160:
499 return CH_WIDTH_160MHZ;
500 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800501 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530502 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800503 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530504 default:
505 hdd_err("Invalid channel width %d, setting to default",
506 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800507 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530508 }
509}
510
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530511/* wlan_hdd_find_opclass() - Find operating class for a channel
512 * @hal: handler to HAL
513 * @channel: channel id
514 * @bw_offset: bandwidth offset
515 *
516 * Function invokes sme api to find the operating class
517 *
518 * Return: operating class
519 */
520uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
521 uint8_t bw_offset)
522{
523 uint8_t opclass = 0;
524
525 sme_get_opclass(hal, channel, bw_offset, &opclass);
526 return opclass;
527}
528
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530530 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800531 * @moduleId: Module whose trace level is being configured
532 * @bitmask: Bitmask of log levels to be enabled
533 *
534 * Called immediately after the cfg.ini is read in order to configure
535 * the desired trace levels.
536 *
537 * Return: None
538 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530539static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800540{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530541 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542
543 /*
544 * if the bitmask is the default value, then a bitmask was not
545 * specified in cfg.ini, so leave the logging level alone (it
546 * will remain at the "compiled in" default value)
547 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530548 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 return;
550 }
551
552 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530553 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554
555 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530556 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557 while (0 != bitmask) {
558 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530559 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800560 }
561 level++;
562 bitmask >>= 1;
563 }
564}
565
566/**
567 * wlan_hdd_validate_context() - check the HDD context
568 * @hdd_ctx: HDD context pointer
569 *
570 * Return: 0 if the context is valid. Error code otherwise
571 */
572int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
573{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530575 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576 return -ENODEV;
577 }
578
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800579 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530580 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
581 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582 return -EAGAIN;
583 }
584
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800585 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530586 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
587 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 return -EAGAIN;
589 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530590
591 if (hdd_ctx->start_modules_in_progress ||
592 hdd_ctx->stop_modules_in_progress) {
593 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
594 (void *)_RET_IP_);
595 return -EAGAIN;
596 }
597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 return 0;
599}
600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601/**
602 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
603 * @hdd_adapter_t Hdd adapter.
604 *
605 * This function sets the IBSS power save config parameters to WMA
606 * which will send it to firmware if FW supports IBSS power save
607 * before vdev start.
608 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530609 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 * on failure.
611 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530612QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613{
614 int ret;
615 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
616
617 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700618 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530619 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 }
621
622 ret = wma_cli_set_command(adapter->sessionId,
623 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
624 hdd_ctx->config->ibssATIMWinSize,
625 VDEV_CMD);
626 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700627 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530628 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629 }
630
631 ret = wma_cli_set_command(adapter->sessionId,
632 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
633 hdd_ctx->config->isIbssPowerSaveAllowed,
634 VDEV_CMD);
635 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700636 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
637 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530638 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 }
640
641 ret = wma_cli_set_command(adapter->sessionId,
642 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
643 hdd_ctx->config->
644 isIbssPowerCollapseAllowed, VDEV_CMD);
645 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700646 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
647 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530648 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 }
650
651 ret = wma_cli_set_command(adapter->sessionId,
652 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
653 hdd_ctx->config->isIbssAwakeOnTxRx,
654 VDEV_CMD);
655 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700656 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530657 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 }
659
660 ret = wma_cli_set_command(adapter->sessionId,
661 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
662 hdd_ctx->config->ibssInactivityCount,
663 VDEV_CMD);
664 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700665 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530666 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 }
668
669 ret = wma_cli_set_command(adapter->sessionId,
670 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
671 hdd_ctx->config->ibssTxSpEndInactivityTime,
672 VDEV_CMD);
673 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700674 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
675 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 }
678
679 ret = wma_cli_set_command(adapter->sessionId,
680 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
681 hdd_ctx->config->ibssPsWarmupTime,
682 VDEV_CMD);
683 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700684 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
685 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530686 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 }
688
689 ret = wma_cli_set_command(adapter->sessionId,
690 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
691 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
692 VDEV_CMD);
693 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700694 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
695 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530696 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 }
698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700}
701
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702#define INTF_MACADDR_MASK 0x7
703
704/**
705 * hdd_update_macaddr() - update mac address
706 * @config: hdd configuration
707 * @hw_macaddr: mac address
708 *
709 * Mac address for multiple virtual interface is found as following
710 * i) The mac address of the first interface is just the actual hw mac address.
711 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
712 * define the mac address for the remaining interfaces and locally
713 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
714 * supported virtual interfaces, right now this is 0x07 (meaning 8
715 * interface).
716 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
717 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
718 *
719 * Return: None
720 */
721void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530722 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800723{
724 int8_t i;
725 uint8_t macaddr_b3, tmp_br3;
726
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530727 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530728 QDF_MAC_ADDR_SIZE);
729 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530730 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530731 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800732 macaddr_b3 = config->intfMacAddr[i].bytes[3];
733 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
734 INTF_MACADDR_MASK;
735 macaddr_b3 += tmp_br3;
736
737 /* XOR-ing bit-24 of the mac address. This will give enough
738 * mac address range before collision
739 */
740 macaddr_b3 ^= (1 << 7);
741
742 /* Set locally administered bit */
743 config->intfMacAddr[i].bytes[0] |= 0x02;
744 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700745 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800746 MAC_ADDRESS_STR, i,
747 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
748 }
749}
750
751static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
752 struct wma_tgt_services *cfg)
753{
754 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755
756 /* Set up UAPSD */
757 config->apUapsdEnabled &= cfg->uapsd;
758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 /* 11AC mode support */
760 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
761 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
762 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763
764 /* ARP offload: override user setting if invalid */
765 config->fhostArpOffload &= cfg->arp_offload;
766
767#ifdef FEATURE_WLAN_SCAN_PNO
768 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700769 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 if (cfg->pno_offload)
771 config->PnoOffload = true;
772#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773#ifdef FEATURE_WLAN_TDLS
774 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530775 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
776 cfg->en_tdls_offchan;
777 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
778 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
780 config->fEnableTDLSSleepSta = true;
781 } else {
782 config->fEnableTDLSSleepSta = false;
783 }
784#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785#ifdef WLAN_FEATURE_ROAM_OFFLOAD
786 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
787#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700788 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789
790}
791
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700792/**
793 * hdd_update_vdev_nss() - sets the vdev nss
794 * @hdd_ctx: HDD context
795 *
796 * Sets the Nss per vdev type based on INI
797 *
798 * Return: None
799 */
800static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
801{
802 struct hdd_config *cfg_ini = hdd_ctx->config;
803 uint8_t max_supp_nss = 1;
804
805 if (cfg_ini->enable2x2)
806 max_supp_nss = 2;
807
808 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
809 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
810
811 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
812 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
813}
814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
816 struct wma_tgt_ht_cap *cfg)
817{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530818 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 uint32_t value, val32;
820 uint16_t val16;
821 struct hdd_config *pconfig = hdd_ctx->config;
822 tSirMacHTCapabilityInfo *phtCapInfo;
823 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
824 uint8_t enable_tx_stbc;
825
826 /* check and update RX STBC */
827 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
828 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
829
830 /* get the MPDU density */
831 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
832
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530833 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700834 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835 value = 0;
836 }
837
838 /*
839 * MPDU density:
840 * override user's setting if value is larger
841 * than the one supported by target
842 */
843 if (value > cfg->mpdu_density) {
844 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
845 cfg->mpdu_density);
846
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530847 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700848 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 }
850
851 /* get the HT capability info */
852 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530853 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700854 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855 return;
856 }
857 val16 = (uint16_t) val32;
858 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
859
860 /* Set the LDPC capability */
861 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
862
863 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
864 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
865
866 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
867 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
868
869 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
870 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
871
872 enable_tx_stbc = pconfig->enableTxSTBC;
873
874 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
875 pconfig->enable2x2 = 1;
876 } else {
877 pconfig->enable2x2 = 0;
878 enable_tx_stbc = 0;
879
880 /* 1x1 */
881 /* Update Rx Highest Long GI data Rate */
882 if (sme_cfg_set_int(hdd_ctx->hHal,
883 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700884 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530885 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700886 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800887 }
888
889 /* Update Tx Highest Long GI data Rate */
890 if (sme_cfg_set_int
891 (hdd_ctx->hHal,
892 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700893 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530894 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700895 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896 }
897 }
898 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
899 enable_tx_stbc = 0;
900 phtCapInfo->txSTBC = enable_tx_stbc;
901
902 val32 = val16;
903 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530904 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700905 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
907 value = SIZE_OF_SUPPORTED_MCS_SET;
908 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530909 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700910 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800911
912 if (pconfig->enable2x2) {
913 for (value = 0; value < cfg->num_rf_chains; value++)
914 mcs_set[value] =
915 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
916
917 status =
918 sme_cfg_set_str(hdd_ctx->hHal,
919 WNI_CFG_SUPPORTED_MCS_SET,
920 mcs_set,
921 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530922 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700923 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800924 }
925 }
926#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
927}
928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
930 struct wma_tgt_vht_cap *cfg)
931{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530932 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800933 uint32_t value = 0;
934 struct hdd_config *pconfig = hdd_ctx->config;
935 struct wiphy *wiphy = hdd_ctx->wiphy;
936 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700937 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700938 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939
Dustin Brown5e06bd32016-10-04 12:49:10 -0700940 if (!band_5g) {
941 hdd_info("5GHz band disabled, skipping capability population");
942 return;
943 }
944
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800945 /* Get the current MPDU length */
946 status =
947 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
948 &value);
949
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530950 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700951 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 value = 0;
953 }
954
955 /*
956 * VHT max MPDU length:
957 * override if user configured value is too high
958 * that the target cannot support
959 */
960 if (value > cfg->vht_max_mpdu) {
961 status = sme_cfg_set_int(hdd_ctx->hHal,
962 WNI_CFG_VHT_MAX_MPDU_LENGTH,
963 cfg->vht_max_mpdu);
964
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530965 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700966 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967 }
968 }
969
970 /* Get the current supported chan width */
971 status = sme_cfg_get_int(hdd_ctx->hHal,
972 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
973 &value);
974
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530975 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700976 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977 value = 0;
978 }
979
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700980 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
981 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
982
983 if (pconfig->enable2x2)
984 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
985
986 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
987 QDF_STATUS_E_FAILURE) {
988 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
989 }
990
991 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
992 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
993 if (pconfig->enable2x2)
994 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
995
996 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
997 QDF_STATUS_E_FAILURE) {
998 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
999 }
1000
1001 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1002 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1003 if (pconfig->enable2x2)
1004 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1005
1006 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1007 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1008
1009 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1010 QDF_STATUS_E_FAILURE) {
1011 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1012 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001013 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001014 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015 &value);
1016
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301017 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001018 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019 value = 0;
1020 }
1021
1022 /* Set the LDPC capability */
1023 if (value && !cfg->vht_rx_ldpc) {
1024 status = sme_cfg_set_int(hdd_ctx->hHal,
1025 WNI_CFG_VHT_LDPC_CODING_CAP,
1026 cfg->vht_rx_ldpc);
1027
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301028 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001029 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001030 }
1031 }
1032
1033 /* Get current GI 80 value */
1034 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1035 &value);
1036
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301037 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001038 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039 value = 0;
1040 }
1041
1042 /* set the Guard interval 80MHz */
1043 if (value && !cfg->vht_short_gi_80) {
1044 status = sme_cfg_set_int(hdd_ctx->hHal,
1045 WNI_CFG_VHT_SHORT_GI_80MHZ,
1046 cfg->vht_short_gi_80);
1047
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301048 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001049 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001050 }
1051 }
1052
1053 /* Get current GI 160 value */
1054 status = sme_cfg_get_int(hdd_ctx->hHal,
1055 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1056 &value);
1057
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301058 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001059 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 value = 0;
1061 }
1062
1063 /* Get VHT TX STBC cap */
1064 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1065
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301066 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001067 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068 value = 0;
1069 }
1070
1071 /* VHT TX STBC cap */
1072 if (value && !cfg->vht_tx_stbc) {
1073 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1074 cfg->vht_tx_stbc);
1075
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301076 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001077 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 }
1079 }
1080
1081 /* Get VHT RX STBC cap */
1082 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1083
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301084 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001085 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001086 value = 0;
1087 }
1088
1089 /* VHT RX STBC cap */
1090 if (value && !cfg->vht_rx_stbc) {
1091 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1092 cfg->vht_rx_stbc);
1093
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301094 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001095 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001096 }
1097 }
1098
1099 /* Get VHT SU Beamformer cap */
1100 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1101 &value);
1102
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301103 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001104 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001105 value = 0;
1106 }
1107
1108 /* set VHT SU Beamformer cap */
1109 if (value && !cfg->vht_su_bformer) {
1110 status = sme_cfg_set_int(hdd_ctx->hHal,
1111 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1112 cfg->vht_su_bformer);
1113
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301114 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001115 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001116 }
1117 }
1118
1119 /* check and update SU BEAMFORMEE capabality */
1120 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1121 pconfig->enableTxBF = cfg->vht_su_bformee;
1122
1123 status = sme_cfg_set_int(hdd_ctx->hHal,
1124 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1125 pconfig->enableTxBF);
1126
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301127 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001128 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001129 }
1130
1131 /* Get VHT MU Beamformer cap */
1132 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1133 &value);
1134
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301135 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001136 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 value = 0;
1138 }
1139
1140 /* set VHT MU Beamformer cap */
1141 if (value && !cfg->vht_mu_bformer) {
1142 status = sme_cfg_set_int(hdd_ctx->hHal,
1143 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1144 cfg->vht_mu_bformer);
1145
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301146 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001147 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 }
1149 }
1150
1151 /* Get VHT MU Beamformee cap */
1152 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1153 &value);
1154
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301155 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001156 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157 value = 0;
1158 }
1159
1160 /* set VHT MU Beamformee cap */
1161 if (value && !cfg->vht_mu_bformee) {
1162 status = sme_cfg_set_int(hdd_ctx->hHal,
1163 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1164 cfg->vht_mu_bformee);
1165
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301166 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001167 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001168 }
1169 }
1170
1171 /* Get VHT MAX AMPDU Len exp */
1172 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1173 &value);
1174
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301175 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001176 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001177 value = 0;
1178 }
1179
1180 /*
1181 * VHT max AMPDU len exp:
1182 * override if user configured value is too high
1183 * that the target cannot support.
1184 * Even though Rome publish ampdu_len=7, it can
1185 * only support 4 because of some h/w bug.
1186 */
1187
1188 if (value > cfg->vht_max_ampdu_len_exp) {
1189 status = sme_cfg_set_int(hdd_ctx->hHal,
1190 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1191 cfg->vht_max_ampdu_len_exp);
1192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301193 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001194 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 }
1196 }
1197
1198 /* Get VHT TXOP PS CAP */
1199 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1200
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301201 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001202 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203 value = 0;
1204 }
1205
1206 /* set VHT TXOP PS cap */
1207 if (value && !cfg->vht_txop_ps) {
1208 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1209 cfg->vht_txop_ps);
1210
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301211 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001212 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 }
1214 }
1215
1216 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1217 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1218 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1219 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1220 else
1221 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1222
1223
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001224 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 band_5g->vht_cap.cap |=
1226 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001227 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001228 band_5g->vht_cap.cap |=
1229 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230
1231 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1232 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1233
1234 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1235 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1236 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1237 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1238
1239 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1240 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1241
1242 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1243 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1244 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1245 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1246 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1247 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1248
1249 band_5g->vht_cap.cap |=
1250 (cfg->vht_max_ampdu_len_exp <<
1251 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1252
1253 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1254 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1255 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1256 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1257 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1258 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1259 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1260 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1261
1262 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1263 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1264
1265}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001267/**
1268 * hdd_generate_macaddr_auto() - Auto-generate mac address
1269 * @hdd_ctx: Pointer to the HDD context
1270 *
1271 * Auto-generate mac address using device serial number.
1272 * Keep the first 3 bytes of OUI as before and replace
1273 * the last 3 bytes with the lower 3 bytes of serial number.
1274 *
1275 * Return: 0 for success
1276 * Non zero failure code for errors
1277 */
1278static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1279{
1280 unsigned int serialno = 0;
1281 struct qdf_mac_addr mac_addr = {
1282 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1283 };
1284
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001285 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001286 if (serialno == 0)
1287 return -EINVAL;
1288
1289 serialno &= 0x00ffffff;
1290
1291 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1292 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1293 mac_addr.bytes[5] = serialno & 0xff;
1294
1295 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1296 return 0;
1297}
1298
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301299/**
1300 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1301 * configuration to cfg_ini in HDD
1302 * @hdd_ctx: Pointer to hdd_ctx
1303 * @cfg: target configuration
1304 *
1305 * Return: None
1306 */
1307#ifdef FEATURE_WLAN_RA_FILTERING
1308static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1309 struct wma_tgt_cfg *cfg)
1310{
1311 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1312}
1313#else
1314static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1315 struct wma_tgt_cfg *cfg)
1316{
1317}
1318#endif
1319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001320void hdd_update_tgt_cfg(void *context, void *param)
1321{
1322 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1323 struct wma_tgt_cfg *cfg = param;
1324 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001325 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301326 QDF_STATUS qdf_status;
1327
1328 qdf_status = hdd_create_and_store_pdev(hdd_ctx);
1329 if (QDF_IS_STATUS_ERROR(qdf_status)) {
1330 hdd_err("Pdev creation fails!");
1331 QDF_BUG(0);
1332 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001333
1334 if (cds_cfg) {
1335 if (hdd_ctx->config->enable_sub_20_channel_width !=
1336 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1337 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1338 cds_cfg->sub_20_channel_width =
1339 WLAN_SUB_20_CH_WIDTH_NONE;
1340 } else {
1341 cds_cfg->sub_20_channel_width =
1342 hdd_ctx->config->enable_sub_20_channel_width;
1343 }
1344 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001345
1346 /* first store the INI band capability */
1347 temp_band_cap = hdd_ctx->config->nBandCapability;
1348
1349 hdd_ctx->config->nBandCapability = cfg->band_cap;
1350
1351 /* now overwrite the target band capability with INI
1352 setting if INI setting is a subset */
1353
1354 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1355 (temp_band_cap != eCSR_BAND_ALL))
1356 hdd_ctx->config->nBandCapability = temp_band_cap;
1357 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1358 (temp_band_cap != eCSR_BAND_ALL) &&
1359 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001360 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 }
1362
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001363 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1365 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1366 }
1367
1368 /* This can be extended to other configurations like ht, vht cap... */
1369
Anurag Chouhanc5548422016-02-24 18:33:27 +05301370 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001372 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001374 static struct qdf_mac_addr default_mac_addr = {
1375 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1376 };
1377 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1378 &default_mac_addr)) {
1379 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1380 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1381 MAC_ADDRESS_STR,
1382 MAC_ADDR_ARRAY(hdd_ctx->config->
1383 intfMacAddr[0].bytes));
1384 } else {
1385 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1386 MAC_ADDRESS_STR,
1387 MAC_ADDR_ARRAY(hdd_ctx->config->
1388 intfMacAddr[0].bytes));
1389 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001390 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001391 }
1392
1393 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001394 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395
1396 hdd_ctx->max_intf_count = cfg->max_intf_count;
1397
Jeff Johnsonc875e242016-09-23 18:12:34 -07001398 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001399 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001401 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1402 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1403
1404 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1405
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001406 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001407
1408 hdd_update_vdev_nss(hdd_ctx);
1409
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001410 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001411 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001412 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001413 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001414
1415 hdd_ctx->current_antenna_mode =
1416 (hdd_ctx->config->enable2x2 == 0x01) ?
1417 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1418 hdd_info("Init current antenna mode: %d",
1419 hdd_ctx->current_antenna_mode);
1420
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001421 hdd_info("Target BPF %d Host BPF %d",
1422 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1423 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1424 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301425 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301426
Arun Khandavallid454d422016-08-17 12:47:05 +05301427 /*
1428 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1429 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1430 * configure the STA mode wow pattern.
1431 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301432 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301433 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301434
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301435 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1436
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001437 /* Configure NAN datapath features */
1438 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001439}
1440
1441/**
1442 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1443 * @context: HDD context pointer
1444 * @param: HDD radar indication pointer
1445 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001446 * This function is invoked in atomic context when a radar
1447 * is found on the SAP current operating channel and Data Tx
1448 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449 * Actions: Stop the netif Tx queues,Indicate Radar present
1450 * in HDD context for future usage.
1451 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301452 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001453 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301454bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455{
1456 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1457 struct wma_dfs_radar_ind *hdd_radar_event =
1458 (struct wma_dfs_radar_ind *)param;
1459 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1460 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301461 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301462 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001463
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301464 if (!hdd_ctx || !hdd_radar_event ||
1465 hdd_ctx->config->disableDFSChSwitch)
1466 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467
1468 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001469 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301470 /*
1471 * Application already triggered channel switch
1472 * on current channel, so return here.
1473 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301474 return false;
1475 }
1476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301478 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001479 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301480 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1481 if ((QDF_SAP_MODE == adapter->device_mode ||
1482 QDF_P2P_GO_MODE == adapter->device_mode) &&
1483 (CHANNEL_STATE_DFS ==
1484 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001485 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1486 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301487 hdd_info("tx blocked for session:%d",
1488 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489 }
1490
1491 status = hdd_get_next_adapter(hdd_ctx,
1492 adapterNode,
1493 &pNext);
1494 adapterNode = pNext;
1495 }
1496 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301497
1498 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500
1501/**
1502 * hdd_is_valid_mac_address() - validate MAC address
1503 * @pMacAddr: Pointer to the input MAC address
1504 *
1505 * This function validates whether the given MAC address is valid or not
1506 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1507 * where X is the hexa decimal digit character and separated by ':'
1508 * This algorithm works even if MAC address is not separated by ':'
1509 *
1510 * This code checks given input string mac contains exactly 12 hexadecimal
1511 * digits and a separator colon : appears in the input string only after
1512 * an even number of hex digits.
1513 *
1514 * Return: 1 for valid and 0 for invalid
1515 */
1516bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1517{
1518 int xdigit = 0;
1519 int separator = 0;
1520 while (*pMacAddr) {
1521 if (isxdigit(*pMacAddr)) {
1522 xdigit++;
1523 } else if (':' == *pMacAddr) {
1524 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1525 break;
1526
1527 ++separator;
1528 } else {
1529 /* Invalid MAC found */
1530 return 0;
1531 }
1532 ++pMacAddr;
1533 }
1534 return xdigit == 12 && (separator == 5 || separator == 0);
1535}
1536
1537/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301538 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1539 * @dev: Handle to struct net_device to be updated.
1540 *
1541 * Return: None
1542 */
1543static void hdd_mon_mode_ether_setup(struct net_device *dev)
1544{
1545 dev->header_ops = NULL;
1546 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1547 dev->hard_header_len = ETH_HLEN;
1548 dev->mtu = ETH_DATA_LEN;
1549 dev->addr_len = ETH_ALEN;
1550 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1551 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1552 dev->priv_flags |= IFF_TX_SKB_SHARING;
1553
1554 memset(dev->broadcast, 0xFF, ETH_ALEN);
1555}
1556
1557/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001558 * __hdd__mon_open() - HDD Open function
1559 * @dev: Pointer to net_device structure
1560 *
1561 * This is called in response to ifconfig up
1562 *
1563 * Return: 0 for success; non-zero for failure
1564 */
1565static int __hdd_mon_open(struct net_device *dev)
1566{
1567 int ret;
1568
1569 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301570 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001571 ret = hdd_set_mon_rx_cb(dev);
1572 return ret;
1573}
1574
1575/**
1576 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1577 * @dev: Pointer to net_device structure
1578 *
1579 * This is called in response to ifconfig up
1580 *
1581 * Return: 0 for success; non-zero for failure
1582 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001583static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001584{
1585 int ret;
1586
1587 cds_ssr_protect(__func__);
1588 ret = __hdd_mon_open(dev);
1589 cds_ssr_unprotect(__func__);
1590
1591 return ret;
1592}
1593
1594/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301595 * hdd_start_adapter() - Wrapper function for device specific adapter
1596 * @adapter: pointer to HDD adapter
1597 *
1598 * This function is called to start the device specific adapter for
1599 * the mode passed in the adapter's device_mode.
1600 *
1601 * Return: 0 for success; non-zero for failure
1602 */
1603int hdd_start_adapter(hdd_adapter_t *adapter)
1604{
1605
1606 int ret;
1607 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1608
1609 ENTER_DEV(adapter->dev);
1610 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1611
1612 switch (device_mode) {
1613 case QDF_P2P_CLIENT_MODE:
1614 case QDF_P2P_DEVICE_MODE:
1615 case QDF_OCB_MODE:
1616 case QDF_STA_MODE:
1617 case QDF_MONITOR_MODE:
1618 ret = hdd_start_station_adapter(adapter);
1619 if (ret)
1620 goto err_start_adapter;
1621 break;
1622 case QDF_P2P_GO_MODE:
1623 case QDF_SAP_MODE:
1624 ret = hdd_start_ap_adapter(adapter);
1625 if (ret)
1626 goto err_start_adapter;
1627 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301628 case QDF_IBSS_MODE:
1629 /*
1630 * For IBSS interface is initialized as part of
1631 * hdd_init_station_mode()
1632 */
1633 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301634 case QDF_FTM_MODE:
1635 ret = hdd_start_ftm_adapter(adapter);
1636 if (ret)
1637 goto err_start_adapter;
1638 break;
1639 default:
1640 hdd_err("Invalid session type %d", device_mode);
1641 QDF_ASSERT(0);
1642 goto err_start_adapter;
1643 }
1644 if (hdd_set_fw_params(adapter))
1645 hdd_err("Failed to set the FW params for the adapter!");
1646
1647 /*
1648 * Action frame registered in one adapter which will
1649 * applicable to all interfaces
1650 */
1651 wlan_hdd_cfg80211_register_frames(adapter);
1652 EXIT();
1653 return 0;
1654err_start_adapter:
1655 return -EINVAL;
1656}
1657
1658/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301659 * hdd_enable_power_management() - API to Enable Power Management
1660 *
1661 * API invokes Bus Interface Layer power management functionality
1662 *
1663 * Return: None
1664 */
1665static void hdd_enable_power_management(void)
1666{
1667 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1668
1669 if (!hif_ctx) {
1670 hdd_err("Bus Interface Context is Invalid");
1671 return;
1672 }
1673
1674 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1675}
1676
1677/**
1678 * hdd_disable_power_management() - API to disable Power Management
1679 *
1680 * API disable Bus Interface Layer Power management functionality
1681 *
1682 * Return: None
1683 */
1684static void hdd_disable_power_management(void)
1685{
1686 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1687
1688 if (!hif_ctx) {
1689 hdd_err("Bus Interface Context is Invalid");
1690 return;
1691 }
1692
1693 hif_disable_power_management(hif_ctx);
1694}
1695
1696/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301697 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1698 * @hdd_ctx: HDD context
1699 * @adapter: HDD adapter
1700 * @reinit: flag to indicate from SSR or normal path
1701 *
1702 * This function maintains the driver state machine it will be invoked from
1703 * startup, reinit and change interface. Depending on the driver state shall
1704 * perform the opening of the modules.
1705 *
1706 * Return: 0 for success; non-zero for failure
1707 */
1708int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1709 bool reinit)
1710{
1711 int ret;
1712 qdf_device_t qdf_dev;
1713 QDF_STATUS status;
1714 p_cds_contextType p_cds_context;
1715 bool unint = false;
1716 void *hif_ctx;
1717
1718 ENTER();
1719
1720 p_cds_context = cds_get_global_context();
1721 if (!p_cds_context) {
1722 hdd_err("Global Context is NULL");
1723 QDF_ASSERT(0);
1724 return -EINVAL;
1725 }
1726
1727 hdd_info("start modules called in state! :%d reinit: %d",
1728 hdd_ctx->driver_status, reinit);
1729
1730 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1731 if (!qdf_dev) {
1732 hdd_err("QDF Device Context is Invalid return");
1733 return -EINVAL;
1734 }
1735
1736 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301737 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301738
1739 if (QDF_TIMER_STATE_RUNNING ==
1740 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1741
1742 hdd_set_idle_ps_config(hdd_ctx, false);
1743 hdd_info("Interface change Timer running Stop timer");
1744 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1745 }
1746
1747 switch (hdd_ctx->driver_status) {
1748 case DRIVER_MODULES_UNINITIALIZED:
1749 unint = true;
1750 /* Fall through dont add break here */
1751 case DRIVER_MODULES_CLOSED:
1752 if (!reinit && !unint) {
1753 ret = pld_power_on(qdf_dev->dev);
1754 if (ret) {
1755 hdd_err("Failed to Powerup the device: %d", ret);
1756 goto release_lock;
1757 }
1758 }
1759 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1760 qdf_dev->bus_type,
1761 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1762 HIF_ENABLE_TYPE_PROBE);
1763 if (ret) {
1764 hdd_err("Failed to open hif: %d", ret);
1765 goto power_down;
1766 }
1767
1768 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301769 if (!hif_ctx) {
1770 hdd_err("hif context is null!!");
1771 goto power_down;
1772 }
1773
Arun Khandavallifae92942016-08-01 13:31:08 +05301774 status = ol_cds_init(qdf_dev, hif_ctx);
1775 if (status != QDF_STATUS_SUCCESS) {
1776 hdd_err("No Memory to Create BMI Context :%d", status);
1777 goto hif_close;
1778 }
1779
Arun Khandavallif6246632016-08-17 17:43:06 +05301780 ret = hdd_update_config(hdd_ctx);
1781 if (ret) {
1782 hdd_err("Failed to update configuration :%d", ret);
1783 goto ol_cds_free;
1784 }
1785
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301786 status = hdd_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID);
1787 if (QDF_IS_STATUS_ERROR(status)) {
1788 hdd_err("Psoc creation fails!");
1789 goto ol_cds_free;
1790 }
1791
1792 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05301793 if (!QDF_IS_STATUS_SUCCESS(status)) {
1794 hdd_err("Failed to Open CDS: %d", status);
1795 goto ol_cds_free;
1796 }
1797
1798 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1799
1800 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1801
1802 status = cds_pre_enable(hdd_ctx->pcds_context);
1803 if (!QDF_IS_STATUS_SUCCESS(status)) {
1804 hdd_err("Failed to pre-enable CDS: %d", status);
1805 goto close;
1806 }
1807
1808 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1809 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1810 hdd_ftm_mc_process_msg);
1811 break;
1812 }
1813 if (unint) {
1814 hdd_info("In phase-1 initialization don't enable modules");
1815 break;
1816 }
1817 /* Fall through dont add break here */
1818 case DRIVER_MODULES_OPENED:
1819 if (!adapter) {
1820 hdd_alert("adapter is Null");
1821 goto close;
1822 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05301823 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1824 hdd_err("in ftm mode, no need to configure cds modules");
1825 break;
1826 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301827 if (hdd_configure_cds(hdd_ctx, adapter)) {
1828 hdd_err("Failed to Enable cds modules");
1829 goto close;
1830 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05301831 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05301832 hdd_info("Driver Modules Successfully Enabled");
1833 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1834 break;
1835 case DRIVER_MODULES_ENABLED:
1836 hdd_info("Driver modules already Enabled");
1837 break;
1838 default:
1839 hdd_err("WLAN start invoked in wrong state! :%d\n",
1840 hdd_ctx->driver_status);
1841 goto release_lock;
1842 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301843 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301844 mutex_unlock(&hdd_ctx->iface_change_lock);
1845 EXIT();
1846 return 0;
1847
1848close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301849 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05301850
1851ol_cds_free:
1852 ol_cds_free();
1853
1854hif_close:
1855 hdd_hif_close(p_cds_context->pHIFContext);
1856power_down:
1857 if (!reinit && !unint)
1858 pld_power_off(qdf_dev->dev);
1859release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301860 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301861 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301862 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301863 return -EINVAL;
1864}
1865
1866/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 * __hdd_open() - HDD Open function
1868 * @dev: Pointer to net_device structure
1869 *
1870 * This is called in response to ifconfig up
1871 *
1872 * Return: 0 for success; non-zero for failure
1873 */
1874static int __hdd_open(struct net_device *dev)
1875{
1876 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1877 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1878 int ret;
1879
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001880 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301881 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301882 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883
1884 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301885 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301887
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888
Arun Khandavallifae92942016-08-01 13:31:08 +05301889 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1890 if (ret) {
1891 hdd_err("Failed to start WLAN modules return");
1892 return -ret;
1893 }
1894
1895
1896 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1897 ret = hdd_start_adapter(adapter);
1898 if (ret) {
1899 hdd_err("Failed to start adapter :%d",
1900 adapter->device_mode);
1901 return ret;
1902 }
1903 }
1904
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1906 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301907 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908 /* Enable TX queues only when we are connected */
1909 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301910 WLAN_START_ALL_NETIF_QUEUE,
1911 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912 }
1913
Naveen Rawat286def52016-09-23 15:38:02 -07001914 /* Enable carrier and transmit queues for NDI */
1915 if (WLAN_HDD_IS_NDI(adapter)) {
1916 hdd_notice("Enabling Tx Queues");
1917 wlan_hdd_netif_queue_control(adapter,
1918 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
1919 WLAN_CONTROL_PATH);
1920 }
1921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 return ret;
1923}
1924
Arun Khandavallifae92942016-08-01 13:31:08 +05301925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926/**
1927 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1928 * @dev: Pointer to net_device structure
1929 *
1930 * This is called in response to ifconfig up
1931 *
1932 * Return: 0 for success; non-zero for failure
1933 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001934static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935{
1936 int ret;
1937
1938 cds_ssr_protect(__func__);
1939 ret = __hdd_open(dev);
1940 cds_ssr_unprotect(__func__);
1941
1942 return ret;
1943}
1944
1945/**
1946 * __hdd_stop() - HDD stop function
1947 * @dev: Pointer to net_device structure
1948 *
1949 * This is called in response to ifconfig down
1950 *
1951 * Return: 0 for success; non-zero for failure
1952 */
1953static int __hdd_stop(struct net_device *dev)
1954{
1955 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1956 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301957 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301959 bool close_modules = true;
1960 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001961
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001962 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301964 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 adapter->sessionId, adapter->device_mode));
1966
1967 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301968 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970
1971 /* Nothing to be done if the interface is not opened */
1972 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001973 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 return -ENODEV;
1975 }
1976
1977 /* Make sure the interface is marked as closed */
1978 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001979 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980
1981 /*
1982 * Disable TX on the interface, after this hard_start_xmit() will not
1983 * be called on that interface
1984 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001985 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1987 WLAN_CONTROL_PATH);
1988
1989 /*
Naveen Rawat286def52016-09-23 15:38:02 -07001990 * NAN data interface is different in some sense. The traffic on NDI is
1991 * bursty in nature and depends on the need to transfer. The service
1992 * layer may down the interface after the usage and up again when
1993 * required. In some sense, the NDI is expected to be available
1994 * (like SAP) iface until NDI delete request is issued by the service
1995 * layer. Skip BSS termination and adapter deletion for NAN Data
1996 * interface (NDI).
1997 */
1998 if (WLAN_HDD_IS_NDI(adapter))
1999 return 0;
2000
2001 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 * The interface is marked as down for outside world (aka kernel)
2003 * But the driver is pretty much alive inside. The driver needs to
2004 * tear down the existing connection on the netdev (session)
2005 * cleanup the data pipes and wait until the control plane is stabilized
2006 * for this interface. The call also needs to wait until the above
2007 * mentioned actions are completed before returning to the caller.
2008 * Notice that the hdd_stop_adapter is requested not to close the session
2009 * That is intentional to be able to scan if it is a STA/P2P interface
2010 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302011 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012
2013 /* DeInit the adapter. This ensures datapath cleanup as well */
2014 hdd_deinit_adapter(hdd_ctx, adapter, true);
2015
Arun Khandavallifae92942016-08-01 13:31:08 +05302016
2017 /*
2018 * Find if any iface is up. If any iface is up then can't put device to
2019 * sleep/power save mode
2020 */
2021 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2022 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2023 if (test_bit(DEVICE_IFACE_OPENED,
2024 &adapternode->pAdapter->event_flags)) {
2025 hdd_info("Still other ifaces are up cannot close modules");
2026 close_modules = false;
2027 break;
2028 }
2029 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2030 adapternode = next;
2031
2032 }
2033
2034 if (close_modules) {
2035 hdd_info("Closing all modules from the hdd_stop");
2036 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2037 hdd_ctx->config->iface_change_wait_time
2038 * 50000);
2039 }
2040
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 EXIT();
2042 return 0;
2043}
2044
2045/**
2046 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2047 * @dev: pointer to net_device structure
2048 *
2049 * This is called in response to ifconfig down
2050 *
2051 * Return: 0 for success and error number for failure
2052 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002053static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054{
2055 int ret;
2056
2057 cds_ssr_protect(__func__);
2058 ret = __hdd_stop(dev);
2059 cds_ssr_unprotect(__func__);
2060
2061 return ret;
2062}
2063
2064/**
2065 * __hdd_uninit() - HDD uninit function
2066 * @dev: Pointer to net_device structure
2067 *
2068 * This is called during the netdev unregister to uninitialize all data
2069 * associated with the device
2070 *
2071 * Return: None
2072 */
2073static void __hdd_uninit(struct net_device *dev)
2074{
2075 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2076
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002077 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078
2079 do {
2080 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002081 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 break;
2083 }
2084
2085 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002086 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 break;
2088 }
2089
2090 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002091 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 /*
2093 * we haven't validated all cases so let this go for
2094 * now
2095 */
2096 }
2097
2098 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2099
2100 /* after uninit our adapter structure will no longer be valid */
2101 adapter->dev = NULL;
2102 adapter->magic = 0;
2103 } while (0);
2104
2105 EXIT();
2106}
2107
2108/**
2109 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2110 * @dev: pointer to net_device structure
2111 *
2112 * This is called during the netdev unregister to uninitialize all data
2113 * associated with the device
2114 *
2115 * Return: none
2116 */
2117static void hdd_uninit(struct net_device *dev)
2118{
2119 cds_ssr_protect(__func__);
2120 __hdd_uninit(dev);
2121 cds_ssr_unprotect(__func__);
2122}
2123
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002124static int hdd_open_cesium_nl_sock(void)
2125{
2126#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2127 struct netlink_kernel_cfg cfg = {
2128 .groups = WLAN_NLINK_MCAST_GRP_ID,
2129 .input = NULL
2130 };
2131#endif
2132 int ret = 0;
2133
2134#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2135 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2136#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2137 THIS_MODULE,
2138#endif
2139 &cfg);
2140#else
2141 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2142 WLAN_NLINK_MCAST_GRP_ID,
2143 NULL, NULL, THIS_MODULE);
2144#endif
2145
2146 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002147 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002148 ret = -ECONNREFUSED;
2149 }
2150
2151 return ret;
2152}
2153
2154static void hdd_close_cesium_nl_sock(void)
2155{
2156 if (NULL != cesium_nl_srv_sock) {
2157 netlink_kernel_release(cesium_nl_srv_sock);
2158 cesium_nl_srv_sock = NULL;
2159 }
2160}
2161
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162/**
2163 * __hdd_set_mac_address() - set the user specified mac address
2164 * @dev: Pointer to the net device.
2165 * @addr: Pointer to the sockaddr.
2166 *
2167 * This function sets the user specified mac address using
2168 * the command ifconfig wlanX hw ether <mac adress>.
2169 *
2170 * Return: 0 for success, non zero for failure
2171 */
2172static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2173{
2174 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2175 hdd_context_t *hdd_ctx;
2176 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302177 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 int ret;
2179
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002180 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181
2182 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2183 ret = wlan_hdd_validate_context(hdd_ctx);
2184 if (0 != ret)
2185 return ret;
2186
2187 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2188 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2189
2190 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302191 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192}
2193
2194/**
2195 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2196 * function from SSR
2197 * @dev: pointer to net_device structure
2198 * @addr: Pointer to the sockaddr
2199 *
2200 * This function sets the user specified mac address using
2201 * the command ifconfig wlanX hw ether <mac adress>.
2202 *
2203 * Return: 0 for success.
2204 */
2205static int hdd_set_mac_address(struct net_device *dev, void *addr)
2206{
2207 int ret;
2208
2209 cds_ssr_protect(__func__);
2210 ret = __hdd_set_mac_address(dev, addr);
2211 cds_ssr_unprotect(__func__);
2212
2213 return ret;
2214}
2215
2216uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2217{
2218 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302219 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2221 break;
2222 }
2223
Anurag Chouhan6d760662016-02-20 16:05:43 +05302224 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 return NULL;
2226
2227 hdd_ctx->config->intfAddrMask |= (1 << i);
2228 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2229}
2230
2231void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2232{
2233 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302234 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235 if (!memcmp(releaseAddr,
2236 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2237 6)) {
2238 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2239 break;
2240 }
2241 }
2242 return;
2243}
2244
2245#ifdef WLAN_FEATURE_PACKET_FILTERING
2246/**
2247 * __hdd_set_multicast_list() - set the multicast address list
2248 * @dev: Pointer to the WLAN device.
2249 * @skb: Pointer to OS packet (sk_buff).
2250 *
2251 * This funciton sets the multicast address list.
2252 *
2253 * Return: None
2254 */
2255static void __hdd_set_multicast_list(struct net_device *dev)
2256{
2257 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2258 int mc_count;
2259 int i = 0, status;
2260 struct netdev_hw_addr *ha;
2261 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2262 static const uint8_t ipv6_router_solicitation[]
2263 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2264
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002265 ENTER_DEV(dev);
2266
Anurag Chouhan6d760662016-02-20 16:05:43 +05302267 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302268 return;
2269
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302271 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002273
2274 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002275 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276 adapter->mc_addr_list.mc_cnt = 0;
2277 } else {
2278 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302279 hdd_notice("mc_count : %u", mc_count);
2280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002281 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Dustin Brown61269462016-09-19 13:25:45 -07002282 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
2283 WLAN_HDD_MAX_MC_ADDR_LIST);
2284 wlan_hdd_set_mc_addr_list(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 adapter->mc_addr_list.mc_cnt = 0;
2286 return;
2287 }
2288
2289 adapter->mc_addr_list.mc_cnt = mc_count;
2290
2291 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302292 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2293 i, MAC_ADDR_ARRAY(ha->addr));
2294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295 if (i == mc_count)
2296 break;
2297 /*
2298 * Skip following addresses:
2299 * 1)IPv6 router solicitation address
2300 * 2)Any other address pattern if its set during
2301 * RXFILTER REMOVE driver command based on
2302 * addr_filter_pattern
2303 */
2304 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2305 ETH_ALEN)) ||
2306 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2307 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002308 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309 MAC_ADDR_ARRAY(ha->addr));
2310 adapter->mc_addr_list.mc_cnt--;
2311 continue;
2312 }
2313
2314 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2315 ETH_ALEN);
2316 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2317 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002318 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2320 i++;
2321 }
2322 }
2323 if (hdd_ctx->config->active_mode_offload) {
2324 hdd_info("enable mc filtering");
2325 wlan_hdd_set_mc_addr_list(adapter, true);
2326 } else {
2327 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2328 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302329 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330 return;
2331}
2332
2333/**
2334 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2335 * @dev: pointer to net_device
2336 *
2337 * Return: none
2338 */
2339static void hdd_set_multicast_list(struct net_device *dev)
2340{
2341 cds_ssr_protect(__func__);
2342 __hdd_set_multicast_list(dev);
2343 cds_ssr_unprotect(__func__);
2344}
2345#endif
2346
2347/**
2348 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2349 * @dev: Pointer to the WLAN device.
2350 * @skb: Pointer to OS packet (sk_buff).
2351 *
2352 * This function is registered with the Linux OS for network
2353 * core to decide which queue to use first.
2354 *
2355 * Return: ac, Queue Index/access category corresponding to UP in IP header
2356 */
2357static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2358#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2359 , void *accel_priv
2360#endif
2361#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2362 , select_queue_fallback_t fallback
2363#endif
2364)
2365{
2366 return hdd_wmm_select_queue(dev, skb);
2367}
2368
2369static struct net_device_ops wlan_drv_ops = {
2370 .ndo_open = hdd_open,
2371 .ndo_stop = hdd_stop,
2372 .ndo_uninit = hdd_uninit,
2373 .ndo_start_xmit = hdd_hard_start_xmit,
2374 .ndo_tx_timeout = hdd_tx_timeout,
2375 .ndo_get_stats = hdd_get_stats,
2376 .ndo_do_ioctl = hdd_ioctl,
2377 .ndo_set_mac_address = hdd_set_mac_address,
2378 .ndo_select_queue = hdd_select_queue,
2379#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381#endif
2382};
2383
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002384/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2385static struct net_device_ops wlan_mon_drv_ops = {
2386 .ndo_open = hdd_mon_open,
2387 .ndo_stop = hdd_stop,
2388 .ndo_get_stats = hdd_get_stats,
2389};
2390
2391/**
2392 * hdd_set_station_ops() - update net_device ops for monitor mode
2393 * @pWlanDev: Handle to struct net_device to be updated.
2394 * Return: None
2395 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396void hdd_set_station_ops(struct net_device *pWlanDev)
2397{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002398 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2399 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2400 else
2401 pWlanDev->netdev_ops = &wlan_drv_ops;
2402}
2403
Komal Seelama89be8d2016-09-29 11:09:26 +05302404#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302405/**
2406 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2407 * @hdd_ctx: HDD context
2408 *
2409 * Return: None
2410 */
2411static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2412{
2413 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2414
2415 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302416 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302417 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302418}
2419
2420/**
2421 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2422 * @hdd_ctx: HDD Context
2423 *
2424 * Return: None
2425 */
2426static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2427{
2428 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2429
2430 qdf_runtime_lock_deinit(ctx->scan);
2431 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302432 qdf_runtime_lock_deinit(ctx->roc);
2433 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302434 qdf_runtime_lock_deinit(ctx->dfs);
2435 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302436}
2437
Komal Seelama89be8d2016-09-29 11:09:26 +05302438static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2439{
2440 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2441
2442 ctx->connect = qdf_runtime_lock_init("connect");
2443}
2444
2445static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2446{
2447 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2448
2449 qdf_runtime_lock_deinit(ctx->connect);
2450 ctx->connect = NULL;
2451}
2452#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302453static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2454static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302455static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2456static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2457#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002458/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002459 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2460 * @hdd_ctx: global hdd context
2461 * @macAddr: mac address to assign to the interface
2462 * @name: User-visible name of the interface
2463 *
2464 * hdd adapter pointer would point to the netdev->priv space, this function
2465 * would retrive the pointer, and setup the hdd adapter configuration.
2466 *
2467 * Return: the pointer to hdd adapter, otherwise NULL
2468 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2470 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002471 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 const char *name)
2473{
2474 struct net_device *pWlanDev = NULL;
2475 hdd_adapter_t *adapter = NULL;
2476 /*
2477 * cfg80211 initialization and registration....
2478 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002479 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2480#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2481 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002483 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2484 hdd_mon_mode_ether_setup : ether_setup),
2485 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486
2487 if (pWlanDev != NULL) {
2488
2489 /* Save the pointer to the net_device in the HDD adapter */
2490 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2491
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302492 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493
2494 adapter->dev = pWlanDev;
2495 adapter->pHddCtx = hdd_ctx;
2496 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302497 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498
2499 init_completion(&adapter->session_open_comp_var);
2500 init_completion(&adapter->session_close_comp_var);
2501 init_completion(&adapter->disconnect_comp_var);
2502 init_completion(&adapter->linkup_event_var);
2503 init_completion(&adapter->cancel_rem_on_chan_var);
2504 init_completion(&adapter->rem_on_chan_ready_event);
2505 init_completion(&adapter->sta_authorized_event);
2506 init_completion(&adapter->offchannel_tx_event);
2507 init_completion(&adapter->tx_action_cnf_event);
2508#ifdef FEATURE_WLAN_TDLS
2509 init_completion(&adapter->tdls_add_station_comp);
2510 init_completion(&adapter->tdls_del_station_comp);
2511 init_completion(&adapter->tdls_mgmt_comp);
2512 init_completion(&adapter->tdls_link_establish_req_comp);
2513#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002514 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515 init_completion(&adapter->change_country_code);
2516
2517
2518 init_completion(&adapter->scan_info.abortscan_event_var);
2519
2520 adapter->offloads_configured = false;
2521 adapter->isLinkUpSvcNeeded = false;
2522 adapter->higherDtimTransition = true;
2523 /* Init the net_device structure */
2524 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2525
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302526 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302528 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529 sizeof(tSirMacAddr));
2530 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002531
2532 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2533 pWlanDev->features |=
2534 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2535 pWlanDev->features |= NETIF_F_RXCSUM;
2536
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002537 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 hdd_set_station_ops(adapter->dev);
2540
2541 pWlanDev->destructor = free_netdev;
2542 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002543 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 adapter->wdev.wiphy = hdd_ctx->wiphy;
2545 adapter->wdev.netdev = pWlanDev;
2546 /* set pWlanDev's parent to underlying device */
2547 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2548 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302549 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302551 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552 }
2553
2554 return adapter;
2555}
2556
Jeff Johnson590e2012016-10-05 16:16:24 -07002557static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2558 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559{
2560 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002562 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2564 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002565 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302566 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 }
2568 }
2569 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002570 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302571 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572 }
2573 } else {
2574 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002575 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302576 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 }
2578 }
2579 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2580
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302581 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582}
2583
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002584QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585{
2586 hdd_adapter_t *adapter = pContext;
2587
2588 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002589 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302590 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591 }
2592
2593 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002594 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302595 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596 }
2597
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002598 /*
2599 * For NAN Data interface, the close session results in the final
2600 * indication to the userspace
2601 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002602 if (adapter->device_mode == QDF_NDI_MODE)
2603 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002604
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 /*
2608 * We can be blocked while waiting for scheduled work to be
2609 * flushed, and the adapter structure can potentially be freed, in
2610 * which case the magic will have been reset. So make sure the
2611 * magic is still good, and hence the adapter structure is still
2612 * valid, before signaling completion
2613 */
2614 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2615 complete(&adapter->session_close_comp_var);
2616
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302617 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618}
2619
Krunal Soni8c37e322016-02-03 16:08:37 -08002620/**
2621 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2622 * @adapter: pointer to device adapter
2623 * @type: type of interface
2624 *
2625 * This routine will check the mode of adapter and if it is required then it
2626 * will initialize the TDLS operations
2627 *
2628 * Return: QDF_STATUS
2629 */
2630#ifdef FEATURE_WLAN_TDLS
2631static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2632{
2633 if (QDF_IBSS_MODE != type) {
2634 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002635 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002636 return QDF_STATUS_E_FAILURE;
2637 }
2638 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2639 }
2640 return QDF_STATUS_SUCCESS;
2641}
2642#else
2643static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2644{
2645 return QDF_STATUS_SUCCESS;
2646}
2647#endif
2648
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302649QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650{
2651 struct net_device *pWlanDev = adapter->dev;
2652 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2653 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302654 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302655 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002656 uint32_t type, subType;
2657 unsigned long rc;
2658 int ret_val;
2659
2660 INIT_COMPLETION(adapter->session_open_comp_var);
2661 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002662 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302664 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002665 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 goto error_sme_open;
2667 }
2668 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302669 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2671 (uint8_t *) &adapter->macAddressCurrent,
2672 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302673 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002674 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302675 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302676 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 goto error_sme_open;
2678 }
2679 /* Block on a completion variable. Can't wait forever though. */
2680 rc = wait_for_completion_timeout(
2681 &adapter->session_open_comp_var,
2682 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2683 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002684 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 rc);
Sandeep Puligillae8065992016-11-14 00:23:43 -08002686 adapter->sessionId = HDD_SESSION_ID_INVALID;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302687 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 }
2689
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302690 status = hdd_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
2691 if (QDF_IS_STATUS_ERROR(status))
2692 goto error_vdev_create;
2693
Naveen Rawata410c5a2016-09-19 14:22:33 -07002694 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302696 qdf_ret_status = hdd_register_wext(pWlanDev);
2697 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002698 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302699 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302700 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002701 goto error_register_wext;
2702 }
2703 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002704 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2706
2707 /* 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
4802 hdd_context_deinit(hdd_ctx);
4803
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304804 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004805 hdd_ctx->config = NULL;
4806
4807 wiphy_free(hdd_ctx->wiphy);
4808}
4809
4810/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 * hdd_wlan_exit() - HDD WLAN exit function
4812 * @hdd_ctx: Pointer to the HDD Context
4813 *
4814 * This is the driver exit point (invoked during rmmod)
4815 *
4816 * Return: None
4817 */
Jeff Johnson590e2012016-10-05 16:16:24 -07004818static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819{
4820 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304821 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004822 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304823 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824
4825 ENTER();
4826
Arun Khandavallifae92942016-08-01 13:31:08 +05304827 if (QDF_TIMER_STATE_RUNNING ==
4828 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4829 hdd_info("Stpp interface change timer");
4830 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 }
4832
Arun Khandavallifae92942016-08-01 13:31:08 +05304833 if (!QDF_IS_STATUS_SUCCESS
4834 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4835 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004836
Arun Khandavallifae92942016-08-01 13:31:08 +05304837
4838 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839
Nitesh Shah61c10d92016-10-19 19:29:15 +05304840 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
4841
Prashanth Bhattaab004382016-10-11 16:08:11 -07004842 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843
4844#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304845 if (QDF_TIMER_STATE_RUNNING ==
4846 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4847 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848 }
4849
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304850 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304851 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004852 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004853 }
Liangwei Dongaef84342016-10-21 05:28:00 -04004854 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4855 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4856 hdd_ctx->last_acs_channel_list = NULL;
4857 hdd_ctx->num_of_channels = 0;
4858 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860
Arun Khandavallifae92942016-08-01 13:31:08 +05304861 mutex_lock(&hdd_ctx->iface_change_lock);
4862 driver_status = hdd_ctx->driver_status;
4863 mutex_unlock(&hdd_ctx->iface_change_lock);
4864
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 /*
4866 * Powersave Offload Case
4867 * Disable Idle Power Save Mode
4868 */
4869 hdd_set_idle_ps_config(hdd_ctx, false);
4870
Arun Khandavallifae92942016-08-01 13:31:08 +05304871 if (driver_status != DRIVER_MODULES_CLOSED) {
4872 hdd_unregister_wext_all_adapters(hdd_ctx);
4873 /*
4874 * Cancel any outstanding scan requests. We are about to close
4875 * all of our adapters, but an adapter structure is what SME
4876 * passes back to our callback function. Hence if there
4877 * are any outstanding scan requests then there is a
4878 * race condition between when the adapter is closed and
4879 * when the callback is invoked. We try to resolve that
4880 * race condition here by canceling any outstanding scans
4881 * before we close the adapters.
4882 * Note that the scans may be cancelled in an asynchronous
4883 * manner, so ideally there needs to be some kind of
4884 * synchronization. Rather than introduce a new
4885 * synchronization here, we will utilize the fact that we are
4886 * about to Request Full Power, and since that is synchronized,
4887 * the expectation is that by the time Request Full Power has
4888 * completed, all scans will be cancelled
4889 */
4890 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07004891 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05304892 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893 }
4894
4895 /*
4896 * Close the scheduler before calling cds_close to make sure no thread
4897 * is scheduled after the each module close is called i.e after all the
4898 * data structures are freed.
4899 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304900 qdf_status = cds_sched_close(p_cds_context);
4901 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004902 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304903 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05304906 hdd_wlan_stop_modules(hdd_ctx);
4907
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304908 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4909 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4910 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 /*
4913 * Close CDS
4914 * This frees pMac(HAL) context. There should not be any call
4915 * that requires pMac access after this.
4916 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07004918 hdd_green_ap_deinit(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004919
Komal Seelam8634b772016-09-29 12:12:24 +05304920 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004921 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922
4923 hdd_ipa_cleanup(hdd_ctx);
4924
4925 /* Free up RoC request queue and flush workqueue */
4926 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304928 wlansap_global_deinit();
Nirav Shahed34b212016-04-25 10:59:16 +05304929 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304931 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004932
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07004933 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004934
Arun Khandavallifae92942016-08-01 13:31:08 +05304935 hdd_exit_netlink_services(hdd_ctx);
4936 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004937 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938}
4939
4940void __hdd_wlan_exit(void)
4941{
4942 hdd_context_t *hdd_ctx;
4943
4944 ENTER();
4945
Anurag Chouhan6d760662016-02-20 16:05:43 +05304946 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004948 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 EXIT();
4950 return;
4951 }
4952
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004953 /* Check IPA HW Pipe shutdown */
4954 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4955
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004956 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05304957 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 /* Do all the cleanup before deregistering the driver */
4960 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962 EXIT();
4963}
4964
4965#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04004966/**
4967 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
4968 * @data: pointer to hdd_context_t
4969 *
4970 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
4971 * Then new ACS request will do a fresh scan without reusing the cached
4972 * scan information.
4973 *
4974 * Return: void
4975 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976void hdd_skip_acs_scan_timer_handler(void *data)
4977{
4978 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4979
Jeff Johnson760350b2016-08-15 14:01:52 -07004980 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04004982 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4983 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4984 hdd_ctx->last_acs_channel_list = NULL;
4985 hdd_ctx->num_of_channels = 0;
4986 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987
4988 if (!hdd_ctx->hHal)
4989 return;
4990 sme_scan_flush_result(hdd_ctx->hHal);
4991}
4992#endif
4993
4994#ifdef QCA_HT_2040_COEX
4995/**
4996 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4997 * @adapter: pointer to adapter
4998 * @staId: station id
4999 * @macAddrSTA: station MAC address
5000 * @channel_type: channel type
5001 *
5002 * This function notifies FW with HT20/HT40 mode
5003 *
5004 * Return: 0 if successful, error number otherwise
5005 */
5006int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305007 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008{
5009 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305010 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 hdd_context_t *hdd_ctx = NULL;
5012
5013 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5014
5015 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305016 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005019 if (!hdd_ctx->hHal)
5020 return -EINVAL;
5021
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305022 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305024 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005025 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005026 return -EINVAL;
5027 }
5028
5029 return 0;
5030}
5031#endif
5032
5033/**
5034 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5035 * @state: state
5036 *
5037 * This function notifies FW with modem power status
5038 *
5039 * Return: 0 if successful, error number otherwise
5040 */
5041int hdd_wlan_notify_modem_power_state(int state)
5042{
5043 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305044 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 hdd_context_t *hdd_ctx;
5046
Anurag Chouhan6d760662016-02-20 16:05:43 +05305047 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305049 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005052 if (!hdd_ctx->hHal)
5053 return -EINVAL;
5054
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305055 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5056 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005057 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 state);
5059 return -EINVAL;
5060 }
5061 return 0;
5062}
5063
5064/**
5065 *
5066 * hdd_post_cds_enable_config() - HDD post cds start config helper
5067 * @adapter - Pointer to the HDD
5068 *
5069 * Return: None
5070 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305071QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305073 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074
5075 /*
5076 * Send ready indication to the HDD. This will kick off the MAC
5077 * into a 'running' state and should kick off an initial scan.
5078 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305079 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5080 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005081 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5082 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305083 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005084 }
5085
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305086 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087}
5088
5089/* wake lock APIs for HDD */
5090void hdd_prevent_suspend(uint32_t reason)
5091{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305092 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005093}
5094
5095void hdd_allow_suspend(uint32_t reason)
5096{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305097 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098}
5099
5100void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5101{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305102 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5103 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005104}
5105
5106/**
5107 * hdd_exchange_version_and_caps() - exchange version and capability with target
5108 * @hdd_ctx: Pointer to HDD context
5109 *
5110 * This is the HDD function to exchange version and capability information
5111 * between Host and Target
5112 *
5113 * This function gets reported version of FW.
5114 * It also finds the version of target headers used to compile the host;
5115 * It compares the above two and prints a warning if they are different;
5116 * It gets the SW and HW version string;
5117 * Finally, it exchanges capabilities between host and target i.e. host
5118 * and target exchange a msg indicating the features they support through a
5119 * bitmap
5120 *
5121 * Return: None
5122 */
5123void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5124{
5125
5126 tSirVersionType versionCompiled;
5127 tSirVersionType versionReported;
5128 tSirVersionString versionString;
5129 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305130 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005131
5132 memset(&versionCompiled, 0, sizeof(versionCompiled));
5133 memset(&versionReported, 0, sizeof(versionReported));
5134
5135 /* retrieve and display WCNSS version information */
5136 do {
5137
5138 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5139 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305140 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005141 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 break;
5143 }
5144
5145 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5146 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305147 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005148 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 break;
5150 }
5151
5152 if ((versionCompiled.major != versionReported.major) ||
5153 (versionCompiled.minor != versionReported.minor) ||
5154 (versionCompiled.version != versionReported.version) ||
5155 (versionCompiled.revision != versionReported.revision)) {
5156 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5157 "Host expected %u.%u.%u.%u\n",
5158 WLAN_MODULE_NAME,
5159 (int)versionReported.major,
5160 (int)versionReported.minor,
5161 (int)versionReported.version,
5162 (int)versionReported.revision,
5163 (int)versionCompiled.major,
5164 (int)versionCompiled.minor,
5165 (int)versionCompiled.version,
5166 (int)versionCompiled.revision);
5167 } else {
5168 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5169 WLAN_MODULE_NAME,
5170 (int)versionReported.major,
5171 (int)versionReported.minor,
5172 (int)versionReported.version,
5173 (int)versionReported.revision);
5174 }
5175
5176 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5177 versionString,
5178 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305179 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005180 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 break;
5182 }
5183
5184 pr_info("%s: WCNSS software version %s\n",
5185 WLAN_MODULE_NAME, versionString);
5186
5187 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5188 versionString,
5189 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305190 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005191 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192 break;
5193 }
5194
5195 pr_info("%s: WCNSS hardware version %s\n",
5196 WLAN_MODULE_NAME, versionString);
5197
5198 /*
5199 * 1.Check if FW version is greater than 0.1.1.0. Only then
5200 * send host-FW capability exchange message
5201 * 2.Host-FW capability exchange message is only present on
5202 * target 1.1 so send the message only if it the target is 1.1
5203 * minor numbers for different target branches:
5204 * 0 -> (1.0)Mainline Build
5205 * 1 -> (1.1)Mainline Build
5206 * 2->(1.04) Stability Build
5207 */
5208 if (((versionReported.major > 0) || (versionReported.minor > 1)
5209 || ((versionReported.minor >= 1)
5210 && (versionReported.version >= 1)))
5211 && ((versionReported.major == 1)
5212 && (versionReported.minor >= 1)))
5213 fwFeatCapsMsgSupported = 1;
5214
5215 if (fwFeatCapsMsgSupported) {
5216 /*
5217 * Indicate if IBSS heartbeat monitoring needs to be
5218 * offloaded
5219 */
5220 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5221 sme_disable_feature_capablity
5222 (IBSS_HEARTBEAT_OFFLOAD);
5223 }
5224
5225 sme_feature_caps_exchange(hdd_ctx->hHal);
5226 }
5227
5228 } while (0);
5229
5230}
5231
5232/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305233QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234{
5235 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5236 hdd_ctx->reg.cc_src);
5237}
5238
5239/**
5240 * hdd_is_5g_supported() - check if hardware supports 5GHz
5241 * @hdd_ctx: Pointer to the hdd context
5242 *
5243 * HDD function to know if hardware supports 5GHz
5244 *
5245 * Return: true if hardware supports 5GHz
5246 */
5247bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5248{
zdingf54169a2016-10-12 17:08:45 +08005249 if (!hdd_ctx || !hdd_ctx->config)
5250 return true;
5251
5252 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5253 return true;
5254 else
5255 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256}
5257
Amar Singhale4f28ee2015-10-21 14:36:56 -07005258static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259{
5260 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005261 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262
5263 wiphy = hdd_ctx->wiphy;
5264
5265 /*
5266 * The channel information in
5267 * wiphy needs to be initialized before wiphy registration
5268 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005269 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5270 if (ret_val) {
5271 hdd_alert("regulatory init failed");
5272 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005273 }
5274
5275#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5276 wiphy->wowlan = &wowlan_support_reg_init;
5277#else
5278 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5279 WIPHY_WOWLAN_MAGIC_PKT |
5280 WIPHY_WOWLAN_DISCONNECT |
5281 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5282 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5283 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5284 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5285 WIPHY_WOWLAN_RFKILL_RELEASE;
5286
5287 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5288 WOW_MAX_FILTERS_PER_LIST);
5289 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5290 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5291#endif
5292
5293 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005294 ret_val = wlan_hdd_cfg80211_register(wiphy);
5295 if (0 > ret_val)
5296 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297
Amar Singhale4f28ee2015-10-21 14:36:56 -07005298 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005299}
5300
Ravi Joshie2331e82015-07-01 18:18:54 -07005301/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005302 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005303 * @hdd_ctx - handle to hdd context
5304 * @tx_packets - transmit packet count
5305 * @rx_packets - receive packet count
5306 *
5307 * The function controls the bus bandwidth and dynamic control of
5308 * tcp delayed ack configuration
5309 *
5310 * Returns: None
5311 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005312#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005313static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5314 const uint64_t tx_packets,
5315 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005316{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005318 uint64_t temp_rx = 0;
5319 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005320 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005321 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5322 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005323 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005326 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005327 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005328 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005329 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005330 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005331 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005332 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005333
Mohit Khannae71e2262015-11-10 09:37:24 -08005334 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5335 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336
5337 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005338 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5339 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005341 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305342 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305343 if (hdd_ctx->hbw_requested) {
5344 pld_remove_pm_qos(hdd_ctx->parent_dev);
5345 hdd_ctx->hbw_requested = false;
5346 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305347 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005348 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305349 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305350 if (!hdd_ctx->hbw_requested) {
5351 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5352 hdd_ctx->hbw_requested = true;
5353 }
5354
Nirav Shah3bbfa512016-05-12 16:43:49 +05305355 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005356 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305357 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005358 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005360
5361 /* fine-tuning parameters for RX Flows */
5362 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 hdd_ctx->prev_rx = rx_packets;
Ravi Joshifed83572016-10-07 16:20:37 -07005365 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5366 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5367 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5368 next_rx_level = WLAN_SVC_TP_HIGH;
5369 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005370 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005371 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005372 hdd_ctx->rx_high_ind_cnt = 0;
5373 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005374
Mohit Khannae71e2262015-11-10 09:37:24 -08005375 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5376 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377
5378 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005379 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 next_rx_level, temp_rx);
5381 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005382 /* Send throughput indication only if it is enabled.
5383 * Disabling tcp_del_ack will revert the tcp stack behavior
5384 * to default delayed ack. Note that this will disable the
5385 * dynamic delayed ack mechanism across the system
5386 */
5387 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305388 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5389 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390 &next_rx_level,
5391 sizeof(next_rx_level));
5392 }
5393
Mohit Khannae71e2262015-11-10 09:37:24 -08005394 /* fine-tuning parameters for TX Flows */
5395 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5396 hdd_ctx->prev_tx = tx_packets;
5397 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5398 next_tx_level = WLAN_SVC_TP_HIGH;
5399 else
5400 next_tx_level = WLAN_SVC_TP_LOW;
5401
5402 if (hdd_ctx->cur_tx_level != next_tx_level) {
5403 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5404 next_tx_level, temp_tx);
5405 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305406 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5407 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005408 &next_tx_level,
5409 sizeof(next_tx_level));
5410 }
5411
5412 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5413 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414 hdd_ctx->hdd_txrx_hist_idx++;
5415 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416}
5417
5418#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
5419static void hdd_bus_bw_compute_cbk(void *priv)
5420{
5421 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
5422 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305423 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305424 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5425 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 uint64_t total_tx = 0, total_rx = 0;
5427 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305428 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305429 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 bool connected = false;
5431 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5432
Prashanth Bhattaab004382016-10-11 16:08:11 -07005433 if (wlan_hdd_validate_context(hdd_ctx))
5434 return;
5435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005436 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305437 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 status =
5439 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5440
5441 if (adapterNode->pAdapter == NULL)
5442 continue;
5443 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305444 /*
5445 * Validate magic so we don't end up accessing
5446 * an invalid adapter.
5447 */
5448 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5449 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005451 if ((adapter->device_mode == QDF_STA_MODE ||
5452 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005453 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5454 != eConnectionState_Associated) {
5455
5456 continue;
5457 }
5458
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005459 if ((adapter->device_mode == QDF_SAP_MODE ||
5460 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5462
5463 continue;
5464 }
5465
5466 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5467 adapter->prev_tx_packets);
5468 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5469 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305470
5471 if (adapter->device_mode == QDF_SAP_MODE ||
5472 adapter->device_mode == QDF_P2P_GO_MODE ||
5473 adapter->device_mode == QDF_IBSS_MODE) {
5474
5475 ret = ol_get_intra_bss_fwd_pkts_count(
5476 adapter->sessionId,
5477 &fwd_tx_packets, &fwd_rx_packets);
5478 if (ret == A_OK) {
5479 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5480 fwd_tx_packets,
5481 adapter->prev_fwd_tx_packets);
5482 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5483 fwd_tx_packets,
5484 adapter->prev_fwd_rx_packets);
5485 }
5486 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487
5488 total_rx += adapter->stats.rx_packets;
5489 total_tx += adapter->stats.tx_packets;
5490
5491 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5492 adapter->prev_tx_packets = adapter->stats.tx_packets;
5493 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305494 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5495 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5497 connected = true;
5498 }
5499
5500 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5501 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5502 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5503 rx_packets;
5504 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5505 tx_packets;
5506
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305507 /* add intra bss forwarded tx and rx packets */
5508 tx_packets += fwd_tx_packets_diff;
5509 rx_packets += fwd_rx_packets_diff;
5510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5512 tx_packets += (uint64_t)ipa_tx_packets;
5513 rx_packets += (uint64_t)ipa_rx_packets;
5514
5515 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005516 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517 return;
5518 }
5519
Yuanyuan Liu13738502016-04-06 17:41:37 -07005520 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521
5522 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5523 hdd_ipa_uc_stat_request(adapter, 2);
5524
Anurag Chouhan210db072016-02-22 18:42:15 +05305525 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526 hdd_ctx->config->busBandwidthComputeInterval);
5527}
Prashanth Bhattaab004382016-10-11 16:08:11 -07005528
5529int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
5530{
5531 spin_lock_init(&hdd_ctx->bus_bw_lock);
5532
5533 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
5534 QDF_TIMER_TYPE_SW,
5535 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5536
5537 return 0;
5538}
5539
5540void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
5541{
5542 if (qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer) ==
5543 QDF_TIMER_STATE_RUNNING)
5544 hdd_reset_tcp_delack(hdd_ctx);
5545
5546 qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer);
5547}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548#endif
5549
5550/**
Nirav Shahed34b212016-04-25 10:59:16 +05305551 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5552 * @hdd_ctx: hdd context
5553 *
5554 * Return: 0 for success or error code
5555 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005556static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305557{
5558 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5559 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5560 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005561 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305562 return -ENOMEM;
5563 }
5564 return 0;
5565}
5566
5567/**
5568 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5569 * @hdd_ctx: hdd context
5570 *
5571 * Return: none
5572 */
5573void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5574{
5575 if (hdd_ctx->hdd_txrx_hist) {
5576 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5577 hdd_ctx->hdd_txrx_hist = NULL;
5578 }
5579}
5580
Nirav Shahda008342016-05-17 18:50:40 +05305581static uint8_t *convert_level_to_string(uint32_t level)
5582{
5583 switch (level) {
5584 /* initialize the wlan sub system */
5585 case WLAN_SVC_TP_NONE:
5586 return "NONE";
5587 case WLAN_SVC_TP_LOW:
5588 return "LOW";
5589 case WLAN_SVC_TP_MEDIUM:
5590 return "MED";
5591 case WLAN_SVC_TP_HIGH:
5592 return "HIGH";
5593 default:
5594 return "INVAL";
5595 }
5596}
5597
Nirav Shahed34b212016-04-25 10:59:16 +05305598
5599/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005600 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5601 * @hdd_ctx: hdd context
5602 *
5603 * Return: none
5604 */
5605void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5606{
5607 int i;
5608
5609#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005610 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305611 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005612 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613 hdd_ctx->config->busBandwidthHighThreshold,
5614 hdd_ctx->config->busBandwidthMediumThreshold,
5615 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005616 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305617 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005618 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619 hdd_ctx->config->tcpDelackThresholdHigh,
5620 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005621 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305622 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005623#endif
5624
Jeff Johnson760350b2016-08-15 14:01:52 -07005625 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305626 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5627
Jeff Johnson760350b2016-08-15 14:01:52 -07005628 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 -08005629
5630 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005631 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5633 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5634 hdd_ctx->hdd_txrx_hist[i].total_tx,
5635 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305636 convert_level_to_string(
5637 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5638 convert_level_to_string(
5639 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5640 convert_level_to_string(
5641 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642 }
5643 return;
5644}
5645
5646/**
5647 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5648 * @hdd_ctx: hdd context
5649 *
5650 * Return: none
5651 */
5652void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5653{
5654 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305655 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5656 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005657}
5658
5659/**
5660 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5661 * @pHddCtx: hdd context
5662 *
5663 * Return: none
5664 */
5665void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5666{
5667
5668 hdd_adapter_t *adapter = NULL;
5669 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305670 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005671 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305672 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005673
5674 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305675 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005676 adapter = adapter_node->pAdapter;
5677
Jeff Johnson760350b2016-08-15 14:01:52 -07005678 hdd_err("\nNetif queue operation statistics:");
5679 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305680 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005681 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305682 curr_time = qdf_system_ticks();
5683 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305684 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305685 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305686 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305687 unpause = adapter->total_unpause_time;
5688 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305689 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305690 pause = adapter->total_pause_time;
5691 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005692 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305693 qdf_system_ticks_to_msecs(total),
5694 qdf_system_ticks_to_msecs(pause),
5695 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005696 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005697
Nirav Shahda008342016-05-17 18:50:40 +05305698 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5699 qdf_time_t pause_delta = 0;
5700
5701 if (adapter->pause_map & (1 << i))
5702 pause_delta = delta;
5703
Jeff Johnson760350b2016-08-15 14:01:52 -07005704 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005705 hdd_reason_type_to_string(i),
5706 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305707 adapter->queue_oper_stats[i].unpause_count,
5708 qdf_system_ticks_to_msecs(
5709 adapter->queue_oper_stats[i].total_pause_time +
5710 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005711 }
5712
Jeff Johnson760350b2016-08-15 14:01:52 -07005713 hdd_err("\nNetif queue operation history:");
5714 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305715 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5716
Jeff Johnson760350b2016-08-15 14:01:52 -07005717 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005718
5719 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005720 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305721 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005722 adapter->queue_oper_history[i].time),
5723 hdd_action_type_to_string(
5724 adapter->queue_oper_history[i].netif_action),
5725 hdd_reason_type_to_string(
5726 adapter->queue_oper_history[i].netif_reason),
5727 adapter->queue_oper_history[i].pause_map);
5728 }
5729
5730 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5731 adapter_node = next;
5732 }
5733
5734
5735}
5736
5737/**
5738 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5739 * @hdd_ctx: hdd context
5740 *
5741 * Return: none
5742 */
5743void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5744{
5745 hdd_adapter_t *adapter = NULL;
5746 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305747 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005748
5749 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305750 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751 adapter = adapter_node->pAdapter;
5752
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305753 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305755 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305757 adapter->history_index = 0;
5758 adapter->start_time = adapter->last_time = qdf_system_ticks();
5759 adapter->total_pause_time = 0;
5760 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5762 adapter_node = next;
5763 }
5764}
5765
5766/**
5767 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5768 * @halHandle: Hal handle
5769 * @pContext: Pointer to the context
5770 * @sessionId: Session ID
5771 * @scanId: Scan ID
5772 * @status: Status
5773 *
5774 * This is the callback to be executed when 11d scan is completed to flush out
5775 * the scan results
5776 *
5777 * 11d scan is done during driver load and is a passive scan on all
5778 * channels supported by the device, 11d scans may find some APs on
5779 * frequencies which are forbidden to be used in the regulatory domain
5780 * the device is operating in. If these APs are notified to the supplicant
5781 * it may try to connect to these APs, thus flush out all the scan results
5782 * which are present in SME after 11d scan is done.
5783 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305784 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005785 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305786static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005787 uint8_t sessionId, uint32_t scanId,
5788 eCsrScanStatus status)
5789{
5790 ENTER();
5791
5792 sme_scan_flush_result(halHandle);
5793
5794 EXIT();
5795
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305796 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797}
5798
5799#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5800/**
5801 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5802 * @hdd_ctx: hdd global context
5803 *
5804 * Return: none
5805 */
5806static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5807{
5808 uint8_t i;
5809
5810 mutex_init(&hdd_ctx->op_ctx.op_lock);
5811 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5812 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5813 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5814 }
5815}
5816#else
5817static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5818{
5819}
5820#endif
5821
5822#ifdef WLAN_FEATURE_FASTPATH
5823/**
5824 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5825 * @hdd_cfg: hdd config
5826 * @context: lower layer context
5827 *
5828 * Return: none
5829 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305830void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831 void *context)
5832{
5833 if (hdd_cfg->fastpath_enable)
5834 hif_enable_fastpath(context);
5835}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836#endif
5837
Yuanyuan Liu13738502016-04-06 17:41:37 -07005838#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005839/**
5840 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005841 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842 * @level: thermal level
5843 *
5844 * Change IPA data path to SW path when the thermal throttle level greater
5845 * than 0, and restore the original data path when throttle level is 0
5846 *
5847 * Return: none
5848 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005849static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005851 hdd_context_t *hdd_ctx = context;
5852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853 /* Change IPA to SW path when throttle level greater than 0 */
5854 if (level > THROTTLE_LEVEL_0)
5855 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5856 else
5857 /* restore original concurrency mode */
5858 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5859}
5860
5861/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305862 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5863 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305864 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305866 * Get a safe channel to restart SAP. PCL already takes into account the
5867 * unsafe channels. So, the PCL is validated with the ACS range to provide
5868 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305870 * Return: Channel number to restart SAP in case of success. In case of any
5871 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005872 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305873static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5874 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005875{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305876 struct sir_pcl_list pcl;
5877 QDF_STATUS status;
5878 uint32_t i, j;
5879 tHalHandle *hal_handle;
5880 hdd_context_t *hdd_ctx;
5881 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005882
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305883 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5884 if (!hdd_ctx) {
5885 hdd_err("invalid HDD context");
5886 return INVALID_CHANNEL_ID;
5887 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005888
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305889 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5890 if (!hal_handle) {
5891 hdd_err("invalid HAL handle");
5892 return INVALID_CHANNEL_ID;
5893 }
5894
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305895 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5896 pcl.pcl_list, &pcl.pcl_len,
5897 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5898 if (QDF_IS_STATUS_ERROR(status)) {
5899 hdd_err("Get PCL failed");
5900 return INVALID_CHANNEL_ID;
5901 }
5902
5903 if (!pcl.pcl_len) {
5904 hdd_alert("pcl length is zero. this is not expected");
5905 return INVALID_CHANNEL_ID;
5906 }
5907
5908 hdd_info("start:%d end:%d",
5909 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5910 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5911
5912 /* PCL already takes unsafe channel into account */
5913 for (i = 0; i < pcl.pcl_len; i++) {
5914 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5915 if ((pcl.pcl_list[i] >=
5916 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5917 (pcl.pcl_list[i] <=
5918 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5919 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5920 return pcl.pcl_list[i];
5921 }
5922 }
5923
5924 hdd_info("no safe channel from PCL found in ACS range");
5925
5926 /* Try for safe channel from all valid channel */
5927 pcl.pcl_len = MAX_NUM_CHAN;
5928 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5929 &pcl.pcl_len);
5930 if (QDF_IS_STATUS_ERROR(status)) {
5931 hdd_err("error in getting valid channel list");
5932 return INVALID_CHANNEL_ID;
5933 }
5934
5935 for (i = 0; i < pcl.pcl_len; i++) {
5936 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5937 found = false;
5938 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07005939 if (pcl.pcl_list[i] ==
5940 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305941 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5942 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943 break;
5944 }
5945 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305946
5947 if (found)
5948 continue;
5949
5950 if ((pcl.pcl_list[i] >=
5951 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5952 (pcl.pcl_list[i] <=
5953 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5954 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5955 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005956 }
5957 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305958
5959 return INVALID_CHANNEL_ID;
5960}
5961
5962/**
5963 * hdd_restart_sap() - Restarts SAP on the given channel
5964 * @adapter: AP adapter
5965 * @channel: Channel
5966 *
5967 * Restarts the SAP interface by invoking the function which executes the
5968 * callback to perform channel switch using (E)CSA.
5969 *
5970 * Return: None
5971 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005972static void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305973{
5974 hdd_ap_ctx_t *hdd_ap_ctx;
5975 tHalHandle *hal_handle;
5976
5977 if (!adapter) {
5978 hdd_err("invalid adapter");
5979 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305981
5982 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5983
5984 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5985 if (!hal_handle) {
5986 hdd_err("invalid HAL handle");
5987 return;
5988 }
5989
5990 hdd_ap_ctx->sapConfig.channel = channel;
5991 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5992 hdd_ap_ctx->sapConfig.ch_width_orig;
5993
5994 hdd_info("chan:%d width:%d",
5995 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5996
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005997 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305998 hdd_ap_ctx->sapConfig.sec_ch,
5999 &hdd_ap_ctx->sapConfig.ch_params);
6000
6001 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006002}
Agrawal Ashish467dde42016-09-08 18:44:22 +05306003/**
6004 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6005 * @hdd_ctx: hdd context pointer
6006 *
6007 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6008 * and if ACS is enabled, driver will ask userspace to restart the
6009 * sap. User space on LTE coex indication restart driver.
6010 *
6011 * Return - none
6012 */
6013void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6014{
6015 QDF_STATUS status;
6016 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6017 hdd_adapter_t *adapter_temp;
6018 uint32_t i;
6019 bool found = false;
6020 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006021
Agrawal Ashish467dde42016-09-08 18:44:22 +05306022 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6023 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6024 adapter_temp = adapter_node->pAdapter;
6025
6026 if (!adapter_temp) {
6027 hdd_err("adapter is NULL, moving to next one");
6028 goto next_adapater;
6029 }
6030
6031 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6032 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
6033 hdd_info("skip device mode:%d acs:%d",
6034 adapter_temp->device_mode,
6035 adapter_temp->sessionCtx.ap.sapConfig.
6036 acs_cfg.acs_mode);
6037 goto next_adapater;
6038 }
6039
6040 found = false;
6041 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006042 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306043 hdd_ctxt->unsafe_channel_list[i]) {
6044 found = true;
6045 hdd_info("operating ch:%d is unsafe",
6046 adapter_temp->sessionCtx.ap.operatingChannel);
6047 break;
6048 }
6049 }
6050
6051 if (!found) {
6052 hdd_info("ch:%d is safe. no need to change channel",
6053 adapter_temp->sessionCtx.ap.operatingChannel);
6054 goto next_adapater;
6055 }
6056
6057 restart_chan =
6058 hdd_get_safe_channel_from_pcl_and_acs_range(
6059 adapter_temp);
6060 if (!restart_chan) {
6061 hdd_alert("fail to restart SAP");
6062 } else {
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306063 /* SAP restart due to unsafe channel. While restarting
6064 * the SAP, make sure to clear acs_channel, channel to
6065 * reset to 0. Otherwise these settings will override
6066 * the ACS while restart.
6067 */
6068 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6069 adapter_temp->sessionCtx.ap.sapConfig.channel =
6070 AUTO_CHANNEL_SELECT;
Agrawal Ashish467dde42016-09-08 18:44:22 +05306071 hdd_info("sending coex indication");
6072 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6073 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6074 hdd_restart_sap(adapter_temp, restart_chan);
6075 }
6076
6077next_adapater:
6078 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6079 adapter_node = next;
6080 }
6081}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006082/**
6083 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6084 * @adapter: HDD adapter pointer
6085 * @indParam: Channel avoid notification parameter
6086 *
6087 * Avoid channel notification from FW handler.
6088 * FW will send un-safe channel list to avoid over wrapping.
6089 * hostapd should not use notified channel
6090 *
6091 * Return: None
6092 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306093void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006094{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 hdd_context_t *hdd_ctxt;
6096 tSirChAvoidIndType *ch_avoid_indi;
6097 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006098 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6099 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006100 uint16_t start_channel;
6101 uint16_t end_channel;
6102 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006103 tHddAvoidFreqList hdd_avoid_freq_list;
6104 uint32_t i;
6105
6106 /* Basic sanity */
6107 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006108 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006109 return;
6110 }
6111
6112 hdd_ctxt = (hdd_context_t *) hdd_context;
6113 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6114 cds_context = hdd_ctxt->pcds_context;
6115
6116 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006117 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006118 ch_avoid_indi->avoid_range_count);
6119
6120 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306121 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006122 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6123 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6124 ch_avoid_indi->avoid_freq_range[i].start_freq;
6125 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6126 ch_avoid_indi->avoid_freq_range[i].end_freq;
6127 }
6128 hdd_avoid_freq_list.avoidFreqRangeCount =
6129 ch_avoid_indi->avoid_range_count;
6130
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006131 /* clear existing unsafe channel cache */
6132 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306133 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006134 sizeof(hdd_ctxt->unsafe_channel_list));
6135
6136 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6137 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006138 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006139 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006140 break;
6141 }
6142
6143 start_channel = ieee80211_frequency_to_channel(
6144 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6145 end_channel = ieee80211_frequency_to_channel(
6146 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006147 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006148 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6149 start_channel,
6150 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6151 end_channel);
6152
6153 /* do not process frequency bands that are not mapped to
6154 * predefined channels
6155 */
6156 if (start_channel == 0 || end_channel == 0)
6157 continue;
6158
Amar Singhalb8d4f152016-02-10 10:21:43 -08006159 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6160 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006161 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006162 ch_avoid_indi->avoid_freq_range[
6163 range_loop].start_freq) {
6164 start_channel_idx = channel_loop;
6165 break;
6166 }
6167 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006168 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6169 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006170 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006171 ch_avoid_indi->avoid_freq_range[
6172 range_loop].end_freq) {
6173 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006174 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006175 ch_avoid_indi->avoid_freq_range[
6176 range_loop].end_freq)
6177 end_channel_idx--;
6178 break;
6179 }
6180 }
6181
Amar Singhalb8d4f152016-02-10 10:21:43 -08006182 if (start_channel_idx == INVALID_CHANNEL ||
6183 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006184 continue;
6185
6186 for (channel_loop = start_channel_idx; channel_loop <=
6187 end_channel_idx; channel_loop++) {
6188 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006189 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006190 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006191 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006192 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006193 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006194 break;
6195 }
6196 }
6197 }
6198
Jeff Johnson34c88b72016-08-15 14:27:11 -07006199 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006200 hdd_ctxt->unsafe_channel_count);
6201
Yuanyuan Liu13738502016-04-06 17:41:37 -07006202 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6203 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006204 hdd_ctxt->unsafe_channel_count)) {
6205 hdd_err("Failed to set unsafe channel");
6206
6207 /* clear existing unsafe channel cache */
6208 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306209 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006210 sizeof(hdd_ctxt->unsafe_channel_list));
6211
6212 return;
6213 }
6214
6215 for (channel_loop = 0;
6216 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006217 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006218 hdd_ctxt->unsafe_channel_list[channel_loop]);
6219 }
6220
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306221 /*
6222 * first update the unsafe channel list to the platform driver and
6223 * send the avoid freq event to the application
6224 */
6225 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6226
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306227 if (!hdd_ctxt->unsafe_channel_count) {
6228 hdd_info("no unsafe channels - not restarting SAP");
6229 return;
6230 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306231 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006232 return;
6233}
6234
6235/**
6236 * hdd_init_channel_avoidance() - Initialize channel avoidance
6237 * @hdd_ctx: HDD global context
6238 *
6239 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006240 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006241 * down to the lower layers. Then subscribe to subsequent channel
6242 * avoidance events.
6243 *
6244 * Return: None
6245 */
6246static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6247{
6248 uint16_t unsafe_channel_count;
6249 int index;
6250
Yuanyuan Liu13738502016-04-06 17:41:37 -07006251 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6252 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006253 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006254 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006255
Jeff Johnson34c88b72016-08-15 14:27:11 -07006256 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006257 hdd_ctx->unsafe_channel_count);
6258
Anurag Chouhan6d760662016-02-20 16:05:43 +05306259 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006260 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006261
6262 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006263 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006264 hdd_ctx->unsafe_channel_list[index]);
6265
6266 }
6267
6268 /* Plug in avoid channel notification callback */
6269 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6270}
6271#else
6272static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6273{
6274}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006275static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006276{
6277}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006278#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006279
6280/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006281 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6282 * user space
6283 * @frame_ind: Management frame data to be informed.
6284 *
6285 * This function is used to indicate management frame to
6286 * user space
6287 *
6288 * Return: None
6289 *
6290 */
6291void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6292{
6293 hdd_context_t *hdd_ctx = NULL;
6294 hdd_adapter_t *adapter = NULL;
6295 void *cds_context = NULL;
6296 int i;
6297
6298 /* Get the global VOSS context.*/
6299 cds_context = cds_get_global_context();
6300 if (!cds_context) {
6301 hdd_err("Global CDS context is Null");
6302 return;
6303 }
6304 /* Get the HDD context.*/
6305 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6306
6307 if (0 != wlan_hdd_validate_context(hdd_ctx))
6308 return;
6309
6310 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6311 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6312 adapter =
6313 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6314 if (adapter)
6315 break;
6316 }
6317 } else {
6318 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6319 frame_ind->sessionId);
6320 }
6321
6322 if ((NULL != adapter) &&
6323 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6324 __hdd_indicate_mgmt_frame(adapter,
6325 frame_ind->frame_len,
6326 frame_ind->frameBuf,
6327 frame_ind->frameType,
6328 frame_ind->rxChan,
6329 frame_ind->rxRssi);
6330 return;
6331}
6332
6333/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006334 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6335 * @hdd_ctx: HDD context
6336 *
6337 * Disables all the dual mac features like DBS, Agile DFS etc.
6338 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306339 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006340 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306341static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006342{
6343 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306344 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006345
6346 if (!hdd_ctx) {
6347 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306348 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006349 }
6350
6351 cfg.scan_config = 0;
6352 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306353 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006354
6355 hdd_debug("Disabling all dual mac features...");
6356
6357 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306358 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006359 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6360 return status;
6361 }
6362
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306363 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006364}
6365
6366/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006367 * hdd_override_ini_config - Override INI config
6368 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006369 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006370 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006371 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006372 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006373 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006374static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006375{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006376
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006377 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6378 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6379 hdd_notice("Module enable_dfs_chan_scan set to %d",
6380 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006381 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006382 if (0 == enable_11d || 1 == enable_11d) {
6383 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6384 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006385 }
Leo Chang11545d62016-10-17 14:53:50 -07006386
6387 if (!hdd_ipa_is_present(hdd_ctx))
6388 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006389}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006390
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006391/**
6392 * hdd_set_trace_level_for_each - Set trace level for each INI config
6393 * @hdd_ctx - HDD context
6394 *
6395 * Set trace level for each module based on INI config.
6396 *
6397 * Return: None
6398 */
6399static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6400{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306401 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6402 hdd_ctx->config->qdf_trace_enable_wdi);
6403 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6404 hdd_ctx->config->qdf_trace_enable_hdd);
6405 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6406 hdd_ctx->config->qdf_trace_enable_sme);
6407 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6408 hdd_ctx->config->qdf_trace_enable_pe);
6409 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6410 hdd_ctx->config->qdf_trace_enable_wma);
6411 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6412 hdd_ctx->config->qdf_trace_enable_sys);
6413 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6414 hdd_ctx->config->qdf_trace_enable_qdf);
6415 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6416 hdd_ctx->config->qdf_trace_enable_sap);
6417 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6418 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6419 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6420 hdd_ctx->config->qdf_trace_enable_bmi);
6421 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6422 hdd_ctx->config->qdf_trace_enable_cfg);
6423 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6424 hdd_ctx->config->qdf_trace_enable_epping);
6425 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6426 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6427 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306428 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306429 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6430 hdd_ctx->config->qdf_trace_enable_htc);
6431 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6432 hdd_ctx->config->qdf_trace_enable_hif);
6433 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6434 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6435 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6436 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006438 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006439}
6440
6441/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006442 * hdd_context_init() - Initialize HDD context
6443 * @hdd_ctx: HDD context.
6444 *
6445 * Initialize HDD context along with all the feature specific contexts.
6446 *
6447 * return: 0 on success and errno on failure.
6448 */
6449static int hdd_context_init(hdd_context_t *hdd_ctx)
6450{
6451 int ret;
6452
6453 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6454 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6455
6456 hdd_init_ll_stats_ctx();
6457
6458 init_completion(&hdd_ctx->mc_sus_event_var);
6459 init_completion(&hdd_ctx->ready_to_suspend);
6460
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306461 hdd_init_bpf_completion();
6462
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006463 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306464 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006465 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306466
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006467 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6468
6469 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6470
6471 ret = hdd_scan_context_init(hdd_ctx);
6472 if (ret)
6473 goto list_destroy;
6474
6475 hdd_tdls_context_init(hdd_ctx);
6476
6477 hdd_rx_wake_lock_create(hdd_ctx);
6478
6479 ret = hdd_sap_context_init(hdd_ctx);
6480 if (ret)
6481 goto scan_destroy;
6482
6483 ret = hdd_roc_context_init(hdd_ctx);
6484 if (ret)
6485 goto sap_destroy;
6486
6487 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6488
6489 hdd_init_offloaded_packets_ctx(hdd_ctx);
6490
6491 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6492 hdd_ctx->config);
6493 if (ret)
6494 goto roc_destroy;
6495
6496 return 0;
6497
6498roc_destroy:
6499 hdd_roc_context_destroy(hdd_ctx);
6500
6501sap_destroy:
6502 hdd_sap_context_destroy(hdd_ctx);
6503
6504scan_destroy:
6505 hdd_scan_context_destroy(hdd_ctx);
6506 hdd_rx_wake_lock_destroy(hdd_ctx);
6507 hdd_tdls_context_destroy(hdd_ctx);
6508
6509list_destroy:
6510 qdf_list_destroy(&hdd_ctx->hddAdapters);
6511 return ret;
6512}
6513
6514/**
6515 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306516 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006517 *
6518 * Allocate and initialize HDD context. HDD context is allocated as part of
6519 * wiphy allocation and then context is initialized.
6520 *
6521 * Return: HDD context on success and ERR_PTR on failure
6522 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006523static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006524{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306525 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006526 int ret = 0;
6527 hdd_context_t *hdd_ctx;
6528 v_CONTEXT_t p_cds_context;
6529
6530 ENTER();
6531
6532 p_cds_context = cds_get_global_context();
6533 if (p_cds_context == NULL) {
6534 hdd_alert("Failed to get CDS global context");
6535 ret = -EINVAL;
6536 goto err_out;
6537 }
6538
6539 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6540
6541 if (hdd_ctx == NULL) {
6542 ret = -ENOMEM;
6543 goto err_out;
6544 }
6545
6546 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006547 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006548
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306549 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006550 if (hdd_ctx->config == NULL) {
6551 hdd_alert("Failed to alloc memory for HDD config!");
6552 ret = -ENOMEM;
6553 goto err_free_hdd_context;
6554 }
6555
6556 /* Read and parse the qcom_cfg.ini file */
6557 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306558 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306559 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006560 WLAN_INI_FILE);
6561 ret = -EINVAL;
6562 goto err_free_config;
6563 }
6564
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006565 hdd_ctx->configuredMcastBcastFilter =
6566 hdd_ctx->config->mcastBcastFilterSetting;
6567
6568 hdd_notice("Setting configuredMcastBcastFilter: %d",
6569 hdd_ctx->config->mcastBcastFilterSetting);
6570
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306571 if (hdd_ctx->config->fhostNSOffload)
6572 hdd_ctx->ns_offload_enable = true;
6573
Abhishek Singh5ea86532016-04-27 14:10:53 +05306574 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6575
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006576 hdd_override_ini_config(hdd_ctx);
6577
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006578 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006579
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006580 ret = hdd_context_init(hdd_ctx);
6581
6582 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006583 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006584
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006585
Yuanyuan Liu13738502016-04-06 17:41:37 -07006586 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6587 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006588
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006589
6590 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306591 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006592
Anurag Chouhan6d760662016-02-20 16:05:43 +05306593 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006594 goto skip_multicast_logging;
6595
6596 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6597
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006598 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6599 if (ret)
6600 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05306601
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006602 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6603 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306604 goto err_free_histogram;
6605
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006606
6607 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306608 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006609 * levels of the code need not be set when the logger thread
6610 * is not enabled.
6611 */
6612 if (cds_is_multicast_logging())
6613 wlan_logging_set_log_level();
6614
6615skip_multicast_logging:
6616 hdd_set_trace_level_for_each(hdd_ctx);
6617
6618 return hdd_ctx;
6619
Nirav Shahed34b212016-04-25 10:59:16 +05306620err_free_histogram:
6621 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6622
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006623err_deinit_hdd_context:
6624 hdd_context_deinit(hdd_ctx);
6625
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006626err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306627 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006628
6629err_free_hdd_context:
6630 wiphy_free(hdd_ctx->wiphy);
6631
6632err_out:
6633 return ERR_PTR(ret);
6634}
6635
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006636#ifdef WLAN_OPEN_P2P_INTERFACE
6637/**
6638 * hdd_open_p2p_interface - Open P2P interface
6639 * @hdd_ctx: HDD context
6640 * @rtnl_held: True if RTNL lock held
6641 *
6642 * Open P2P interface during probe. This function called to open the P2P
6643 * interface at probe along with STA interface.
6644 *
6645 * Return: 0 on success and errno on failure
6646 */
6647static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6648{
6649 hdd_adapter_t *adapter;
6650 uint8_t *p2p_dev_addr;
6651
6652 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6653 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306654 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006655 hdd_ctx->config->intfMacAddr[0].bytes,
6656 sizeof(tSirMacAddr));
6657
6658 /*
6659 * Generate the P2P Device Address. This consists of
6660 * the device's primary MAC address with the locally
6661 * administered bit set.
6662 */
6663 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6664 } else {
6665 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6666 if (p2p_dev_addr == NULL) {
6667 hdd_alert("Failed to allocate mac_address for p2p_device");
6668 return -ENOSPC;
6669 }
6670
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306671 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306672 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006673 }
6674
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006675 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006676 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006677 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006678
6679 if (NULL == adapter) {
6680 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6681 return -ENOSPC;
6682 }
6683
6684 return 0;
6685}
6686#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306687static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006688 bool rtnl_held)
6689{
6690 return 0;
6691}
6692#endif
6693
6694/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306695 * hdd_start_station_adapter()- Start the Station Adapter
6696 * @adapter: HDD adapter
6697 *
6698 * This function initializes the adapter for the station mode.
6699 *
6700 * Return: 0 on success or errno on failure.
6701 */
6702int hdd_start_station_adapter(hdd_adapter_t *adapter)
6703{
6704 QDF_STATUS status;
6705
6706 ENTER_DEV(adapter->dev);
6707
6708 status = hdd_init_station_mode(adapter);
6709
6710 if (QDF_STATUS_SUCCESS != status) {
6711 hdd_err("Error Initializing station mode: %d", status);
6712 return qdf_status_to_os_return(status);
6713 }
6714
Arun Khandavallifae92942016-08-01 13:31:08 +05306715 hdd_register_tx_flow_control(adapter,
6716 hdd_tx_resume_timer_expired_handler,
6717 hdd_tx_resume_cb);
6718
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306719 EXIT();
6720 return 0;
6721}
6722
6723/**
6724 * hdd_start_ap_adapter()- Start AP Adapter
6725 * @adapter: HDD adapter
6726 *
6727 * This function initializes the adapter for the AP mode.
6728 *
6729 * Return: 0 on success errno on failure.
6730 */
6731int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6732{
6733 QDF_STATUS status;
6734
6735 ENTER();
6736
6737 status = hdd_init_ap_mode(adapter);
6738
6739 if (QDF_STATUS_SUCCESS != status) {
6740 hdd_err("Error Initializing the AP mode: %d", status);
6741 return qdf_status_to_os_return(status);
6742 }
6743
Arun Khandavallifae92942016-08-01 13:31:08 +05306744 hdd_register_tx_flow_control(adapter,
6745 hdd_softap_tx_resume_timer_expired_handler,
6746 hdd_softap_tx_resume_cb);
6747
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306748 EXIT();
6749 return 0;
6750}
6751
6752/**
6753 * hdd_start_ftm_adapter()- Start FTM adapter
6754 * @adapter: HDD adapter
6755 *
6756 * This function initializes the adapter for the FTM mode.
6757 *
6758 * Return: 0 on success or errno on failure.
6759 */
6760int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6761{
6762 QDF_STATUS qdf_status;
6763
6764 ENTER_DEV(adapter->dev);
6765
6766 qdf_status = hdd_init_tx_rx(adapter);
6767
6768 if (QDF_STATUS_SUCCESS != qdf_status) {
6769 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6770 return qdf_status_to_os_return(qdf_status);
6771 }
6772
6773 return 0;
6774 EXIT();
6775}
6776
6777/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006778 * hdd_open_interfaces - Open all required interfaces
6779 * hdd_ctx: HDD context
6780 * rtnl_held: True if RTNL lock is held
6781 *
6782 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6783 *
6784 * Return: Primary adapter on success and PTR_ERR on failure
6785 */
6786static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6787 bool rtnl_held)
6788{
6789 hdd_adapter_t *adapter = NULL;
6790 hdd_adapter_t *adapter_11p = NULL;
6791 int ret;
6792
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006793 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306794 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006795 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006796 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006797 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006798
6799 if (adapter == NULL)
6800 return ERR_PTR(-ENOSPC);
6801
6802 return adapter;
6803 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006804 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006805 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006806 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006807
6808 if (adapter == NULL)
6809 return ERR_PTR(-ENOSPC);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006810 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6811 if (ret)
6812 goto err_close_adapter;
6813
6814 /* Open 802.11p Interface */
6815 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006816 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006817 "wlanocb%d",
6818 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006819 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006820 if (adapter_11p == NULL) {
6821 hdd_err("Failed to open 802.11p interface");
6822 goto err_close_adapter;
6823 }
6824 }
6825
6826 return adapter;
6827
6828err_close_adapter:
6829 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6830 return ERR_PTR(ret);
6831}
6832
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006833/**
6834 * hdd_update_country_code - Update country code
6835 * @hdd_ctx: HDD context
6836 * @adapter: Primary adapter context
6837 *
6838 * Update country code based on module parameter country_code at SME and wait
6839 * for the settings to take effect.
6840 *
6841 * Return: 0 on success and errno on failure
6842 */
6843static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6844 hdd_adapter_t *adapter)
6845{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306846 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006847 int ret = 0;
6848 unsigned long rc;
6849
6850 if (country_code == NULL)
6851 return 0;
6852
6853 INIT_COMPLETION(adapter->change_country_code);
6854
6855 status = sme_change_country_code(hdd_ctx->hHal,
6856 wlan_hdd_change_country_code_callback,
6857 country_code, adapter,
6858 hdd_ctx->pcds_context, eSIR_TRUE,
6859 eSIR_TRUE);
6860
6861
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306862 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006863 hdd_err("SME Change Country code from module param fail ret=%d",
6864 ret);
6865 return -EINVAL;
6866 }
6867
6868 rc = wait_for_completion_timeout(&adapter->change_country_code,
6869 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6870 if (!rc) {
6871 hdd_err("SME while setting country code timed out");
6872 ret = -ETIMEDOUT;
6873 }
6874
6875 return ret;
6876}
6877
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306878#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6879/**
6880 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6881 * @cds_cfg: CDS Configuration
6882 * @hdd_ctx: Pointer to hdd context
6883 *
6884 * Return: none
6885 */
6886static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6887 *cds_cfg,
6888 hdd_context_t *hdd_ctx)
6889{
6890 cds_cfg->tx_flow_stop_queue_th =
6891 hdd_ctx->config->TxFlowStopQueueThreshold;
6892 cds_cfg->tx_flow_start_queue_offset =
6893 hdd_ctx->config->TxFlowStartQueueOffset;
6894}
6895#else
6896static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6897 *cds_cfg,
6898 hdd_context_t *hdd_ctx)
6899{
6900}
6901#endif
6902
6903#ifdef FEATURE_WLAN_RA_FILTERING
6904/**
6905 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6906 * @cds_cfg: CDS Configuration
6907 * @hdd_ctx: Pointer to hdd context
6908 *
6909 * Return: none
6910 */
6911inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6912 hdd_context_t *hdd_ctx)
6913{
6914 cds_cfg->ra_ratelimit_interval =
6915 hdd_ctx->config->RArateLimitInterval;
6916 cds_cfg->is_ra_ratelimit_enabled =
6917 hdd_ctx->config->IsRArateLimitEnabled;
6918}
6919#else
6920inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6921 hdd_context_t *hdd_ctx)
6922{
6923}
6924#endif
6925
6926/**
6927 * hdd_update_cds_config() - API to update cds configuration parameters
6928 * @hdd_ctx: HDD Context
6929 *
6930 * Return: 0 for Success, errno on failure
6931 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006932static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306933{
6934 struct cds_config_info *cds_cfg;
6935
6936 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6937 if (!cds_cfg) {
6938 hdd_err("failed to allocate cds config");
6939 return -ENOMEM;
6940 }
6941
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306942 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
6943 cds_cfg->powersave_offload_enabled =
6944 hdd_ctx->config->enablePowersaveOffload;
6945 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
6946 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
6947 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
6948 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
6949 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
6950
6951 /* Here ol_ini_info is used to store ini status of arp offload
6952 * ns offload and others. Currently 1st bit is used for arp
6953 * off load and 2nd bit for ns offload currently, rest bits are unused
6954 */
6955 if (hdd_ctx->config->fhostArpOffload)
6956 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
6957 if (hdd_ctx->config->fhostNSOffload)
6958 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
6959
6960 /*
6961 * Copy the DFS Phyerr Filtering Offload status.
6962 * This parameter reflects the value of the
6963 * dfs_phyerr_filter_offload flag as set in the ini.
6964 */
6965 cds_cfg->dfs_phyerr_filter_offload =
6966 hdd_ctx->config->fDfsPhyerrFilterOffload;
6967 if (hdd_ctx->config->ssdp)
6968 cds_cfg->ssdp = hdd_ctx->config->ssdp;
6969
6970 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
6971 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
6972
6973 cds_cfg->ap_maxoffload_reorderbuffs =
6974 hdd_ctx->config->apMaxOffloadReorderBuffs;
6975
6976 cds_cfg->ap_disable_intrabss_fwd =
6977 hdd_ctx->config->apDisableIntraBssFwd;
6978
6979 cds_cfg->dfs_pri_multiplier =
6980 hdd_ctx->config->dfsRadarPriMultiplier;
6981 cds_cfg->reorder_offload =
6982 hdd_ctx->config->reorderOffloadSupport;
6983
6984 /* IPA micro controller data path offload resource config item */
6985 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
6986 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
6987 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
6988 cds_cfg->uc_rxind_ringcount =
6989 hdd_ctx->config->IpaUcRxIndRingCount;
6990 cds_cfg->uc_tx_partition_base =
6991 hdd_ctx->config->IpaUcTxPartitionBase;
6992 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
6993
6994 cds_cfg->ip_tcp_udp_checksum_offload =
6995 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05306996 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306997 cds_cfg->ce_classify_enabled =
6998 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07006999 cds_cfg->bpf_packet_filter_enable =
7000 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307001 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7002 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7003 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007004 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007005 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007006 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007007 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307008
7009 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7010 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7011 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007012 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307013 cds_init_ini_config(cds_cfg);
7014 return 0;
7015}
7016
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007017/**
7018 * hdd_init_thermal_info - Initialize thermal level
7019 * @hdd_ctx: HDD context
7020 *
7021 * Initialize thermal level at SME layer and set the thermal level callback
7022 * which would be called when a configured thermal threshold is hit.
7023 *
7024 * Return: 0 on success and errno on failure
7025 */
7026static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7027{
7028 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307029 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007030
7031 thermal_param.smeThermalMgmtEnabled =
7032 hdd_ctx->config->thermalMitigationEnable;
7033 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7034
Poddar, Siddarth83905022016-04-16 17:56:08 -07007035 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7036 hdd_ctx->config->throttle_dutycycle_level0;
7037 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7038 hdd_ctx->config->throttle_dutycycle_level1;
7039 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7040 hdd_ctx->config->throttle_dutycycle_level2;
7041 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7042 hdd_ctx->config->throttle_dutycycle_level3;
7043
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007044 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7045 hdd_ctx->config->thermalTempMinLevel0;
7046 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7047 hdd_ctx->config->thermalTempMaxLevel0;
7048 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7049 hdd_ctx->config->thermalTempMinLevel1;
7050 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7051 hdd_ctx->config->thermalTempMaxLevel1;
7052 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7053 hdd_ctx->config->thermalTempMinLevel2;
7054 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7055 hdd_ctx->config->thermalTempMaxLevel2;
7056 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7057 hdd_ctx->config->thermalTempMinLevel3;
7058 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7059 hdd_ctx->config->thermalTempMaxLevel3;
7060
7061 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307063 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307064 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007065
7066 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7067 hdd_set_thermal_level_cb);
7068
7069 return 0;
7070
7071}
7072
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007073#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7074/**
7075 * hdd_hold_rtnl_lock - Hold RTNL lock
7076 *
7077 * Hold RTNL lock
7078 *
7079 * Return: True if held and false otherwise
7080 */
7081static inline bool hdd_hold_rtnl_lock(void)
7082{
7083 rtnl_lock();
7084 return true;
7085}
7086
7087/**
7088 * hdd_release_rtnl_lock - Release RTNL lock
7089 *
7090 * Release RTNL lock
7091 *
7092 * Return: None
7093 */
7094static inline void hdd_release_rtnl_lock(void)
7095{
7096 rtnl_unlock();
7097}
7098#else
7099static inline bool hdd_hold_rtnl_lock(void) { return false; }
7100static inline void hdd_release_rtnl_lock(void) { }
7101#endif
7102
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007103#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007104
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307105/* MAX iwpriv command support */
7106#define PKTLOG_SET_BUFF_SIZE 3
7107#define MAX_PKTLOG_SIZE 16
7108
7109/**
7110 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7111 * @hdd_ctx: hdd context
7112 * @set_value2: pktlog buffer size value
7113 *
7114 *
7115 * Return: 0 for success or error.
7116 */
7117static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7118{
7119 struct sir_wifi_start_log start_log = { 0 };
7120 QDF_STATUS status;
7121
7122 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7123 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7124 start_log.ini_triggered = cds_is_packet_log_enabled();
7125 start_log.user_triggered = 1;
7126 start_log.size = set_value2;
7127
7128 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7129 if (!QDF_IS_STATUS_SUCCESS(status)) {
7130 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7131 EXIT();
7132 return -EINVAL;
7133 }
7134
7135 return 0;
7136}
7137
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007138/**
7139 * hdd_process_pktlog_command() - process pktlog command
7140 * @hdd_ctx: hdd context
7141 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307142 * @set_value2: pktlog buffer size value
7143 *
7144 * This function process pktlog command.
7145 * set_value2 only matters when set_value is 3 (set buff size)
7146 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007147 *
7148 * Return: 0 for success or error.
7149 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307150int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
7151 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007152{
7153 int ret;
7154 bool enable;
7155 uint8_t user_triggered = 0;
7156
7157 ret = wlan_hdd_validate_context(hdd_ctx);
7158 if (0 != ret)
7159 return ret;
7160
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307161 hdd_info("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007162
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307163 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007164 hdd_err("invalid pktlog value %d", set_value);
7165 return -EINVAL;
7166 }
7167
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307168 if (set_value == PKTLOG_SET_BUFF_SIZE) {
7169 if (set_value2 <= 0) {
7170 hdd_err("invalid pktlog size %d", set_value2);
7171 return -EINVAL;
7172 } else if (set_value2 > MAX_PKTLOG_SIZE) {
7173 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
7174 return -EINVAL;
7175 }
7176 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
7177 }
7178
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007179 /*
7180 * set_value = 0 then disable packetlog
7181 * set_value = 1 enable packetlog forcefully
7182 * set_vlaue = 2 then disable packetlog if disabled through ini or
7183 * enable packetlog with AUTO type.
7184 */
7185 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
7186 true : false;
7187
7188 if (1 == set_value) {
7189 enable = true;
7190 user_triggered = 1;
7191 }
7192
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307193 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007194}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007195/**
7196 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
7197 * @hdd_ctx: HDD context
7198 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307199 * @user_triggered: triggered through iwpriv
7200 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007201 *
7202 * Return: 0 on success; error number otherwise
7203 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007204int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307205 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007206{
7207 struct sir_wifi_start_log start_log;
7208 QDF_STATUS status;
7209
7210 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7211 start_log.verbose_level =
7212 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007213 start_log.ini_triggered = cds_is_packet_log_enabled();
7214 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307215 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307216 /*
7217 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7218 * commands. Host uses this flag to decide whether to send pktlog
7219 * disable command to fw without sending pktlog enable command
7220 * previously. For eg, If vendor sends pktlog disable command without
7221 * sending pktlog enable command, then host discards the packet
7222 * but for iwpriv command, host will send it to fw.
7223 */
7224 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007225 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7226 if (!QDF_IS_STATUS_SUCCESS(status)) {
7227 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7228 EXIT();
7229 return -EINVAL;
7230 }
7231
7232 return 0;
7233}
7234#endif /* REMOVE_PKT_LOG */
7235
7236
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307237#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7238/**
7239 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7240 * switch without restart
7241 *
7242 * Registers callback function to change the operating channel of SAP by using
7243 * channel switch announcements instead of restarting SAP.
7244 *
7245 * Return: QDF_STATUS
7246 */
7247QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7248{
7249 QDF_STATUS status;
7250
7251 status = cds_register_sap_restart_channel_switch_cb(
7252 (void *)hdd_sap_restart_with_channel_switch);
7253 if (!QDF_IS_STATUS_SUCCESS(status))
7254 hdd_err("restart cb registration failed");
7255
7256 return status;
7257}
7258#endif
7259
Komal Seelam92fff912016-03-24 11:51:41 +05307260/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007261 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
7262 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05307263 * @dev: Device Pointer
7264 * @num: Number of Valid Mac address
7265 *
7266 * Return: Pointer to MAC address buffer
7267 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007268static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
7269 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05307270{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007271 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05307272}
Komal Seelam92fff912016-03-24 11:51:41 +05307273
7274/**
7275 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7276 * @hdd_ctx: HDD Context
7277 * @num: Number of random mac addresses needed
7278 *
7279 * Generate random addresses using bit manipulation on the base mac address
7280 *
7281 * Return: None
7282 */
7283static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7284{
7285 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7286 uint32_t iter;
7287 struct hdd_config *ini = hdd_ctx->config;
7288 uint8_t *buf = NULL;
7289 uint8_t macaddr_b3, tmp_br3;
7290 uint8_t *src = ini->intfMacAddr[0].bytes;
7291
7292 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
7293 buf = ini->intfMacAddr[iter].bytes;
7294 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7295 macaddr_b3 = buf[3];
7296 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7297 INTF_MACADDR_MASK;
7298 macaddr_b3 += tmp_br3;
7299 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7300 buf[0] |= 0x02;
7301 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007302 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307303 }
7304}
7305
7306/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007307 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05307308 * @hdd_ctx: HDD Context
7309 *
7310 * API to get mac addresses from platform driver and update the driver
7311 * structures and configure FW with the base mac address.
7312 * Return: int
7313 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007314static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05307315{
7316 uint32_t no_of_mac_addr, iter;
7317 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7318 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7319 uint8_t *addr, *buf;
7320 struct device *dev = hdd_ctx->parent_dev;
7321 struct hdd_config *ini = hdd_ctx->config;
7322 tSirMacAddr mac_addr;
7323 QDF_STATUS status;
7324
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007325 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05307326
7327 if (no_of_mac_addr == 0 || !addr) {
7328 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7329 return -EINVAL;
7330 }
7331
7332 if (no_of_mac_addr > max_mac_addr)
7333 no_of_mac_addr = max_mac_addr;
7334
7335 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7336
7337 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7338 buf = ini->intfMacAddr[iter].bytes;
7339 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007340 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307341 }
7342
7343 status = sme_set_custom_mac_addr(mac_addr);
7344
7345 if (!QDF_IS_STATUS_SUCCESS(status))
7346 return -EAGAIN;
7347 if (no_of_mac_addr < max_mac_addr)
7348 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7349 no_of_mac_addr);
7350 return 0;
7351}
7352
7353/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007354 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7355 * @hdd_ctx: HDD Context
7356 *
7357 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7358 * will generate its own MAC and update it to FW.
7359 *
7360 * Return: 0 for success
7361 * Non-zero error code for failure
7362 */
7363static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7364{
7365 tSirMacAddr customMacAddr;
7366 QDF_STATUS status;
7367
7368 qdf_mem_copy(&customMacAddr,
7369 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7370 sizeof(tSirMacAddr));
7371 status = sme_set_custom_mac_addr(customMacAddr);
7372 if (!QDF_IS_STATUS_SUCCESS(status))
7373 return -EAGAIN;
7374 return 0;
7375}
7376
7377/**
Komal Seelam92fff912016-03-24 11:51:41 +05307378 * hdd_initialize_mac_address() - API to get wlan mac addresses
7379 * @hdd_ctx: HDD Context
7380 *
7381 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
7382 * is provisioned with mac addresses, driver uses it, else it will use
7383 * wlan_mac.bin to update HW MAC addresses.
7384 *
7385 * Return: None
7386 */
7387static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
7388{
7389 QDF_STATUS status;
7390 int ret;
7391
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007392 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05307393 if (ret == 0)
7394 return;
7395
7396 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7397
7398 status = hdd_update_mac_config(hdd_ctx);
7399
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007400 if (QDF_IS_STATUS_SUCCESS(status))
7401 return;
7402
7403 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
7404
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007405 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007406 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007407 if (ret != 0) {
7408 hdd_err("MAC address out-of-sync, ret:%d", ret);
7409 QDF_ASSERT(ret);
7410 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007411 }
Komal Seelam92fff912016-03-24 11:51:41 +05307412}
7413
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007414/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007415 * hdd_tsf_init() - Initialize the TSF synchronization interface
7416 * @hdd_ctx: HDD global context
7417 *
7418 * When TSF synchronization via GPIO is supported by the driver and
7419 * has been enabled in the configuration file, this function plumbs
7420 * the GPIO value down to firmware via SME.
7421 *
7422 * Return: None
7423 */
7424#ifdef WLAN_FEATURE_TSF
7425static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7426{
7427 QDF_STATUS status;
7428
7429 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7430 return;
7431
7432 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7433 hdd_ctx->config->tsf_gpio_pin);
7434 if (!QDF_IS_STATUS_SUCCESS(status))
7435 hdd_err("Set tsf GPIO failed, status: %d", status);
7436}
7437#else
7438static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7439{
7440}
7441#endif
7442
7443/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007444 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7445 * @hdd_ctx: HDD context
7446 *
7447 * Pre configurations to be done at lower layer before calling cds enable.
7448 *
7449 * Return: 0 on success and errno on failure.
7450 */
7451static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7452{
7453 int ret;
7454 QDF_STATUS status;
7455 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07007456 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007457
Leo Changfdb45c32016-10-28 11:09:23 -07007458 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007459 /*
7460 * Set 802.11p config
7461 * TODO-OCB: This has been temporarily added here to ensure this
7462 * parameter is set in CSR when we init the channel list. This should
7463 * be removed once the 5.9 GHz channels are added to the regulatory
7464 * domain.
7465 */
7466 hdd_set_dot11p_config(hdd_ctx);
7467
7468 /*
7469 * Note that the cds_pre_enable() sequence triggers the cfg download.
7470 * The cfg download must occur before we update the SME config
7471 * since the SME config operation must access the cfg database
7472 */
7473 status = hdd_set_sme_config(hdd_ctx);
7474
7475 if (QDF_STATUS_SUCCESS != status) {
7476 hdd_alert("Failed hdd_set_sme_config: %d", status);
7477 ret = qdf_status_to_os_return(status);
7478 goto out;
7479 }
7480
7481 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7482 hdd_ctx->config->tx_chain_mask_1ss,
7483 PDEV_CMD);
7484 if (0 != ret) {
7485 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7486 goto out;
7487 }
7488
7489 hdd_program_country_code(hdd_ctx);
7490
7491 status = hdd_set_sme_chan_list(hdd_ctx);
7492 if (status != QDF_STATUS_SUCCESS) {
7493 hdd_alert("Failed to init channel list: %d", status);
7494 ret = qdf_status_to_os_return(status);
7495 goto out;
7496 }
7497
7498 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07007499 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07007500 hdd_alert("config update failed");
7501 ret = -EINVAL;
7502 goto out;
7503 }
7504
Prashanth Bhatta07998752016-04-28 12:35:33 -07007505 /*
7506 * Set the MAC Address Currently this is used by HAL to add self sta.
7507 * Remove this once self sta is added as part of session open.
7508 */
7509 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7510 hdd_ctx->config->intfMacAddr[0].bytes,
7511 sizeof(hdd_ctx->config->intfMacAddr[0]));
7512
7513 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7514 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7515 hal_status, hal_status);
7516 ret = -EINVAL;
7517 goto out;
7518 }
7519
7520 hdd_init_channel_avoidance(hdd_ctx);
7521
7522out:
7523 return ret;
7524}
7525
7526/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007527 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7528 * @context_ptr - hdd context pointer
7529 * @event_ptr - event structure pointer
7530 *
7531 * This is the p2p listen offload stop event handler, it sends vendor
7532 * event back to supplicant to notify the stop reason.
7533 *
7534 * Return: None
7535 */
7536static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7537 void *event_ptr)
7538{
7539 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7540 struct sir_p2p_lo_event *evt = event_ptr;
7541 struct sk_buff *vendor_event;
7542
7543 ENTER();
7544
7545 if (hdd_ctx == NULL) {
7546 hdd_err("Invalid HDD context pointer");
7547 return;
7548 }
7549
7550 vendor_event =
7551 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7552 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7553 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7554 GFP_KERNEL);
7555
7556 if (!vendor_event) {
7557 hdd_err("cfg80211_vendor_event_alloc failed");
7558 return;
7559 }
7560
7561 if (nla_put_u32(vendor_event,
7562 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7563 evt->reason_code)) {
7564 hdd_err("nla put failed");
7565 kfree_skb(vendor_event);
7566 return;
7567 }
7568
7569 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7570}
7571
7572/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307573 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7574 * @hdd_ctx: HDD context
7575 *
7576 * This function sends the adaptive dwell time config configuration to the
7577 * firmware via WMA
7578 *
7579 * Return: 0 - success, < 0 - failure
7580 */
7581static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7582{
7583 QDF_STATUS status;
7584 struct adaptive_dwelltime_params dwelltime_params;
7585
7586 dwelltime_params.is_enabled =
7587 hdd_ctx->config->adaptive_dwell_mode_enabled;
7588 dwelltime_params.dwelltime_mode =
7589 hdd_ctx->config->global_adapt_dwelltime_mode;
7590 dwelltime_params.lpf_weight =
7591 hdd_ctx->config->adapt_dwell_lpf_weight;
7592 dwelltime_params.passive_mon_intval =
7593 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7594 dwelltime_params.wifi_act_threshold =
7595 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7596
7597 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7598 &dwelltime_params);
7599
7600 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7601 if (!QDF_IS_STATUS_SUCCESS(status)) {
7602 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7603 return -EAGAIN;
7604 }
7605 return 0;
7606}
7607
Arun Khandavallid4349a92016-07-25 11:10:43 +05307608#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7609/**
7610 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7611 * @hdd_ctx: HDD context
7612 *
7613 * Set auto shutdown callback to get indications from firmware to indicate
7614 * userspace to shutdown WLAN after a configured amount of inactivity.
7615 *
7616 * Return: 0 on success and errno on failure.
7617 */
7618static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7619{
7620 QDF_STATUS status;
7621
7622 if (!hdd_ctx->config->WlanAutoShutdown)
7623 return 0;
7624
7625 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7626 wlan_hdd_auto_shutdown_cb);
7627 if (status != QDF_STATUS_SUCCESS)
7628 hdd_err("Auto shutdown feature could not be enabled: %d",
7629 status);
7630
7631 return qdf_status_to_os_return(status);
7632}
7633#else
7634static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7635{
7636 return 0;
7637}
7638#endif
7639
7640/**
7641 * hdd_features_init() - Init features
7642 * @hdd_ctx: HDD context
7643 * @adapter: Primary adapter context
7644 *
7645 * Initialize features and their feature context after WLAN firmware is up.
7646 *
7647 * Return: 0 on success and errno on failure.
7648 */
7649static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7650{
7651 tSirTxPowerLimit hddtxlimit;
7652 QDF_STATUS status;
7653 int ret;
7654
7655 ENTER();
7656
7657 ret = hdd_update_country_code(hdd_ctx, adapter);
7658 if (ret) {
7659 hdd_err("Failed to update country code: %d", ret);
7660 goto out;
7661 }
7662
7663 /* FW capabilities received, Set the Dot11 mode */
7664 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07007665 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
7666 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307667
Arun Khandavallid4349a92016-07-25 11:10:43 +05307668
7669 if (hdd_ctx->config->fIsImpsEnabled)
7670 hdd_set_idle_ps_config(hdd_ctx, true);
7671 else
7672 hdd_set_idle_ps_config(hdd_ctx, false);
7673
7674 if (hdd_lro_init(hdd_ctx))
7675 hdd_err("Unable to initialize LRO in fw");
7676
7677 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7678 hdd_err("Unable to send adaptive dwelltime setting to FW");
7679
7680 ret = hdd_init_thermal_info(hdd_ctx);
7681 if (ret) {
7682 hdd_err("Error while initializing thermal information");
7683 goto deregister_frames;
7684 }
7685
7686 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7687 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7688 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7689 if (!QDF_IS_STATUS_SUCCESS(status))
7690 hdd_err("Error setting txlimit in sme: %d", status);
7691
7692 hdd_tsf_init(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307693 hdd_encrypt_decrypt_init(hdd_ctx);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307694
Arun Khandavallid4349a92016-07-25 11:10:43 +05307695 ret = hdd_register_cb(hdd_ctx);
7696 if (ret) {
7697 hdd_err("Failed to register HDD callbacks!");
7698 goto deregister_frames;
7699 }
7700
7701 if (hdd_ctx->config->dual_mac_feature_disable) {
7702 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7703 if (status != QDF_STATUS_SUCCESS) {
7704 hdd_err("Failed to disable dual mac features");
7705 goto deregister_cb;
7706 }
7707 }
7708
7709 /* register P2P Listen Offload event callback */
7710 if (wma_is_p2p_lo_capable())
7711 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7712 wlan_hdd_p2p_lo_event_callback);
7713
7714 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7715
7716 if (ret)
7717 goto deregister_cb;
7718
7719 EXIT();
7720 return 0;
7721
7722deregister_cb:
7723 hdd_deregister_cb(hdd_ctx);
7724deregister_frames:
7725 wlan_hdd_cfg80211_deregister_frames(adapter);
7726out:
7727 return -EINVAL;
7728
7729}
7730
7731
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307732/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307733 * hdd_configure_cds() - Configure cds modules
7734 * @hdd_ctx: HDD context
7735 * @adapter: Primary adapter context
7736 *
7737 * Enable Cds modules after WLAN firmware is up.
7738 *
7739 * Return: 0 on success and errno on failure.
7740 */
7741int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7742{
7743 int ret;
7744 QDF_STATUS status;
7745 /* structure of function pointers to be used by CDS */
7746 struct cds_sme_cbacks sme_cbacks;
7747
7748 ret = hdd_pre_enable_configure(hdd_ctx);
7749 if (ret) {
7750 hdd_err("Failed to pre-configure cds");
7751 goto out;
7752 }
7753
7754 /*
7755 * Start CDS which starts up the SME/MAC/HAL modules and everything
7756 * else
7757 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307758 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307759
7760 if (!QDF_IS_STATUS_SUCCESS(status)) {
7761 hdd_alert("cds_enable failed");
7762 goto out;
7763 }
7764
7765 status = hdd_post_cds_enable_config(hdd_ctx);
7766 if (!QDF_IS_STATUS_SUCCESS(status)) {
7767 hdd_alert("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007768 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307769 }
7770
7771 ret = hdd_features_init(hdd_ctx, adapter);
7772 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007773 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307774
7775 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7776 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7777 status = cds_init_policy_mgr(&sme_cbacks);
7778 if (!QDF_IS_STATUS_SUCCESS(status)) {
7779 hdd_err("Policy manager initialization failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007780 goto hdd_features_deinit;
Arun Khandavallifae92942016-08-01 13:31:08 +05307781 }
7782
7783 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007784
7785hdd_features_deinit:
7786 hdd_deregister_cb(hdd_ctx);
7787 wlan_hdd_cfg80211_deregister_frames(adapter);
7788cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307789 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007790
Arun Khandavallifae92942016-08-01 13:31:08 +05307791out:
7792 return -EINVAL;
7793}
7794
7795/**
7796 * hdd_deconfigure_cds() -De-Configure cds
7797 * @hdd_ctx: HDD context
7798 *
7799 * Deconfigure Cds modules before WLAN firmware is down.
7800 *
7801 * Return: 0 on success and errno on failure.
7802 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007803static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307804{
7805 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07007806 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307807
7808 ENTER();
7809 /* De-register the SME callbacks */
7810 hdd_deregister_cb(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307811 hdd_encrypt_decrypt_deinit(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307812
7813 /* De-init Policy Manager */
7814 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7815 hdd_err("Failed to deinit policy manager");
7816 /* Proceed and complete the clean up */
Houston Hoffman6640cf32016-10-10 16:44:29 -07007817 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307818 }
7819
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307820 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307821 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7822 hdd_err("Failed to Disable the CDS Modules! :%d",
7823 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07007824 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307825 }
7826
7827 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07007828 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307829}
7830
7831
7832/**
7833 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7834 * @hdd_ctx: HDD context
Arun Khandavallifae92942016-08-01 13:31:08 +05307835 *
7836 * This function maintains the driver state machine it will be invoked from
7837 * exit, shutdown and con_mode change handler. Depending on the driver state
7838 * shall perform the stopping/closing of the modules.
7839 *
7840 * Return: 0 for success; non-zero for failure
7841 */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007842int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307843{
7844 void *hif_ctx;
7845 qdf_device_t qdf_ctx;
7846 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307847 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307848 p_cds_sched_context cds_sched_context = NULL;
7849
7850 ENTER();
7851
7852 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7853 if (!qdf_ctx) {
7854 hdd_err("QDF device context NULL");
7855 return -EINVAL;
7856 }
7857
7858 cds_sched_context = get_cds_sched_ctxt();
7859 if (!cds_sched_context) {
7860 hdd_err("cds scheduler context NULL");
7861 return -EINVAL;
7862 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307863 mutex_lock(&hdd_ctx->iface_change_lock);
7864 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307865
7866 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7867
7868 switch (hdd_ctx->driver_status) {
7869 case DRIVER_MODULES_UNINITIALIZED:
7870 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307871 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307872 case DRIVER_MODULES_CLOSED:
7873 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307874 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307875 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05307876 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05307877 if (hdd_deconfigure_cds(hdd_ctx)) {
7878 hdd_alert("Failed to de-configure CDS");
7879 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307880 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307881 }
7882 hdd_info("successfully Disabled the CDS modules!");
7883 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7884 break;
7885 case DRIVER_MODULES_OPENED:
7886 hdd_info("Closing CDS modules!");
7887 break;
7888 default:
7889 hdd_err("Trying to stop wlan in a wrong state: %d",
7890 hdd_ctx->driver_status);
7891 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307892 ret = -EINVAL;
7893 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307894 }
7895
Govind Singhb048e872016-09-27 22:07:43 +05307896 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
7897 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7898 hdd_err("Failed to process post CDS disable Modules! :%d",
7899 qdf_status);
7900 ret = -EINVAL;
7901 QDF_ASSERT(0);
7902 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307903 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307904 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7905 hdd_warn("Failed to stop CDS:%d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05307906 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307907 QDF_ASSERT(0);
7908 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07007909
Rajeev Kumar3a6c13c2017-01-06 13:01:08 -08007910 qdf_status = hdd_release_and_destroy_pdev(hdd_ctx);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307911 if (QDF_IS_STATUS_ERROR(qdf_status))
7912 hdd_err("Pdev delete failed");
7913
Rajeev Kumar1cba9d02017-01-06 11:36:14 -08007914 qdf_status = hdd_release_and_destroy_psoc(hdd_ctx);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307915 if (QDF_IS_STATUS_ERROR(qdf_status))
7916 hdd_err("Psoc delete failed");
7917
Arun Khandavallifae92942016-08-01 13:31:08 +05307918 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
7919 if (!hif_ctx) {
7920 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307921 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307922 }
7923
7924 hdd_hif_close(hif_ctx);
7925
7926 ol_cds_free();
7927
Arunk Khandavalli649c0092016-11-22 21:20:43 +05307928 if (!cds_is_driver_recovering() && !cds_is_driver_unloading()) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307929 ret = pld_power_off(qdf_ctx->dev);
7930 if (ret)
7931 hdd_err("CNSS power down failed put device into Low power mode:%d",
7932 ret);
7933 }
7934 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
7935
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307936done:
7937 hdd_ctx->stop_modules_in_progress = false;
7938 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05307939 EXIT();
7940
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307941 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307942
7943}
7944
7945/**
7946 * hdd_iface_change_callback() - Function invoked when stop modules expires
7947 * @priv: pointer to hdd context
7948 *
7949 * This function is invoked when the timer waiting for the interface change
7950 * expires, it shall cut-down the power to wlan and stop all the modules.
7951 *
7952 * Return: void
7953 */
7954static void hdd_iface_change_callback(void *priv)
7955{
7956 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
7957 int ret;
7958 int status = wlan_hdd_validate_context(hdd_ctx);
7959
7960 if (status)
7961 return;
7962
7963 ENTER();
7964 hdd_info("Interface change timer expired close the modules!");
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007965 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307966 if (ret)
7967 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05307968 EXIT();
7969}
7970
7971/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05307972 * hdd_state_info_dump() - prints state information of hdd layer
7973 * @buf: buffer pointer
7974 * @size: size of buffer to be filled
7975 *
7976 * This function is used to dump state information of hdd layer
7977 *
7978 * Return: None
7979 */
7980static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
7981{
7982 hdd_context_t *hdd_ctx;
7983 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7984 QDF_STATUS status;
7985 hdd_station_ctx_t *hdd_sta_ctx;
7986 hdd_adapter_t *adapter;
7987 uint16_t len = 0;
7988 char *buf = *buf_ptr;
7989
7990 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7991 if (!hdd_ctx) {
7992 hdd_err("Failed to get hdd context ");
7993 return;
7994 }
7995
7996 hdd_notice("size of buffer: %d", *size);
7997
7998 len += scnprintf(buf + len, *size - len,
7999 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8000 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008001 "\n is_scheduler_suspended %d",
8002 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308003
8004 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8005
8006 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8007 adapter = adapter_node->pAdapter;
8008 if (adapter->dev)
8009 len += scnprintf(buf + len, *size - len,
8010 "\n device name: %s", adapter->dev->name);
8011 len += scnprintf(buf + len, *size - len,
8012 "\n device_mode: %d", adapter->device_mode);
8013 switch (adapter->device_mode) {
8014 case QDF_STA_MODE:
8015 case QDF_P2P_CLIENT_MODE:
8016 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8017 len += scnprintf(buf + len, *size - len,
8018 "\n connState: %d",
8019 hdd_sta_ctx->conn_info.connState);
8020 break;
8021
8022 default:
8023 break;
8024 }
8025 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
8026 adapter_node = next;
8027 }
8028
8029 *size -= len;
8030 *buf_ptr += len;
8031}
8032
8033/**
8034 * hdd_register_debug_callback() - registration function for hdd layer
8035 * to print hdd state information
8036 *
8037 * Return: None
8038 */
8039static void hdd_register_debug_callback(void)
8040{
8041 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
8042}
8043
8044/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008045 * hdd_wlan_startup() - HDD init function
8046 * @dev: Pointer to the underlying device
8047 *
8048 * This is the driver startup code executed once a WLAN device has been detected
8049 *
8050 * Return: 0 for success, < 0 for failure
8051 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308052int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008053{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308054 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008055 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008056 hdd_context_t *hdd_ctx = NULL;
8057 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308058 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008059 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308060 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008061
8062 ENTER();
8063
Arun Khandavallifae92942016-08-01 13:31:08 +05308064 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008065
8066 if (IS_ERR(hdd_ctx))
8067 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008068
Arun Khandavallifae92942016-08-01 13:31:08 +05308069 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
8070 hdd_iface_change_callback, (void *)hdd_ctx);
8071
8072 mutex_init(&hdd_ctx->iface_change_lock);
8073
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008074 ret = hdd_init_netlink_services(hdd_ctx);
8075 if (ret)
8076 goto err_hdd_free_context;
8077
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07008078 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308079
Arun Khandavallifae92942016-08-01 13:31:08 +05308080 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
8081 if (ret) {
8082 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008083 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008084 }
8085
Yingying Tang80e15f32016-09-27 18:23:01 +08008086 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008087
Anurag Chouhan6d760662016-02-20 16:05:43 +05308088 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008089
8090 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008091 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05308092 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008093 }
8094
Prashanth Bhatta07998752016-04-28 12:35:33 -07008095 ret = hdd_wiphy_init(hdd_ctx);
8096 if (ret) {
8097 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05308098 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008099 }
8100
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05308101 if (hdd_ctx->config->enable_dp_trace)
8102 qdf_dp_trace_init();
8103
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308104 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008105 goto err_wiphy_unregister;
8106
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07008107 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08008108
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008109 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008110
Arun Khandavallifae92942016-08-01 13:31:08 +05308111 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008112
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008113 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008114 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008115 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05308116 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008117 }
8118
Arun Khandavallifae92942016-08-01 13:31:08 +05308119 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308120 if (!hif_sc) {
8121 hdd_err("HIF context is NULL");
8122 goto err_close_adapter;
8123 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008124 /*
8125 * target hw version/revision would only be retrieved after firmware
8126 * donwload
8127 */
8128 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
8129 &hdd_ctx->target_hw_revision,
8130 &hdd_ctx->target_hw_name);
8131
8132 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05308133 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008134
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008135 hdd_release_rtnl_lock();
8136 rtnl_held = false;
8137
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05308138 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8139 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08008140
8141 wlan_hdd_update_11n_mode(hdd_ctx->config);
8142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008143#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05308144 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308145 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008146 hdd_skip_acs_scan_timer_handler,
8147 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308148 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07008149 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04008150 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008151#endif
8152
Nitesh Shah61c10d92016-10-19 19:29:15 +05308153 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
8154 QDF_TIMER_TYPE_SW,
8155 wlan_hdd_change_tdls_mode,
8156 hdd_ctx);
8157
Prashanth Bhattaab004382016-10-11 16:08:11 -07008158 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008159
Jeff Johnson9afc5012016-09-23 13:56:27 -07008160 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008161
Nirav Shahbd36b062016-07-18 11:12:59 +05308162 if (hdd_ctx->rps)
8163 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07008164
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008165
8166 if (cds_is_packet_log_enabled())
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308167 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008168
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008169 ret = hdd_register_notifiers(hdd_ctx);
8170 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05308171 goto err_debugfs_exit;
8172
8173 status = wlansap_global_init();
8174 if (QDF_IS_STATUS_ERROR(status))
8175 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008176
Komal Seelam8634b772016-09-29 12:12:24 +05308177 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008178 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308179 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008180
bings612b9c42016-11-07 10:52:03 +08008181 if (hdd_enable_egap(hdd_ctx))
8182 hdd_err("enhance green ap is not enabled");
8183
Arun Khandavallifae92942016-08-01 13:31:08 +05308184 if (hdd_ctx->config->fIsImpsEnabled)
8185 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308186
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308187 if (hdd_ctx->config->sifs_burst_duration) {
8188 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
8189 hdd_ctx->config->sifs_burst_duration;
8190
8191 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
8192 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
8193 set_value, PDEV_CMD);
8194 }
8195
Arun Khandavallifae92942016-08-01 13:31:08 +05308196 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
8197 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308198
8199 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8200 status = sme_enable_disable_chanavoidind_event(
8201 hdd_ctx->hHal, 0);
8202 if (!QDF_IS_STATUS_SUCCESS(status))
8203 hdd_err("Failed to disable Chan Avoidance Indication");
8204 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008205 goto success;
8206
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008207err_debugfs_exit:
8208 hdd_debugfs_exit(adapter);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308209
8210err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008211 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008212
Arun Khandavallid4349a92016-07-25 11:10:43 +05308213 if (rtnl_held)
8214 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008215
Anurag Chouhance6a4052016-09-14 18:20:42 +05308216err_ipa_cleanup:
8217 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08008218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008219err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008220 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008221
Arun Khandavallifae92942016-08-01 13:31:08 +05308222err_stop_modules:
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008223 hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308224
8225
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008226 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308227 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008228 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308229 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008230 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008231
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008232err_exit_nl_srv:
Houston Hoffman47a4a052016-11-14 23:22:44 -08008233 hdd_green_ap_deinit(hdd_ctx);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008234 hdd_exit_netlink_services(hdd_ctx);
8235
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308236 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008237err_hdd_free_context:
Houston Hoffman47a4a052016-11-14 23:22:44 -08008238 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308239 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
8240 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07008241 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308242 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008244 return -EIO;
8245
8246success:
8247 EXIT();
8248 return 0;
8249}
8250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008251/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308252 * hdd_wlan_update_target_info() - update target type info
8253 * @hdd_ctx: HDD context
8254 * @context: hif context
8255 *
8256 * Update target info received from firmware in hdd context
8257 * Return:None
8258 */
8259
8260void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
8261{
8262 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
8263
8264 if (!tgt_info) {
8265 hdd_err("Target info is Null");
8266 return;
8267 }
8268
8269 hdd_ctx->target_type = tgt_info->target_type;
8270}
8271
8272/**
8273 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308274 * @hdd_ctx: HDD context
8275 *
8276 * Register the HDD callbacks to CDS/SME.
8277 *
8278 * Return: 0 for success or Error code for failure
8279 */
8280int hdd_register_cb(hdd_context_t *hdd_ctx)
8281{
8282 QDF_STATUS status;
8283 int ret = 0;
8284
8285 ENTER();
8286
8287 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
8288
8289 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
8290 hdd_send_oem_data_rsp_msg);
8291
8292 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
8293 wlan_hdd_cfg80211_fw_mem_dump_cb);
8294 if (!QDF_IS_STATUS_SUCCESS(status)) {
8295 hdd_err("Failed to register memdump callback");
8296 ret = -EINVAL;
8297 return ret;
8298 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05308299 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
8300 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308301 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
8302 sme_nan_register_callback(hdd_ctx->hHal,
8303 wlan_hdd_cfg80211_nan_callback);
8304 sme_stats_ext_register_callback(hdd_ctx->hHal,
8305 wlan_hdd_cfg80211_stats_ext_callback);
8306
8307 sme_ext_scan_register_callback(hdd_ctx->hHal,
8308 wlan_hdd_cfg80211_extscan_callback);
8309
8310 status = cds_register_sap_restart_channel_switch_cb(
8311 (void *)hdd_sap_restart_with_channel_switch);
8312 if (!QDF_IS_STATUS_SUCCESS(status)) {
8313 hdd_err("restart cb registration failed");
8314 ret = -EINVAL;
8315 return ret;
8316 }
8317
8318 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
8319 hdd_rssi_threshold_breached);
8320
8321 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
8322 hdd_get_bpf_offload_cb);
8323 if (!QDF_IS_STATUS_SUCCESS(status)) {
8324 hdd_err("set bpf offload callback failed");
8325 ret = -EINVAL;
8326 return ret;
8327 }
8328
8329 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
8330 wlan_hdd_cfg80211_link_layer_stats_callback);
8331
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05308332 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
8333 hdd_lost_link_info_cb);
8334 /* print error and not block the startup process */
8335 if (!QDF_IS_STATUS_SUCCESS(status))
8336 hdd_err("set lost link info callback failed");
8337
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308338 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
8339
8340 EXIT();
8341
8342 return ret;
8343}
8344
8345/**
8346 * hdd_deregister_cb() - De-Register HDD callbacks.
8347 * @hdd_ctx: HDD context
8348 *
8349 * De-Register the HDD callbacks to CDS/SME.
8350 *
8351 * Return: void
8352 */
8353void hdd_deregister_cb(hdd_context_t *hdd_ctx)
8354{
8355 QDF_STATUS status;
8356
8357 ENTER();
8358
8359 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
8360 if (!QDF_IS_STATUS_SUCCESS(status))
8361 hdd_err("De-register of dcc stats callback failed: %d",
8362 status);
8363
8364 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
8365 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
8366 if (!QDF_IS_STATUS_SUCCESS(status))
8367 hdd_err("De-register bpf offload callback failed: %d",
8368 status);
8369 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
8370
8371 status = cds_deregister_sap_restart_channel_switch_cb();
8372 if (!QDF_IS_STATUS_SUCCESS(status))
8373 hdd_err("De-register restart cb registration failed: %d",
8374 status);
8375
8376 sme_stats_ext_register_callback(hdd_ctx->hHal,
8377 wlan_hdd_cfg80211_stats_ext_callback);
8378
8379 sme_nan_deregister_callback(hdd_ctx->hHal);
8380 status = sme_reset_tsfcb(hdd_ctx->hHal);
8381 if (!QDF_IS_STATUS_SUCCESS(status))
8382 hdd_err("Failed to de-register tsfcb the callback:%d",
8383 status);
8384 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
8385 if (!QDF_IS_STATUS_SUCCESS(status))
8386 hdd_err("Failed to de-register the fw mem dump callback: %d",
8387 status);
8388
8389 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
8390 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
8391
8392 EXIT();
8393}
8394
8395/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008396 * hdd_softap_sta_deauth() - handle deauth req from HDD
8397 * @adapter: Pointer to the HDD
8398 * @enable: bool value
8399 *
8400 * This to take counter measure to handle deauth req from HDD
8401 *
8402 * Return: None
8403 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308404QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008405 struct tagCsrDelStaParams *pDelStaParams)
8406{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308407 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008408
8409 ENTER();
8410
Jeff Johnson34c88b72016-08-15 14:27:11 -07008411 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008412 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8413
8414 /* Ignore request to deauth bcmc station */
8415 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308416 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008417
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308418 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008419 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8420 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008421
8422 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308423 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008424}
8425
8426/**
8427 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
8428 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308429 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008430 *
8431 * This to take counter measure to handle deauth req from HDD
8432 *
8433 * Return: None
8434 */
8435void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308436 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008437{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008438 ENTER();
8439
Jeff Johnson34c88b72016-08-15 14:27:11 -07008440 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008441 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8442
8443 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308444 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008445 return;
8446
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008447 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308448 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008449}
8450
8451void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
8452 bool enable)
8453{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008454 ENTER();
8455
Jeff Johnson34c88b72016-08-15 14:27:11 -07008456 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008457 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8458
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008459 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8460 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008461}
8462
8463/**
8464 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
8465 * @hdd_ctx: HDD Context
8466 *
8467 * API to find if there is any STA or P2P-Client is connected
8468 *
8469 * Return: true if connected; false otherwise
8470 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308471QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008472{
8473 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
8474}
8475
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008476/**
8477 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
8478 * @adapter: HDD adapter pointer
8479 *
8480 * This function loop through each adapter and disable roaming on each STA
8481 * device mode except the input adapter.
8482 *
8483 * Note: On the input adapter roaming is not enabled yet hence no need to
8484 * disable.
8485 *
8486 * Return: None
8487 */
8488void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8489{
8490 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8491 hdd_adapter_t *adapterIdx = NULL;
8492 hdd_adapter_list_node_t *adapterNode = NULL;
8493 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308494 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008495
8496 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8497 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008498 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008499 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008500 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008501 adapter->sessionId);
8502 /*
8503 * Loop through adapter and disable roaming for each STA device
8504 * mode except the input adapter.
8505 */
8506 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8507
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308508 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008509 adapterIdx = adapterNode->pAdapter;
8510
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008511 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008512 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008513 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008514 adapterIdx->sessionId);
8515 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8516 (adapterIdx),
8517 adapterIdx->sessionId, 0);
8518 }
8519
8520 status = hdd_get_next_adapter(hdd_ctx,
8521 adapterNode,
8522 &pNext);
8523 adapterNode = pNext;
8524 }
8525 }
8526}
8527
8528/**
8529 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8530 * @adapter: HDD adapter pointer
8531 *
8532 * This function loop through each adapter and enable roaming on each STA
8533 * device mode except the input adapter.
8534 * Note: On the input adapter no need to enable roaming because link got
8535 * disconnected on this.
8536 *
8537 * Return: None
8538 */
8539void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8540{
8541 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8542 hdd_adapter_t *adapterIdx = NULL;
8543 hdd_adapter_list_node_t *adapterNode = NULL;
8544 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308545 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008546
8547 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8548 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008549 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008550 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008551 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008552 adapter->sessionId);
8553 /*
8554 * Loop through adapter and enable roaming for each STA device
8555 * mode except the input adapter.
8556 */
8557 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8558
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308559 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008560 adapterIdx = adapterNode->pAdapter;
8561
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008562 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008564 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008565 adapterIdx->sessionId);
8566 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8567 (adapterIdx),
8568 adapterIdx->sessionId,
8569 REASON_CONNECT);
8570 }
8571
8572 status = hdd_get_next_adapter(hdd_ctx,
8573 adapterNode,
8574 &pNext);
8575 adapterNode = pNext;
8576 }
8577 }
8578}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008579
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308580void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008581{
8582 struct sk_buff *skb;
8583 struct nlmsghdr *nlh;
8584 tAniMsgHdr *ani_hdr;
8585 void *nl_data = NULL;
8586 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308587 struct radio_index_tlv *radio_info;
8588 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008589
8590 if (in_interrupt() || irqs_disabled() || in_atomic())
8591 flags = GFP_ATOMIC;
8592
8593 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8594
8595 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008596 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008597 return;
8598 }
8599
8600 nlh = (struct nlmsghdr *)skb->data;
8601 nlh->nlmsg_pid = 0; /* from kernel */
8602 nlh->nlmsg_flags = 0;
8603 nlh->nlmsg_seq = 0;
8604 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8605
8606 ani_hdr = NLMSG_DATA(nlh);
8607 ani_hdr->type = type;
8608
8609 switch (type) {
8610 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05308611 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008612 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008613 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008614 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008615 ani_hdr->length = 0;
8616 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8617 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8618 break;
8619 case WLAN_SVC_WLAN_STATUS_IND:
8620 case WLAN_SVC_WLAN_VERSION_IND:
8621 case WLAN_SVC_DFS_CAC_START_IND:
8622 case WLAN_SVC_DFS_CAC_END_IND:
8623 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8624 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8625 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008626 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308627 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008628 ani_hdr->length = len;
8629 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8630 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8631 memcpy(nl_data, data, len);
8632 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
8633 break;
8634
8635 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008636 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008637 type);
8638 kfree_skb(skb);
8639 return;
8640 }
8641
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308642 /*
8643 * Add radio index at the end of the svc event in TLV format to maintain
8644 * the backward compatibility with userspace applications.
8645 */
8646
8647 tlv_len = 0;
8648
8649 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8650 < WLAN_NL_MAX_PAYLOAD) {
8651 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8652 sizeof(*ani_hdr) + len);
8653 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8654 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8655 radio_info->radio = radio;
8656 tlv_len = sizeof(*radio_info);
8657 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8658 "Added radio index tlv - radio index %d",
8659 radio_info->radio);
8660 }
8661
8662 nlh->nlmsg_len += tlv_len;
8663 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008665 nl_srv_bcast(skb);
8666
8667 return;
8668}
8669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008670#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8671void wlan_hdd_auto_shutdown_cb(void)
8672{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008673 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308674
8675 if (!hdd_ctx)
8676 return;
8677
Jeff Johnson28f8a772016-08-15 15:30:36 -07008678 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308679 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8680 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008681}
8682
8683void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8684{
8685 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308686 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008687 hdd_adapter_t *adapter;
8688 bool ap_connected = false, sta_connected = false;
8689 tHalHandle hal_handle;
8690
8691 hal_handle = hdd_ctx->hHal;
8692 if (hal_handle == NULL)
8693 return;
8694
8695 if (hdd_ctx->config->WlanAutoShutdown == 0)
8696 return;
8697
8698 if (enable == false) {
8699 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308700 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008701 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008702 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308703 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008704 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008705 return;
8706 }
8707
8708 /* To enable shutdown timer check conncurrency */
8709 if (cds_concurrent_open_sessions_running()) {
8710 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8711
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308712 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008713 adapter = adapterNode->pAdapter;
8714 if (adapter
8715 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008716 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008717 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8718 conn_info.connState ==
8719 eConnectionState_Associated) {
8720 sta_connected = true;
8721 break;
8722 }
8723 }
8724 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008725 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8727 bApActive == true) {
8728 ap_connected = true;
8729 break;
8730 }
8731 }
8732 status = hdd_get_next_adapter(hdd_ctx,
8733 adapterNode,
8734 &pNext);
8735 adapterNode = pNext;
8736 }
8737 }
8738
8739 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008740 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008741 return;
8742 } else {
8743 if (sme_set_auto_shutdown_timer(hal_handle,
8744 hdd_ctx->config->
8745 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308746 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008747 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008748 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008749 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008750 hdd_ctx->config->WlanAutoShutdown);
8751
8752 }
8753}
8754#endif
8755
8756hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8757 bool check_start_bss)
8758{
8759 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8760 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308761 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008762 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8763
8764 con_sap_adapter = NULL;
8765
8766 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308767 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008768 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008769 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8770 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008771 adapter != this_sap_adapter) {
8772 if (check_start_bss) {
8773 if (test_bit(SOFTAP_BSS_STARTED,
8774 &adapter->event_flags)) {
8775 con_sap_adapter = adapter;
8776 break;
8777 }
8778 } else {
8779 con_sap_adapter = adapter;
8780 break;
8781 }
8782 }
8783 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8784 adapterNode = pNext;
8785 }
8786
8787 return con_sap_adapter;
8788}
8789
8790#ifdef MSM_PLATFORM
8791void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8792{
8793 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8794
Anurag Chouhan210db072016-02-22 18:42:15 +05308795 if (QDF_TIMER_STATE_RUNNING ==
8796 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008797 return;
8798
Anurag Chouhan210db072016-02-22 18:42:15 +05308799 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008800 hdd_ctx->config->busBandwidthComputeInterval);
8801}
8802
8803void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8804{
8805 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308806 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008807 bool can_stop = true;
8808 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8809
Anurag Chouhan210db072016-02-22 18:42:15 +05308810 if (QDF_TIMER_STATE_RUNNING !=
8811 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008812 /* trying to stop timer, when not running is not good */
Srinivas Girigowda0ee96442016-08-17 19:10:56 -07008813 hdd_info("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008814 return;
8815 }
8816
8817 if (cds_concurrent_open_sessions_running()) {
8818 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8819
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308820 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008821 adapter = adapterNode->pAdapter;
8822 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008823 && (adapter->device_mode == QDF_STA_MODE
8824 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008825 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8826 conn_info.connState ==
8827 eConnectionState_Associated) {
8828 can_stop = false;
8829 break;
8830 }
8831 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008832 && (adapter->device_mode == QDF_SAP_MODE
8833 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008834 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8835 true) {
8836 can_stop = false;
8837 break;
8838 }
8839 status = hdd_get_next_adapter(hdd_ctx,
8840 adapterNode,
8841 &pNext);
8842 adapterNode = pNext;
8843 }
8844 }
8845
Ravi Joshib89e7f72016-09-07 13:43:15 -07008846 if (can_stop == true) {
Chris Guoc0c95bf2016-11-10 14:28:25 +08008847 /* reset the ipa perf level */
8848 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
Anurag Chouhan210db072016-02-22 18:42:15 +05308849 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Ravi Joshib89e7f72016-09-07 13:43:15 -07008850 hdd_reset_tcp_delack(hdd_ctx);
8851 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008852}
8853#endif
8854
8855/**
8856 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8857 * and sta's operating channel.
8858 * @sta_adapter: Describe the first argument to foobar.
8859 * @ap_adapter: Describe the second argument to foobar.
8860 * @roam_profile: Roam profile of AP to which STA wants to connect.
8861 * @concurrent_chnl_same: If both SAP and STA channels are same then
8862 * set this flag to true else false.
8863 *
8864 * This function checks the sap's operating channel and sta's operating channel.
8865 * if both are same then it will return false else it will restart the sap in
8866 * sta's channel and return true.
8867 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308868 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008869 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308870QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008871 hdd_adapter_t *ap_adapter,
8872 tCsrRoamProfile *roam_profile,
8873 tScanResultHandle *scan_cache,
8874 bool *concurrent_chnl_same)
8875{
8876 hdd_ap_ctx_t *hdd_ap_ctx;
8877 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308878 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008879 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008880 *concurrent_chnl_same = true;
8881
8882 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8883 status =
8884 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8885 roam_profile,
8886 scan_cache,
8887 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308888 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008889 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008890 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8891 if (hdd_ap_ctx->operatingChannel != channel_id) {
8892 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008893 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008894 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008895 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008896 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8897 if (hdd_ap_ctx->operatingChannel != channel_id) {
8898 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008899 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008900 }
8901 }
8902 } else {
8903 /*
8904 * Lets handle worst case scenario here, Scan cache lookup is
8905 * failed so we have to stop the SAP to avoid any channel
8906 * discrepancy between SAP's channel and STA's channel.
8907 * Return the status as failure so caller function could know
8908 * that scan look up is failed.
8909 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008910 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308911 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008912 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308913 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008914}
8915
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008916/**
8917 * wlan_hdd_stop_sap() - This function stops bss of SAP.
8918 * @ap_adapter: SAP adapter
8919 *
8920 * This function will process the stopping of sap adapter.
8921 *
8922 * Return: None
8923 */
8924void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
8925{
8926 hdd_ap_ctx_t *hdd_ap_ctx;
8927 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308928 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008929 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008930
8931 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008932 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008933 return;
8934 }
8935
8936 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8937 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308938 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008939 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008941 mutex_lock(&hdd_ctx->sap_lock);
8942 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08008943 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008944 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
8945 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008946 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308947 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308948 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008949 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05308950 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308951 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008952 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308953 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008954 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008955 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008956 return;
8957 }
8958 }
8959 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008960 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008961 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008962 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008963 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008964 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008965 }
8966 mutex_unlock(&hdd_ctx->sap_lock);
8967 return;
8968}
8969
8970/**
8971 * wlan_hdd_start_sap() - this function starts bss of SAP.
8972 * @ap_adapter: SAP adapter
8973 *
8974 * This function will process the starting of sap adapter.
8975 *
8976 * Return: None
8977 */
8978void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
8979{
8980 hdd_ap_ctx_t *hdd_ap_ctx;
8981 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308982 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008983 hdd_context_t *hdd_ctx;
8984 tsap_Config_t *sap_config;
8985
8986 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008987 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008988 return;
8989 }
8990
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008991 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07008992 hdd_err("SoftAp role has not been enabled");
8993 return;
8994 }
8995
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008996 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
8997 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8998 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8999 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
9000
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309001 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009002 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309003
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009004 mutex_lock(&hdd_ctx->sap_lock);
9005 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
9006 goto end;
9007
9008 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009009 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009010 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9011 goto end;
9012 }
9013
Wei Song2f76f642016-11-18 16:32:53 +08009014 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009015 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
9016 &hdd_ap_ctx->sapConfig,
9017 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309018 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009019 goto end;
9020
Jeff Johnson28f8a772016-08-15 15:30:36 -07009021 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309022 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009023 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309024 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009025 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009026 goto end;
9027 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07009028 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009029 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -08009030 if (hostapd_state->bssState == BSS_START)
9031 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009032 ap_adapter->sessionId);
9033 hostapd_state->bCommit = true;
9034
9035end:
9036 mutex_unlock(&hdd_ctx->sap_lock);
9037 return;
9038}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009039
9040/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08009041 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
9042 * mac scan config
9043 * @status: Status of set antenna mode
9044 *
9045 * Callback on setting the dual mac configuration
9046 *
9047 * Return: None
9048 */
9049void wlan_hdd_soc_set_antenna_mode_cb(
9050 enum set_antenna_mode_status status)
9051{
9052 hdd_context_t *hdd_ctx;
9053
9054 hdd_info("Status: %d", status);
9055
9056 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9057 if (0 != wlan_hdd_validate_context(hdd_ctx))
9058 return;
9059
9060 /* Signal the completion of set dual mac config */
9061 complete(&hdd_ctx->set_antenna_mode_cmpl);
9062}
9063
9064/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009065 * hdd_get_fw_version() - Get FW version
9066 * @hdd_ctx: pointer to HDD context.
9067 * @major_spid: FW version - major spid.
9068 * @minor_spid: FW version - minor spid
9069 * @ssid: FW version - ssid
9070 * @crmid: FW version - crmid
9071 *
9072 * This function is called to get the firmware build version stored
9073 * as part of the HDD context
9074 *
9075 * Return: None
9076 */
9077void hdd_get_fw_version(hdd_context_t *hdd_ctx,
9078 uint32_t *major_spid, uint32_t *minor_spid,
9079 uint32_t *siid, uint32_t *crmid)
9080{
9081 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
9082 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
9083 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
9084 *crmid = hdd_ctx->target_fw_version & 0x7fff;
9085}
9086
9087#ifdef QCA_CONFIG_SMP
9088/**
9089 * wlan_hdd_get_cpu() - get cpu_index
9090 *
9091 * Return: cpu_index
9092 */
9093int wlan_hdd_get_cpu(void)
9094{
9095 int cpu_index = get_cpu();
9096 put_cpu();
9097 return cpu_index;
9098}
9099#endif
9100
9101/**
9102 * hdd_get_fwpath() - get framework path
9103 *
9104 * This function is used to get the string written by
9105 * userspace to start the wlan driver
9106 *
9107 * Return: string
9108 */
9109const char *hdd_get_fwpath(void)
9110{
9111 return fwpath.string;
9112}
9113
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009114/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009115 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009116 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009117 * This function initilizes CDS global context with the help of cds_init. This
9118 * has to be the first function called after probe to get a valid global
9119 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009120 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009121 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009122 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009123int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009124{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009125 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009126 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009127
9128#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9129 wlan_logging_sock_init_svc();
9130#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009131 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009132
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009133 if (p_cds_context == NULL) {
9134 hdd_alert("Failed to allocate CDS context");
9135 ret = -ENOMEM;
9136 goto err_out;
9137 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009138
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009139 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309140 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009141
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009142err_out:
9143 return ret;
9144}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009145
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009146/**
9147 * hdd_deinit() - Deinitialize Driver
9148 *
9149 * This function frees CDS global context with the help of cds_deinit. This
9150 * has to be the last function call in remove callback to free the global
9151 * context.
9152 */
9153void hdd_deinit(void)
9154{
9155 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009156
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009157#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9158 wlan_logging_sock_deinit_svc();
9159#endif
9160}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009161
9162#ifdef QCA_WIFI_3_0_ADRASTEA
9163#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
9164#else
9165#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
9166#endif
9167
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009168/**
9169 * __hdd_module_init - Module init helper
9170 *
9171 * Module init helper function used by both module and static driver.
9172 *
9173 * Return: 0 for success, errno on failure
9174 */
9175static int __hdd_module_init(void)
9176{
9177 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009178
Arun Khandavallifae92942016-08-01 13:31:08 +05309179 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009180 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009181
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009182 pld_init();
9183
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309184 ret = hdd_init();
9185 if (ret) {
9186 pr_err("hdd_init failed %x\n", ret);
9187 goto err_hdd_init;
9188 }
9189
Rajeev Kumar97767a02016-11-30 11:20:40 -08009190 dispatcher_init();
9191
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309192 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009193
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009194 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009195
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009196 ret = wlan_hdd_register_driver();
9197 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07009198 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
9199 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009200 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009201 }
9202
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309203 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009204
9205 return 0;
9206out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309207 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -08009208 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309209 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009210
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309211err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009212 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009213
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009214 return ret;
9215}
9216
9217/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309218 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
9219 *
9220 * Block the unloading of the driver until the cds recovery is completed
9221 *
9222 * Return: None
9223 */
9224static void hdd_wait_for_recovery_completion(void)
9225{
9226 int retry = 0;
9227
9228 /* Wait for recovery to complete */
9229 while (cds_is_driver_recovering()) {
9230 hdd_alert("Recovery in progress; wait here!!!");
9231 msleep(1000);
9232 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
9233 hdd_alert("SSR never completed, fatal error");
9234 QDF_BUG(0);
9235 }
9236 }
9237}
9238
9239/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009240 * __hdd_module_exit - Module exit helper
9241 *
9242 * Module exit helper function used by both module and static driver.
9243 */
9244static void __hdd_module_exit(void)
9245{
9246 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
9247 QWLAN_VERSIONSTR);
9248
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309249 hdd_wait_for_recovery_completion();
9250
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009251 wlan_hdd_unregister_driver();
9252
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309253 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009254
Rajeev Kumar97767a02016-11-30 11:20:40 -08009255 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309256 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009257 pld_deinit();
9258
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009259 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009260}
9261
Arun Khandavallifae92942016-08-01 13:31:08 +05309262#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009263/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309264 * wlan_boot_cb() - Wlan boot callback
9265 * @kobj: object whose directory we're creating the link in.
9266 * @attr: attribute the user is interacting with
9267 * @buff: the buffer containing the user data
9268 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009269 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309270 * This callback is invoked when the fs is ready to start the
9271 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009272 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309273 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009274 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309275static ssize_t wlan_boot_cb(struct kobject *kobj,
9276 struct kobj_attribute *attr,
9277 const char *buf,
9278 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009279{
Arun Khandavallifae92942016-08-01 13:31:08 +05309280
9281 int ret = 0;
9282
9283 if (wlan_loader->loaded_state) {
9284 pr_info("Wlan driver already initialized");
9285 return 0;
9286 }
9287
9288
9289 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9290 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9291
9292 if (__hdd_module_init()) {
9293 pr_err("%s: Failed to register handler\n", __func__);
9294 ret = -EINVAL;
9295 } else
9296 wlan_loader->loaded_state = MODULE_INITIALIZED;
9297
9298 return count;
9299
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009300}
Arun Khandavallifae92942016-08-01 13:31:08 +05309301
9302/**
9303 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
9304 * ready
9305 *
9306 * This is creates the syfs entry boot_wlan. Which shall be invoked
9307 * when the filesystem is ready.
9308 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009309 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +05309310 */
9311static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009312{
Arun Khandavallifae92942016-08-01 13:31:08 +05309313 int ret = -EINVAL;
9314
9315 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
9316 if (!wlan_loader) {
9317 pr_err("%s: memory alloc failed\n", __func__);
9318 ret = -ENOMEM;
9319 return ret;
9320 }
9321
9322 wlan_loader->boot_wlan_obj = NULL;
9323 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
9324 GFP_KERNEL);
9325 if (!wlan_loader->attr_group) {
9326 pr_err("%s: malloc attr_group failed\n", __func__);
9327 ret = -ENOMEM;
9328 goto error_return;
9329 }
9330
9331 wlan_loader->loaded_state = 0;
9332 wlan_loader->attr_group->attrs = attrs;
9333
9334 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
9335 kernel_kobj);
9336 if (!wlan_loader->boot_wlan_obj) {
9337 pr_err("%s: sysfs create and add failed\n", __func__);
9338 ret = -ENOMEM;
9339 goto error_return;
9340 }
9341
9342 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
9343 wlan_loader->attr_group);
9344 if (ret) {
9345 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
9346 goto error_return;
9347 }
9348
9349 return 0;
9350
9351error_return:
9352
9353 if (wlan_loader->boot_wlan_obj) {
9354 kobject_del(wlan_loader->boot_wlan_obj);
9355 wlan_loader->boot_wlan_obj = NULL;
9356 }
9357
9358 return ret;
9359}
9360
9361/**
9362 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
9363 *
9364 * Return: 0 on success or errno on failure
9365 */
9366static int wlan_deinit_sysfs(void)
9367{
9368
9369 if (!wlan_loader) {
9370 hdd_alert("wlan loader context is Null!");
9371 return -EINVAL;
9372 }
9373
9374 if (wlan_loader->boot_wlan_obj) {
9375 sysfs_remove_group(wlan_loader->boot_wlan_obj,
9376 wlan_loader->attr_group);
9377 kobject_del(wlan_loader->boot_wlan_obj);
9378 wlan_loader->boot_wlan_obj = NULL;
9379 }
9380
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009381 return 0;
9382}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009383
Arun Khandavallifae92942016-08-01 13:31:08 +05309384#endif
9385
9386#ifdef MODULE
9387/**
9388 * __hdd_module_init - Module init helper
9389 *
9390 * Module init helper function used by both module and static driver.
9391 *
9392 * Return: 0 for success, errno on failure
9393 */
9394static int hdd_module_init(void)
9395{
9396 int ret = 0;
9397
9398 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9399 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9400
9401 if (__hdd_module_init()) {
9402 pr_err("%s: Failed to register handler\n", __func__);
9403 ret = -EINVAL;
9404 }
9405
9406 return ret;
9407}
9408#else
9409static int __init hdd_module_init(void)
9410{
9411 int ret = -EINVAL;
9412
9413 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009414 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +05309415 pr_err("Failed to create sysfs entry for loading wlan");
9416
9417 return ret;
9418}
9419#endif
9420
9421
9422#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009423/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009424 * hdd_module_exit() - Exit function
9425 *
9426 * This is the driver exit point (invoked when module is unloaded using rmmod)
9427 *
9428 * Return: None
9429 */
9430static void __exit hdd_module_exit(void)
9431{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009432 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009433}
Arun Khandavallifae92942016-08-01 13:31:08 +05309434#else
9435static void __exit hdd_module_exit(void)
9436{
9437 __hdd_module_exit();
9438 wlan_deinit_sysfs();
9439}
9440#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009441
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009442static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
9443{
9444 return param_set_copystring(kmessage, kp);
9445}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009446
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309447/**
9448 * is_con_mode_valid() check con mode is valid or not
9449 * @mode: global con mode
9450 *
9451 * Return: TRUE on success FALSE on failure
9452 */
9453static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
9454{
9455 switch (mode) {
9456 case QDF_GLOBAL_MONITOR_MODE:
9457 case QDF_GLOBAL_FTM_MODE:
9458 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309459 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309460 return true;
9461 default:
9462 return false;
9463 }
9464}
9465
9466/**
9467 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
9468 * @mode: global con mode
9469 *
9470 * Return: adapter mode
9471 */
9472static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
9473 enum tQDF_GLOBAL_CON_MODE mode)
9474{
9475
9476 switch (mode) {
9477 case QDF_GLOBAL_MISSION_MODE:
9478 return QDF_STA_MODE;
9479 case QDF_GLOBAL_MONITOR_MODE:
9480 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309481 case QDF_GLOBAL_EPPING_MODE:
9482 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309483 case QDF_GLOBAL_FTM_MODE:
9484 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309485 case QDF_GLOBAL_QVIT_MODE:
9486 return QDF_QVIT_MODE;
9487 default:
9488 return QDF_MAX_NO_OF_MODE;
9489 }
9490}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009491
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309492static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
9493 enum tQDF_GLOBAL_CON_MODE curr_mode)
9494{
9495 switch (curr_mode) {
9496 case QDF_GLOBAL_MISSION_MODE:
9497 case QDF_GLOBAL_MONITOR_MODE:
9498 case QDF_GLOBAL_FTM_MODE:
9499 hdd_abort_mac_scan_all_adapters(hdd_ctx);
9500 hdd_stop_all_adapters(hdd_ctx);
9501 hdd_deinit_all_adapters(hdd_ctx, false);
9502 hdd_close_all_adapters(hdd_ctx, false);
9503 break;
9504 case QDF_GLOBAL_EPPING_MODE:
9505 epping_disable();
9506 epping_close();
9507 break;
9508 default:
9509 return;
9510 }
9511}
9512
9513static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
9514 enum tQDF_GLOBAL_CON_MODE mode)
9515{
9516 hdd_adapter_t *adapter;
9517 int ret = 0;
9518 bool rtnl_held;
9519 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
9520 QDF_STATUS status;
9521
9522 if (!qdf_dev) {
9523 hdd_err("qdf device context is Null return!");
9524 return -EINVAL;
9525 }
9526
9527 rtnl_held = hdd_hold_rtnl_lock();
9528 switch (mode) {
9529 case QDF_GLOBAL_MISSION_MODE:
9530 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
9531 if (IS_ERR(adapter)) {
9532 hdd_alert("Failed to open interface, adapter is NULL");
9533 ret = -EINVAL;
9534 }
9535 break;
9536 case QDF_GLOBAL_FTM_MODE:
9537 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
9538 wlan_hdd_get_intf_addr(hdd_ctx),
9539 NET_NAME_UNKNOWN, rtnl_held);
9540 if (adapter == NULL)
9541 ret = -EINVAL;
9542 break;
9543 case QDF_GLOBAL_MONITOR_MODE:
9544 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
9545 wlan_hdd_get_intf_addr(hdd_ctx),
9546 NET_NAME_UNKNOWN, rtnl_held);
9547 if (adapter == NULL)
9548 ret = -EINVAL;
9549 break;
9550 case QDF_GLOBAL_EPPING_MODE:
9551 status = epping_open();
9552 if (status != QDF_STATUS_SUCCESS) {
9553 hdd_err("Failed to open in eeping mode: %d", status);
9554 ret = -EINVAL;
9555 break;
9556 }
9557 ret = epping_enable(qdf_dev->dev);
9558 if (ret) {
9559 hdd_err("Failed to enable in epping mode : %d", ret);
9560 epping_close();
9561 }
9562 break;
9563 default:
9564 hdd_info("Mode not supported");
9565 ret = -ENOTSUPP;
9566 break;
9567 }
9568 hdd_release_rtnl_lock();
9569 rtnl_held = false;
9570 return ret;
9571}
9572
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009573/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309574 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309575 * @kmessage: con mode name on which driver to be bring up
9576 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309577 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009578 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309579 * This function is invoked when user updates con mode using sys entry,
9580 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009581 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309582 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009583 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309584static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
9585 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009586{
9587 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309588 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309589 enum tQDF_GLOBAL_CON_MODE curr_mode;
9590 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309591
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309592 ret = wlan_hdd_validate_context(hdd_ctx);
9593 if (ret)
9594 return ret;
9595
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309596 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009597
Arun Khandavallifae92942016-08-01 13:31:08 +05309598 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009599 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05309600
Arun Khandavallifae92942016-08-01 13:31:08 +05309601
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309602
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309603 if (!(is_con_mode_valid(con_mode))) {
9604 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309605 ret = -EINVAL;
9606 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309607 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309608
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309609 curr_mode = hdd_get_conparam();
9610 if (curr_mode == con_mode) {
9611 hdd_err("curr mode: %d is same as user triggered mode %d",
9612 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309613 ret = 0;
9614 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309615 }
9616
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309617 /* Cleanup present mode before switching to new mode */
9618 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05309619
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07009620 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309621 if (ret) {
9622 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309623 goto reset_flags;
9624 }
9625
9626 hdd_set_conparam(con_mode);
9627
9628 /* Register for new con_mode & then kick_start modules again */
9629 ret = hdd_register_req_mode(hdd_ctx, con_mode);
9630 if (ret) {
9631 hdd_err("Failed to register for new mode");
9632 goto reset_flags;
9633 }
9634
9635 adapter_mode = hdd_get_adpter_mode(con_mode);
9636 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
9637 hdd_err("invalid adapter");
9638 ret = -EINVAL;
9639 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309640 }
9641
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309642 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309643 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309644 hdd_err("Failed to get adapter:%d", adapter_mode);
9645 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309646 }
9647
9648 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
9649 if (ret) {
9650 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309651 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309652 }
9653
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309654 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
9655 con_mode == QDF_GLOBAL_FTM_MODE) {
9656 if (hdd_start_adapter(adapter)) {
9657 hdd_err("Failed to start %s adapter", kmessage);
9658 ret = -EINVAL;
9659 goto reset_flags;
9660 }
Arun Khandavallifae92942016-08-01 13:31:08 +05309661 }
9662
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309663 hdd_info("Mode successfully changed to %s", kmessage);
9664 ret = 0;
9665
9666reset_flags:
9667 cds_set_load_in_progress(false);
9668 return ret;
9669}
9670
9671
9672static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
9673{
9674 int ret;
9675 hdd_context_t *hdd_ctx;
9676
9677 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9678 ret = wlan_hdd_validate_context(hdd_ctx);
9679 if (ret)
9680 return ret;
9681
9682 cds_ssr_protect(__func__);
9683 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
9684 cds_ssr_unprotect(__func__);
9685
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009686 return ret;
9687}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009688
9689/**
9690 * hdd_get_conparam() - driver exit point
9691 *
9692 * This is the driver exit point (invoked when module is unloaded using rmmod)
9693 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309694 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009695 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309696enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009697{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309698 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009699}
9700
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009701void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009702{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009703 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009704}
9705
Komal Seelamc11bb222016-01-27 18:57:10 +05309706/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309707 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9708 * @hdd_ctx: HDD context
9709 *
9710 * Cleans up the pre cac interface, if it exists
9711 *
9712 * Return: None
9713 */
9714void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9715{
9716 uint8_t session_id;
9717 QDF_STATUS status;
9718 struct hdd_adapter_s *precac_adapter;
9719
9720 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9721 if (QDF_IS_STATUS_ERROR(status)) {
9722 hdd_err("failed to get pre cac vdev id");
9723 return;
9724 }
9725
9726 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9727 if (!precac_adapter) {
9728 hdd_err("invalid pre cac adapater");
9729 return;
9730 }
9731
9732 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9733 wlan_hdd_sap_pre_cac_failure,
9734 (void *)precac_adapter);
9735 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9736
9737}
9738
9739/**
Komal Seelamec702b02016-02-24 18:42:16 +05309740 * hdd_update_ol_config - API to update ol configuration parameters
9741 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309742 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309743 * Return: void
9744 */
Komal Seelamec702b02016-02-24 18:42:16 +05309745static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309746{
Komal Seelamec702b02016-02-24 18:42:16 +05309747 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309748 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309749
Komal Seelamec702b02016-02-24 18:42:16 +05309750 if (!ol_ctx)
9751 return;
9752
9753 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9754 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9755 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9756 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -07009757 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +05309758
9759 ol_init_ini_config(ol_ctx, &cfg);
9760}
9761
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009762#ifdef FEATURE_RUNTIME_PM
9763/**
9764 * hdd_populate_runtime_cfg() - populate runtime configuration
9765 * @hdd_ctx: hdd context
9766 * @cfg: pointer to the configuration memory being populated
9767 *
9768 * Return: void
9769 */
9770static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9771 struct hif_config_info *cfg)
9772{
9773 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9774 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9775}
9776#else
9777static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9778 struct hif_config_info *cfg)
9779{
9780}
9781#endif
9782
Komal Seelamec702b02016-02-24 18:42:16 +05309783/**
9784 * hdd_update_hif_config - API to update HIF configuration parameters
9785 * @hdd_ctx: HDD Context
9786 *
9787 * Return: void
9788 */
9789static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9790{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309791 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309792 struct hif_config_info cfg;
9793
9794 if (!scn)
9795 return;
9796
9797 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009798 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05309799 hif_init_ini_config(scn, &cfg);
9800}
9801
9802/**
9803 * hdd_update_config() - Initialize driver per module ini parameters
9804 * @hdd_ctx: HDD Context
9805 *
9806 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309807 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05309808 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309809int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05309810{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309811 int ret;
9812
Komal Seelamec702b02016-02-24 18:42:16 +05309813 hdd_update_ol_config(hdd_ctx);
9814 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309815 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
9816 ret = hdd_update_cds_config_ftm(hdd_ctx);
9817 else
9818 ret = hdd_update_cds_config(hdd_ctx);
9819
9820 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05309821}
9822
Agrawal Ashish65634612016-08-18 13:24:32 +05309823/**
9824 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
9825 * @mode : cfg80211 DFS mode
9826 *
9827 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
9828 */
9829enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
9830{
9831 switch (mode) {
9832 case DFS_MODE_ENABLE:
9833 return ACS_DFS_MODE_ENABLE;
9834 break;
9835 case DFS_MODE_DISABLE:
9836 return ACS_DFS_MODE_DISABLE;
9837 break;
9838 case DFS_MODE_DEPRIORITIZE:
9839 return ACS_DFS_MODE_DEPRIORITIZE;
9840 break;
9841 default:
9842 hdd_err("ACS dfs mode is NONE");
9843 return ACS_DFS_MODE_NONE;
9844 }
9845}
9846
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309847/**
9848 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
9849 * @hddctx: pointer to hdd context
9850 * @set_value: enable/disable
9851 *
9852 * When Host sends vendor command enable, FW will send *ONE* CA ind to
9853 * Host(even though it is duplicate). When Host send vendor command
9854 * disable,FW doesn't perform any action. Whenever any change in
9855 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
9856 *
9857 * return - 0 on success, appropriate error values on failure.
9858 */
9859int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
9860{
9861 QDF_STATUS status;
9862
9863 if (0 != wlan_hdd_validate_context(hddctx)) {
9864 return -EAGAIN;
9865 }
9866
9867 if (!hddctx->config->goptimize_chan_avoid_event) {
9868 hdd_warn("goptimize_chan_avoid_event ini param disabled");
9869 return -EINVAL;
9870 }
9871
9872 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
9873 if (!QDF_IS_STATUS_SUCCESS(status)) {
9874 hdd_err("Failed to send chan avoid command to SME");
9875 return -EINVAL;
9876 }
9877 return 0;
9878}
Agrawal Ashish65634612016-08-18 13:24:32 +05309879
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -08009880/**
9881 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
9882 * @value: value to set
9883 *
9884 * This function will set the passed value to roaming in progress flag.
9885 *
9886 * Return: None
9887 */
9888void hdd_set_roaming_in_progress(bool value)
9889{
9890 hdd_context_t *hdd_ctx;
9891
9892 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9893 if (!hdd_ctx) {
9894 hdd_err("HDD context is NULL");
9895 return;
9896 }
9897
9898 hdd_ctx->roaming_in_progress = value;
9899 hdd_info("Roaming in Progress set to %d", value);
9900}
9901
9902/**
9903 * hdd_is_roaming_in_progress() - check if roaming is in progress
9904 * @hdd_ctx - HDD context
9905 *
9906 * Return: true if roaming is in progress else false
9907 */
9908bool hdd_is_roaming_in_progress(void)
9909{
9910 hdd_context_t *hdd_ctx;
9911
9912 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9913 if (!hdd_ctx) {
9914 hdd_err("HDD context is NULL");
9915 return false;
9916 }
9917 return hdd_ctx->roaming_in_progress;
9918}
9919
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05309920QDF_STATUS hdd_create_and_store_psoc(hdd_context_t *hdd_ctx, uint8_t psoc_id)
9921{
9922 struct wlan_objmgr_psoc *psoc;
9923
9924 psoc = wlan_objmgr_psoc_obj_create(psoc_id, WLAN_DEV_OL);
9925 if (!psoc)
9926 return QDF_STATUS_E_FAILURE;
9927
9928 hdd_ctx->hdd_psoc = psoc;
9929
9930 return QDF_STATUS_SUCCESS;
9931}
9932
Rajeev Kumar1cba9d02017-01-06 11:36:14 -08009933QDF_STATUS hdd_release_and_destroy_psoc(hdd_context_t *hdd_ctx)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05309934{
9935 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
9936
9937 hdd_ctx->hdd_psoc = NULL;
9938 if (psoc) {
9939 wlan_objmgr_psoc_obj_delete(psoc);
9940 return QDF_STATUS_SUCCESS;
9941 } else
9942 return QDF_STATUS_E_FAILURE;
9943}
9944
9945QDF_STATUS hdd_create_and_store_pdev(hdd_context_t *hdd_ctx)
9946{
9947 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
9948 struct wlan_objmgr_pdev *pdev;
9949
9950 if (!psoc) {
9951 hdd_err("Psoc NULL");
9952 return QDF_STATUS_E_FAILURE;
9953 }
9954
9955 pdev = wlan_objmgr_pdev_obj_create(psoc, NULL);
9956 if (!pdev) {
9957 hdd_err("pdev obj create failed");
9958 return QDF_STATUS_E_FAILURE;
9959 }
9960 hdd_ctx->hdd_pdev = pdev;
9961
9962 return QDF_STATUS_SUCCESS;
9963}
9964
Rajeev Kumar3a6c13c2017-01-06 13:01:08 -08009965QDF_STATUS hdd_release_and_destroy_pdev(hdd_context_t *hdd_ctx)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05309966{
9967 struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
9968
9969 hdd_ctx->hdd_pdev = NULL;
9970 if (pdev) {
9971 wlan_objmgr_pdev_obj_delete(pdev);
9972 return QDF_STATUS_SUCCESS;
9973 } else
9974 return QDF_STATUS_E_FAILURE;
9975}
9976
9977QDF_STATUS hdd_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
9978 hdd_adapter_t *adapter)
9979{
9980 struct wlan_objmgr_vdev *vdev;
9981 struct wlan_objmgr_peer *peer;
9982 struct wlan_vdev_create_params vdev_params;
9983
9984 vdev_params.opmode = adapter->device_mode;
9985 qdf_mem_copy(vdev_params.macaddr, adapter->macAddressCurrent.bytes,
9986 QDF_NET_MAC_ADDR_MAX_LEN);
9987 if (!pdev) {
9988 hdd_err("pdev NULL");
9989 return QDF_STATUS_E_FAILURE;
9990 }
9991
9992 vdev = wlan_objmgr_vdev_obj_create(pdev, &vdev_params);
9993 if (!vdev) {
9994 hdd_err("vdev obj create fails");
9995 return QDF_STATUS_E_FAILURE;
9996 }
9997
9998 if (adapter->sessionId != wlan_vdev_get_id(vdev)) {
9999 hdd_err("session id and vdev id mismatch");
10000 wlan_objmgr_vdev_obj_delete(vdev);
10001 QDF_ASSERT(0);
10002 return QDF_STATUS_E_FAILURE;
10003 }
10004
10005 peer = wlan_objmgr_peer_obj_create(vdev, WLAN_PEER_SELF,
10006 vdev_params.macaddr);
10007 if (!peer) {
10008 hdd_err("obj manager self peer create fails for adapter %d",
10009 adapter->device_mode);
10010 wlan_objmgr_vdev_obj_delete(vdev);
10011 return QDF_STATUS_E_FAILURE;
10012 }
Himanshu Agarwal2fdf77a2016-12-29 11:41:00 +053010013 wlan_objmgr_peer_ref_peer(peer);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +053010014 adapter->hdd_vdev = vdev;
10015
10016 return QDF_STATUS_SUCCESS;
10017}
10018
Rajeev Kumarba778852017-01-06 13:23:04 -080010019QDF_STATUS hdd_release_and_destroy_vdev(hdd_adapter_t *adapter)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +053010020{
10021 struct wlan_objmgr_vdev *vdev = adapter->hdd_vdev;
10022
10023 adapter->hdd_vdev = NULL;
10024 if (vdev) {
10025 if (hdd_remove_peer_object(vdev,
10026 wlan_vdev_mlme_get_macaddr(vdev))) {
10027 hdd_err("Self peer delete fails");
10028 return QDF_STATUS_E_FAILURE;
10029 }
10030
10031 wlan_objmgr_vdev_obj_delete(vdev);
10032 return QDF_STATUS_SUCCESS;
10033 } else
10034 return QDF_STATUS_E_FAILURE;
10035}
10036
10037QDF_STATUS hdd_add_peer_object(struct wlan_objmgr_vdev *vdev,
10038 enum tQDF_ADAPTER_MODE adapter_mode,
10039 uint8_t *mac_addr)
10040{
10041 enum wlan_peer_type peer_type;
10042
10043 if ((adapter_mode == QDF_STA_MODE) ||
10044 (adapter_mode == QDF_P2P_CLIENT_MODE))
10045 peer_type = WLAN_PEER_AP;
10046 else if ((adapter_mode == QDF_SAP_MODE) ||
10047 (adapter_mode == QDF_P2P_GO_MODE))
10048 peer_type = WLAN_PEER_STA;
10049 else if (adapter_mode == QDF_IBSS_MODE)
10050 peer_type = WLAN_PEER_IBSS;
10051 else {
10052 hdd_err("Unsupported device mode %d", adapter_mode);
10053 return QDF_STATUS_E_FAILURE;
10054 }
10055
10056 if (!vdev) {
10057 hdd_err("vdev NULL");
10058 QDF_ASSERT(0);
10059 return QDF_STATUS_E_FAILURE;
10060 }
10061
10062 if (!wlan_objmgr_peer_obj_create(vdev, peer_type, mac_addr))
10063 return QDF_STATUS_E_FAILURE;
10064
10065 hdd_info("Peer object "MAC_ADDRESS_STR" add success!",
10066 MAC_ADDR_ARRAY(mac_addr));
10067
10068 return QDF_STATUS_SUCCESS;
10069}
10070
10071QDF_STATUS hdd_remove_peer_object(struct wlan_objmgr_vdev *vdev,
10072 uint8_t *mac_addr)
10073{
10074 struct wlan_objmgr_psoc *psoc;
10075 struct wlan_objmgr_peer *peer;
10076
10077 if (!vdev) {
10078 hdd_err("vdev NULL");
10079 QDF_ASSERT(0);
10080 return QDF_STATUS_E_FAILURE;
10081 }
10082
10083 psoc = wlan_vdev_get_psoc(vdev);
10084 if (!psoc) {
10085 hdd_err("Psoc NUll");
10086 QDF_ASSERT(0);
10087 return QDF_STATUS_E_FAILURE;
10088 }
10089
10090 peer = wlan_objmgr_find_peer(psoc, mac_addr);
10091 if (peer) {
10092 if (wlan_objmgr_peer_obj_delete(peer))
10093 return QDF_STATUS_E_FAILURE;
10094
10095 hdd_info("Peer obj "MAC_ADDRESS_STR" deleted",
10096 MAC_ADDR_ARRAY(mac_addr));
10097 return QDF_STATUS_SUCCESS;
10098 }
10099
10100 hdd_err("Peer obj "MAC_ADDRESS_STR" not found",
10101 MAC_ADDR_ARRAY(mac_addr));
10102
10103 return QDF_STATUS_E_FAILURE;
10104}
10105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010106/* Register the module init/exit functions */
10107module_init(hdd_module_init);
10108module_exit(hdd_module_exit);
10109
10110MODULE_LICENSE("Dual BSD/GPL");
10111MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10112MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010114module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10115 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010116
10117module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
10118 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
10119
10120module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
10121
10122module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
10123
10124module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);