blob: fecc73f874652b7fb627e4dd2b815997d242eac8 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnsond9f08602016-12-02 11:31:30 -08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053039#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#include <linux/etherdevice.h>
41#include <linux/firmware.h>
42#include <wlan_hdd_tx_rx.h>
43#include <wni_api.h>
44#include <wlan_hdd_cfg.h>
45#include <wlan_ptt_sock_svc.h>
46#include <dbglog_host.h>
47#include <wlan_logging_sock_svc.h>
48#include <wlan_hdd_wowl.h>
49#include <wlan_hdd_misc.h>
50#include <wlan_hdd_wext.h>
51#include "wlan_hdd_trace.h"
52#include "wlan_hdd_ioctl.h"
53#include "wlan_hdd_ftm.h"
54#include "wlan_hdd_power.h"
55#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070056#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053057#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053058#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070059#include <cdp_txrx_peer_ops.h>
Dhanashri Atrea8f82f22017-01-23 12:58:24 -080060#include <cdp_txrx_misc.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080061
62#include <net/addrconf.h>
63#include <linux/wireless.h>
64#include <net/cfg80211.h>
65#include <linux/inetdevice.h>
66#include <net/addrconf.h>
67#include "wlan_hdd_cfg80211.h"
68#include "wlan_hdd_ext_scan.h"
69#include "wlan_hdd_p2p.h"
70#include <linux/rtnetlink.h>
71#include "sap_api.h"
72#include <linux/semaphore.h>
73#include <linux/ctype.h>
74#include <linux/compat.h>
75#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076#include <soc/qcom/subsystem_restart.h>
77#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078#include <wlan_hdd_hostapd.h>
79#include <wlan_hdd_softap_tx_rx.h>
80#include "cfg_api.h"
81#include "qwlan_version.h"
82#include "wma_types.h"
83#include "wlan_hdd_tdls.h"
84#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053085#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080086#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080087#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070088#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080089#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080090#include "wlan_hdd_nan.h"
91#include "wlan_hdd_debugfs.h"
92#include "wlan_hdd_driver_ops.h"
93#include "epping_main.h"
94#include "wlan_hdd_memdump.h"
95
96#include <wlan_hdd_ipa.h>
97#include "hif.h"
98#include "wma.h"
99#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700100#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800101#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530102#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700103#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700104#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530105#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700106#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530107#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800108#include <dispatcher_init_deinit.h>
Rajeev Kumar699debf2017-01-06 14:17:00 -0800109#include "wlan_hdd_object_manager.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530110#include "cds_utils.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111
112#ifdef MODULE
113#define WLAN_MODULE_NAME module_name(THIS_MODULE)
114#else
115#define WLAN_MODULE_NAME "wlan"
116#endif
117
118#ifdef TIMER_MANAGER
119#define TIMER_MANAGER_STR " +TIMER_MANAGER"
120#else
121#define TIMER_MANAGER_STR ""
122#endif
123
124#ifdef MEMORY_DEBUG
125#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
126#else
127#define MEMORY_DEBUG_STR ""
128#endif
129
Arun Khandavallifae92942016-08-01 13:31:08 +0530130#ifndef MODULE
131static struct gwlan_loader *wlan_loader;
132static ssize_t wlan_boot_cb(struct kobject *kobj,
133 struct kobj_attribute *attr,
134 const char *buf, size_t count);
135struct gwlan_loader {
136 bool loaded_state;
137 struct kobject *boot_wlan_obj;
138 struct attribute_group *attr_group;
139};
140
141static struct kobj_attribute wlan_boot_attribute =
142 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
143
144static struct attribute *attrs[] = {
145 &wlan_boot_attribute.attr,
146 NULL,
147};
148
149#define MODULE_INITIALIZED 1
150#endif
151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152/* the Android framework expects this param even though we don't use it */
153#define BUF_LEN 20
154static char fwpath_buffer[BUF_LEN];
155static struct kparam_string fwpath = {
156 .string = fwpath_buffer,
157 .maxlen = BUF_LEN,
158};
159
160static char *country_code;
161static int enable_11d = -1;
162static int enable_dfs_chan_scan = -1;
163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164/*
165 * spinlock for synchronizing asynchronous request/response
166 * (full description of use in wlan_hdd_main.h)
167 */
168DEFINE_SPINLOCK(hdd_context_lock);
169
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800170#define WLAN_NLINK_CESIUM 30
171
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530172static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800173
174#define WOW_MAX_FILTER_LISTS 1
175#define WOW_MAX_FILTERS_PER_LIST 4
176#define WOW_MIN_PATTERN_SIZE 6
177#define WOW_MAX_PATTERN_SIZE 64
178
179#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
180static const struct wiphy_wowlan_support wowlan_support_reg_init = {
181 .flags = WIPHY_WOWLAN_ANY |
182 WIPHY_WOWLAN_MAGIC_PKT |
183 WIPHY_WOWLAN_DISCONNECT |
184 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
185 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
186 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
187 WIPHY_WOWLAN_4WAY_HANDSHAKE |
188 WIPHY_WOWLAN_RFKILL_RELEASE,
189 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
190 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
191 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
192};
193#endif
194
195/* internal function declaration */
196
197struct sock *cesium_nl_srv_sock;
198
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
200void wlan_hdd_auto_shutdown_cb(void);
201#endif
202
203/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530204 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
205 * @hdd_ctx: pointer to hdd_context_t
206 *
207 * Return: none
208 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700209static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530210{
211 hdd_adapter_t *adapter;
212 hdd_adapter_list_node_t *adapter_node, *next;
213 QDF_STATUS status = QDF_STATUS_SUCCESS;
214
215 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
216 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
217 adapter = adapter_node->pAdapter;
218 if (NULL != adapter)
219 hdd_send_rps_ind(adapter);
220 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
221 adapter_node = next;
222 }
223}
224
225/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
227 * @vdev_id: vdev_id
228 * @action: action type
229 * @reason: reason type
230 *
231 * Return: none
232 */
233void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
234 enum netif_action_type action, enum netif_reason_type reason)
235{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530236 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237 hdd_adapter_t *adapter;
238
239 if (!hdd_ctx) {
240 hdd_err("hdd ctx is NULL");
241 return;
242 }
243 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
244
245 wlan_hdd_netif_queue_control(adapter, action, reason);
246 return;
247}
248
249/*
250 * Store WLAN driver version info in a global variable such that crash debugger
251 * can extract it from driver debug symbol and crashdump for post processing
252 */
253uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
254
255/**
256 * hdd_device_mode_to_string() - return string conversion of device mode
257 * @device_mode: device mode
258 *
259 * This utility function helps log string conversion of device mode.
260 *
261 * Return: string conversion of device mode, if match found;
262 * "Unknown" otherwise.
263 */
264const char *hdd_device_mode_to_string(uint8_t device_mode)
265{
266 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800267 CASE_RETURN_STRING(QDF_STA_MODE);
268 CASE_RETURN_STRING(QDF_SAP_MODE);
269 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
270 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
271 CASE_RETURN_STRING(QDF_FTM_MODE);
272 CASE_RETURN_STRING(QDF_IBSS_MODE);
273 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
274 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700275 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 default:
277 return "Unknown";
278 }
279}
280
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530281/**
282 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
283 * @adapter: HDD adapter
284 * @chan_number: Channel number
285 * @chan_bw: Bandwidth
286 *
287 * Checks if the given bandwidth is valid for the given channel number.
288 *
289 * Return: 0 for success, non-zero for failure
290 */
291int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
292 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800293 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530294{
295 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
296 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
297 bool found = false;
298 tHalHandle hal;
299
300 hal = WLAN_HDD_GET_HAL_CTX(adapter);
301 if (!hal) {
302 hdd_err("Invalid HAL context");
303 return -EINVAL;
304 }
305
306 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
307 hdd_err("No valid channel list");
308 return -EOPNOTSUPP;
309 }
310
311 for (i = 0; i < len; i++) {
312 if (chan[i] == chan_number) {
313 found = true;
314 break;
315 }
316 }
317
318 if (found == false) {
319 hdd_err("Channel not in driver's valid channel list");
320 return -EOPNOTSUPP;
321 }
322
323 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
324 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
325 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
326 return -EINVAL;
327 }
328
329 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
330 if (chan_bw == CH_WIDTH_80MHZ) {
331 hdd_err("BW80 not possible in 2.4GHz band");
332 return -EINVAL;
333 }
334 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
335 (chan_bw != CH_WIDTH_MAX)) {
336 hdd_err("Only BW20 possible on channel 14");
337 return -EINVAL;
338 }
339 }
340
341 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
342 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
343 (chan_bw != CH_WIDTH_MAX)) {
344 hdd_err("Only BW20 possible on channel 165");
345 return -EINVAL;
346 }
347 }
348
349 return 0;
350}
351
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352static int __hdd_netdev_notifier_call(struct notifier_block *nb,
353 unsigned long state, void *data)
354{
355#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
356 struct netdev_notifier_info *dev_notif_info = data;
357 struct net_device *dev = dev_notif_info->dev;
358#else
359 struct net_device *dev = data;
360#endif
361 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
362 hdd_context_t *hdd_ctx;
363
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800364 ENTER_DEV(dev);
365
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366 /* Make sure that this callback corresponds to our device. */
367 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
368 return NOTIFY_DONE;
369
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530370 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700372 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 return NOTIFY_DONE;
374 }
375
376 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700377 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 return NOTIFY_DONE;
379 }
380
381 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
382 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700383 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530384 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 return NOTIFY_DONE;
386 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800387 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 return NOTIFY_DONE;
389
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700390 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 dev->name, state);
392
393 switch (state) {
394 case NETDEV_REGISTER:
395 break;
396
397 case NETDEV_UNREGISTER:
398 break;
399
400 case NETDEV_UP:
401 sme_ch_avoid_update_req(hdd_ctx->hHal);
402 break;
403
404 case NETDEV_DOWN:
405 break;
406
407 case NETDEV_CHANGE:
408 if (true == adapter->isLinkUpSvcNeeded)
409 complete(&adapter->linkup_event_var);
410 break;
411
412 case NETDEV_GOING_DOWN:
413 if (adapter->scan_info.mScanPending != false) {
414 unsigned long rc;
415 INIT_COMPLETION(adapter->scan_info.
416 abortscan_event_var);
417 hdd_abort_mac_scan(adapter->pHddCtx,
418 adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530419 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420 eCSR_SCAN_ABORT_DEFAULT);
421 rc = wait_for_completion_timeout(
422 &adapter->scan_info.abortscan_event_var,
423 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
424 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700425 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800426 }
427 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700428 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429 }
430 break;
431
432 default:
433 break;
434 }
435
436 return NOTIFY_DONE;
437}
438
439/**
440 * hdd_netdev_notifier_call() - netdev notifier callback function
441 * @nb: pointer to notifier block
442 * @state: state
443 * @ndev: ndev pointer
444 *
445 * Return: 0 on success, error number otherwise.
446 */
447static int hdd_netdev_notifier_call(struct notifier_block *nb,
448 unsigned long state,
449 void *ndev)
450{
451 int ret;
452
453 cds_ssr_protect(__func__);
454 ret = __hdd_netdev_notifier_call(nb, state, ndev);
455 cds_ssr_unprotect(__func__);
456
457 return ret;
458}
459
460struct notifier_block hdd_netdev_notifier = {
461 .notifier_call = hdd_netdev_notifier_call,
462};
463
464/* variable to hold the insmod parameters */
465static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800466
467/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800468static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800469
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530470/**
471 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
472 * @ch_width: NL channel width
473 *
474 * Converts the NL channel width to the driver's internal representation
475 *
476 * Return: Converted channel width. In case of non matching NL channel width,
477 * CH_WIDTH_MAX will be returned.
478 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800479enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530480{
481 switch (ch_width) {
482 case NL80211_CHAN_WIDTH_20_NOHT:
483 case NL80211_CHAN_WIDTH_20:
484 return CH_WIDTH_20MHZ;
485 case NL80211_CHAN_WIDTH_40:
486 return CH_WIDTH_40MHZ;
487 break;
488 case NL80211_CHAN_WIDTH_80:
489 return CH_WIDTH_80MHZ;
490 case NL80211_CHAN_WIDTH_80P80:
491 return CH_WIDTH_80P80MHZ;
492 case NL80211_CHAN_WIDTH_160:
493 return CH_WIDTH_160MHZ;
494 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800495 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530496 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800497 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530498 default:
499 hdd_err("Invalid channel width %d, setting to default",
500 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800501 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530502 }
503}
504
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530505/* wlan_hdd_find_opclass() - Find operating class for a channel
506 * @hal: handler to HAL
507 * @channel: channel id
508 * @bw_offset: bandwidth offset
509 *
510 * Function invokes sme api to find the operating class
511 *
512 * Return: operating class
513 */
514uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
515 uint8_t bw_offset)
516{
517 uint8_t opclass = 0;
518
519 sme_get_opclass(hal, channel, bw_offset, &opclass);
520 return opclass;
521}
522
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530524 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 * @moduleId: Module whose trace level is being configured
526 * @bitmask: Bitmask of log levels to be enabled
527 *
528 * Called immediately after the cfg.ini is read in order to configure
529 * the desired trace levels.
530 *
531 * Return: None
532 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530533static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530535 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530536 int qdf_print_idx = -1;
537 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 /*
539 * if the bitmask is the default value, then a bitmask was not
540 * specified in cfg.ini, so leave the logging level alone (it
541 * will remain at the "compiled in" default value)
542 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530543 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800544 return;
545 }
546
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530547 qdf_print_idx = qdf_get_pidx();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530549 /* a mask was specified. start by disabling all logging */
550 status = qdf_print_set_category_verbose(qdf_print_idx, moduleId,
551 QDF_TRACE_LEVEL_NONE, 0);
552
553 if (QDF_STATUS_SUCCESS != status)
554 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800555 /* 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) {
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530559 status = qdf_print_set_category_verbose(qdf_print_idx,
560 moduleId, level, 1);
561 if (QDF_STATUS_SUCCESS != status)
562 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 }
564 level++;
565 bitmask >>= 1;
566 }
567}
568
569/**
570 * wlan_hdd_validate_context() - check the HDD context
571 * @hdd_ctx: HDD context pointer
572 *
573 * Return: 0 if the context is valid. Error code otherwise
574 */
575int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
576{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530578 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579 return -ENODEV;
580 }
581
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800582 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530583 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
584 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585 return -EAGAIN;
586 }
587
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800588 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530589 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
590 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 return -EAGAIN;
592 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530593
594 if (hdd_ctx->start_modules_in_progress ||
595 hdd_ctx->stop_modules_in_progress) {
596 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
597 (void *)_RET_IP_);
598 return -EAGAIN;
599 }
600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 return 0;
602}
603
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604/**
605 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
606 * @hdd_adapter_t Hdd adapter.
607 *
608 * This function sets the IBSS power save config parameters to WMA
609 * which will send it to firmware if FW supports IBSS power save
610 * before vdev start.
611 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530612 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800613 * on failure.
614 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530615QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616{
617 int ret;
618 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
619
620 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700621 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530622 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623 }
624
625 ret = wma_cli_set_command(adapter->sessionId,
626 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
627 hdd_ctx->config->ibssATIMWinSize,
628 VDEV_CMD);
629 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700630 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530631 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632 }
633
634 ret = wma_cli_set_command(adapter->sessionId,
635 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
636 hdd_ctx->config->isIbssPowerSaveAllowed,
637 VDEV_CMD);
638 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700639 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
640 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530641 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642 }
643
644 ret = wma_cli_set_command(adapter->sessionId,
645 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
646 hdd_ctx->config->
647 isIbssPowerCollapseAllowed, VDEV_CMD);
648 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700649 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
650 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530651 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 }
653
654 ret = wma_cli_set_command(adapter->sessionId,
655 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
656 hdd_ctx->config->isIbssAwakeOnTxRx,
657 VDEV_CMD);
658 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700659 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530660 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 }
662
663 ret = wma_cli_set_command(adapter->sessionId,
664 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
665 hdd_ctx->config->ibssInactivityCount,
666 VDEV_CMD);
667 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700668 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530669 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800670 }
671
672 ret = wma_cli_set_command(adapter->sessionId,
673 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
674 hdd_ctx->config->ibssTxSpEndInactivityTime,
675 VDEV_CMD);
676 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700677 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
678 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530679 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 }
681
682 ret = wma_cli_set_command(adapter->sessionId,
683 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
684 hdd_ctx->config->ibssPsWarmupTime,
685 VDEV_CMD);
686 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700687 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
688 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530689 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 }
691
692 ret = wma_cli_set_command(adapter->sessionId,
693 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
694 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
695 VDEV_CMD);
696 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700697 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
698 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 }
701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530702 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703}
704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705#define INTF_MACADDR_MASK 0x7
706
707/**
708 * hdd_update_macaddr() - update mac address
709 * @config: hdd configuration
710 * @hw_macaddr: mac address
711 *
712 * Mac address for multiple virtual interface is found as following
713 * i) The mac address of the first interface is just the actual hw mac address.
714 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
715 * define the mac address for the remaining interfaces and locally
716 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
717 * supported virtual interfaces, right now this is 0x07 (meaning 8
718 * interface).
719 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
720 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
721 *
722 * Return: None
723 */
724void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530725 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726{
727 int8_t i;
728 uint8_t macaddr_b3, tmp_br3;
729
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530730 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530731 QDF_MAC_ADDR_SIZE);
732 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530733 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530734 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800735 macaddr_b3 = config->intfMacAddr[i].bytes[3];
736 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
737 INTF_MACADDR_MASK;
738 macaddr_b3 += tmp_br3;
739
740 /* XOR-ing bit-24 of the mac address. This will give enough
741 * mac address range before collision
742 */
743 macaddr_b3 ^= (1 << 7);
744
745 /* Set locally administered bit */
746 config->intfMacAddr[i].bytes[0] |= 0x02;
747 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700748 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800749 MAC_ADDRESS_STR, i,
750 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
751 }
752}
753
754static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
755 struct wma_tgt_services *cfg)
756{
757 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758
759 /* Set up UAPSD */
760 config->apUapsdEnabled &= cfg->uapsd;
761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762 /* 11AC mode support */
763 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
764 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
765 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766
767 /* ARP offload: override user setting if invalid */
768 config->fhostArpOffload &= cfg->arp_offload;
769
770#ifdef FEATURE_WLAN_SCAN_PNO
771 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700772 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 if (cfg->pno_offload)
774 config->PnoOffload = true;
775#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776#ifdef FEATURE_WLAN_TDLS
777 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530778 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
779 cfg->en_tdls_offchan;
780 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
781 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
783 config->fEnableTDLSSleepSta = true;
784 } else {
785 config->fEnableTDLSSleepSta = false;
786 }
787#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788#ifdef WLAN_FEATURE_ROAM_OFFLOAD
789 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
790#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700791 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792
793}
794
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700795/**
796 * hdd_update_vdev_nss() - sets the vdev nss
797 * @hdd_ctx: HDD context
798 *
799 * Sets the Nss per vdev type based on INI
800 *
801 * Return: None
802 */
803static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
804{
805 struct hdd_config *cfg_ini = hdd_ctx->config;
806 uint8_t max_supp_nss = 1;
807
Naveen Rawat10b1c152017-01-18 11:16:06 -0800808 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700809 max_supp_nss = 2;
810
811 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
812 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
813
814 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
815 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
816}
817
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
819 struct wma_tgt_ht_cap *cfg)
820{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530821 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 uint32_t value, val32;
823 uint16_t val16;
824 struct hdd_config *pconfig = hdd_ctx->config;
825 tSirMacHTCapabilityInfo *phtCapInfo;
826 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
827 uint8_t enable_tx_stbc;
828
829 /* check and update RX STBC */
830 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
831 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
832
833 /* get the MPDU density */
834 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
835
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530836 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700837 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 value = 0;
839 }
840
841 /*
842 * MPDU density:
843 * override user's setting if value is larger
844 * than the one supported by target
845 */
846 if (value > cfg->mpdu_density) {
847 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
848 cfg->mpdu_density);
849
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530850 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700851 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852 }
853
854 /* get the HT capability info */
855 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530856 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700857 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858 return;
859 }
860 val16 = (uint16_t) val32;
861 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
862
863 /* Set the LDPC capability */
864 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
865
866 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
867 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
868
869 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
870 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
871
872 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
873 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
874
875 enable_tx_stbc = pconfig->enableTxSTBC;
876
877 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
878 pconfig->enable2x2 = 1;
879 } else {
880 pconfig->enable2x2 = 0;
881 enable_tx_stbc = 0;
882
883 /* 1x1 */
884 /* Update Rx Highest Long GI data Rate */
885 if (sme_cfg_set_int(hdd_ctx->hHal,
886 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700887 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530888 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700889 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890 }
891
892 /* Update Tx Highest Long GI data Rate */
893 if (sme_cfg_set_int
894 (hdd_ctx->hHal,
895 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700896 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530897 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700898 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800899 }
900 }
901 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
902 enable_tx_stbc = 0;
903 phtCapInfo->txSTBC = enable_tx_stbc;
904
905 val32 = val16;
906 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530907 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700908 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
910 value = SIZE_OF_SUPPORTED_MCS_SET;
911 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530912 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700913 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914
915 if (pconfig->enable2x2) {
916 for (value = 0; value < cfg->num_rf_chains; value++)
917 mcs_set[value] =
918 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
919
920 status =
921 sme_cfg_set_str(hdd_ctx->hHal,
922 WNI_CFG_SUPPORTED_MCS_SET,
923 mcs_set,
924 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530925 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700926 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800927 }
928 }
929#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
930}
931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800932static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
933 struct wma_tgt_vht_cap *cfg)
934{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530935 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936 uint32_t value = 0;
937 struct hdd_config *pconfig = hdd_ctx->config;
938 struct wiphy *wiphy = hdd_ctx->wiphy;
939 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700940 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700941 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942
Dustin Brown5e06bd32016-10-04 12:49:10 -0700943 if (!band_5g) {
944 hdd_info("5GHz band disabled, skipping capability population");
945 return;
946 }
947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948 /* Get the current MPDU length */
949 status =
950 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
951 &value);
952
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530953 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700954 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955 value = 0;
956 }
957
958 /*
959 * VHT max MPDU length:
960 * override if user configured value is too high
961 * that the target cannot support
962 */
963 if (value > cfg->vht_max_mpdu) {
964 status = sme_cfg_set_int(hdd_ctx->hHal,
965 WNI_CFG_VHT_MAX_MPDU_LENGTH,
966 cfg->vht_max_mpdu);
967
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530968 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700969 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970 }
971 }
972
973 /* Get the current supported chan width */
974 status = sme_cfg_get_int(hdd_ctx->hHal,
975 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
976 &value);
977
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530978 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700979 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800980 value = 0;
981 }
982
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700983 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
984 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
985
986 if (pconfig->enable2x2)
987 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
988
989 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
990 QDF_STATUS_E_FAILURE) {
991 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
992 }
993
994 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
995 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
996 if (pconfig->enable2x2)
997 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
998
999 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1000 QDF_STATUS_E_FAILURE) {
1001 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1002 }
1003
1004 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1005 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1006 if (pconfig->enable2x2)
1007 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1008
1009 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1010 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1011
1012 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1013 QDF_STATUS_E_FAILURE) {
1014 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1015 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001017 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001018 &value);
1019
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301020 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001021 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001022 value = 0;
1023 }
1024
1025 /* Set the LDPC capability */
1026 if (value && !cfg->vht_rx_ldpc) {
1027 status = sme_cfg_set_int(hdd_ctx->hHal,
1028 WNI_CFG_VHT_LDPC_CODING_CAP,
1029 cfg->vht_rx_ldpc);
1030
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301031 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001032 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001033 }
1034 }
1035
1036 /* Get current GI 80 value */
1037 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1038 &value);
1039
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301040 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001041 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 value = 0;
1043 }
1044
1045 /* set the Guard interval 80MHz */
1046 if (value && !cfg->vht_short_gi_80) {
1047 status = sme_cfg_set_int(hdd_ctx->hHal,
1048 WNI_CFG_VHT_SHORT_GI_80MHZ,
1049 cfg->vht_short_gi_80);
1050
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301051 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001052 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053 }
1054 }
1055
1056 /* Get current GI 160 value */
1057 status = sme_cfg_get_int(hdd_ctx->hHal,
1058 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1059 &value);
1060
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301061 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001062 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 value = 0;
1064 }
1065
1066 /* Get VHT TX STBC cap */
1067 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1068
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301069 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001070 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 value = 0;
1072 }
1073
1074 /* VHT TX STBC cap */
1075 if (value && !cfg->vht_tx_stbc) {
1076 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1077 cfg->vht_tx_stbc);
1078
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301079 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001080 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001081 }
1082 }
1083
1084 /* Get VHT RX STBC cap */
1085 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1086
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301087 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001088 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001089 value = 0;
1090 }
1091
1092 /* VHT RX STBC cap */
1093 if (value && !cfg->vht_rx_stbc) {
1094 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1095 cfg->vht_rx_stbc);
1096
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301097 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001098 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001099 }
1100 }
1101
1102 /* Get VHT SU Beamformer cap */
1103 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1104 &value);
1105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301106 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001107 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 value = 0;
1109 }
1110
1111 /* set VHT SU Beamformer cap */
1112 if (value && !cfg->vht_su_bformer) {
1113 status = sme_cfg_set_int(hdd_ctx->hHal,
1114 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1115 cfg->vht_su_bformer);
1116
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301117 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001118 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001119 }
1120 }
1121
1122 /* check and update SU BEAMFORMEE capabality */
1123 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1124 pconfig->enableTxBF = cfg->vht_su_bformee;
1125
1126 status = sme_cfg_set_int(hdd_ctx->hHal,
1127 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1128 pconfig->enableTxBF);
1129
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301130 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001131 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 }
1133
1134 /* Get VHT MU Beamformer cap */
1135 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1136 &value);
1137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301138 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001139 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 value = 0;
1141 }
1142
1143 /* set VHT MU Beamformer cap */
1144 if (value && !cfg->vht_mu_bformer) {
1145 status = sme_cfg_set_int(hdd_ctx->hHal,
1146 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1147 cfg->vht_mu_bformer);
1148
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301149 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001150 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 }
1152 }
1153
1154 /* Get VHT MU Beamformee cap */
1155 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1156 &value);
1157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301158 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001159 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 value = 0;
1161 }
1162
1163 /* set VHT MU Beamformee cap */
1164 if (value && !cfg->vht_mu_bformee) {
1165 status = sme_cfg_set_int(hdd_ctx->hHal,
1166 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1167 cfg->vht_mu_bformee);
1168
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301169 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001170 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171 }
1172 }
1173
1174 /* Get VHT MAX AMPDU Len exp */
1175 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1176 &value);
1177
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301178 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001179 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001180 value = 0;
1181 }
1182
1183 /*
1184 * VHT max AMPDU len exp:
1185 * override if user configured value is too high
1186 * that the target cannot support.
1187 * Even though Rome publish ampdu_len=7, it can
1188 * only support 4 because of some h/w bug.
1189 */
1190
1191 if (value > cfg->vht_max_ampdu_len_exp) {
1192 status = sme_cfg_set_int(hdd_ctx->hHal,
1193 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1194 cfg->vht_max_ampdu_len_exp);
1195
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301196 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001197 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001198 }
1199 }
1200
1201 /* Get VHT TXOP PS CAP */
1202 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1203
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301204 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001205 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 value = 0;
1207 }
1208
1209 /* set VHT TXOP PS cap */
1210 if (value && !cfg->vht_txop_ps) {
1211 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1212 cfg->vht_txop_ps);
1213
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301214 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001215 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 }
1217 }
1218
1219 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1220 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1221 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1222 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1223 else
1224 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1225
1226
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001227 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001228 band_5g->vht_cap.cap |=
1229 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001230 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 band_5g->vht_cap.cap |=
1232 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233
1234 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1235 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1236
1237 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1238 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1239 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1240 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1241
1242 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1243 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1244
1245 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1246 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1247 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1248 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1249 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1250 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1251
1252 band_5g->vht_cap.cap |=
1253 (cfg->vht_max_ampdu_len_exp <<
1254 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1255
1256 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1257 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1258 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1259 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1260 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1261 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1262 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1263 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1264
1265 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1266 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1267
1268}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001270/**
1271 * hdd_generate_macaddr_auto() - Auto-generate mac address
1272 * @hdd_ctx: Pointer to the HDD context
1273 *
1274 * Auto-generate mac address using device serial number.
1275 * Keep the first 3 bytes of OUI as before and replace
1276 * the last 3 bytes with the lower 3 bytes of serial number.
1277 *
1278 * Return: 0 for success
1279 * Non zero failure code for errors
1280 */
1281static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1282{
1283 unsigned int serialno = 0;
1284 struct qdf_mac_addr mac_addr = {
1285 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1286 };
1287
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001288 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001289 if (serialno == 0)
1290 return -EINVAL;
1291
1292 serialno &= 0x00ffffff;
1293
1294 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1295 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1296 mac_addr.bytes[5] = serialno & 0xff;
1297
1298 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1299 return 0;
1300}
1301
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301302/**
1303 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1304 * configuration to cfg_ini in HDD
1305 * @hdd_ctx: Pointer to hdd_ctx
1306 * @cfg: target configuration
1307 *
1308 * Return: None
1309 */
1310#ifdef FEATURE_WLAN_RA_FILTERING
1311static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1312 struct wma_tgt_cfg *cfg)
1313{
1314 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1315}
1316#else
1317static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1318 struct wma_tgt_cfg *cfg)
1319{
1320}
1321#endif
1322
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323void hdd_update_tgt_cfg(void *context, void *param)
1324{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001325 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1327 struct wma_tgt_cfg *cfg = param;
1328 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001329 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301330
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001331 ret = hdd_create_and_store_pdev(hdd_ctx);
1332 if (ret) {
1333 hdd_err("pdev creation fails!");
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301334 QDF_BUG(0);
1335 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001336
1337 if (cds_cfg) {
1338 if (hdd_ctx->config->enable_sub_20_channel_width !=
1339 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1340 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1341 cds_cfg->sub_20_channel_width =
1342 WLAN_SUB_20_CH_WIDTH_NONE;
1343 } else {
1344 cds_cfg->sub_20_channel_width =
1345 hdd_ctx->config->enable_sub_20_channel_width;
1346 }
1347 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001348
1349 /* first store the INI band capability */
1350 temp_band_cap = hdd_ctx->config->nBandCapability;
1351
1352 hdd_ctx->config->nBandCapability = cfg->band_cap;
1353
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001354 /*
1355 * now overwrite the target band capability with INI
1356 * setting if INI setting is a subset
1357 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358
1359 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1360 (temp_band_cap != eCSR_BAND_ALL))
1361 hdd_ctx->config->nBandCapability = temp_band_cap;
1362 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1363 (temp_band_cap != eCSR_BAND_ALL) &&
1364 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001365 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 }
1367
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001368 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1370 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1371 }
1372
1373 /* This can be extended to other configurations like ht, vht cap... */
1374
Anurag Chouhanc5548422016-02-24 18:33:27 +05301375 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001377 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001379 static struct qdf_mac_addr default_mac_addr = {
1380 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1381 };
1382 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1383 &default_mac_addr)) {
1384 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1385 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1386 MAC_ADDRESS_STR,
1387 MAC_ADDR_ARRAY(hdd_ctx->config->
1388 intfMacAddr[0].bytes));
1389 } else {
1390 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1391 MAC_ADDRESS_STR,
1392 MAC_ADDR_ARRAY(hdd_ctx->config->
1393 intfMacAddr[0].bytes));
1394 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001395 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396 }
1397
1398 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001399 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001400
1401 hdd_ctx->max_intf_count = cfg->max_intf_count;
1402
Jeff Johnsonc875e242016-09-23 18:12:34 -07001403 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001404 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001405
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001406 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1407 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1408
1409 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001412
1413 hdd_update_vdev_nss(hdd_ctx);
1414
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001415 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001416 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001417 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001418 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001419
1420 hdd_ctx->current_antenna_mode =
1421 (hdd_ctx->config->enable2x2 == 0x01) ?
1422 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1423 hdd_info("Init current antenna mode: %d",
1424 hdd_ctx->current_antenna_mode);
1425
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001426 hdd_info("Target BPF %d Host BPF %d",
1427 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1428 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1429 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301430 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301431
Arun Khandavallid454d422016-08-17 12:47:05 +05301432 /*
1433 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1434 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1435 * configure the STA mode wow pattern.
1436 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301437 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301438 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301439
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301440 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1441
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001442 /* Configure NAN datapath features */
1443 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444}
1445
1446/**
1447 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1448 * @context: HDD context pointer
1449 * @param: HDD radar indication pointer
1450 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001451 * This function is invoked in atomic context when a radar
1452 * is found on the SAP current operating channel and Data Tx
1453 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 * Actions: Stop the netif Tx queues,Indicate Radar present
1455 * in HDD context for future usage.
1456 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301457 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301459bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460{
1461 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1462 struct wma_dfs_radar_ind *hdd_radar_event =
1463 (struct wma_dfs_radar_ind *)param;
1464 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1465 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301466 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301467 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301469 if (!hdd_ctx || !hdd_radar_event ||
1470 hdd_ctx->config->disableDFSChSwitch)
1471 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472
1473 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001474 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301475 /*
1476 * Application already triggered channel switch
1477 * on current channel, so return here.
1478 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301479 return false;
1480 }
1481
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301483 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001484 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301485 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1486 if ((QDF_SAP_MODE == adapter->device_mode ||
1487 QDF_P2P_GO_MODE == adapter->device_mode) &&
1488 (CHANNEL_STATE_DFS ==
1489 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001490 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1491 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301492 hdd_info("tx blocked for session:%d",
1493 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494 }
1495
1496 status = hdd_get_next_adapter(hdd_ctx,
1497 adapterNode,
1498 &pNext);
1499 adapterNode = pNext;
1500 }
1501 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301502
1503 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001504}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505
1506/**
1507 * hdd_is_valid_mac_address() - validate MAC address
1508 * @pMacAddr: Pointer to the input MAC address
1509 *
1510 * This function validates whether the given MAC address is valid or not
1511 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1512 * where X is the hexa decimal digit character and separated by ':'
1513 * This algorithm works even if MAC address is not separated by ':'
1514 *
1515 * This code checks given input string mac contains exactly 12 hexadecimal
1516 * digits and a separator colon : appears in the input string only after
1517 * an even number of hex digits.
1518 *
1519 * Return: 1 for valid and 0 for invalid
1520 */
1521bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1522{
1523 int xdigit = 0;
1524 int separator = 0;
1525 while (*pMacAddr) {
1526 if (isxdigit(*pMacAddr)) {
1527 xdigit++;
1528 } else if (':' == *pMacAddr) {
1529 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1530 break;
1531
1532 ++separator;
1533 } else {
1534 /* Invalid MAC found */
1535 return 0;
1536 }
1537 ++pMacAddr;
1538 }
1539 return xdigit == 12 && (separator == 5 || separator == 0);
1540}
1541
1542/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301543 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1544 * @dev: Handle to struct net_device to be updated.
1545 *
1546 * Return: None
1547 */
1548static void hdd_mon_mode_ether_setup(struct net_device *dev)
1549{
1550 dev->header_ops = NULL;
1551 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1552 dev->hard_header_len = ETH_HLEN;
1553 dev->mtu = ETH_DATA_LEN;
1554 dev->addr_len = ETH_ALEN;
1555 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1556 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1557 dev->priv_flags |= IFF_TX_SKB_SHARING;
1558
1559 memset(dev->broadcast, 0xFF, ETH_ALEN);
1560}
1561
1562/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001563 * __hdd__mon_open() - HDD Open function
1564 * @dev: Pointer to net_device structure
1565 *
1566 * This is called in response to ifconfig up
1567 *
1568 * Return: 0 for success; non-zero for failure
1569 */
1570static int __hdd_mon_open(struct net_device *dev)
1571{
1572 int ret;
1573
1574 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301575 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001576 ret = hdd_set_mon_rx_cb(dev);
1577 return ret;
1578}
1579
1580/**
1581 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1582 * @dev: Pointer to net_device structure
1583 *
1584 * This is called in response to ifconfig up
1585 *
1586 * Return: 0 for success; non-zero for failure
1587 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001588static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001589{
1590 int ret;
1591
1592 cds_ssr_protect(__func__);
1593 ret = __hdd_mon_open(dev);
1594 cds_ssr_unprotect(__func__);
1595
1596 return ret;
1597}
1598
1599/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301600 * hdd_start_adapter() - Wrapper function for device specific adapter
1601 * @adapter: pointer to HDD adapter
1602 *
1603 * This function is called to start the device specific adapter for
1604 * the mode passed in the adapter's device_mode.
1605 *
1606 * Return: 0 for success; non-zero for failure
1607 */
1608int hdd_start_adapter(hdd_adapter_t *adapter)
1609{
1610
1611 int ret;
1612 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1613
1614 ENTER_DEV(adapter->dev);
1615 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1616
1617 switch (device_mode) {
1618 case QDF_P2P_CLIENT_MODE:
1619 case QDF_P2P_DEVICE_MODE:
1620 case QDF_OCB_MODE:
1621 case QDF_STA_MODE:
1622 case QDF_MONITOR_MODE:
1623 ret = hdd_start_station_adapter(adapter);
1624 if (ret)
1625 goto err_start_adapter;
1626 break;
1627 case QDF_P2P_GO_MODE:
1628 case QDF_SAP_MODE:
1629 ret = hdd_start_ap_adapter(adapter);
1630 if (ret)
1631 goto err_start_adapter;
1632 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301633 case QDF_IBSS_MODE:
1634 /*
1635 * For IBSS interface is initialized as part of
1636 * hdd_init_station_mode()
1637 */
1638 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301639 case QDF_FTM_MODE:
1640 ret = hdd_start_ftm_adapter(adapter);
1641 if (ret)
1642 goto err_start_adapter;
1643 break;
1644 default:
1645 hdd_err("Invalid session type %d", device_mode);
1646 QDF_ASSERT(0);
1647 goto err_start_adapter;
1648 }
1649 if (hdd_set_fw_params(adapter))
1650 hdd_err("Failed to set the FW params for the adapter!");
1651
1652 /*
1653 * Action frame registered in one adapter which will
1654 * applicable to all interfaces
1655 */
1656 wlan_hdd_cfg80211_register_frames(adapter);
1657 EXIT();
1658 return 0;
1659err_start_adapter:
1660 return -EINVAL;
1661}
1662
1663/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301664 * hdd_enable_power_management() - API to Enable Power Management
1665 *
1666 * API invokes Bus Interface Layer power management functionality
1667 *
1668 * Return: None
1669 */
1670static void hdd_enable_power_management(void)
1671{
1672 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1673
1674 if (!hif_ctx) {
1675 hdd_err("Bus Interface Context is Invalid");
1676 return;
1677 }
1678
1679 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1680}
1681
1682/**
1683 * hdd_disable_power_management() - API to disable Power Management
1684 *
1685 * API disable Bus Interface Layer Power management functionality
1686 *
1687 * Return: None
1688 */
1689static void hdd_disable_power_management(void)
1690{
1691 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1692
1693 if (!hif_ctx) {
1694 hdd_err("Bus Interface Context is Invalid");
1695 return;
1696 }
1697
1698 hif_disable_power_management(hif_ctx);
1699}
1700
1701/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301702 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1703 * @hdd_ctx: HDD context
1704 * @adapter: HDD adapter
1705 * @reinit: flag to indicate from SSR or normal path
1706 *
1707 * This function maintains the driver state machine it will be invoked from
1708 * startup, reinit and change interface. Depending on the driver state shall
1709 * perform the opening of the modules.
1710 *
1711 * Return: 0 for success; non-zero for failure
1712 */
1713int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1714 bool reinit)
1715{
1716 int ret;
1717 qdf_device_t qdf_dev;
1718 QDF_STATUS status;
1719 p_cds_contextType p_cds_context;
1720 bool unint = false;
1721 void *hif_ctx;
1722
1723 ENTER();
1724
1725 p_cds_context = cds_get_global_context();
1726 if (!p_cds_context) {
1727 hdd_err("Global Context is NULL");
1728 QDF_ASSERT(0);
1729 return -EINVAL;
1730 }
1731
1732 hdd_info("start modules called in state! :%d reinit: %d",
1733 hdd_ctx->driver_status, reinit);
1734
1735 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1736 if (!qdf_dev) {
1737 hdd_err("QDF Device Context is Invalid return");
1738 return -EINVAL;
1739 }
1740
1741 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301742 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301743
1744 if (QDF_TIMER_STATE_RUNNING ==
1745 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1746
1747 hdd_set_idle_ps_config(hdd_ctx, false);
1748 hdd_info("Interface change Timer running Stop timer");
1749 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1750 }
1751
1752 switch (hdd_ctx->driver_status) {
1753 case DRIVER_MODULES_UNINITIALIZED:
1754 unint = true;
1755 /* Fall through dont add break here */
1756 case DRIVER_MODULES_CLOSED:
1757 if (!reinit && !unint) {
1758 ret = pld_power_on(qdf_dev->dev);
1759 if (ret) {
1760 hdd_err("Failed to Powerup the device: %d", ret);
1761 goto release_lock;
1762 }
1763 }
1764 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1765 qdf_dev->bus_type,
1766 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1767 HIF_ENABLE_TYPE_PROBE);
1768 if (ret) {
1769 hdd_err("Failed to open hif: %d", ret);
1770 goto power_down;
1771 }
1772
1773 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301774 if (!hif_ctx) {
1775 hdd_err("hif context is null!!");
1776 goto power_down;
1777 }
1778
Arun Khandavallifae92942016-08-01 13:31:08 +05301779 status = ol_cds_init(qdf_dev, hif_ctx);
1780 if (status != QDF_STATUS_SUCCESS) {
1781 hdd_err("No Memory to Create BMI Context :%d", status);
1782 goto hif_close;
1783 }
1784
Arun Khandavallif6246632016-08-17 17:43:06 +05301785 ret = hdd_update_config(hdd_ctx);
1786 if (ret) {
1787 hdd_err("Failed to update configuration :%d", ret);
1788 goto ol_cds_free;
1789 }
1790
Rajeev Kumar138ef912017-01-13 15:19:48 -08001791 ret = hdd_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID);
1792 if (ret) {
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301793 hdd_err("Psoc creation fails!");
1794 goto ol_cds_free;
1795 }
1796
1797 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05301798 if (!QDF_IS_STATUS_SUCCESS(status)) {
1799 hdd_err("Failed to Open CDS: %d", status);
Selvaraj, Sridhara7dc2382017-01-27 18:29:39 +05301800 goto destroy_psoc_object;
Arun Khandavallifae92942016-08-01 13:31:08 +05301801 }
1802
1803 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1804
1805 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1806
1807 status = cds_pre_enable(hdd_ctx->pcds_context);
1808 if (!QDF_IS_STATUS_SUCCESS(status)) {
1809 hdd_err("Failed to pre-enable CDS: %d", status);
1810 goto close;
1811 }
1812
1813 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1814 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1815 hdd_ftm_mc_process_msg);
1816 break;
1817 }
1818 if (unint) {
1819 hdd_info("In phase-1 initialization don't enable modules");
1820 break;
1821 }
1822 /* Fall through dont add break here */
1823 case DRIVER_MODULES_OPENED:
1824 if (!adapter) {
1825 hdd_alert("adapter is Null");
1826 goto close;
1827 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05301828 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1829 hdd_err("in ftm mode, no need to configure cds modules");
1830 break;
1831 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301832 if (hdd_configure_cds(hdd_ctx, adapter)) {
1833 hdd_err("Failed to Enable cds modules");
1834 goto close;
1835 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05301836 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05301837 hdd_info("Driver Modules Successfully Enabled");
1838 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1839 break;
1840 case DRIVER_MODULES_ENABLED:
1841 hdd_info("Driver modules already Enabled");
1842 break;
1843 default:
1844 hdd_err("WLAN start invoked in wrong state! :%d\n",
1845 hdd_ctx->driver_status);
1846 goto release_lock;
1847 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301848 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301849 mutex_unlock(&hdd_ctx->iface_change_lock);
1850 EXIT();
1851 return 0;
1852
1853close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301854 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05301855
Selvaraj, Sridhara7dc2382017-01-27 18:29:39 +05301856destroy_psoc_object:
1857 hdd_release_and_destroy_psoc(hdd_ctx);
1858
Arun Khandavallifae92942016-08-01 13:31:08 +05301859ol_cds_free:
1860 ol_cds_free();
1861
1862hif_close:
1863 hdd_hif_close(p_cds_context->pHIFContext);
1864power_down:
1865 if (!reinit && !unint)
1866 pld_power_off(qdf_dev->dev);
1867release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301868 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301869 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301870 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301871 return -EINVAL;
1872}
1873
1874/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 * __hdd_open() - HDD Open function
1876 * @dev: Pointer to net_device structure
1877 *
1878 * This is called in response to ifconfig up
1879 *
1880 * Return: 0 for success; non-zero for failure
1881 */
1882static int __hdd_open(struct net_device *dev)
1883{
1884 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1885 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1886 int ret;
1887
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001888 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301889 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301890 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891
1892 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301893 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896
Arun Khandavallifae92942016-08-01 13:31:08 +05301897 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1898 if (ret) {
1899 hdd_err("Failed to start WLAN modules return");
1900 return -ret;
1901 }
1902
1903
1904 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1905 ret = hdd_start_adapter(adapter);
1906 if (ret) {
1907 hdd_err("Failed to start adapter :%d",
1908 adapter->device_mode);
1909 return ret;
1910 }
1911 }
1912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1914 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301915 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 /* Enable TX queues only when we are connected */
1917 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301918 WLAN_START_ALL_NETIF_QUEUE,
1919 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920 }
1921
Naveen Rawat286def52016-09-23 15:38:02 -07001922 /* Enable carrier and transmit queues for NDI */
1923 if (WLAN_HDD_IS_NDI(adapter)) {
1924 hdd_notice("Enabling Tx Queues");
1925 wlan_hdd_netif_queue_control(adapter,
1926 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
1927 WLAN_CONTROL_PATH);
1928 }
1929
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 return ret;
1931}
1932
Arun Khandavallifae92942016-08-01 13:31:08 +05301933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934/**
1935 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1936 * @dev: Pointer to net_device structure
1937 *
1938 * This is called in response to ifconfig up
1939 *
1940 * Return: 0 for success; non-zero for failure
1941 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001942static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943{
1944 int ret;
1945
1946 cds_ssr_protect(__func__);
1947 ret = __hdd_open(dev);
1948 cds_ssr_unprotect(__func__);
1949
1950 return ret;
1951}
1952
1953/**
1954 * __hdd_stop() - HDD stop function
1955 * @dev: Pointer to net_device structure
1956 *
1957 * This is called in response to ifconfig down
1958 *
1959 * Return: 0 for success; non-zero for failure
1960 */
1961static int __hdd_stop(struct net_device *dev)
1962{
1963 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1964 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301965 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301967 bool close_modules = true;
1968 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001970 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301972 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 adapter->sessionId, adapter->device_mode));
1974
1975 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301976 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978
1979 /* Nothing to be done if the interface is not opened */
1980 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001981 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 return -ENODEV;
1983 }
1984
1985 /* Make sure the interface is marked as closed */
1986 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001987 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988
1989 /*
1990 * Disable TX on the interface, after this hard_start_xmit() will not
1991 * be called on that interface
1992 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001993 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1995 WLAN_CONTROL_PATH);
1996
1997 /*
Naveen Rawat286def52016-09-23 15:38:02 -07001998 * NAN data interface is different in some sense. The traffic on NDI is
1999 * bursty in nature and depends on the need to transfer. The service
2000 * layer may down the interface after the usage and up again when
2001 * required. In some sense, the NDI is expected to be available
2002 * (like SAP) iface until NDI delete request is issued by the service
2003 * layer. Skip BSS termination and adapter deletion for NAN Data
2004 * interface (NDI).
2005 */
2006 if (WLAN_HDD_IS_NDI(adapter))
2007 return 0;
2008
2009 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 * The interface is marked as down for outside world (aka kernel)
2011 * But the driver is pretty much alive inside. The driver needs to
2012 * tear down the existing connection on the netdev (session)
2013 * cleanup the data pipes and wait until the control plane is stabilized
2014 * for this interface. The call also needs to wait until the above
2015 * mentioned actions are completed before returning to the caller.
2016 * Notice that the hdd_stop_adapter is requested not to close the session
2017 * That is intentional to be able to scan if it is a STA/P2P interface
2018 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302019 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020
2021 /* DeInit the adapter. This ensures datapath cleanup as well */
2022 hdd_deinit_adapter(hdd_ctx, adapter, true);
2023
Arun Khandavallifae92942016-08-01 13:31:08 +05302024
2025 /*
2026 * Find if any iface is up. If any iface is up then can't put device to
2027 * sleep/power save mode
2028 */
2029 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2030 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2031 if (test_bit(DEVICE_IFACE_OPENED,
2032 &adapternode->pAdapter->event_flags)) {
2033 hdd_info("Still other ifaces are up cannot close modules");
2034 close_modules = false;
2035 break;
2036 }
2037 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2038 adapternode = next;
2039
2040 }
2041
2042 if (close_modules) {
2043 hdd_info("Closing all modules from the hdd_stop");
2044 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2045 hdd_ctx->config->iface_change_wait_time
2046 * 50000);
2047 }
2048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049 EXIT();
2050 return 0;
2051}
2052
2053/**
2054 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2055 * @dev: pointer to net_device structure
2056 *
2057 * This is called in response to ifconfig down
2058 *
2059 * Return: 0 for success and error number for failure
2060 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002061static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062{
2063 int ret;
2064
2065 cds_ssr_protect(__func__);
2066 ret = __hdd_stop(dev);
2067 cds_ssr_unprotect(__func__);
2068
2069 return ret;
2070}
2071
2072/**
2073 * __hdd_uninit() - HDD uninit function
2074 * @dev: Pointer to net_device structure
2075 *
2076 * This is called during the netdev unregister to uninitialize all data
2077 * associated with the device
2078 *
2079 * Return: None
2080 */
2081static void __hdd_uninit(struct net_device *dev)
2082{
2083 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2084
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002085 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086
2087 do {
2088 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002089 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002090 break;
2091 }
2092
2093 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002094 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 break;
2096 }
2097
2098 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002099 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100 /*
2101 * we haven't validated all cases so let this go for
2102 * now
2103 */
2104 }
2105
2106 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2107
2108 /* after uninit our adapter structure will no longer be valid */
2109 adapter->dev = NULL;
2110 adapter->magic = 0;
2111 } while (0);
2112
2113 EXIT();
2114}
2115
2116/**
2117 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2118 * @dev: pointer to net_device structure
2119 *
2120 * This is called during the netdev unregister to uninitialize all data
2121 * associated with the device
2122 *
2123 * Return: none
2124 */
2125static void hdd_uninit(struct net_device *dev)
2126{
2127 cds_ssr_protect(__func__);
2128 __hdd_uninit(dev);
2129 cds_ssr_unprotect(__func__);
2130}
2131
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002132static int hdd_open_cesium_nl_sock(void)
2133{
2134#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2135 struct netlink_kernel_cfg cfg = {
2136 .groups = WLAN_NLINK_MCAST_GRP_ID,
2137 .input = NULL
2138 };
2139#endif
2140 int ret = 0;
2141
2142#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2143 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2144#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2145 THIS_MODULE,
2146#endif
2147 &cfg);
2148#else
2149 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2150 WLAN_NLINK_MCAST_GRP_ID,
2151 NULL, NULL, THIS_MODULE);
2152#endif
2153
2154 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002155 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002156 ret = -ECONNREFUSED;
2157 }
2158
2159 return ret;
2160}
2161
2162static void hdd_close_cesium_nl_sock(void)
2163{
2164 if (NULL != cesium_nl_srv_sock) {
2165 netlink_kernel_release(cesium_nl_srv_sock);
2166 cesium_nl_srv_sock = NULL;
2167 }
2168}
2169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170/**
2171 * __hdd_set_mac_address() - set the user specified mac address
2172 * @dev: Pointer to the net device.
2173 * @addr: Pointer to the sockaddr.
2174 *
2175 * This function sets the user specified mac address using
2176 * the command ifconfig wlanX hw ether <mac adress>.
2177 *
2178 * Return: 0 for success, non zero for failure
2179 */
2180static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2181{
2182 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2183 hdd_context_t *hdd_ctx;
2184 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302185 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 int ret;
2187
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002188 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189
2190 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2191 ret = wlan_hdd_validate_context(hdd_ctx);
2192 if (0 != ret)
2193 return ret;
2194
2195 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2196 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2197
2198 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302199 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200}
2201
2202/**
2203 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2204 * function from SSR
2205 * @dev: pointer to net_device structure
2206 * @addr: Pointer to the sockaddr
2207 *
2208 * This function sets the user specified mac address using
2209 * the command ifconfig wlanX hw ether <mac adress>.
2210 *
2211 * Return: 0 for success.
2212 */
2213static int hdd_set_mac_address(struct net_device *dev, void *addr)
2214{
2215 int ret;
2216
2217 cds_ssr_protect(__func__);
2218 ret = __hdd_set_mac_address(dev, addr);
2219 cds_ssr_unprotect(__func__);
2220
2221 return ret;
2222}
2223
2224uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2225{
2226 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302227 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2229 break;
2230 }
2231
Anurag Chouhan6d760662016-02-20 16:05:43 +05302232 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 return NULL;
2234
2235 hdd_ctx->config->intfAddrMask |= (1 << i);
2236 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2237}
2238
2239void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2240{
2241 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302242 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002243 if (!memcmp(releaseAddr,
2244 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2245 6)) {
2246 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2247 break;
2248 }
2249 }
2250 return;
2251}
2252
2253#ifdef WLAN_FEATURE_PACKET_FILTERING
2254/**
2255 * __hdd_set_multicast_list() - set the multicast address list
2256 * @dev: Pointer to the WLAN device.
2257 * @skb: Pointer to OS packet (sk_buff).
2258 *
2259 * This funciton sets the multicast address list.
2260 *
2261 * Return: None
2262 */
2263static void __hdd_set_multicast_list(struct net_device *dev)
2264{
2265 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2266 int mc_count;
2267 int i = 0, status;
2268 struct netdev_hw_addr *ha;
2269 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2270 static const uint8_t ipv6_router_solicitation[]
2271 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2272
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002273 ENTER_DEV(dev);
2274
Anurag Chouhan6d760662016-02-20 16:05:43 +05302275 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302276 return;
2277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302279 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002281
2282 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002283 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284 adapter->mc_addr_list.mc_cnt = 0;
2285 } else {
2286 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302287 hdd_notice("mc_count : %u", mc_count);
2288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Dustin Brown61269462016-09-19 13:25:45 -07002290 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
2291 WLAN_HDD_MAX_MC_ADDR_LIST);
2292 wlan_hdd_set_mc_addr_list(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 adapter->mc_addr_list.mc_cnt = 0;
2294 return;
2295 }
2296
2297 adapter->mc_addr_list.mc_cnt = mc_count;
2298
2299 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302300 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2301 i, MAC_ADDR_ARRAY(ha->addr));
2302
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 if (i == mc_count)
2304 break;
2305 /*
2306 * Skip following addresses:
2307 * 1)IPv6 router solicitation address
2308 * 2)Any other address pattern if its set during
2309 * RXFILTER REMOVE driver command based on
2310 * addr_filter_pattern
2311 */
2312 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2313 ETH_ALEN)) ||
2314 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2315 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002316 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 MAC_ADDR_ARRAY(ha->addr));
2318 adapter->mc_addr_list.mc_cnt--;
2319 continue;
2320 }
2321
2322 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2323 ETH_ALEN);
2324 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2325 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002326 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2328 i++;
2329 }
2330 }
2331 if (hdd_ctx->config->active_mode_offload) {
2332 hdd_info("enable mc filtering");
2333 wlan_hdd_set_mc_addr_list(adapter, true);
2334 } else {
2335 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2336 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302337 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 return;
2339}
2340
2341/**
2342 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2343 * @dev: pointer to net_device
2344 *
2345 * Return: none
2346 */
2347static void hdd_set_multicast_list(struct net_device *dev)
2348{
2349 cds_ssr_protect(__func__);
2350 __hdd_set_multicast_list(dev);
2351 cds_ssr_unprotect(__func__);
2352}
2353#endif
2354
2355/**
2356 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2357 * @dev: Pointer to the WLAN device.
2358 * @skb: Pointer to OS packet (sk_buff).
2359 *
2360 * This function is registered with the Linux OS for network
2361 * core to decide which queue to use first.
2362 *
2363 * Return: ac, Queue Index/access category corresponding to UP in IP header
2364 */
2365static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2366#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2367 , void *accel_priv
2368#endif
2369#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2370 , select_queue_fallback_t fallback
2371#endif
2372)
2373{
2374 return hdd_wmm_select_queue(dev, skb);
2375}
2376
2377static struct net_device_ops wlan_drv_ops = {
2378 .ndo_open = hdd_open,
2379 .ndo_stop = hdd_stop,
2380 .ndo_uninit = hdd_uninit,
2381 .ndo_start_xmit = hdd_hard_start_xmit,
2382 .ndo_tx_timeout = hdd_tx_timeout,
2383 .ndo_get_stats = hdd_get_stats,
2384 .ndo_do_ioctl = hdd_ioctl,
2385 .ndo_set_mac_address = hdd_set_mac_address,
2386 .ndo_select_queue = hdd_select_queue,
2387#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389#endif
2390};
2391
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002392/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2393static struct net_device_ops wlan_mon_drv_ops = {
2394 .ndo_open = hdd_mon_open,
2395 .ndo_stop = hdd_stop,
2396 .ndo_get_stats = hdd_get_stats,
2397};
2398
2399/**
2400 * hdd_set_station_ops() - update net_device ops for monitor mode
2401 * @pWlanDev: Handle to struct net_device to be updated.
2402 * Return: None
2403 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404void hdd_set_station_ops(struct net_device *pWlanDev)
2405{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002406 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2407 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2408 else
2409 pWlanDev->netdev_ops = &wlan_drv_ops;
2410}
2411
Komal Seelama89be8d2016-09-29 11:09:26 +05302412#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302413/**
2414 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2415 * @hdd_ctx: HDD context
2416 *
2417 * Return: None
2418 */
2419static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2420{
2421 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2422
2423 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302424 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302425 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302426}
2427
2428/**
2429 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2430 * @hdd_ctx: HDD Context
2431 *
2432 * Return: None
2433 */
2434static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2435{
2436 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2437
2438 qdf_runtime_lock_deinit(ctx->scan);
2439 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302440 qdf_runtime_lock_deinit(ctx->roc);
2441 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302442 qdf_runtime_lock_deinit(ctx->dfs);
2443 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302444}
2445
Komal Seelama89be8d2016-09-29 11:09:26 +05302446static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2447{
2448 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2449
2450 ctx->connect = qdf_runtime_lock_init("connect");
2451}
2452
2453static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2454{
2455 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2456
2457 qdf_runtime_lock_deinit(ctx->connect);
2458 ctx->connect = NULL;
2459}
2460#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302461static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2462static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302463static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2464static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2465#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002466/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002467 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2468 * @hdd_ctx: global hdd context
2469 * @macAddr: mac address to assign to the interface
2470 * @name: User-visible name of the interface
2471 *
2472 * hdd adapter pointer would point to the netdev->priv space, this function
2473 * would retrive the pointer, and setup the hdd adapter configuration.
2474 *
2475 * Return: the pointer to hdd adapter, otherwise NULL
2476 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2478 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002479 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 const char *name)
2481{
2482 struct net_device *pWlanDev = NULL;
2483 hdd_adapter_t *adapter = NULL;
2484 /*
2485 * cfg80211 initialization and registration....
2486 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002487 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2488#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2489 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002491 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2492 hdd_mon_mode_ether_setup : ether_setup),
2493 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494
2495 if (pWlanDev != NULL) {
2496
2497 /* Save the pointer to the net_device in the HDD adapter */
2498 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2499
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302500 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501
2502 adapter->dev = pWlanDev;
2503 adapter->pHddCtx = hdd_ctx;
2504 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302505 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506
2507 init_completion(&adapter->session_open_comp_var);
2508 init_completion(&adapter->session_close_comp_var);
2509 init_completion(&adapter->disconnect_comp_var);
2510 init_completion(&adapter->linkup_event_var);
2511 init_completion(&adapter->cancel_rem_on_chan_var);
2512 init_completion(&adapter->rem_on_chan_ready_event);
2513 init_completion(&adapter->sta_authorized_event);
2514 init_completion(&adapter->offchannel_tx_event);
2515 init_completion(&adapter->tx_action_cnf_event);
2516#ifdef FEATURE_WLAN_TDLS
2517 init_completion(&adapter->tdls_add_station_comp);
2518 init_completion(&adapter->tdls_del_station_comp);
2519 init_completion(&adapter->tdls_mgmt_comp);
2520 init_completion(&adapter->tdls_link_establish_req_comp);
2521#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002522 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 init_completion(&adapter->change_country_code);
2524
2525
2526 init_completion(&adapter->scan_info.abortscan_event_var);
2527
2528 adapter->offloads_configured = false;
2529 adapter->isLinkUpSvcNeeded = false;
2530 adapter->higherDtimTransition = true;
2531 /* Init the net_device structure */
2532 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2533
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302534 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302536 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 sizeof(tSirMacAddr));
2538 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539
2540 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2541 pWlanDev->features |=
2542 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2543 pWlanDev->features |= NETIF_F_RXCSUM;
2544
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002545 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 hdd_set_station_ops(adapter->dev);
2548
2549 pWlanDev->destructor = free_netdev;
2550 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002551 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552 adapter->wdev.wiphy = hdd_ctx->wiphy;
2553 adapter->wdev.netdev = pWlanDev;
2554 /* set pWlanDev's parent to underlying device */
2555 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2556 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302557 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302559 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 }
2561
2562 return adapter;
2563}
2564
Jeff Johnson590e2012016-10-05 16:16:24 -07002565static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2566 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567{
2568 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002570 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2572 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002573 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302574 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 }
2576 }
2577 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002578 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302579 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 }
2581 } else {
2582 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002583 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302584 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585 }
2586 }
2587 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2588
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302589 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590}
2591
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002592QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593{
2594 hdd_adapter_t *adapter = pContext;
2595
2596 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002597 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302598 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 }
2600
2601 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002602 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302603 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 }
2605
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002606 /*
2607 * For NAN Data interface, the close session results in the final
2608 * indication to the userspace
2609 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002610 if (adapter->device_mode == QDF_NDI_MODE)
2611 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002612
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2614
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615 /*
2616 * We can be blocked while waiting for scheduled work to be
2617 * flushed, and the adapter structure can potentially be freed, in
2618 * which case the magic will have been reset. So make sure the
2619 * magic is still good, and hence the adapter structure is still
2620 * valid, before signaling completion
2621 */
2622 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2623 complete(&adapter->session_close_comp_var);
2624
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302625 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626}
2627
Krunal Soni8c37e322016-02-03 16:08:37 -08002628/**
2629 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2630 * @adapter: pointer to device adapter
2631 * @type: type of interface
2632 *
2633 * This routine will check the mode of adapter and if it is required then it
2634 * will initialize the TDLS operations
2635 *
2636 * Return: QDF_STATUS
2637 */
2638#ifdef FEATURE_WLAN_TDLS
2639static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2640{
2641 if (QDF_IBSS_MODE != type) {
2642 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002643 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002644 return QDF_STATUS_E_FAILURE;
2645 }
2646 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2647 }
2648 return QDF_STATUS_SUCCESS;
2649}
2650#else
2651static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2652{
2653 return QDF_STATUS_SUCCESS;
2654}
2655#endif
2656
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302657QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658{
2659 struct net_device *pWlanDev = adapter->dev;
2660 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2661 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302662 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302663 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 uint32_t type, subType;
2665 unsigned long rc;
2666 int ret_val;
2667
2668 INIT_COMPLETION(adapter->session_open_comp_var);
2669 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002670 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302672 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002673 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 goto error_sme_open;
2675 }
2676 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302677 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2679 (uint8_t *) &adapter->macAddressCurrent,
2680 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302681 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002682 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302683 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302684 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 goto error_sme_open;
2686 }
2687 /* Block on a completion variable. Can't wait forever though. */
2688 rc = wait_for_completion_timeout(
2689 &adapter->session_open_comp_var,
2690 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2691 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002692 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002693 rc);
Sandeep Puligillae8065992016-11-14 00:23:43 -08002694 adapter->sessionId = HDD_SESSION_ID_INVALID;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302695 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 }
2697
Rajeev Kumardeabf3e2017-01-13 15:55:05 -08002698 ret_val = hdd_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
2699 if (ret_val)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302700 goto error_vdev_create;
2701
Naveen Rawata410c5a2016-09-19 14:22:33 -07002702 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302704 qdf_ret_status = hdd_register_wext(pWlanDev);
2705 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002706 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302707 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302708 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 goto error_register_wext;
2710 }
2711 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002712 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2714
Deepak Dhamdherea2785822016-11-17 01:17:45 -08002715 /* set fast roaming capability in sme session */
2716 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
2717 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718 /* Set the default operation channel */
2719 pHddStaCtx->conn_info.operationChannel =
2720 hdd_ctx->config->OperatingChannel;
2721
2722 /* Make the default Auth Type as OPEN */
2723 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2724
2725 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302726 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002727 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728 status, status);
2729 goto error_init_txrx;
2730 }
2731
2732 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2733
2734 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302735 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002736 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737 status, status);
2738 goto error_wmm_init;
2739 }
2740
2741 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2742
2743 ret_val = wma_cli_set_command(adapter->sessionId,
2744 WMI_PDEV_PARAM_BURST_ENABLE,
2745 hdd_ctx->config->enableSifsBurst,
2746 PDEV_CMD);
2747
2748 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002749 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 ret_val);
2751 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002752 status = hdd_check_and_init_tdls(adapter, type);
2753 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302756 status = hdd_lro_enable(hdd_ctx, adapter);
2757 if (status != QDF_STATUS_SUCCESS)
2758 goto error_lro_enable;
2759
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302760 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302762error_lro_enable:
2763 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764error_tdls_init:
2765 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2766 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767error_wmm_init:
2768 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2769 hdd_deinit_tx_rx(adapter);
2770error_init_txrx:
2771 hdd_unregister_wext(pWlanDev);
2772error_register_wext:
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08002773 ret_val = hdd_release_and_destroy_vdev(adapter);
2774 if (ret_val)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302775 hdd_err("vdev delete failed");
2776error_vdev_create:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2778 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302779 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 adapter->sessionId,
2781 hdd_sme_close_session_callback,
2782 adapter)) {
2783 unsigned long rc;
2784
2785 /*
2786 * Block on a completion variable.
2787 * Can't wait forever though.
2788 */
2789 rc = wait_for_completion_timeout(
2790 &adapter->session_close_comp_var,
2791 msecs_to_jiffies
2792 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2793 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002794 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002795 rc);
2796 }
2797 }
2798error_sme_open:
2799 return status;
2800}
2801
2802void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2803{
2804 hdd_cfg80211_state_t *cfgState;
2805
2806 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2807
2808 if (NULL != cfgState->buf) {
2809 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 rc = wait_for_completion_timeout(
2811 &adapter->tx_action_cnf_event,
2812 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2813 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002814 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302815 /*
2816 * Inform tx status as FAILURE to upper layer and free
2817 * cfgState->buf
2818 */
2819 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 }
2821 }
2822 return;
2823}
2824
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302825/**
2826 * hdd_station_adapter_deinit() - De-initialize the station adapter
2827 * @hdd_ctx: global hdd context
2828 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07002829 * @rtnl_held: Used to indicate whether or not the caller is holding
2830 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302831 *
2832 * This function De-initializes the STA/P2P/OCB adapter.
2833 *
2834 * Return: None.
2835 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002836static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2837 hdd_adapter_t *adapter,
2838 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302839{
2840 ENTER_DEV(adapter->dev);
2841
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302842 if (adapter->dev) {
2843 if (rtnl_held)
2844 adapter->dev->wireless_handlers = NULL;
2845 else {
2846 rtnl_lock();
2847 adapter->dev->wireless_handlers = NULL;
2848 rtnl_unlock();
2849 }
2850 }
2851
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302852 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2853 hdd_deinit_tx_rx(adapter);
2854 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2855 }
2856
2857 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2858 hdd_wmm_adapter_close(adapter);
2859 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2860 }
2861
2862 hdd_cleanup_actionframe(hdd_ctx, adapter);
2863 wlan_hdd_tdls_exit(adapter);
2864
2865 EXIT();
2866}
2867
2868/**
2869 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2870 * @hdd_ctx: global hdd context
2871 * @adapter: HDD adapter
2872 * @rtnl_held: the rtnl lock hold flag
2873 * This function De-initializes the AP/P2PGo adapter.
2874 *
2875 * Return: None.
2876 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002877static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
2878 hdd_adapter_t *adapter,
2879 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302880{
2881 ENTER_DEV(adapter->dev);
2882
2883 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2884 hdd_wmm_adapter_close(adapter);
2885 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2886 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002887 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302888
2889 hdd_cleanup_actionframe(hdd_ctx, adapter);
2890
2891 hdd_unregister_hostapd(adapter, rtnl_held);
2892
2893 EXIT();
2894}
2895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2897 bool rtnl_held)
2898{
2899 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002902 case QDF_STA_MODE:
2903 case QDF_P2P_CLIENT_MODE:
2904 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302906 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 break;
2908 }
2909
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002910 case QDF_SAP_MODE:
2911 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 {
2913
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302914 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 break;
2916 }
2917
2918 default:
2919 break;
2920 }
2921
2922 EXIT();
2923}
2924
Jeff Johnson590e2012016-10-05 16:16:24 -07002925static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2926 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927{
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08002928 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 struct net_device *pWlanDev = NULL;
2930
2931 if (adapter)
2932 pWlanDev = adapter->dev;
2933 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002934 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 return;
2936 }
2937
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08002938 ret = hdd_release_and_destroy_vdev(adapter);
2939 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302940 hdd_err("vdev delete failed");
2941
Rajeev Kumardca5f812016-02-04 17:28:06 -08002942 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05302943
2944 if (adapter->scan_info.default_scan_ies) {
2945 qdf_mem_free(adapter->scan_info.default_scan_ies);
2946 adapter->scan_info.default_scan_ies = NULL;
2947 }
2948
Komal Seelama89be8d2016-09-29 11:09:26 +05302949 hdd_adapter_runtime_suspend_denit(adapter);
2950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951 /*
2952 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2953 * the driver is almost closed and cannot handle either control
2954 * messages or data. However, unregister_netdevice() call above will
2955 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2956 * to close the active connections (basically excites control path) which
2957 * is not right. Setting this flag helps hdd_stop() to recognize that
2958 * the interface is closed and restricts any operations on that
2959 */
2960 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2961
2962 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2963 if (rtnl_held) {
2964 unregister_netdevice(pWlanDev);
2965 } else {
2966 unregister_netdev(pWlanDev);
2967 }
2968 /*
2969 * Note that the adapter is no longer valid at this point
2970 * since the memory has been reclaimed
2971 */
2972 }
2973}
2974
Jeff Johnson590e2012016-10-05 16:16:24 -07002975static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
2976 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977{
2978 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2979 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302980 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302982 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002983 adapter = adapterNode->pAdapter;
2984 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302985 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002986 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302987 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002988 }
2989 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2990 adapterNode = pNext;
2991 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302992 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002993}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002994
Arun Khandavalli2358d522016-05-16 18:05:37 +05302995#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2996/**
2997 * hdd_set_fw_log_params() - Set log parameters to FW
2998 * @hdd_ctx: HDD Context
2999 * @adapter: HDD Adapter
3000 *
3001 * This function set the FW Debug log level based on the INI.
3002 *
3003 * Return: None
3004 */
3005static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3006 hdd_adapter_t *adapter)
3007{
3008 uint8_t count = 0, numentries = 0,
3009 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3010 uint32_t value = 0;
3011 int ret;
3012
Arun Khandavallifae92942016-08-01 13:31:08 +05303013 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3014 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303015 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
3016 return;
3017 }
3018
Arun Khandavallifae92942016-08-01 13:31:08 +05303019 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303020 hdd_ctx->fw_log_settings.dl_type =
3021 hdd_ctx->config->enableFwLogType;
3022 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303023 WMI_DBGLOG_TYPE,
3024 hdd_ctx->config->enableFwLogType,
3025 DBG_CMD);
3026 if (ret != 0)
3027 hdd_err("Failed to enable FW log type ret %d",
3028 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303029
3030 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303031 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303032 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303033 WMI_DBGLOG_LOG_LEVEL,
3034 hdd_ctx->config->enableFwLogLevel,
3035 DBG_CMD);
3036 if (ret != 0)
3037 hdd_err("Failed to enable FW log level ret %d",
3038 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303039
3040 hdd_string_to_u8_array(
3041 hdd_ctx->config->enableFwModuleLogLevel,
3042 moduleloglevel,
3043 &numentries,
3044 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3045
3046 while (count < numentries) {
3047 /*
3048 * FW module log level input string looks like
3049 * below:
3050 * gFwDebugModuleLoglevel=<FW Module ID>,
3051 * <Log Level>,...
3052 * For example:
3053 * gFwDebugModuleLoglevel=
3054 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3055 * Above input string means :
3056 * For FW module ID 1 enable log level 0
3057 * For FW module ID 2 enable log level 1
3058 * For FW module ID 3 enable log level 2
3059 * For FW module ID 4 enable log level 3
3060 * For FW module ID 5 enable log level 4
3061 * For FW module ID 6 enable log level 5
3062 * For FW module ID 7 enable log level 6
3063 */
3064
Arun Khandavallifae92942016-08-01 13:31:08 +05303065 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05303066 * Module ID * 10 + Module Log level
3067 */
3068 value = ((moduleloglevel[count] * 10) +
3069 moduleloglevel[count + 1]);
3070 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303071 WMI_DBGLOG_MOD_LOG_LEVEL,
3072 value, DBG_CMD);
3073 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303074 hdd_err("Failed to enable FW module log level %d ret %d",
3075 value, ret);
3076
3077 count += 2;
3078 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303079
Arun Khandavalli2358d522016-05-16 18:05:37 +05303080}
3081#else
3082static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3083 hdd_adapter_t *adapter)
3084{
3085}
3086
3087#endif
3088
3089/**
3090 * hdd_set_fw_params() - Set parameters to firmware
3091 * @adapter: HDD adapter
3092 *
3093 * This function Sets various parameters to fw once the
3094 * adapter is started.
3095 *
3096 * Return: 0 on success or errno on failure
3097 */
3098int hdd_set_fw_params(hdd_adapter_t *adapter)
3099{
3100 int ret;
3101 hdd_context_t *hdd_ctx;
3102
3103 ENTER_DEV(adapter->dev);
3104
3105 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3106 if (!hdd_ctx)
3107 return -EINVAL;
3108
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003109 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303110 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303111#define HDD_DTIM_1CHAIN_RX_ID 0x5
3112#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003113 /*
3114 * Disable DTIM 1 chain Rx when in 1x1,
3115 * we are passing two value
3116 * as param_id << 29 | param_value.
3117 * Below param_value = 0(disable)
3118 */
3119 ret = wma_cli_set_command(adapter->sessionId,
3120 WMI_STA_SMPS_PARAM_CMDID,
3121 HDD_DTIM_1CHAIN_RX_ID <<
3122 HDD_SMPS_PARAM_VALUE_S,
3123 VDEV_CMD);
3124 if (ret) {
3125 hdd_err("DTIM 1 chain set failed %d", ret);
3126 goto error;
3127 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303128
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003129 ret = wma_cli_set_command(adapter->sessionId,
3130 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3131 hdd_ctx->config->txchainmask1x1,
3132 PDEV_CMD);
3133 if (ret) {
3134 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3135 ret);
3136 goto error;
3137 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303138
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003139 ret = wma_cli_set_command(adapter->sessionId,
3140 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3141 hdd_ctx->config->rxchainmask1x1,
3142 PDEV_CMD);
3143 if (ret) {
3144 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3145 ret);
3146 goto error;
3147 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303148#undef HDD_DTIM_1CHAIN_RX_ID
3149#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003150 } else {
3151 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3152 }
3153
Arun Khandavallifae92942016-08-01 13:31:08 +05303154 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3155 ret = wma_cli_set_command(adapter->sessionId,
3156 WMI_PDEV_PARAM_HYST_EN,
3157 hdd_ctx->config->enableMemDeepSleep,
3158 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303159
Arun Khandavallifae92942016-08-01 13:31:08 +05303160 if (ret) {
3161 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3162 ret);
3163 goto error;
3164 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303165
3166 ret = wma_cli_set_command(adapter->sessionId,
3167 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3168 hdd_ctx->config->rts_profile,
3169 VDEV_CMD);
3170 if (ret) {
3171 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3172 goto error;
3173 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303174 }
3175
3176 hdd_set_fw_log_params(hdd_ctx, adapter);
3177
3178 EXIT();
3179 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303180
Arun Khandavalli2358d522016-05-16 18:05:37 +05303181error:
3182 return -EINVAL;
3183}
3184
Ryan Hsu07495ea2016-01-21 15:25:39 -08003185/**
3186 * hdd_open_adapter() - open and setup the hdd adatper
3187 * @hdd_ctx: global hdd context
3188 * @session_type: type of the interface to be created
3189 * @iface_name: User-visible name of the interface
3190 * @macAddr: MAC address to assign to the interface
3191 * @name_assign_type: the name of assign type of the netdev
3192 * @rtnl_held: the rtnl lock hold flag
3193 *
3194 * This function open and setup the hdd adpater according to the device
3195 * type request, assign the name, the mac address assigned, and then prepared
3196 * the hdd related parameters, queue, lock and ready to start.
3197 *
3198 * Return: the pointer of hdd adapter, otherwise NULL.
3199 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3201 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003202 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003203 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204{
3205 hdd_adapter_t *adapter = NULL;
3206 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303207 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209
Arun Khandavallifae92942016-08-01 13:31:08 +05303210 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211
3212 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3213 /*
3214 * Max limit reached on the number of vdevs configured by the
3215 * host. Return error
3216 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303217 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3218 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219 return NULL;
3220 }
3221
3222 if (macAddr == NULL) {
3223 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303224 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 return NULL;
3226 }
3227 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303228 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303229 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3230 " already exists",
3231 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 return NULL;
3233 }
3234
3235 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003236 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 /* Reset locally administered bit if the device mode is STA */
3238 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3239 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003240 case QDF_P2P_CLIENT_MODE:
3241 case QDF_P2P_DEVICE_MODE:
3242 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003243 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303244 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003245 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3246 name_assign_type,
3247 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248
3249 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303250 hdd_err("failed to allocate adapter for session %d",
3251 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 return NULL;
3253 }
3254
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003255 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003257 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003258 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303259 else if (QDF_MONITOR_MODE == session_type)
3260 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 else
3262 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3263
3264 adapter->device_mode = session_type;
3265
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303266 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003267 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303268 if (QDF_STATUS_SUCCESS != status)
3269 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303270 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 /*
3273 * Workqueue which gets scheduled in IPv4 notification
3274 * callback
3275 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3277 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278
3279#ifdef WLAN_NS_OFFLOAD
3280 /*
3281 * Workqueue which gets scheduled in IPv6
3282 * notification callback.
3283 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3285 hdd_ipv6_notifier_work_queue);
3286#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303288 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303290 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291 }
3292
3293 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303294 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303296 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3297 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003298 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303299
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003300
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003301 case QDF_P2P_GO_MODE:
3302 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003303 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3304 name_assign_type,
3305 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303307 hdd_alert("failed to allocate adapter for session %d",
3308 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309 return NULL;
3310 }
3311
3312 adapter->wdev.iftype =
3313 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003314 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003315 NL80211_IFTYPE_P2P_GO;
3316 adapter->device_mode = session_type;
3317
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003318 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303319 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003320 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3321 goto err_free_netdev;
3322 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303323 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003324 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303325 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3326 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303328 case QDF_FTM_MODE:
3329 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3330 name_assign_type,
3331 "wlan0");
3332 if (NULL == adapter) {
3333 hdd_err("Failed to allocate adapter for FTM mode");
3334 return NULL;
3335 }
3336 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3337 adapter->device_mode = session_type;
3338 status = hdd_register_interface(adapter, rtnl_held);
3339 if (QDF_STATUS_SUCCESS != status) {
3340 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3341 goto err_free_netdev;
3342 }
3343 /* Stop the Interface TX queue. */
3344 hdd_info("Disabling queues");
3345 wlan_hdd_netif_queue_control(adapter,
3346 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3347 WLAN_CONTROL_PATH);
3348 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303350 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303351 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 return NULL;
3353 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354
3355 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3356 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3357
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303358 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359 /* Add it to the hdd's session list. */
3360 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303361 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303363 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 } else {
3365 pHddAdapterNode->pAdapter = adapter;
3366 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3367 }
3368 }
3369
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303370 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003371 if (NULL != adapter) {
3372 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3373 adapter = NULL;
3374 }
3375 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303376 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 }
3378 return NULL;
3379 }
3380
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303381 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003382 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003383
3384 /* Initialize the WoWL service */
3385 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003386 hdd_alert("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303387 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 }
3389
3390 /* Adapter successfully added. Increment the vdev count */
3391 hdd_ctx->current_intf_count++;
3392
Jeff Johnson5880d792016-08-15 13:32:30 -07003393 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394 hdd_ctx->current_intf_count);
3395
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003396 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003397 }
3398
Rajeev Kumardca5f812016-02-04 17:28:06 -08003399 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3400 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003401
3402 return adapter;
3403
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303404err_close_adapter:
3405 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003406err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303408 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409
3410 return NULL;
3411}
3412
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303413QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003414 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415{
3416 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303417 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418
3419 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303420 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003421 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 status);
3423 return status;
3424 }
3425
3426 while (pCurrent->pAdapter != adapter) {
3427 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303428 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 break;
3430
3431 pCurrent = pNext;
3432 }
3433 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303434 if (QDF_STATUS_SUCCESS == status) {
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303435 hdd_info("wait for bus bw work to flush");
3436 cancel_work_sync(&hdd_ctx->bus_bw_work);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003437 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3439
3440 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303441 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 adapterNode = NULL;
3443
3444 /* Adapter removed. Decrement vdev count */
3445 if (hdd_ctx->current_intf_count != 0)
3446 hdd_ctx->current_intf_count--;
3447
3448 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303449 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003450 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303451
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303452 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003453}
3454
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003455/**
3456 * hdd_close_all_adapters - Close all open adapters
3457 * @hdd_ctx: Hdd context
3458 * rtnl_held: True if RTNL lock held
3459 *
3460 * Close all open adapters.
3461 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303462 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003463 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303464QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465{
3466 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303467 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468
3469 ENTER();
3470
3471 do {
3472 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303473 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303474 wlan_hdd_release_intf_addr(hdd_ctx,
3475 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003477 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303478 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303479 /* Adapter removed. Decrement vdev count */
3480 if (hdd_ctx->current_intf_count != 0)
3481 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303483 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484
3485 EXIT();
3486
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303487 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488}
3489
3490void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3491{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303492 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493 tSirUpdateIE updateIE;
3494 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003495 case QDF_STA_MODE:
3496 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497 {
3498 hdd_station_ctx_t *pHddStaCtx =
3499 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003500 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003501 break;
3502 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003503 case QDF_SAP_MODE:
3504 case QDF_P2P_GO_MODE:
3505 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003507 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508 break;
3509 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003510 case QDF_FTM_MODE:
3511 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 default:
3513 /*
3514 * wlan_hdd_reset_prob_rspies should not have been called
3515 * for these kind of devices
3516 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003517 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 pHostapdAdapter->device_mode);
3519 return;
3520 }
3521
Anurag Chouhanc5548422016-02-24 18:33:27 +05303522 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3524 updateIE.ieBufferlength = 0;
3525 updateIE.pAdditionIEBuffer = NULL;
3526 updateIE.append = true;
3527 updateIE.notify = false;
3528 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3529 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303530 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003531 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 }
3533}
3534
Peng Xu66162de2016-02-11 17:01:20 -08003535/**
3536 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3537 * @hdd_ctx: HDD context which is already NULL validated
3538 * @adapter: HDD adapter which is already NULL validated
3539 *
3540 * Close the SME session and wait for its completion, if needed.
3541 *
3542 * Return: None
3543 */
3544static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3545 hdd_adapter_t *adapter)
3546{
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003547 int ret;
Peng Xu66162de2016-02-11 17:01:20 -08003548 unsigned long rc;
3549
3550 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3551 hdd_err("session is not opened:%d", adapter->sessionId);
3552 return;
3553 }
3554
3555 INIT_COMPLETION(adapter->session_close_comp_var);
3556 if (QDF_STATUS_SUCCESS ==
3557 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3558 hdd_sme_close_session_callback,
3559 adapter)) {
3560 /*
3561 * Block on a completion variable. Can't wait
3562 * forever though.
3563 */
3564 rc = wait_for_completion_timeout(
3565 &adapter->session_close_comp_var,
3566 msecs_to_jiffies
3567 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003568 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003569 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003570 if (adapter->device_mode == QDF_NDI_MODE)
3571 hdd_ndp_session_end_handler(adapter);
3572 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303573 return;
Sandeep Puligillaada72922016-09-29 19:31:21 -07003574 }
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003575 ret = hdd_release_and_destroy_vdev(adapter);
3576 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303577 hdd_err("vdev delete failed");
3578
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303579 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003580 }
3581}
3582
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303583QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 const bool bCloseSession)
3585{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303586 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3588 union iwreq_data wrqu;
3589 tSirUpdateIE updateIE;
3590 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303591 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592
3593 ENTER();
3594
Sachin Ahuja988fd102016-09-15 17:16:25 +05303595 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003596 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003597 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3598 WLAN_CONTROL_PATH);
3599 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003600 case QDF_STA_MODE:
3601 case QDF_P2P_CLIENT_MODE:
3602 case QDF_IBSS_MODE:
3603 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003604 case QDF_NDI_MODE:
3605 if ((QDF_NDI_MODE == adapter->device_mode) ||
3606 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3608 hdd_is_connecting(
3609 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003610 INIT_COMPLETION(adapter->disconnect_comp_var);
3611 /*
3612 * For NDI do not use pWextState from sta_ctx, if needed
3613 * extract from ndi_ctx.
3614 */
3615 if (QDF_NDI_MODE == adapter->device_mode)
3616 qdf_ret_status = sme_roam_disconnect(
3617 hdd_ctx->hHal,
3618 adapter->sessionId,
3619 eCSR_DISCONNECT_REASON_NDI_DELETE);
3620 else if (pWextState->roamProfile.BSSType ==
3621 eCSR_BSS_TYPE_START_IBSS)
3622 qdf_ret_status = sme_roam_disconnect(
3623 hdd_ctx->hHal,
3624 adapter->sessionId,
3625 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003627 qdf_ret_status = sme_roam_disconnect(
3628 hdd_ctx->hHal,
3629 adapter->sessionId,
3630 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003631 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303632 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633 rc = wait_for_completion_timeout(
3634 &adapter->disconnect_comp_var,
3635 msecs_to_jiffies
3636 (WLAN_WAIT_TIME_DISCONNECT));
3637 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003638 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003639 }
3640 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003641 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 }
3643 memset(&wrqu, '\0', sizeof(wrqu));
3644 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3645 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3646 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3647 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303648 }
3649 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303650 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003651 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303652 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303653 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654
3655#ifdef WLAN_OPEN_SOURCE
3656 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3657#endif
3658
3659 hdd_deregister_tx_flow_control(adapter);
3660
3661#ifdef WLAN_NS_OFFLOAD
3662#ifdef WLAN_OPEN_SOURCE
3663 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3664#endif
3665#endif
3666
3667 /*
3668 * It is possible that the caller of this function does not
3669 * wish to close the session
3670 */
Peng Xu66162de2016-02-11 17:01:20 -08003671 if (true == bCloseSession)
3672 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 break;
3674
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003675 case QDF_SAP_MODE:
3676 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003677 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003678 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 /*
3680 * Before stopping the sap adapter, lets make sure there
3681 * is no sap restart work pending.
3682 */
3683 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003684 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003685 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 }
3687 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003688 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3690
3691 hdd_deregister_tx_flow_control(adapter);
3692
3693 mutex_lock(&hdd_ctx->sap_lock);
3694 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303695 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303696 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697
3698 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003699 status = wlansap_stop_bss(
3700 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303702 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003703 hdd_hostapd_state_t *hostapd_state =
3704 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303705 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303706 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303707 qdf_status =
3708 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08003709 qdf_stop_bss_event,
3710 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003711
Anurag Chouhance0dc992016-02-16 18:18:03 +05303712 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003713 hdd_err("failure waiting for wlansap_stop_bss %d",
3714 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 }
3716 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003717 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003718 }
3719 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003720 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003721 adapter->device_mode,
3722 adapter->sessionId);
3723
Anurag Chouhanc5548422016-02-24 18:33:27 +05303724 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003725 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 updateIE.smeSessionId = adapter->sessionId;
3727 updateIE.ieBufferlength = 0;
3728 updateIE.pAdditionIEBuffer = NULL;
3729 updateIE.append = false;
3730 updateIE.notify = false;
3731 /* Probe bcn reset */
3732 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3733 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303734 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003735 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736 }
3737 /* Assoc resp reset */
3738 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3739 &updateIE,
3740 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303741 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003742 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743 }
3744 /* Reset WNI_CFG_PROBE_RSP Flags */
3745 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303746 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003747 adapter->sessionCtx.ap.beacon = NULL;
3748 }
3749 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003750 if (true == bCloseSession)
3751 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003753 case QDF_OCB_MODE:
Leo Changfdb45c32016-10-28 11:09:23 -07003754 cdp_peer_clear(cds_get_context(QDF_MODULE_ID_SOC),
3755 cds_get_context(QDF_MODULE_ID_TXRX),
3756 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757 break;
3758 default:
3759 break;
3760 }
3761
3762 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303763 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003764}
3765
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05303766/**
3767 * hdd_deinit_all_adapters - deinit all adapters
3768 * @hdd_ctx: HDD context
3769 * @rtnl_held: True if RTNL lock held
3770 *
3771 */
3772void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
3773{
3774 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3775 QDF_STATUS status;
3776 hdd_adapter_t *adapter;
3777
3778 ENTER();
3779
3780 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
3781
3782 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
3783 adapter = adapter_node->pAdapter;
3784 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3785 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
3786 adapter_node = next;
3787 }
3788
3789 EXIT();
3790}
3791
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303792QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793{
3794 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303795 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796 hdd_adapter_t *adapter;
3797
3798 ENTER();
3799
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303800 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003802 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3803
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303804 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003805 adapter = adapterNode->pAdapter;
3806 hdd_stop_adapter(hdd_ctx, adapter, true);
3807 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3808 adapterNode = pNext;
3809 }
3810
3811 EXIT();
3812
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303813 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814}
3815
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303816QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817{
3818 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303819 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003820 hdd_adapter_t *adapter;
3821
3822 ENTER();
3823
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303824 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3827
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303828 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003829 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003830 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 wlan_hdd_netif_queue_control(adapter,
3832 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3833 WLAN_CONTROL_PATH);
3834
3835 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3836
3837 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003838 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 adapter->sessionId);
3840 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3841 hdd_wmm_adapter_close(adapter);
3842 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3843 }
3844
Wu Gao36717432016-11-21 15:09:48 +08003845 /*
3846 * If adapter is SAP, set session ID to invalid since SAP
3847 * session will be cleanup during SSR.
3848 */
3849 if (adapter->device_mode == QDF_SAP_MODE)
3850 wlansap_set_invalid_session(
3851 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3854 adapterNode = pNext;
3855 }
3856
3857 EXIT();
3858
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303859 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860}
3861
Arun Khandavallifae92942016-08-01 13:31:08 +05303862/**
3863 * hdd_is_interface_up()- Checkfor interface up before ssr
3864 * @hdd_ctx: HDD context
3865 *
3866 * check if there are any wlan interfaces before SSR accordingly start
3867 * the interface.
3868 *
3869 * Return: 0 if interface was opened else false
3870 */
3871static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3872{
3873 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3874 return true;
3875 else
3876 return false;
3877}
3878
Anurag Chouhanc4092922016-09-08 15:56:11 +05303879#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05303880 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303881struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3882 struct ieee80211_channel *channel,
3883 const u8 *bssid, const u8 *ssid,
3884 size_t ssid_len)
3885{
3886 return cfg80211_get_bss(wiphy, channel, bssid,
3887 ssid, ssid_len,
3888 WLAN_CAPABILITY_ESS,
3889 WLAN_CAPABILITY_ESS);
3890}
3891#else
3892struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3893 struct ieee80211_channel *channel,
3894 const u8 *bssid, const u8 *ssid,
3895 size_t ssid_len)
3896{
3897 return cfg80211_get_bss(wiphy, channel, bssid,
3898 ssid, ssid_len,
3899 IEEE80211_BSS_TYPE_ESS,
3900 IEEE80211_PRIVACY_ANY);
3901}
3902#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303903
Abhishek Singha84d3952016-09-13 13:45:05 +05303904#if defined CFG80211_CONNECT_BSS
3905/**
3906 * hdd_connect_bss() - API to send connection status to supplicant
3907 * @dev: network device
3908 * @bssid: bssid to which we want to associate
3909 * @req_ie: Request Information Element
3910 * @req_ie_len: len of the req IE
3911 * @resp_ie: Response IE
3912 * @resp_ie_len: len of ht response IE
3913 * @status: status
3914 * @gfp: Kernel Flag
3915 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
3916 *
3917 * The API is a wrapper to send connection status to supplicant
3918 *
3919 * Return: Void
3920 */
3921#if defined CFG80211_CONNECT_TIMEOUT
3922static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3923 struct cfg80211_bss *bss, const u8 *req_ie,
3924 size_t req_ie_len, const u8 *resp_ie,
3925 size_t resp_ie_len, int status, gfp_t gfp,
3926 bool connect_timeout)
3927{
3928 if (connect_timeout)
3929 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
3930 else
3931 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3932 resp_ie, resp_ie_len, status, gfp);
3933}
3934#else
3935static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3936 struct cfg80211_bss *bss, const u8 *req_ie,
3937 size_t req_ie_len, const u8 *resp_ie,
3938 size_t resp_ie_len, int status, gfp_t gfp,
3939 bool connect_timeout)
3940{
3941 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3942 resp_ie, resp_ie_len, status, gfp);
3943}
3944#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303945
3946/**
3947 * hdd_connect_result() - API to send connection status to supplicant
3948 * @dev: network device
3949 * @bssid: bssid to which we want to associate
3950 * @roam_info: information about connected bss
3951 * @req_ie: Request Information Element
3952 * @req_ie_len: len of the req IE
3953 * @resp_ie: Response IE
3954 * @resp_ie_len: len of ht response IE
3955 * @status: status
3956 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05303957 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
Anurag Chouhanc4092922016-09-08 15:56:11 +05303958 *
3959 * The API is a wrapper to send connection status to supplicant
3960 * and allow runtime suspend
3961 *
3962 * Return: Void
3963 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303964void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3965 tCsrRoamInfo *roam_info, const u8 *req_ie,
3966 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303967 size_t resp_ie_len, u16 status, gfp_t gfp,
3968 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303969{
3970 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3971 struct cfg80211_bss *bss = NULL;
3972
3973 if (WLAN_STATUS_SUCCESS == status) {
3974 struct ieee80211_channel *chan;
3975 int freq;
3976 int chan_no = roam_info->pBssDesc->channelId;
3977
3978 if (chan_no <= 14)
3979 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07003980 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303981 else
3982 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07003983 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303984
3985 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
3986 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
3987 roam_info->u.pConnectedProfile->SSID.ssId,
3988 roam_info->u.pConnectedProfile->SSID.length);
3989 }
Komal Seelama89be8d2016-09-29 11:09:26 +05303990
Abhishek Singha84d3952016-09-13 13:45:05 +05303991 hdd_connect_bss(dev, bssid, bss, req_ie,
3992 req_ie_len, resp_ie, resp_ie_len,
3993 status, gfp, connect_timeout);
Komal Seelama89be8d2016-09-29 11:09:26 +05303994
3995 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303996}
3997#else
3998void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3999 tCsrRoamInfo *roam_info, const u8 *req_ie,
4000 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304001 size_t resp_ie_len, u16 status, gfp_t gfp,
4002 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304003{
Komal Seelama89be8d2016-09-29 11:09:26 +05304004 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4005
Anurag Chouhanc4092922016-09-08 15:56:11 +05304006 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4007 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304008 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304009}
4010#endif
4011
4012
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304013QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004014{
4015 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304016 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 hdd_adapter_t *adapter;
4018#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304019 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020#endif
4021 eConnectionState connState;
4022
4023 ENTER();
4024
4025 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304026 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 adapter = adapterNode->pAdapter;
4028
Arun Khandavallifae92942016-08-01 13:31:08 +05304029 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304030 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032 hdd_wmm_init(adapter);
4033
4034 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004035 case QDF_STA_MODE:
4036 case QDF_P2P_CLIENT_MODE:
4037 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038
4039 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4040 ->conn_info.connState;
4041
4042 hdd_init_station_mode(adapter);
4043 /* Open the gates for HDD to receive Wext commands */
4044 adapter->isLinkUpSvcNeeded = false;
4045 adapter->scan_info.mScanPending = false;
4046
4047 /* Indicate disconnect event to supplicant if associated previously */
4048 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004049 eConnectionState_IbssConnected == connState ||
4050 eConnectionState_NotConnected == connState ||
4051 eConnectionState_IbssDisconnected == connState ||
4052 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053 union iwreq_data wrqu;
4054 memset(&wrqu, '\0', sizeof(wrqu));
4055 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4056 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4057 wireless_send_event(adapter->dev, SIOCGIWAP,
4058 &wrqu, NULL);
4059 adapter->sessionCtx.station.
4060 hdd_ReassocScenario = false;
4061
4062 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304063 wlan_hdd_cfg80211_indicate_disconnect(
4064 adapter->dev, false,
4065 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 } else if (eConnectionState_Connecting == connState) {
4067 /*
4068 * Indicate connect failure to supplicant if we were in the
4069 * process of connecting
4070 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304071 hdd_connect_result(adapter->dev, NULL, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072 NULL, 0, NULL, 0,
4073 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Abhishek Singha84d3952016-09-13 13:45:05 +05304074 GFP_KERNEL, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 }
4076
4077 hdd_register_tx_flow_control(adapter,
4078 hdd_tx_resume_timer_expired_handler,
4079 hdd_tx_resume_cb);
4080
4081 break;
4082
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004083 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 /* softAP can handle SSR */
4085 break;
4086
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004087 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004088#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07004089 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004090 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4091#else
Jeff Johnson5880d792016-08-15 13:32:30 -07004092 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093 /* event supplicant to restart */
4094 cfg80211_del_sta(adapter->dev,
4095 (const u8 *)&bcastMac.bytes[0],
4096 GFP_KERNEL);
4097#endif
4098 break;
4099
4100 default:
4101 break;
4102 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304103get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4105 adapterNode = pNext;
4106 }
4107
4108 EXIT();
4109
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304110 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111}
4112
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304113QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 hdd_adapter_list_node_t **padapterNode)
4115{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304116 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004117 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304118 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4119 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004120 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 return status;
4122}
4123
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304124QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004125 hdd_adapter_list_node_t *adapterNode,
4126 hdd_adapter_list_node_t **pNextAdapterNode)
4127{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304128 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004129 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304130 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4131 (qdf_list_node_t *) adapterNode,
4132 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004133
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004134 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 return status;
4136}
4137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304138QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 hdd_adapter_list_node_t *adapterNode)
4140{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304141 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004142 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304143 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004145 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146 return status;
4147}
4148
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304149QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 hdd_adapter_list_node_t **padapterNode)
4151{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304152 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004153 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304154 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4155 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004156 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 return status;
4158}
4159
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304160QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161 hdd_adapter_list_node_t *adapterNode)
4162{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304163 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004164 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304165 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4166 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004167 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168 return status;
4169}
4170
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304171QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172 hdd_adapter_list_node_t *adapterNode)
4173{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304174 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004175 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304176 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4177 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004178 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004179 return status;
4180}
4181
4182hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4183 tSirMacAddr macAddr)
4184{
4185 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4186 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304187 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188
4189 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4190
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304191 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192 adapter = adapterNode->pAdapter;
4193
4194 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304195 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004196 macAddr, sizeof(tSirMacAddr))) {
4197 return adapter;
4198 }
4199 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4200 adapterNode = pNext;
4201 }
4202
4203 return NULL;
4204
4205}
4206
4207hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4208 uint32_t vdev_id)
4209{
4210 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4211 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304212 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004213
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304214 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304216 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004217 adapter = adapterNode->pAdapter;
4218
4219 if (adapter->sessionId == vdev_id)
4220 return adapter;
4221
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304222 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004223 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4224 adapterNode = pNext;
4225 }
4226
Jeff Johnson5880d792016-08-15 13:32:30 -07004227 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004228
4229 return NULL;
4230}
4231
Abhishek Singh7996eb72015-12-30 17:24:02 +05304232/**
4233 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4234 * the sessionid
4235 * @hdd_ctx: hdd context.
4236 * @sme_session_id: sme session is for the adapter to get.
4237 *
4238 * This function is used to get the adapter with provided session id
4239 *
4240 * Return: adapter pointer if found
4241 *
4242 */
4243hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4244 uint32_t sme_session_id)
4245{
4246 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4247 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304248 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304249
4250
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304251 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304252
4253 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304254 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304255 adapter = adapter_node->pAdapter;
4256
4257 if (adapter &&
4258 adapter->sessionId == sme_session_id)
4259 return adapter;
4260
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304261 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304262 hdd_get_next_adapter(hdd_ctx,
4263 adapter_node, &next);
4264 adapter_node = next;
4265 }
4266 return NULL;
4267}
4268
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004269/**
4270 * hdd_get_adapter() - to get adapter matching the mode
4271 * @hdd_ctx: hdd context
4272 * @mode: adapter mode
4273 *
4274 * This routine will return the pointer to adapter matching
4275 * with the passed mode.
4276 *
4277 * Return: pointer to adapter or null
4278 */
4279hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4280 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004281{
4282 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4283 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304284 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285
4286 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4287
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304288 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289 adapter = adapterNode->pAdapter;
4290
4291 if (adapter && (mode == adapter->device_mode))
4292 return adapter;
4293
4294 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4295 adapterNode = pNext;
4296 }
4297
4298 return NULL;
4299
4300}
4301
4302/**
4303 * hdd_get_operating_channel() - return operating channel of the device mode
4304 * @hdd_ctx: Pointer to the HDD context.
4305 * @mode: Device mode for which operating channel is required.
4306 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004307 * QDF_STA_MODE,
4308 * QDF_P2P_CLIENT_MODE,
4309 * QDF_SAP_MODE,
4310 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311 *
4312 * This API returns the operating channel of the requested device mode
4313 *
4314 * Return: channel number. "0" id the requested device is not found OR it is
4315 * not connected.
4316 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004317uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4318 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004319{
4320 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304321 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 hdd_adapter_t *adapter;
4323 uint8_t operatingChannel = 0;
4324
4325 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4326
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304327 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004328 adapter = adapterNode->pAdapter;
4329
4330 if (mode == adapter->device_mode) {
4331 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004332 case QDF_STA_MODE:
4333 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 if (hdd_conn_is_connected
4335 (WLAN_HDD_GET_STATION_CTX_PTR
4336 (adapter))) {
4337 operatingChannel =
4338 (WLAN_HDD_GET_STATION_CTX_PTR
4339 (adapter))->conn_info.
4340 operationChannel;
4341 }
4342 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004343 case QDF_SAP_MODE:
4344 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 /* softap connection info */
4346 if (test_bit
4347 (SOFTAP_BSS_STARTED,
4348 &adapter->event_flags))
4349 operatingChannel =
4350 (WLAN_HDD_GET_AP_CTX_PTR
4351 (adapter))->operatingChannel;
4352 break;
4353 default:
4354 break;
4355 }
4356
4357 break; /* Found the device of interest. break the loop */
4358 }
4359
4360 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4361 adapterNode = pNext;
4362 }
4363 return operatingChannel;
4364}
4365
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304366static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 hdd_ctx)
4368{
4369 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304370 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004371 hdd_adapter_t *adapter;
4372
4373 ENTER();
4374
4375 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4376
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304377 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004379 if ((adapter->device_mode == QDF_STA_MODE) ||
4380 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4381 (adapter->device_mode == QDF_IBSS_MODE) ||
4382 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4383 (adapter->device_mode == QDF_SAP_MODE) ||
4384 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385 wlan_hdd_cfg80211_deregister_frames(adapter);
4386 hdd_unregister_wext(adapter->dev);
4387 }
4388 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4389 adapterNode = pNext;
4390 }
4391
4392 EXIT();
4393
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304394 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395}
4396
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304397QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398{
4399 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304400 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 hdd_adapter_t *adapter;
4402
4403 ENTER();
4404
4405 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4406
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304407 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004409 if ((adapter->device_mode == QDF_STA_MODE) ||
4410 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4411 (adapter->device_mode == QDF_IBSS_MODE) ||
4412 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4413 (adapter->device_mode == QDF_SAP_MODE) ||
4414 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05304416 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 eCSR_SCAN_ABORT_DEFAULT);
4418 }
4419 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4420 adapterNode = pNext;
4421 }
4422
4423 EXIT();
4424
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304425 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426}
4427
Dustin Brownf27bce82016-11-03 12:52:27 -07004428/**
4429 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4430 * adapters
4431 * @hdd_ctx: The HDD context containing the adapters to operate on
4432 *
4433 * return: QDF_STATUS_SUCCESS
4434 */
4435static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4436{
4437 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4438 QDF_STATUS status;
4439 hdd_adapter_t *adapter;
4440 int err;
4441
4442 ENTER();
4443
4444 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4445
4446 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4447 adapter = adapter_node->pAdapter;
4448 if ((adapter->device_mode == QDF_STA_MODE) ||
4449 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4450 (adapter->device_mode == QDF_IBSS_MODE) ||
4451 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4452 (adapter->device_mode == QDF_SAP_MODE) ||
4453 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4454 err = wlan_hdd_sched_scan_stop(adapter->dev);
4455 if (err)
4456 hdd_err("Unable to stop scheduled scan");
4457 }
4458 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node);
4459 adapter_node = next_node;
4460 }
4461
4462 EXIT();
4463
4464 return QDF_STATUS_SUCCESS;
4465}
4466
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004467#ifdef WLAN_NS_OFFLOAD
4468/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004469 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470 * @hdd_ctx: Pointer to hdd context
4471 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004472 * Unregister for IPv6 address change notifications.
4473 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 * Return: None
4475 */
4476static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4477{
4478 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4479
4480 return;
4481}
4482
4483/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004484 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485 * @hdd_ctx: Pointer to hdd context
4486 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004487 * Register for IPv6 address change notifications.
4488 *
4489 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004491static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492{
4493 int ret;
4494
4495 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4496 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004497 if (ret) {
4498 hdd_err("Failed to register IPv6 notifier: %d", ret);
4499 goto out;
4500 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004501
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004502 hdd_info("Registered IPv6 notifier");
4503out:
4504 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505}
4506#else
4507/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004508 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 * @hdd_ctx: Pointer to hdd context
4510 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004511 * Unregister for IPv6 address change notifications.
4512 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513 * Return: None
4514 */
4515static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4516{
4517}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004518
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004520 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 * @hdd_ctx: Pointer to hdd context
4522 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004523 * Register for IPv6 address change notifications.
4524 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525 * Return: None
4526 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004527static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004529 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530}
4531#endif
4532
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304533#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4534/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004535 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304536 * @hdd_ctx: HDD context
4537 *
4538 * Activates the logging service
4539 *
4540 * Return: Zero in case of success, negative value otherwise
4541 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004542static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304543{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004544 int ret;
4545 struct hdd_config *config = hdd_ctx->config;
4546
4547 if (!config->wlanLoggingEnable)
4548 return 0;
4549
4550 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4551 config->wlanLoggingNumBuf);
4552 if (ret)
4553 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4554 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304555}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004556
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304557/**
4558 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4559 * @hdd_ctx: HDD context
4560 *
4561 * Deactivates the logging service
4562 *
4563 * Return: 0 on deactivating the logging service
4564 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004565static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304566{
4567 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4568 return wlan_logging_sock_deactivate_svc();
4569
4570 return 0;
4571}
4572#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004573static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304574{
4575 return 0;
4576}
4577
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004578static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304579{
4580 return 0;
4581}
4582#endif
4583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004584/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004585 * hdd_register_notifiers - Register netdev notifiers.
4586 * @hdd_ctx: HDD context
4587 *
4588 * Register netdev notifiers like IPv4 and IPv6.
4589 *
4590 * Return: 0 on success and errno on failure
4591 */
4592static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4593{
4594 int ret;
4595
4596 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4597 if (ret) {
4598 hdd_err("register_netdevice_notifier failed: %d", ret);
4599 goto out;
4600 }
4601
4602 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4603 if (ret)
4604 goto unregister_notifier;
4605
4606 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4607 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4608 if (ret) {
4609 hdd_err("Failed to register IPv4 notifier: %d", ret);
4610 goto unregister_ip6_notifier;
4611 }
4612
4613 return 0;
4614
4615unregister_ip6_notifier:
4616 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4617unregister_notifier:
4618 unregister_netdevice_notifier(&hdd_netdev_notifier);
4619out:
4620 return ret;
4621
4622}
4623
4624/**
4625 * hdd_unregister_notifiers - Unregister netdev notifiers.
4626 * @hdd_ctx: HDD context
4627 *
4628 * Unregister netdev notifiers like IPv4 and IPv6.
4629 *
4630 * Return: None.
4631 */
4632static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4633{
4634 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4635
4636 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4637
4638 unregister_netdevice_notifier(&hdd_netdev_notifier);
4639}
4640
4641/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004642 * hdd_exit_netlink_services - Exit netlink services
4643 * @hdd_ctx: HDD context
4644 *
4645 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4646 * nl service.
4647 *
4648 * Return: None.
4649 */
4650static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4651{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004652 hdd_close_cesium_nl_sock();
4653
4654 ptt_sock_deactivate_svc();
4655
4656 nl_srv_exit();
4657}
4658
4659/**
4660 * hdd_init_netlink_services- Init netlink services
4661 * @hdd_ctx: HDD context
4662 *
4663 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4664 * nl service.
4665 *
4666 * Return: 0 on success and errno on failure.
4667 */
4668static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4669{
4670 int ret;
4671
Ryan Hsuceddceb2016-04-28 10:20:14 -07004672 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004673 if (ret) {
4674 hdd_alert("nl_srv_init failed: %d", ret);
4675 goto out;
4676 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004677 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004678
4679 ret = oem_activate_service(hdd_ctx);
4680 if (ret) {
4681 hdd_alert("oem_activate_service failed: %d", ret);
4682 goto err_nl_srv;
4683 }
4684
4685 ret = ptt_sock_activate_svc();
4686 if (ret) {
4687 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4688 goto err_nl_srv;
4689 }
4690
4691 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004692 if (ret)
4693 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004694
4695 ret = cnss_diag_activate_service();
4696 if (ret) {
4697 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4698 goto err_close_cesium;
4699 }
4700
4701 return 0;
4702
4703err_close_cesium:
4704 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004705 ptt_sock_deactivate_svc();
4706err_nl_srv:
4707 nl_srv_exit();
4708out:
4709 return ret;
4710}
4711
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004712/**
4713 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4714 * @hdd_ctx: HDD context.
4715 *
4716 * Destroy RX wakelock.
4717 *
4718 * Return: None.
4719 */
4720static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4721{
4722 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4723}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004724
4725/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004726 * hdd_rx_wake_lock_create() - Create RX wakelock
4727 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004728 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004729 * Create RX wakelock.
4730 *
4731 * Return: None.
4732 */
4733static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4734{
4735 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4736}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004737
4738/**
4739 * hdd_roc_context_init() - Init ROC context
4740 * @hdd_ctx: HDD context.
4741 *
4742 * Initialize ROC context.
4743 *
4744 * Return: 0 on success and errno on failure.
4745 */
4746static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4747{
4748 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4749 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4750
4751 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4752
4753 return 0;
4754}
4755
4756/**
4757 * hdd_roc_context_destroy() - Destroy ROC context
4758 * @hdd_ctx: HDD context.
4759 *
4760 * Destroy roc list and flush the pending roc work.
4761 *
4762 * Return: None.
4763 */
4764static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4765{
4766 flush_delayed_work(&hdd_ctx->roc_req_work);
4767 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08004768 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004769}
4770
4771/**
Houston Hoffman160db392016-10-10 17:37:51 -07004772 * hdd_context_deinit() - Deinitialize HDD context
4773 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004774 *
Houston Hoffman160db392016-10-10 17:37:51 -07004775 * Deinitialize HDD context along with all the feature specific contexts but
4776 * do not free hdd context itself. Caller of this API is supposed to free
4777 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004778 *
Houston Hoffman160db392016-10-10 17:37:51 -07004779 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004780 */
Houston Hoffman160db392016-10-10 17:37:51 -07004781static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004782{
Houston Hoffman160db392016-10-10 17:37:51 -07004783 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004784
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004785 hdd_roc_context_destroy(hdd_ctx);
4786
4787 hdd_sap_context_destroy(hdd_ctx);
4788
4789 hdd_rx_wake_lock_destroy(hdd_ctx);
4790
4791 hdd_tdls_context_destroy(hdd_ctx);
4792
4793 hdd_scan_context_destroy(hdd_ctx);
4794
4795 qdf_list_destroy(&hdd_ctx->hddAdapters);
4796
Houston Hoffman160db392016-10-10 17:37:51 -07004797 return 0;
4798}
4799
4800/**
4801 * hdd_context_destroy() - Destroy HDD context
4802 * @hdd_ctx: HDD context to be destroyed.
4803 *
4804 * Free config and HDD context as well as destroy all the resources.
4805 *
4806 * Return: None
4807 */
4808static void hdd_context_destroy(hdd_context_t *hdd_ctx)
4809{
4810 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
4811 hdd_logging_sock_deactivate_svc(hdd_ctx);
4812
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05304813 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
4814
Houston Hoffman160db392016-10-10 17:37:51 -07004815 hdd_context_deinit(hdd_ctx);
4816
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304817 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004818 hdd_ctx->config = NULL;
4819
4820 wiphy_free(hdd_ctx->wiphy);
4821}
4822
4823/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824 * hdd_wlan_exit() - HDD WLAN exit function
4825 * @hdd_ctx: Pointer to the HDD Context
4826 *
4827 * This is the driver exit point (invoked during rmmod)
4828 *
4829 * Return: None
4830 */
Jeff Johnson590e2012016-10-05 16:16:24 -07004831static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832{
4833 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304834 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004835 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304836 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837
4838 ENTER();
4839
Arun Khandavallifae92942016-08-01 13:31:08 +05304840 if (QDF_TIMER_STATE_RUNNING ==
4841 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4842 hdd_info("Stpp interface change timer");
4843 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004844 }
4845
Arun Khandavallifae92942016-08-01 13:31:08 +05304846 if (!QDF_IS_STATUS_SUCCESS
4847 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4848 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004849
Arun Khandavallifae92942016-08-01 13:31:08 +05304850
4851 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004852
Nitesh Shah61c10d92016-10-19 19:29:15 +05304853 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
4854
Prashanth Bhattaab004382016-10-11 16:08:11 -07004855 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004856
4857#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304858 if (QDF_TIMER_STATE_RUNNING ==
4859 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4860 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861 }
4862
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304863 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304864 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004865 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 }
Liangwei Dongaef84342016-10-21 05:28:00 -04004867 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4868 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4869 hdd_ctx->last_acs_channel_list = NULL;
4870 hdd_ctx->num_of_channels = 0;
4871 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873
Arun Khandavallifae92942016-08-01 13:31:08 +05304874 mutex_lock(&hdd_ctx->iface_change_lock);
4875 driver_status = hdd_ctx->driver_status;
4876 mutex_unlock(&hdd_ctx->iface_change_lock);
4877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878 /*
4879 * Powersave Offload Case
4880 * Disable Idle Power Save Mode
4881 */
4882 hdd_set_idle_ps_config(hdd_ctx, false);
4883
Arun Khandavallifae92942016-08-01 13:31:08 +05304884 if (driver_status != DRIVER_MODULES_CLOSED) {
4885 hdd_unregister_wext_all_adapters(hdd_ctx);
4886 /*
4887 * Cancel any outstanding scan requests. We are about to close
4888 * all of our adapters, but an adapter structure is what SME
4889 * passes back to our callback function. Hence if there
4890 * are any outstanding scan requests then there is a
4891 * race condition between when the adapter is closed and
4892 * when the callback is invoked. We try to resolve that
4893 * race condition here by canceling any outstanding scans
4894 * before we close the adapters.
4895 * Note that the scans may be cancelled in an asynchronous
4896 * manner, so ideally there needs to be some kind of
4897 * synchronization. Rather than introduce a new
4898 * synchronization here, we will utilize the fact that we are
4899 * about to Request Full Power, and since that is synchronized,
4900 * the expectation is that by the time Request Full Power has
4901 * completed, all scans will be cancelled
4902 */
4903 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07004904 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05304905 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906 }
4907
4908 /*
4909 * Close the scheduler before calling cds_close to make sure no thread
4910 * is scheduled after the each module close is called i.e after all the
4911 * data structures are freed.
4912 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304913 qdf_status = cds_sched_close(p_cds_context);
4914 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004915 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304916 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05304919 hdd_wlan_stop_modules(hdd_ctx);
4920
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304921 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4922 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4923 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925 /*
4926 * Close CDS
4927 * This frees pMac(HAL) context. There should not be any call
4928 * that requires pMac access after this.
4929 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07004931 hdd_green_ap_deinit(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932
Komal Seelam8634b772016-09-29 12:12:24 +05304933 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004934 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935
4936 hdd_ipa_cleanup(hdd_ctx);
4937
4938 /* Free up RoC request queue and flush workqueue */
4939 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304941 wlansap_global_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004942 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304943 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004944
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07004945 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004946
Arun Khandavallifae92942016-08-01 13:31:08 +05304947 hdd_exit_netlink_services(hdd_ctx);
4948 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004949 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004950}
4951
4952void __hdd_wlan_exit(void)
4953{
4954 hdd_context_t *hdd_ctx;
4955
4956 ENTER();
4957
Anurag Chouhan6d760662016-02-20 16:05:43 +05304958 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004960 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004961 EXIT();
4962 return;
4963 }
4964
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004965 /* Check IPA HW Pipe shutdown */
4966 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4967
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004968 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05304969 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004970
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 /* Do all the cleanup before deregistering the driver */
4972 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004973
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004974 EXIT();
4975}
4976
4977#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04004978/**
4979 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
4980 * @data: pointer to hdd_context_t
4981 *
4982 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
4983 * Then new ACS request will do a fresh scan without reusing the cached
4984 * scan information.
4985 *
4986 * Return: void
4987 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004988void hdd_skip_acs_scan_timer_handler(void *data)
4989{
4990 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4991
Jeff Johnson760350b2016-08-15 14:01:52 -07004992 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04004994 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4995 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4996 hdd_ctx->last_acs_channel_list = NULL;
4997 hdd_ctx->num_of_channels = 0;
4998 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999
5000 if (!hdd_ctx->hHal)
5001 return;
5002 sme_scan_flush_result(hdd_ctx->hHal);
5003}
5004#endif
5005
5006#ifdef QCA_HT_2040_COEX
5007/**
5008 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5009 * @adapter: pointer to adapter
5010 * @staId: station id
5011 * @macAddrSTA: station MAC address
5012 * @channel_type: channel type
5013 *
5014 * This function notifies FW with HT20/HT40 mode
5015 *
5016 * Return: 0 if successful, error number otherwise
5017 */
5018int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305019 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020{
5021 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305022 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023 hdd_context_t *hdd_ctx = NULL;
5024
5025 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5026
5027 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305028 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305030
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031 if (!hdd_ctx->hHal)
5032 return -EINVAL;
5033
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305034 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005035 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305036 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005037 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038 return -EINVAL;
5039 }
5040
5041 return 0;
5042}
5043#endif
5044
5045/**
5046 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5047 * @state: state
5048 *
5049 * This function notifies FW with modem power status
5050 *
5051 * Return: 0 if successful, error number otherwise
5052 */
5053int hdd_wlan_notify_modem_power_state(int state)
5054{
5055 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305056 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057 hdd_context_t *hdd_ctx;
5058
Anurag Chouhan6d760662016-02-20 16:05:43 +05305059 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005060 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305061 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305063
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 if (!hdd_ctx->hHal)
5065 return -EINVAL;
5066
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305067 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5068 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005069 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005070 state);
5071 return -EINVAL;
5072 }
5073 return 0;
5074}
5075
5076/**
5077 *
5078 * hdd_post_cds_enable_config() - HDD post cds start config helper
5079 * @adapter - Pointer to the HDD
5080 *
5081 * Return: None
5082 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305083QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005084{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305085 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005086
5087 /*
5088 * Send ready indication to the HDD. This will kick off the MAC
5089 * into a 'running' state and should kick off an initial scan.
5090 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305091 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5092 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005093 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5094 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305095 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005096 }
5097
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305098 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099}
5100
5101/* wake lock APIs for HDD */
5102void hdd_prevent_suspend(uint32_t reason)
5103{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305104 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005105}
5106
5107void hdd_allow_suspend(uint32_t reason)
5108{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305109 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005110}
5111
5112void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5113{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305114 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5115 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005116}
5117
5118/**
5119 * hdd_exchange_version_and_caps() - exchange version and capability with target
5120 * @hdd_ctx: Pointer to HDD context
5121 *
5122 * This is the HDD function to exchange version and capability information
5123 * between Host and Target
5124 *
5125 * This function gets reported version of FW.
5126 * It also finds the version of target headers used to compile the host;
5127 * It compares the above two and prints a warning if they are different;
5128 * It gets the SW and HW version string;
5129 * Finally, it exchanges capabilities between host and target i.e. host
5130 * and target exchange a msg indicating the features they support through a
5131 * bitmap
5132 *
5133 * Return: None
5134 */
5135void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5136{
5137
5138 tSirVersionType versionCompiled;
5139 tSirVersionType versionReported;
5140 tSirVersionString versionString;
5141 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305142 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143
5144 memset(&versionCompiled, 0, sizeof(versionCompiled));
5145 memset(&versionReported, 0, sizeof(versionReported));
5146
5147 /* retrieve and display WCNSS version information */
5148 do {
5149
5150 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5151 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305152 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005153 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005154 break;
5155 }
5156
5157 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5158 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305159 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005160 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005161 break;
5162 }
5163
5164 if ((versionCompiled.major != versionReported.major) ||
5165 (versionCompiled.minor != versionReported.minor) ||
5166 (versionCompiled.version != versionReported.version) ||
5167 (versionCompiled.revision != versionReported.revision)) {
5168 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5169 "Host expected %u.%u.%u.%u\n",
5170 WLAN_MODULE_NAME,
5171 (int)versionReported.major,
5172 (int)versionReported.minor,
5173 (int)versionReported.version,
5174 (int)versionReported.revision,
5175 (int)versionCompiled.major,
5176 (int)versionCompiled.minor,
5177 (int)versionCompiled.version,
5178 (int)versionCompiled.revision);
5179 } else {
5180 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5181 WLAN_MODULE_NAME,
5182 (int)versionReported.major,
5183 (int)versionReported.minor,
5184 (int)versionReported.version,
5185 (int)versionReported.revision);
5186 }
5187
5188 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5189 versionString,
5190 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305191 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005192 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005193 break;
5194 }
5195
5196 pr_info("%s: WCNSS software version %s\n",
5197 WLAN_MODULE_NAME, versionString);
5198
5199 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5200 versionString,
5201 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305202 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005203 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005204 break;
5205 }
5206
5207 pr_info("%s: WCNSS hardware version %s\n",
5208 WLAN_MODULE_NAME, versionString);
5209
5210 /*
5211 * 1.Check if FW version is greater than 0.1.1.0. Only then
5212 * send host-FW capability exchange message
5213 * 2.Host-FW capability exchange message is only present on
5214 * target 1.1 so send the message only if it the target is 1.1
5215 * minor numbers for different target branches:
5216 * 0 -> (1.0)Mainline Build
5217 * 1 -> (1.1)Mainline Build
5218 * 2->(1.04) Stability Build
5219 */
5220 if (((versionReported.major > 0) || (versionReported.minor > 1)
5221 || ((versionReported.minor >= 1)
5222 && (versionReported.version >= 1)))
5223 && ((versionReported.major == 1)
5224 && (versionReported.minor >= 1)))
5225 fwFeatCapsMsgSupported = 1;
5226
5227 if (fwFeatCapsMsgSupported) {
5228 /*
5229 * Indicate if IBSS heartbeat monitoring needs to be
5230 * offloaded
5231 */
5232 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5233 sme_disable_feature_capablity
5234 (IBSS_HEARTBEAT_OFFLOAD);
5235 }
5236
5237 sme_feature_caps_exchange(hdd_ctx->hHal);
5238 }
5239
5240 } while (0);
5241
5242}
5243
5244/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305245QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246{
5247 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5248 hdd_ctx->reg.cc_src);
5249}
5250
5251/**
5252 * hdd_is_5g_supported() - check if hardware supports 5GHz
5253 * @hdd_ctx: Pointer to the hdd context
5254 *
5255 * HDD function to know if hardware supports 5GHz
5256 *
5257 * Return: true if hardware supports 5GHz
5258 */
5259bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5260{
zdingf54169a2016-10-12 17:08:45 +08005261 if (!hdd_ctx || !hdd_ctx->config)
5262 return true;
5263
5264 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5265 return true;
5266 else
5267 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268}
5269
Amar Singhale4f28ee2015-10-21 14:36:56 -07005270static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005271{
5272 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005273 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005274
5275 wiphy = hdd_ctx->wiphy;
5276
5277 /*
5278 * The channel information in
5279 * wiphy needs to be initialized before wiphy registration
5280 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005281 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5282 if (ret_val) {
5283 hdd_alert("regulatory init failed");
5284 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 }
5286
5287#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5288 wiphy->wowlan = &wowlan_support_reg_init;
5289#else
5290 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5291 WIPHY_WOWLAN_MAGIC_PKT |
5292 WIPHY_WOWLAN_DISCONNECT |
5293 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5294 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5295 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5296 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5297 WIPHY_WOWLAN_RFKILL_RELEASE;
5298
5299 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5300 WOW_MAX_FILTERS_PER_LIST);
5301 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5302 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5303#endif
5304
5305 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005306 ret_val = wlan_hdd_cfg80211_register(wiphy);
5307 if (0 > ret_val)
5308 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309
Amar Singhale4f28ee2015-10-21 14:36:56 -07005310 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005311}
5312
Ravi Joshie2331e82015-07-01 18:18:54 -07005313/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005314 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005315 * @hdd_ctx - handle to hdd context
5316 * @tx_packets - transmit packet count
5317 * @rx_packets - receive packet count
5318 *
5319 * The function controls the bus bandwidth and dynamic control of
5320 * tcp delayed ack configuration
5321 *
5322 * Returns: None
5323 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005325static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5326 const uint64_t tx_packets,
5327 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005330 uint64_t temp_rx = 0;
5331 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005332 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005333 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5334 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005335 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005337 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005338 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005339 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005340 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005341 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005342 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005343 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005344 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005345
Mohit Khannae71e2262015-11-10 09:37:24 -08005346 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5347 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348
5349 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005350 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5351 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005353 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305354 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305355 if (hdd_ctx->hbw_requested) {
5356 pld_remove_pm_qos(hdd_ctx->parent_dev);
5357 hdd_ctx->hbw_requested = false;
5358 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305359 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005360 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305361 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305362 if (!hdd_ctx->hbw_requested) {
5363 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5364 hdd_ctx->hbw_requested = true;
5365 }
5366
Nirav Shah3bbfa512016-05-12 16:43:49 +05305367 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005368 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305369 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005370 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005372
5373 /* fine-tuning parameters for RX Flows */
5374 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 hdd_ctx->prev_rx = rx_packets;
Ravi Joshifed83572016-10-07 16:20:37 -07005377 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5378 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5379 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5380 next_rx_level = WLAN_SVC_TP_HIGH;
5381 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005382 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005383 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005384 hdd_ctx->rx_high_ind_cnt = 0;
5385 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386
Mohit Khannae71e2262015-11-10 09:37:24 -08005387 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5388 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389
5390 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005391 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005392 next_rx_level, temp_rx);
5393 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005394 /* Send throughput indication only if it is enabled.
5395 * Disabling tcp_del_ack will revert the tcp stack behavior
5396 * to default delayed ack. Note that this will disable the
5397 * dynamic delayed ack mechanism across the system
5398 */
5399 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305400 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5401 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402 &next_rx_level,
5403 sizeof(next_rx_level));
5404 }
5405
Mohit Khannae71e2262015-11-10 09:37:24 -08005406 /* fine-tuning parameters for TX Flows */
5407 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5408 hdd_ctx->prev_tx = tx_packets;
5409 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5410 next_tx_level = WLAN_SVC_TP_HIGH;
5411 else
5412 next_tx_level = WLAN_SVC_TP_LOW;
5413
5414 if (hdd_ctx->cur_tx_level != next_tx_level) {
5415 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5416 next_tx_level, temp_tx);
5417 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305418 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5419 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005420 &next_tx_level,
5421 sizeof(next_tx_level));
5422 }
5423
5424 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5425 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 hdd_ctx->hdd_txrx_hist_idx++;
5427 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428}
5429
5430#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305431static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305433 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5434 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305436 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305437 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5438 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 uint64_t total_tx = 0, total_rx = 0;
5440 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305441 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305442 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 bool connected = false;
5444 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5445
Prashanth Bhattaab004382016-10-11 16:08:11 -07005446 if (wlan_hdd_validate_context(hdd_ctx))
5447 return;
5448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305450 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005451 status =
5452 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5453
5454 if (adapterNode->pAdapter == NULL)
5455 continue;
5456 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305457 /*
5458 * Validate magic so we don't end up accessing
5459 * an invalid adapter.
5460 */
5461 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5462 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005463
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005464 if ((adapter->device_mode == QDF_STA_MODE ||
5465 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005466 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5467 != eConnectionState_Associated) {
5468
5469 continue;
5470 }
5471
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005472 if ((adapter->device_mode == QDF_SAP_MODE ||
5473 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5475
5476 continue;
5477 }
5478
5479 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5480 adapter->prev_tx_packets);
5481 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5482 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305483
5484 if (adapter->device_mode == QDF_SAP_MODE ||
5485 adapter->device_mode == QDF_P2P_GO_MODE ||
5486 adapter->device_mode == QDF_IBSS_MODE) {
5487
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08005488 ret = cdp_get_intra_bss_fwd_pkts_count(
5489 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305490 adapter->sessionId,
5491 &fwd_tx_packets, &fwd_rx_packets);
5492 if (ret == A_OK) {
5493 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5494 fwd_tx_packets,
5495 adapter->prev_fwd_tx_packets);
5496 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5497 fwd_tx_packets,
5498 adapter->prev_fwd_rx_packets);
5499 }
5500 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501
5502 total_rx += adapter->stats.rx_packets;
5503 total_tx += adapter->stats.tx_packets;
5504
5505 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5506 adapter->prev_tx_packets = adapter->stats.tx_packets;
5507 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305508 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5509 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005510 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5511 connected = true;
5512 }
5513
5514 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5515 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5516 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5517 rx_packets;
5518 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5519 tx_packets;
5520
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305521 /* add intra bss forwarded tx and rx packets */
5522 tx_packets += fwd_tx_packets_diff;
5523 rx_packets += fwd_rx_packets_diff;
5524
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5526 tx_packets += (uint64_t)ipa_tx_packets;
5527 rx_packets += (uint64_t)ipa_rx_packets;
5528
5529 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005530 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 return;
5532 }
5533
Yuanyuan Liu13738502016-04-06 17:41:37 -07005534 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535
5536 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5537 hdd_ipa_uc_stat_request(adapter, 2);
5538
Dustin Brown2ed60362017-01-18 12:25:50 -08005539 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08005540 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08005541 if (hdd_ctx->bus_bw_timer_running)
Dustin Brownfce08d12017-01-17 16:29:38 -08005542 qdf_timer_start(&hdd_ctx->bus_bw_timer,
5543 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08005544 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005545}
Prashanth Bhattaab004382016-10-11 16:08:11 -07005546
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305547/**
5548 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
5549 * @arg: Argument of timer function
5550 *
5551 * Schedule a workqueue in this function where all the processing is done.
5552 *
5553 * Return: None.
5554 */
5555static void __hdd_bus_bw_cbk(void *arg)
5556{
5557 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
5558
5559 if (wlan_hdd_validate_context(hdd_ctx))
5560 return;
5561
5562 schedule_work(&hdd_ctx->bus_bw_work);
5563}
5564
5565/**
5566 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
5567 * @arg: Argument of timer function
5568 *
5569 * Return: None.
5570 */
5571static void hdd_bus_bw_cbk(void *arg)
5572{
5573 cds_ssr_protect(__func__);
5574 __hdd_bus_bw_cbk(arg);
5575 cds_ssr_unprotect(__func__);
5576}
5577
Prashanth Bhattaab004382016-10-11 16:08:11 -07005578int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
5579{
5580 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305581 INIT_WORK(&hdd_ctx->bus_bw_work,
5582 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08005583 hdd_ctx->bus_bw_timer_running = false;
5584 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305585 qdf_timer_init(NULL,
5586 &hdd_ctx->bus_bw_timer,
5587 hdd_bus_bw_cbk, (void *)hdd_ctx,
5588 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005589
5590 return 0;
5591}
5592
5593void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
5594{
Dustin Brownfce08d12017-01-17 16:29:38 -08005595 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07005596 hdd_reset_tcp_delack(hdd_ctx);
5597
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305598 hdd_info("wait for bus bw work to flush");
5599 cancel_work_sync(&hdd_ctx->bus_bw_work);
5600 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08005601 hdd_ctx->bus_bw_timer_running = false;
5602 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005603}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604#endif
5605
5606/**
Nirav Shahed34b212016-04-25 10:59:16 +05305607 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5608 * @hdd_ctx: hdd context
5609 *
5610 * Return: 0 for success or error code
5611 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005612static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305613{
5614 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5615 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5616 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005617 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305618 return -ENOMEM;
5619 }
5620 return 0;
5621}
5622
5623/**
5624 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5625 * @hdd_ctx: hdd context
5626 *
5627 * Return: none
5628 */
5629void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5630{
5631 if (hdd_ctx->hdd_txrx_hist) {
5632 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5633 hdd_ctx->hdd_txrx_hist = NULL;
5634 }
5635}
5636
Nirav Shahda008342016-05-17 18:50:40 +05305637static uint8_t *convert_level_to_string(uint32_t level)
5638{
5639 switch (level) {
5640 /* initialize the wlan sub system */
5641 case WLAN_SVC_TP_NONE:
5642 return "NONE";
5643 case WLAN_SVC_TP_LOW:
5644 return "LOW";
5645 case WLAN_SVC_TP_MEDIUM:
5646 return "MED";
5647 case WLAN_SVC_TP_HIGH:
5648 return "HIGH";
5649 default:
5650 return "INVAL";
5651 }
5652}
5653
Nirav Shahed34b212016-04-25 10:59:16 +05305654
5655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5657 * @hdd_ctx: hdd context
5658 *
5659 * Return: none
5660 */
5661void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5662{
5663 int i;
5664
5665#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005666 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305667 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005668 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005669 hdd_ctx->config->busBandwidthHighThreshold,
5670 hdd_ctx->config->busBandwidthMediumThreshold,
5671 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005672 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305673 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005674 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005675 hdd_ctx->config->tcpDelackThresholdHigh,
5676 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005677 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305678 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005679#endif
5680
Jeff Johnson760350b2016-08-15 14:01:52 -07005681 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305682 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5683
Jeff Johnson760350b2016-08-15 14:01:52 -07005684 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 -08005685
5686 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005687 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005688 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5689 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5690 hdd_ctx->hdd_txrx_hist[i].total_tx,
5691 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305692 convert_level_to_string(
5693 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5694 convert_level_to_string(
5695 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5696 convert_level_to_string(
5697 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005698 }
5699 return;
5700}
5701
5702/**
5703 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5704 * @hdd_ctx: hdd context
5705 *
5706 * Return: none
5707 */
5708void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5709{
5710 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305711 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5712 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005713}
5714
5715/**
5716 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5717 * @pHddCtx: hdd context
5718 *
5719 * Return: none
5720 */
5721void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5722{
5723
5724 hdd_adapter_t *adapter = NULL;
5725 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305726 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305728 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005729
5730 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305731 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005732 adapter = adapter_node->pAdapter;
5733
Jeff Johnson760350b2016-08-15 14:01:52 -07005734 hdd_err("\nNetif queue operation statistics:");
5735 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305736 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005737 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305738 curr_time = qdf_system_ticks();
5739 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305740 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305741 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305742 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305743 unpause = adapter->total_unpause_time;
5744 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305745 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305746 pause = adapter->total_pause_time;
5747 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005748 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305749 qdf_system_ticks_to_msecs(total),
5750 qdf_system_ticks_to_msecs(pause),
5751 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005752 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753
Nirav Shahda008342016-05-17 18:50:40 +05305754 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5755 qdf_time_t pause_delta = 0;
5756
5757 if (adapter->pause_map & (1 << i))
5758 pause_delta = delta;
5759
Jeff Johnson760350b2016-08-15 14:01:52 -07005760 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761 hdd_reason_type_to_string(i),
5762 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305763 adapter->queue_oper_stats[i].unpause_count,
5764 qdf_system_ticks_to_msecs(
5765 adapter->queue_oper_stats[i].total_pause_time +
5766 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 }
5768
Jeff Johnson760350b2016-08-15 14:01:52 -07005769 hdd_err("\nNetif queue operation history:");
5770 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305771 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5772
Jeff Johnson760350b2016-08-15 14:01:52 -07005773 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005774
5775 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005776 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305777 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778 adapter->queue_oper_history[i].time),
5779 hdd_action_type_to_string(
5780 adapter->queue_oper_history[i].netif_action),
5781 hdd_reason_type_to_string(
5782 adapter->queue_oper_history[i].netif_reason),
5783 adapter->queue_oper_history[i].pause_map);
5784 }
5785
5786 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5787 adapter_node = next;
5788 }
5789
5790
5791}
5792
5793/**
5794 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5795 * @hdd_ctx: hdd context
5796 *
5797 * Return: none
5798 */
5799void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5800{
5801 hdd_adapter_t *adapter = NULL;
5802 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305803 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005804
5805 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305806 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005807 adapter = adapter_node->pAdapter;
5808
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305809 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005810 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305811 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005812 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305813 adapter->history_index = 0;
5814 adapter->start_time = adapter->last_time = qdf_system_ticks();
5815 adapter->total_pause_time = 0;
5816 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5818 adapter_node = next;
5819 }
5820}
5821
5822/**
5823 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5824 * @halHandle: Hal handle
5825 * @pContext: Pointer to the context
5826 * @sessionId: Session ID
5827 * @scanId: Scan ID
5828 * @status: Status
5829 *
5830 * This is the callback to be executed when 11d scan is completed to flush out
5831 * the scan results
5832 *
5833 * 11d scan is done during driver load and is a passive scan on all
5834 * channels supported by the device, 11d scans may find some APs on
5835 * frequencies which are forbidden to be used in the regulatory domain
5836 * the device is operating in. If these APs are notified to the supplicant
5837 * it may try to connect to these APs, thus flush out all the scan results
5838 * which are present in SME after 11d scan is done.
5839 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305840 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305842static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005843 uint8_t sessionId, uint32_t scanId,
5844 eCsrScanStatus status)
5845{
5846 ENTER();
5847
5848 sme_scan_flush_result(halHandle);
5849
5850 EXIT();
5851
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305852 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853}
5854
5855#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5856/**
5857 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5858 * @hdd_ctx: hdd global context
5859 *
5860 * Return: none
5861 */
5862static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5863{
5864 uint8_t i;
5865
5866 mutex_init(&hdd_ctx->op_ctx.op_lock);
5867 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5868 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5869 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5870 }
5871}
5872#else
5873static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5874{
5875}
5876#endif
5877
Yingying Tang95409972016-10-20 15:16:15 +08005878#ifdef WLAN_FEATURE_WOW_PULSE
5879/**
5880 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
5881 * @phddctx: hdd_context_t structure pointer
5882 * @enable: enable or disable this behaviour
5883 *
5884 * Return: int
5885 */
5886static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
5887{
5888 struct hdd_config *pcfg_ini = phddctx->config;
5889 struct wow_pulse_mode wow_pulse_set_info;
5890 QDF_STATUS status;
5891
5892 hdd_notice("wow pulse enable flag is %d", enable);
5893
5894 if (false == phddctx->config->wow_pulse_support)
5895 return 0;
5896
5897 /* prepare the request to send to SME */
5898 if (enable == true) {
5899 wow_pulse_set_info.wow_pulse_enable = true;
5900 wow_pulse_set_info.wow_pulse_pin =
5901 pcfg_ini->wow_pulse_pin;
5902 wow_pulse_set_info.wow_pulse_interval_low =
5903 pcfg_ini->wow_pulse_interval_low;
5904 wow_pulse_set_info.wow_pulse_interval_high =
5905 pcfg_ini->wow_pulse_interval_high;
5906 } else {
5907 wow_pulse_set_info.wow_pulse_enable = false;
5908 wow_pulse_set_info.wow_pulse_pin = 0;
5909 wow_pulse_set_info.wow_pulse_interval_low = 0;
5910 wow_pulse_set_info.wow_pulse_interval_high = 0;
5911 }
5912 hdd_notice("enable %d pin %d low %d high %d",
5913 wow_pulse_set_info.wow_pulse_enable,
5914 wow_pulse_set_info.wow_pulse_pin,
5915 wow_pulse_set_info.wow_pulse_interval_low,
5916 wow_pulse_set_info.wow_pulse_interval_high);
5917
5918 status = sme_set_wow_pulse(&wow_pulse_set_info);
5919 if (QDF_STATUS_E_FAILURE == status) {
5920 hdd_notice("sme_set_wow_pulse failure!");
5921 return -EIO;
5922 }
5923 hdd_notice("sme_set_wow_pulse success!");
5924 return 0;
5925}
5926#else
5927static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
5928{
5929 return 0;
5930}
5931#endif
5932
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005933#ifdef WLAN_FEATURE_FASTPATH
5934/**
5935 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5936 * @hdd_cfg: hdd config
5937 * @context: lower layer context
5938 *
5939 * Return: none
5940 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305941void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005942 void *context)
5943{
5944 if (hdd_cfg->fastpath_enable)
5945 hif_enable_fastpath(context);
5946}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005947#endif
5948
Yuanyuan Liu13738502016-04-06 17:41:37 -07005949#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950/**
5951 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005952 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953 * @level: thermal level
5954 *
5955 * Change IPA data path to SW path when the thermal throttle level greater
5956 * than 0, and restore the original data path when throttle level is 0
5957 *
5958 * Return: none
5959 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005960static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005961{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005962 hdd_context_t *hdd_ctx = context;
5963
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964 /* Change IPA to SW path when throttle level greater than 0 */
5965 if (level > THROTTLE_LEVEL_0)
5966 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5967 else
5968 /* restore original concurrency mode */
5969 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5970}
5971
5972/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305973 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5974 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305975 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005976 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305977 * Get a safe channel to restart SAP. PCL already takes into account the
5978 * unsafe channels. So, the PCL is validated with the ACS range to provide
5979 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305981 * Return: Channel number to restart SAP in case of success. In case of any
5982 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005983 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305984static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5985 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305987 struct sir_pcl_list pcl;
5988 QDF_STATUS status;
5989 uint32_t i, j;
5990 tHalHandle *hal_handle;
5991 hdd_context_t *hdd_ctx;
5992 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305994 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5995 if (!hdd_ctx) {
5996 hdd_err("invalid HDD context");
5997 return INVALID_CHANNEL_ID;
5998 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005999
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306000 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6001 if (!hal_handle) {
6002 hdd_err("invalid HAL handle");
6003 return INVALID_CHANNEL_ID;
6004 }
6005
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306006 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
6007 pcl.pcl_list, &pcl.pcl_len,
6008 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6009 if (QDF_IS_STATUS_ERROR(status)) {
6010 hdd_err("Get PCL failed");
6011 return INVALID_CHANNEL_ID;
6012 }
6013
6014 if (!pcl.pcl_len) {
6015 hdd_alert("pcl length is zero. this is not expected");
6016 return INVALID_CHANNEL_ID;
6017 }
6018
6019 hdd_info("start:%d end:%d",
6020 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6021 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6022
6023 /* PCL already takes unsafe channel into account */
6024 for (i = 0; i < pcl.pcl_len; i++) {
6025 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6026 if ((pcl.pcl_list[i] >=
6027 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6028 (pcl.pcl_list[i] <=
6029 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6030 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
6031 return pcl.pcl_list[i];
6032 }
6033 }
6034
6035 hdd_info("no safe channel from PCL found in ACS range");
6036
6037 /* Try for safe channel from all valid channel */
6038 pcl.pcl_len = MAX_NUM_CHAN;
6039 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
6040 &pcl.pcl_len);
6041 if (QDF_IS_STATUS_ERROR(status)) {
6042 hdd_err("error in getting valid channel list");
6043 return INVALID_CHANNEL_ID;
6044 }
6045
6046 for (i = 0; i < pcl.pcl_len; i++) {
6047 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6048 found = false;
6049 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006050 if (pcl.pcl_list[i] ==
6051 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306052 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
6053 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006054 break;
6055 }
6056 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306057
6058 if (found)
6059 continue;
6060
6061 if ((pcl.pcl_list[i] >=
6062 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6063 (pcl.pcl_list[i] <=
6064 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6065 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
6066 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006067 }
6068 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306069
6070 return INVALID_CHANNEL_ID;
6071}
6072
6073/**
6074 * hdd_restart_sap() - Restarts SAP on the given channel
6075 * @adapter: AP adapter
6076 * @channel: Channel
6077 *
6078 * Restarts the SAP interface by invoking the function which executes the
6079 * callback to perform channel switch using (E)CSA.
6080 *
6081 * Return: None
6082 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006083static void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306084{
6085 hdd_ap_ctx_t *hdd_ap_ctx;
6086 tHalHandle *hal_handle;
6087
6088 if (!adapter) {
6089 hdd_err("invalid adapter");
6090 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006091 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306092
6093 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6094
6095 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6096 if (!hal_handle) {
6097 hdd_err("invalid HAL handle");
6098 return;
6099 }
6100
6101 hdd_ap_ctx->sapConfig.channel = channel;
6102 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6103 hdd_ap_ctx->sapConfig.ch_width_orig;
6104
6105 hdd_info("chan:%d width:%d",
6106 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6107
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006108 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306109 hdd_ap_ctx->sapConfig.sec_ch,
6110 &hdd_ap_ctx->sapConfig.ch_params);
6111
6112 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006113}
Agrawal Ashish467dde42016-09-08 18:44:22 +05306114/**
6115 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6116 * @hdd_ctx: hdd context pointer
6117 *
6118 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6119 * and if ACS is enabled, driver will ask userspace to restart the
6120 * sap. User space on LTE coex indication restart driver.
6121 *
6122 * Return - none
6123 */
6124void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6125{
6126 QDF_STATUS status;
6127 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6128 hdd_adapter_t *adapter_temp;
6129 uint32_t i;
6130 bool found = false;
6131 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006132
Agrawal Ashish467dde42016-09-08 18:44:22 +05306133 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6134 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6135 adapter_temp = adapter_node->pAdapter;
6136
6137 if (!adapter_temp) {
6138 hdd_err("adapter is NULL, moving to next one");
6139 goto next_adapater;
6140 }
6141
6142 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6143 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
6144 hdd_info("skip device mode:%d acs:%d",
6145 adapter_temp->device_mode,
6146 adapter_temp->sessionCtx.ap.sapConfig.
6147 acs_cfg.acs_mode);
6148 goto next_adapater;
6149 }
6150
6151 found = false;
6152 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006153 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306154 hdd_ctxt->unsafe_channel_list[i]) {
6155 found = true;
6156 hdd_info("operating ch:%d is unsafe",
6157 adapter_temp->sessionCtx.ap.operatingChannel);
6158 break;
6159 }
6160 }
6161
6162 if (!found) {
6163 hdd_info("ch:%d is safe. no need to change channel",
6164 adapter_temp->sessionCtx.ap.operatingChannel);
6165 goto next_adapater;
6166 }
6167
6168 restart_chan =
6169 hdd_get_safe_channel_from_pcl_and_acs_range(
6170 adapter_temp);
6171 if (!restart_chan) {
6172 hdd_alert("fail to restart SAP");
6173 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006174 /*
6175 * SAP restart due to unsafe channel. While
6176 * restarting the SAP, make sure to clear
6177 * acs_channel, channel to reset to
6178 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306179 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006180 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306181 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6182 adapter_temp->sessionCtx.ap.sapConfig.channel =
6183 AUTO_CHANNEL_SELECT;
Agrawal Ashish467dde42016-09-08 18:44:22 +05306184 hdd_info("sending coex indication");
6185 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6186 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6187 hdd_restart_sap(adapter_temp, restart_chan);
6188 }
6189
6190next_adapater:
6191 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6192 adapter_node = next;
6193 }
6194}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006195/**
6196 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6197 * @adapter: HDD adapter pointer
6198 * @indParam: Channel avoid notification parameter
6199 *
6200 * Avoid channel notification from FW handler.
6201 * FW will send un-safe channel list to avoid over wrapping.
6202 * hostapd should not use notified channel
6203 *
6204 * Return: None
6205 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306206void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006207{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006208 hdd_context_t *hdd_ctxt;
6209 tSirChAvoidIndType *ch_avoid_indi;
6210 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006211 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6212 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006213 uint16_t start_channel;
6214 uint16_t end_channel;
6215 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006216 tHddAvoidFreqList hdd_avoid_freq_list;
6217 uint32_t i;
6218
6219 /* Basic sanity */
6220 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006221 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006222 return;
6223 }
6224
6225 hdd_ctxt = (hdd_context_t *) hdd_context;
6226 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6227 cds_context = hdd_ctxt->pcds_context;
6228
6229 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006230 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006231 ch_avoid_indi->avoid_range_count);
6232
6233 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306234 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006235 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6236 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6237 ch_avoid_indi->avoid_freq_range[i].start_freq;
6238 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6239 ch_avoid_indi->avoid_freq_range[i].end_freq;
6240 }
6241 hdd_avoid_freq_list.avoidFreqRangeCount =
6242 ch_avoid_indi->avoid_range_count;
6243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006244 /* clear existing unsafe channel cache */
6245 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306246 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006247 sizeof(hdd_ctxt->unsafe_channel_list));
6248
6249 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6250 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006251 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006252 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006253 break;
6254 }
6255
6256 start_channel = ieee80211_frequency_to_channel(
6257 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6258 end_channel = ieee80211_frequency_to_channel(
6259 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006260 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006261 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6262 start_channel,
6263 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6264 end_channel);
6265
6266 /* do not process frequency bands that are not mapped to
6267 * predefined channels
6268 */
6269 if (start_channel == 0 || end_channel == 0)
6270 continue;
6271
Amar Singhalb8d4f152016-02-10 10:21:43 -08006272 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6273 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006274 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006275 ch_avoid_indi->avoid_freq_range[
6276 range_loop].start_freq) {
6277 start_channel_idx = channel_loop;
6278 break;
6279 }
6280 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006281 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6282 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006283 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006284 ch_avoid_indi->avoid_freq_range[
6285 range_loop].end_freq) {
6286 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006287 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006288 ch_avoid_indi->avoid_freq_range[
6289 range_loop].end_freq)
6290 end_channel_idx--;
6291 break;
6292 }
6293 }
6294
Amar Singhalb8d4f152016-02-10 10:21:43 -08006295 if (start_channel_idx == INVALID_CHANNEL ||
6296 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006297 continue;
6298
6299 for (channel_loop = start_channel_idx; channel_loop <=
6300 end_channel_idx; channel_loop++) {
6301 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006302 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006303 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006304 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006305 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006306 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006307 break;
6308 }
6309 }
6310 }
6311
Jeff Johnson34c88b72016-08-15 14:27:11 -07006312 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006313 hdd_ctxt->unsafe_channel_count);
6314
Yuanyuan Liu13738502016-04-06 17:41:37 -07006315 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6316 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006317 hdd_ctxt->unsafe_channel_count)) {
6318 hdd_err("Failed to set unsafe channel");
6319
6320 /* clear existing unsafe channel cache */
6321 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306322 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006323 sizeof(hdd_ctxt->unsafe_channel_list));
6324
6325 return;
6326 }
6327
6328 for (channel_loop = 0;
6329 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006330 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006331 hdd_ctxt->unsafe_channel_list[channel_loop]);
6332 }
6333
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306334 /*
6335 * first update the unsafe channel list to the platform driver and
6336 * send the avoid freq event to the application
6337 */
6338 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6339
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306340 if (!hdd_ctxt->unsafe_channel_count) {
6341 hdd_info("no unsafe channels - not restarting SAP");
6342 return;
6343 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306344 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006345 return;
6346}
6347
6348/**
6349 * hdd_init_channel_avoidance() - Initialize channel avoidance
6350 * @hdd_ctx: HDD global context
6351 *
6352 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006353 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006354 * down to the lower layers. Then subscribe to subsequent channel
6355 * avoidance events.
6356 *
6357 * Return: None
6358 */
6359static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6360{
6361 uint16_t unsafe_channel_count;
6362 int index;
6363
Yuanyuan Liu13738502016-04-06 17:41:37 -07006364 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6365 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006366 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006367 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006368
Jeff Johnson34c88b72016-08-15 14:27:11 -07006369 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006370 hdd_ctx->unsafe_channel_count);
6371
Anurag Chouhan6d760662016-02-20 16:05:43 +05306372 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006373 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006374
6375 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006376 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006377 hdd_ctx->unsafe_channel_list[index]);
6378
6379 }
6380
6381 /* Plug in avoid channel notification callback */
6382 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6383}
6384#else
6385static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6386{
6387}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006388static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006389{
6390}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006391#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006392
6393/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006394 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6395 * user space
6396 * @frame_ind: Management frame data to be informed.
6397 *
6398 * This function is used to indicate management frame to
6399 * user space
6400 *
6401 * Return: None
6402 *
6403 */
6404void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6405{
6406 hdd_context_t *hdd_ctx = NULL;
6407 hdd_adapter_t *adapter = NULL;
6408 void *cds_context = NULL;
6409 int i;
6410
6411 /* Get the global VOSS context.*/
6412 cds_context = cds_get_global_context();
6413 if (!cds_context) {
6414 hdd_err("Global CDS context is Null");
6415 return;
6416 }
6417 /* Get the HDD context.*/
6418 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6419
6420 if (0 != wlan_hdd_validate_context(hdd_ctx))
6421 return;
6422
6423 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6424 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6425 adapter =
6426 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6427 if (adapter)
6428 break;
6429 }
6430 } else {
6431 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6432 frame_ind->sessionId);
6433 }
6434
6435 if ((NULL != adapter) &&
6436 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6437 __hdd_indicate_mgmt_frame(adapter,
6438 frame_ind->frame_len,
6439 frame_ind->frameBuf,
6440 frame_ind->frameType,
6441 frame_ind->rxChan,
6442 frame_ind->rxRssi);
6443 return;
6444}
6445
6446/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006447 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6448 * @hdd_ctx: HDD context
6449 *
6450 * Disables all the dual mac features like DBS, Agile DFS etc.
6451 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306452 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006453 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306454static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006455{
6456 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306457 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006458
6459 if (!hdd_ctx) {
6460 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306461 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006462 }
6463
6464 cfg.scan_config = 0;
6465 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306466 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006467
6468 hdd_debug("Disabling all dual mac features...");
6469
6470 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306471 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006472 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6473 return status;
6474 }
6475
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306476 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006477}
6478
6479/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006480 * hdd_override_ini_config - Override INI config
6481 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006483 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006484 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006485 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006486 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006487static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006488{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006489
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006490 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6491 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6492 hdd_notice("Module enable_dfs_chan_scan set to %d",
6493 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006494 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006495 if (0 == enable_11d || 1 == enable_11d) {
6496 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6497 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006498 }
Leo Chang11545d62016-10-17 14:53:50 -07006499
6500 if (!hdd_ipa_is_present(hdd_ctx))
6501 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006502}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006503
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006504/**
6505 * hdd_set_trace_level_for_each - Set trace level for each INI config
6506 * @hdd_ctx - HDD context
6507 *
6508 * Set trace level for each module based on INI config.
6509 *
6510 * Return: None
6511 */
6512static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6513{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306514 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6515 hdd_ctx->config->qdf_trace_enable_wdi);
6516 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6517 hdd_ctx->config->qdf_trace_enable_hdd);
6518 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6519 hdd_ctx->config->qdf_trace_enable_sme);
6520 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6521 hdd_ctx->config->qdf_trace_enable_pe);
6522 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6523 hdd_ctx->config->qdf_trace_enable_wma);
6524 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6525 hdd_ctx->config->qdf_trace_enable_sys);
6526 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6527 hdd_ctx->config->qdf_trace_enable_qdf);
6528 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6529 hdd_ctx->config->qdf_trace_enable_sap);
6530 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6531 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6532 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6533 hdd_ctx->config->qdf_trace_enable_bmi);
6534 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6535 hdd_ctx->config->qdf_trace_enable_cfg);
6536 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6537 hdd_ctx->config->qdf_trace_enable_epping);
6538 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6539 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6540 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306541 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306542 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6543 hdd_ctx->config->qdf_trace_enable_htc);
6544 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6545 hdd_ctx->config->qdf_trace_enable_hif);
6546 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6547 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6548 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6549 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306550
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006551 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006552}
6553
6554/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006555 * hdd_context_init() - Initialize HDD context
6556 * @hdd_ctx: HDD context.
6557 *
6558 * Initialize HDD context along with all the feature specific contexts.
6559 *
6560 * return: 0 on success and errno on failure.
6561 */
6562static int hdd_context_init(hdd_context_t *hdd_ctx)
6563{
6564 int ret;
6565
6566 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6567 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6568
6569 hdd_init_ll_stats_ctx();
6570
6571 init_completion(&hdd_ctx->mc_sus_event_var);
6572 init_completion(&hdd_ctx->ready_to_suspend);
6573
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306574 hdd_init_bpf_completion();
6575
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006576 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306577 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006578 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306579
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006580 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6581
6582 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6583
6584 ret = hdd_scan_context_init(hdd_ctx);
6585 if (ret)
6586 goto list_destroy;
6587
Nitesh Shahd1266d72017-01-25 22:07:07 +05306588 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006589
6590 hdd_rx_wake_lock_create(hdd_ctx);
6591
6592 ret = hdd_sap_context_init(hdd_ctx);
6593 if (ret)
6594 goto scan_destroy;
6595
6596 ret = hdd_roc_context_init(hdd_ctx);
6597 if (ret)
6598 goto sap_destroy;
6599
6600 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6601
6602 hdd_init_offloaded_packets_ctx(hdd_ctx);
6603
6604 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6605 hdd_ctx->config);
6606 if (ret)
6607 goto roc_destroy;
6608
6609 return 0;
6610
6611roc_destroy:
6612 hdd_roc_context_destroy(hdd_ctx);
6613
6614sap_destroy:
6615 hdd_sap_context_destroy(hdd_ctx);
6616
6617scan_destroy:
6618 hdd_scan_context_destroy(hdd_ctx);
6619 hdd_rx_wake_lock_destroy(hdd_ctx);
6620 hdd_tdls_context_destroy(hdd_ctx);
6621
6622list_destroy:
6623 qdf_list_destroy(&hdd_ctx->hddAdapters);
6624 return ret;
6625}
6626
6627/**
6628 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306629 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006630 *
6631 * Allocate and initialize HDD context. HDD context is allocated as part of
6632 * wiphy allocation and then context is initialized.
6633 *
6634 * Return: HDD context on success and ERR_PTR on failure
6635 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006636static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006637{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306638 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006639 int ret = 0;
6640 hdd_context_t *hdd_ctx;
6641 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05306642 int qdf_print_idx = -1;
6643
6644 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
6645 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
6646 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
6647 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
6648 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
6649 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
6650 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
6651 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
6652 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
6653 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
6654 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
6655 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
6656 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
6657 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
6658 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
6659 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
6660 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
6661 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
6662 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
6663 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
6664 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
6665 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL}
6666 };
6667
6668 status = qdf_print_setup();
6669 if (status != QDF_STATUS_SUCCESS) {
6670 pr_err("QDF print control object setup failed\n");
6671 ret = -EINVAL;
6672 goto err_out;
6673 }
6674 /* Register the module here with QDF */
6675 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
6676 "MCL_WLAN");
6677
6678 /* if qdf_print_idx is negative */
6679 if (qdf_print_idx < 0) {
6680 pr_err("QDF print control can not be registered %d\n",
6681 qdf_print_idx);
6682 ret = -EINVAL;
6683 goto err_out;
6684 }
6685
6686 /* Store the qdf_pidx information into qdf module */
6687 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006688
6689 ENTER();
6690
6691 p_cds_context = cds_get_global_context();
6692 if (p_cds_context == NULL) {
6693 hdd_alert("Failed to get CDS global context");
6694 ret = -EINVAL;
6695 goto err_out;
6696 }
6697
6698 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6699
6700 if (hdd_ctx == NULL) {
6701 ret = -ENOMEM;
6702 goto err_out;
6703 }
6704
6705 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006706 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006707
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306708 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006709 if (hdd_ctx->config == NULL) {
6710 hdd_alert("Failed to alloc memory for HDD config!");
6711 ret = -ENOMEM;
6712 goto err_free_hdd_context;
6713 }
6714
6715 /* Read and parse the qcom_cfg.ini file */
6716 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306717 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306718 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006719 WLAN_INI_FILE);
6720 ret = -EINVAL;
6721 goto err_free_config;
6722 }
6723
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006724 hdd_ctx->configuredMcastBcastFilter =
6725 hdd_ctx->config->mcastBcastFilterSetting;
6726
6727 hdd_notice("Setting configuredMcastBcastFilter: %d",
6728 hdd_ctx->config->mcastBcastFilterSetting);
6729
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306730 if (hdd_ctx->config->fhostNSOffload)
6731 hdd_ctx->ns_offload_enable = true;
6732
Abhishek Singh5ea86532016-04-27 14:10:53 +05306733 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6734
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006735 hdd_override_ini_config(hdd_ctx);
6736
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006737 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006738
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006739 ret = hdd_context_init(hdd_ctx);
6740
6741 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006742 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006743
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006744
Yuanyuan Liu13738502016-04-06 17:41:37 -07006745 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6746 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006747
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006748
6749 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306750 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006751
Anurag Chouhan6d760662016-02-20 16:05:43 +05306752 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006753 goto skip_multicast_logging;
6754
6755 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6756
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006757 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6758 if (ret)
6759 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05306760
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006761 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6762 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306763 goto err_free_histogram;
6764
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006765skip_multicast_logging:
6766 hdd_set_trace_level_for_each(hdd_ctx);
6767
6768 return hdd_ctx;
6769
Nirav Shahed34b212016-04-25 10:59:16 +05306770err_free_histogram:
6771 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6772
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006773err_deinit_hdd_context:
6774 hdd_context_deinit(hdd_ctx);
6775
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006776err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306777 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006778
6779err_free_hdd_context:
6780 wiphy_free(hdd_ctx->wiphy);
6781
6782err_out:
6783 return ERR_PTR(ret);
6784}
6785
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006786#ifdef WLAN_OPEN_P2P_INTERFACE
6787/**
6788 * hdd_open_p2p_interface - Open P2P interface
6789 * @hdd_ctx: HDD context
6790 * @rtnl_held: True if RTNL lock held
6791 *
6792 * Open P2P interface during probe. This function called to open the P2P
6793 * interface at probe along with STA interface.
6794 *
6795 * Return: 0 on success and errno on failure
6796 */
6797static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6798{
6799 hdd_adapter_t *adapter;
6800 uint8_t *p2p_dev_addr;
6801
6802 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6803 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306804 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006805 hdd_ctx->config->intfMacAddr[0].bytes,
6806 sizeof(tSirMacAddr));
6807
6808 /*
6809 * Generate the P2P Device Address. This consists of
6810 * the device's primary MAC address with the locally
6811 * administered bit set.
6812 */
6813 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6814 } else {
6815 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6816 if (p2p_dev_addr == NULL) {
6817 hdd_alert("Failed to allocate mac_address for p2p_device");
6818 return -ENOSPC;
6819 }
6820
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306821 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306822 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006823 }
6824
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006825 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006826 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006827 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006828
6829 if (NULL == adapter) {
6830 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6831 return -ENOSPC;
6832 }
6833
6834 return 0;
6835}
6836#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306837static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006838 bool rtnl_held)
6839{
6840 return 0;
6841}
6842#endif
6843
6844/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306845 * hdd_start_station_adapter()- Start the Station Adapter
6846 * @adapter: HDD adapter
6847 *
6848 * This function initializes the adapter for the station mode.
6849 *
6850 * Return: 0 on success or errno on failure.
6851 */
6852int hdd_start_station_adapter(hdd_adapter_t *adapter)
6853{
6854 QDF_STATUS status;
6855
6856 ENTER_DEV(adapter->dev);
6857
6858 status = hdd_init_station_mode(adapter);
6859
6860 if (QDF_STATUS_SUCCESS != status) {
6861 hdd_err("Error Initializing station mode: %d", status);
6862 return qdf_status_to_os_return(status);
6863 }
6864
Arun Khandavallifae92942016-08-01 13:31:08 +05306865 hdd_register_tx_flow_control(adapter,
6866 hdd_tx_resume_timer_expired_handler,
6867 hdd_tx_resume_cb);
6868
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306869 EXIT();
6870 return 0;
6871}
6872
6873/**
6874 * hdd_start_ap_adapter()- Start AP Adapter
6875 * @adapter: HDD adapter
6876 *
6877 * This function initializes the adapter for the AP mode.
6878 *
6879 * Return: 0 on success errno on failure.
6880 */
6881int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6882{
6883 QDF_STATUS status;
6884
6885 ENTER();
6886
6887 status = hdd_init_ap_mode(adapter);
6888
6889 if (QDF_STATUS_SUCCESS != status) {
6890 hdd_err("Error Initializing the AP mode: %d", status);
6891 return qdf_status_to_os_return(status);
6892 }
6893
Arun Khandavallifae92942016-08-01 13:31:08 +05306894 hdd_register_tx_flow_control(adapter,
6895 hdd_softap_tx_resume_timer_expired_handler,
6896 hdd_softap_tx_resume_cb);
6897
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306898 EXIT();
6899 return 0;
6900}
6901
6902/**
6903 * hdd_start_ftm_adapter()- Start FTM adapter
6904 * @adapter: HDD adapter
6905 *
6906 * This function initializes the adapter for the FTM mode.
6907 *
6908 * Return: 0 on success or errno on failure.
6909 */
6910int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6911{
6912 QDF_STATUS qdf_status;
6913
6914 ENTER_DEV(adapter->dev);
6915
6916 qdf_status = hdd_init_tx_rx(adapter);
6917
6918 if (QDF_STATUS_SUCCESS != qdf_status) {
6919 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6920 return qdf_status_to_os_return(qdf_status);
6921 }
6922
6923 return 0;
6924 EXIT();
6925}
6926
6927/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006928 * hdd_open_interfaces - Open all required interfaces
6929 * hdd_ctx: HDD context
6930 * rtnl_held: True if RTNL lock is held
6931 *
6932 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6933 *
6934 * Return: Primary adapter on success and PTR_ERR on failure
6935 */
6936static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6937 bool rtnl_held)
6938{
6939 hdd_adapter_t *adapter = NULL;
6940 hdd_adapter_t *adapter_11p = NULL;
6941 int ret;
6942
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006943 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306944 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006945 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006946 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006947 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006948
6949 if (adapter == NULL)
6950 return ERR_PTR(-ENOSPC);
6951
6952 return adapter;
6953 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006954 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006955 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006956 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006957
6958 if (adapter == NULL)
6959 return ERR_PTR(-ENOSPC);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08006960 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
6961 adapter->fast_roaming_allowed = true;
6962
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006963 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6964 if (ret)
6965 goto err_close_adapter;
6966
6967 /* Open 802.11p Interface */
6968 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006969 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006970 "wlanocb%d",
6971 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006972 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006973 if (adapter_11p == NULL) {
6974 hdd_err("Failed to open 802.11p interface");
6975 goto err_close_adapter;
6976 }
6977 }
6978
6979 return adapter;
6980
6981err_close_adapter:
6982 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6983 return ERR_PTR(ret);
6984}
6985
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006986/**
6987 * hdd_update_country_code - Update country code
6988 * @hdd_ctx: HDD context
6989 * @adapter: Primary adapter context
6990 *
6991 * Update country code based on module parameter country_code at SME and wait
6992 * for the settings to take effect.
6993 *
6994 * Return: 0 on success and errno on failure
6995 */
6996static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6997 hdd_adapter_t *adapter)
6998{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306999 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007000 int ret = 0;
7001 unsigned long rc;
7002
7003 if (country_code == NULL)
7004 return 0;
7005
7006 INIT_COMPLETION(adapter->change_country_code);
7007
7008 status = sme_change_country_code(hdd_ctx->hHal,
7009 wlan_hdd_change_country_code_callback,
7010 country_code, adapter,
7011 hdd_ctx->pcds_context, eSIR_TRUE,
7012 eSIR_TRUE);
7013
7014
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307015 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007016 hdd_err("SME Change Country code from module param fail ret=%d",
7017 ret);
7018 return -EINVAL;
7019 }
7020
7021 rc = wait_for_completion_timeout(&adapter->change_country_code,
7022 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
7023 if (!rc) {
7024 hdd_err("SME while setting country code timed out");
7025 ret = -ETIMEDOUT;
7026 }
7027
7028 return ret;
7029}
7030
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307031#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7032/**
7033 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7034 * @cds_cfg: CDS Configuration
7035 * @hdd_ctx: Pointer to hdd context
7036 *
7037 * Return: none
7038 */
7039static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7040 *cds_cfg,
7041 hdd_context_t *hdd_ctx)
7042{
7043 cds_cfg->tx_flow_stop_queue_th =
7044 hdd_ctx->config->TxFlowStopQueueThreshold;
7045 cds_cfg->tx_flow_start_queue_offset =
7046 hdd_ctx->config->TxFlowStartQueueOffset;
7047}
7048#else
7049static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7050 *cds_cfg,
7051 hdd_context_t *hdd_ctx)
7052{
7053}
7054#endif
7055
7056#ifdef FEATURE_WLAN_RA_FILTERING
7057/**
7058 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7059 * @cds_cfg: CDS Configuration
7060 * @hdd_ctx: Pointer to hdd context
7061 *
7062 * Return: none
7063 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307064static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307065 hdd_context_t *hdd_ctx)
7066{
7067 cds_cfg->ra_ratelimit_interval =
7068 hdd_ctx->config->RArateLimitInterval;
7069 cds_cfg->is_ra_ratelimit_enabled =
7070 hdd_ctx->config->IsRArateLimitEnabled;
7071}
7072#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307073static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307074 hdd_context_t *hdd_ctx)
7075{
7076}
7077#endif
7078
7079/**
7080 * hdd_update_cds_config() - API to update cds configuration parameters
7081 * @hdd_ctx: HDD Context
7082 *
7083 * Return: 0 for Success, errno on failure
7084 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007085static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307086{
7087 struct cds_config_info *cds_cfg;
7088
7089 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7090 if (!cds_cfg) {
7091 hdd_err("failed to allocate cds config");
7092 return -ENOMEM;
7093 }
7094
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307095 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
7096 cds_cfg->powersave_offload_enabled =
7097 hdd_ctx->config->enablePowersaveOffload;
7098 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7099 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7100 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7101 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7102 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7103
7104 /* Here ol_ini_info is used to store ini status of arp offload
7105 * ns offload and others. Currently 1st bit is used for arp
7106 * off load and 2nd bit for ns offload currently, rest bits are unused
7107 */
7108 if (hdd_ctx->config->fhostArpOffload)
7109 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7110 if (hdd_ctx->config->fhostNSOffload)
7111 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7112
7113 /*
7114 * Copy the DFS Phyerr Filtering Offload status.
7115 * This parameter reflects the value of the
7116 * dfs_phyerr_filter_offload flag as set in the ini.
7117 */
7118 cds_cfg->dfs_phyerr_filter_offload =
7119 hdd_ctx->config->fDfsPhyerrFilterOffload;
7120 if (hdd_ctx->config->ssdp)
7121 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7122
7123 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7124 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7125
7126 cds_cfg->ap_maxoffload_reorderbuffs =
7127 hdd_ctx->config->apMaxOffloadReorderBuffs;
7128
7129 cds_cfg->ap_disable_intrabss_fwd =
7130 hdd_ctx->config->apDisableIntraBssFwd;
7131
7132 cds_cfg->dfs_pri_multiplier =
7133 hdd_ctx->config->dfsRadarPriMultiplier;
7134 cds_cfg->reorder_offload =
7135 hdd_ctx->config->reorderOffloadSupport;
7136
7137 /* IPA micro controller data path offload resource config item */
7138 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007139 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7140 /* IpaUcTxBufCount should be power of 2 */
7141 hdd_err("Round down IpaUcTxBufCount %d to nearest power of 2",
7142 hdd_ctx->config->IpaUcTxBufCount);
7143 hdd_ctx->config->IpaUcTxBufCount =
7144 rounddown_pow_of_two(
7145 hdd_ctx->config->IpaUcTxBufCount);
7146 if (!hdd_ctx->config->IpaUcTxBufCount) {
7147 hdd_err("Failed to round down IpaUcTxBufCount");
7148 return -EINVAL;
7149 }
7150 hdd_err("IpaUcTxBufCount rounded down to %d",
7151 hdd_ctx->config->IpaUcTxBufCount);
7152 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307153 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7154 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007155 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7156 /* IpaUcRxIndRingCount should be power of 2 */
7157 hdd_err("Round down IpaUcRxIndRingCount %d to nearest power of 2",
7158 hdd_ctx->config->IpaUcRxIndRingCount);
7159 hdd_ctx->config->IpaUcRxIndRingCount =
7160 rounddown_pow_of_two(
7161 hdd_ctx->config->IpaUcRxIndRingCount);
7162 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7163 hdd_err("Failed to round down IpaUcRxIndRingCount");
7164 return -EINVAL;
7165 }
7166 hdd_err("IpaUcRxIndRingCount rounded down to %d",
7167 hdd_ctx->config->IpaUcRxIndRingCount);
7168 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307169 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007170 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307171 cds_cfg->uc_tx_partition_base =
7172 hdd_ctx->config->IpaUcTxPartitionBase;
7173 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7174
7175 cds_cfg->ip_tcp_udp_checksum_offload =
7176 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307177 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307178 cds_cfg->ce_classify_enabled =
7179 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007180 cds_cfg->bpf_packet_filter_enable =
7181 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307182 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7183 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7184 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007185 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007186 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007187 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007188 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307189
7190 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7191 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7192 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007193 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307194 cds_init_ini_config(cds_cfg);
7195 return 0;
7196}
7197
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007198/**
7199 * hdd_init_thermal_info - Initialize thermal level
7200 * @hdd_ctx: HDD context
7201 *
7202 * Initialize thermal level at SME layer and set the thermal level callback
7203 * which would be called when a configured thermal threshold is hit.
7204 *
7205 * Return: 0 on success and errno on failure
7206 */
7207static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7208{
7209 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307210 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007211
7212 thermal_param.smeThermalMgmtEnabled =
7213 hdd_ctx->config->thermalMitigationEnable;
7214 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7215
Poddar, Siddarth83905022016-04-16 17:56:08 -07007216 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7217 hdd_ctx->config->throttle_dutycycle_level0;
7218 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7219 hdd_ctx->config->throttle_dutycycle_level1;
7220 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7221 hdd_ctx->config->throttle_dutycycle_level2;
7222 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7223 hdd_ctx->config->throttle_dutycycle_level3;
7224
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007225 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7226 hdd_ctx->config->thermalTempMinLevel0;
7227 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7228 hdd_ctx->config->thermalTempMaxLevel0;
7229 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7230 hdd_ctx->config->thermalTempMinLevel1;
7231 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7232 hdd_ctx->config->thermalTempMaxLevel1;
7233 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7234 hdd_ctx->config->thermalTempMinLevel2;
7235 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7236 hdd_ctx->config->thermalTempMaxLevel2;
7237 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7238 hdd_ctx->config->thermalTempMinLevel3;
7239 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7240 hdd_ctx->config->thermalTempMaxLevel3;
7241
7242 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7243
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307244 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307245 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007246
7247 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7248 hdd_set_thermal_level_cb);
7249
7250 return 0;
7251
7252}
7253
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007254#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7255/**
7256 * hdd_hold_rtnl_lock - Hold RTNL lock
7257 *
7258 * Hold RTNL lock
7259 *
7260 * Return: True if held and false otherwise
7261 */
7262static inline bool hdd_hold_rtnl_lock(void)
7263{
7264 rtnl_lock();
7265 return true;
7266}
7267
7268/**
7269 * hdd_release_rtnl_lock - Release RTNL lock
7270 *
7271 * Release RTNL lock
7272 *
7273 * Return: None
7274 */
7275static inline void hdd_release_rtnl_lock(void)
7276{
7277 rtnl_unlock();
7278}
7279#else
7280static inline bool hdd_hold_rtnl_lock(void) { return false; }
7281static inline void hdd_release_rtnl_lock(void) { }
7282#endif
7283
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007284#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007285
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307286/* MAX iwpriv command support */
7287#define PKTLOG_SET_BUFF_SIZE 3
7288#define MAX_PKTLOG_SIZE 16
7289
7290/**
7291 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7292 * @hdd_ctx: hdd context
7293 * @set_value2: pktlog buffer size value
7294 *
7295 *
7296 * Return: 0 for success or error.
7297 */
7298static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7299{
7300 struct sir_wifi_start_log start_log = { 0 };
7301 QDF_STATUS status;
7302
7303 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7304 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7305 start_log.ini_triggered = cds_is_packet_log_enabled();
7306 start_log.user_triggered = 1;
7307 start_log.size = set_value2;
7308
7309 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7310 if (!QDF_IS_STATUS_SUCCESS(status)) {
7311 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7312 EXIT();
7313 return -EINVAL;
7314 }
7315
7316 return 0;
7317}
7318
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007319/**
7320 * hdd_process_pktlog_command() - process pktlog command
7321 * @hdd_ctx: hdd context
7322 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307323 * @set_value2: pktlog buffer size value
7324 *
7325 * This function process pktlog command.
7326 * set_value2 only matters when set_value is 3 (set buff size)
7327 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007328 *
7329 * Return: 0 for success or error.
7330 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307331int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
7332 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007333{
7334 int ret;
7335 bool enable;
7336 uint8_t user_triggered = 0;
7337
7338 ret = wlan_hdd_validate_context(hdd_ctx);
7339 if (0 != ret)
7340 return ret;
7341
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307342 hdd_info("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007343
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307344 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007345 hdd_err("invalid pktlog value %d", set_value);
7346 return -EINVAL;
7347 }
7348
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307349 if (set_value == PKTLOG_SET_BUFF_SIZE) {
7350 if (set_value2 <= 0) {
7351 hdd_err("invalid pktlog size %d", set_value2);
7352 return -EINVAL;
7353 } else if (set_value2 > MAX_PKTLOG_SIZE) {
7354 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
7355 return -EINVAL;
7356 }
7357 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
7358 }
7359
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007360 /*
7361 * set_value = 0 then disable packetlog
7362 * set_value = 1 enable packetlog forcefully
7363 * set_vlaue = 2 then disable packetlog if disabled through ini or
7364 * enable packetlog with AUTO type.
7365 */
7366 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
7367 true : false;
7368
7369 if (1 == set_value) {
7370 enable = true;
7371 user_triggered = 1;
7372 }
7373
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307374 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007375}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007376/**
7377 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
7378 * @hdd_ctx: HDD context
7379 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307380 * @user_triggered: triggered through iwpriv
7381 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007382 *
7383 * Return: 0 on success; error number otherwise
7384 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007385int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307386 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007387{
7388 struct sir_wifi_start_log start_log;
7389 QDF_STATUS status;
7390
7391 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7392 start_log.verbose_level =
7393 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007394 start_log.ini_triggered = cds_is_packet_log_enabled();
7395 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307396 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307397 /*
7398 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7399 * commands. Host uses this flag to decide whether to send pktlog
7400 * disable command to fw without sending pktlog enable command
7401 * previously. For eg, If vendor sends pktlog disable command without
7402 * sending pktlog enable command, then host discards the packet
7403 * but for iwpriv command, host will send it to fw.
7404 */
7405 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007406 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7407 if (!QDF_IS_STATUS_SUCCESS(status)) {
7408 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7409 EXIT();
7410 return -EINVAL;
7411 }
7412
7413 return 0;
7414}
7415#endif /* REMOVE_PKT_LOG */
7416
7417
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307418#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7419/**
7420 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7421 * switch without restart
7422 *
7423 * Registers callback function to change the operating channel of SAP by using
7424 * channel switch announcements instead of restarting SAP.
7425 *
7426 * Return: QDF_STATUS
7427 */
7428QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7429{
7430 QDF_STATUS status;
7431
7432 status = cds_register_sap_restart_channel_switch_cb(
7433 (void *)hdd_sap_restart_with_channel_switch);
7434 if (!QDF_IS_STATUS_SUCCESS(status))
7435 hdd_err("restart cb registration failed");
7436
7437 return status;
7438}
7439#endif
7440
Komal Seelam92fff912016-03-24 11:51:41 +05307441/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007442 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
7443 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05307444 * @dev: Device Pointer
7445 * @num: Number of Valid Mac address
7446 *
7447 * Return: Pointer to MAC address buffer
7448 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007449static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
7450 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05307451{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007452 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05307453}
Komal Seelam92fff912016-03-24 11:51:41 +05307454
7455/**
7456 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7457 * @hdd_ctx: HDD Context
7458 * @num: Number of random mac addresses needed
7459 *
7460 * Generate random addresses using bit manipulation on the base mac address
7461 *
7462 * Return: None
7463 */
7464static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7465{
7466 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7467 uint32_t iter;
7468 struct hdd_config *ini = hdd_ctx->config;
7469 uint8_t *buf = NULL;
7470 uint8_t macaddr_b3, tmp_br3;
7471 uint8_t *src = ini->intfMacAddr[0].bytes;
7472
7473 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
7474 buf = ini->intfMacAddr[iter].bytes;
7475 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7476 macaddr_b3 = buf[3];
7477 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7478 INTF_MACADDR_MASK;
7479 macaddr_b3 += tmp_br3;
7480 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7481 buf[0] |= 0x02;
7482 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007483 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307484 }
7485}
7486
7487/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007488 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05307489 * @hdd_ctx: HDD Context
7490 *
7491 * API to get mac addresses from platform driver and update the driver
7492 * structures and configure FW with the base mac address.
7493 * Return: int
7494 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007495static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05307496{
7497 uint32_t no_of_mac_addr, iter;
7498 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7499 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7500 uint8_t *addr, *buf;
7501 struct device *dev = hdd_ctx->parent_dev;
7502 struct hdd_config *ini = hdd_ctx->config;
7503 tSirMacAddr mac_addr;
7504 QDF_STATUS status;
7505
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007506 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05307507
7508 if (no_of_mac_addr == 0 || !addr) {
7509 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7510 return -EINVAL;
7511 }
7512
7513 if (no_of_mac_addr > max_mac_addr)
7514 no_of_mac_addr = max_mac_addr;
7515
7516 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7517
7518 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7519 buf = ini->intfMacAddr[iter].bytes;
7520 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007521 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307522 }
7523
7524 status = sme_set_custom_mac_addr(mac_addr);
7525
7526 if (!QDF_IS_STATUS_SUCCESS(status))
7527 return -EAGAIN;
7528 if (no_of_mac_addr < max_mac_addr)
7529 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7530 no_of_mac_addr);
7531 return 0;
7532}
7533
7534/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007535 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7536 * @hdd_ctx: HDD Context
7537 *
7538 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7539 * will generate its own MAC and update it to FW.
7540 *
7541 * Return: 0 for success
7542 * Non-zero error code for failure
7543 */
7544static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7545{
7546 tSirMacAddr customMacAddr;
7547 QDF_STATUS status;
7548
7549 qdf_mem_copy(&customMacAddr,
7550 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7551 sizeof(tSirMacAddr));
7552 status = sme_set_custom_mac_addr(customMacAddr);
7553 if (!QDF_IS_STATUS_SUCCESS(status))
7554 return -EAGAIN;
7555 return 0;
7556}
7557
7558/**
Komal Seelam92fff912016-03-24 11:51:41 +05307559 * hdd_initialize_mac_address() - API to get wlan mac addresses
7560 * @hdd_ctx: HDD Context
7561 *
7562 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
7563 * is provisioned with mac addresses, driver uses it, else it will use
7564 * wlan_mac.bin to update HW MAC addresses.
7565 *
7566 * Return: None
7567 */
7568static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
7569{
7570 QDF_STATUS status;
7571 int ret;
7572
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007573 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05307574 if (ret == 0)
7575 return;
7576
7577 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7578
7579 status = hdd_update_mac_config(hdd_ctx);
7580
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007581 if (QDF_IS_STATUS_SUCCESS(status))
7582 return;
7583
7584 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
7585
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007586 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007587 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007588 if (ret != 0) {
7589 hdd_err("MAC address out-of-sync, ret:%d", ret);
7590 QDF_ASSERT(ret);
7591 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007592 }
Komal Seelam92fff912016-03-24 11:51:41 +05307593}
7594
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007595/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007596 * hdd_tsf_init() - Initialize the TSF synchronization interface
7597 * @hdd_ctx: HDD global context
7598 *
7599 * When TSF synchronization via GPIO is supported by the driver and
7600 * has been enabled in the configuration file, this function plumbs
7601 * the GPIO value down to firmware via SME.
7602 *
7603 * Return: None
7604 */
7605#ifdef WLAN_FEATURE_TSF
7606static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7607{
7608 QDF_STATUS status;
7609
7610 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7611 return;
7612
7613 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7614 hdd_ctx->config->tsf_gpio_pin);
7615 if (!QDF_IS_STATUS_SUCCESS(status))
7616 hdd_err("Set tsf GPIO failed, status: %d", status);
7617}
7618#else
7619static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7620{
7621}
7622#endif
7623
7624/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007625 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7626 * @hdd_ctx: HDD context
7627 *
7628 * Pre configurations to be done at lower layer before calling cds enable.
7629 *
7630 * Return: 0 on success and errno on failure.
7631 */
7632static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7633{
7634 int ret;
7635 QDF_STATUS status;
7636 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07007637 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007638
Leo Changfdb45c32016-10-28 11:09:23 -07007639 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007640 /*
7641 * Set 802.11p config
7642 * TODO-OCB: This has been temporarily added here to ensure this
7643 * parameter is set in CSR when we init the channel list. This should
7644 * be removed once the 5.9 GHz channels are added to the regulatory
7645 * domain.
7646 */
7647 hdd_set_dot11p_config(hdd_ctx);
7648
7649 /*
7650 * Note that the cds_pre_enable() sequence triggers the cfg download.
7651 * The cfg download must occur before we update the SME config
7652 * since the SME config operation must access the cfg database
7653 */
7654 status = hdd_set_sme_config(hdd_ctx);
7655
7656 if (QDF_STATUS_SUCCESS != status) {
7657 hdd_alert("Failed hdd_set_sme_config: %d", status);
7658 ret = qdf_status_to_os_return(status);
7659 goto out;
7660 }
7661
7662 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7663 hdd_ctx->config->tx_chain_mask_1ss,
7664 PDEV_CMD);
7665 if (0 != ret) {
7666 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7667 goto out;
7668 }
7669
7670 hdd_program_country_code(hdd_ctx);
7671
7672 status = hdd_set_sme_chan_list(hdd_ctx);
7673 if (status != QDF_STATUS_SUCCESS) {
7674 hdd_alert("Failed to init channel list: %d", status);
7675 ret = qdf_status_to_os_return(status);
7676 goto out;
7677 }
7678
7679 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07007680 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07007681 hdd_alert("config update failed");
7682 ret = -EINVAL;
7683 goto out;
7684 }
7685
Prashanth Bhatta07998752016-04-28 12:35:33 -07007686 /*
7687 * Set the MAC Address Currently this is used by HAL to add self sta.
7688 * Remove this once self sta is added as part of session open.
7689 */
7690 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7691 hdd_ctx->config->intfMacAddr[0].bytes,
7692 sizeof(hdd_ctx->config->intfMacAddr[0]));
7693
7694 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7695 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7696 hal_status, hal_status);
7697 ret = -EINVAL;
7698 goto out;
7699 }
7700
7701 hdd_init_channel_avoidance(hdd_ctx);
7702
7703out:
7704 return ret;
7705}
7706
7707/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007708 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7709 * @context_ptr - hdd context pointer
7710 * @event_ptr - event structure pointer
7711 *
7712 * This is the p2p listen offload stop event handler, it sends vendor
7713 * event back to supplicant to notify the stop reason.
7714 *
7715 * Return: None
7716 */
7717static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7718 void *event_ptr)
7719{
7720 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7721 struct sir_p2p_lo_event *evt = event_ptr;
7722 struct sk_buff *vendor_event;
7723
7724 ENTER();
7725
7726 if (hdd_ctx == NULL) {
7727 hdd_err("Invalid HDD context pointer");
7728 return;
7729 }
7730
7731 vendor_event =
7732 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7733 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7734 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7735 GFP_KERNEL);
7736
7737 if (!vendor_event) {
7738 hdd_err("cfg80211_vendor_event_alloc failed");
7739 return;
7740 }
7741
7742 if (nla_put_u32(vendor_event,
7743 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7744 evt->reason_code)) {
7745 hdd_err("nla put failed");
7746 kfree_skb(vendor_event);
7747 return;
7748 }
7749
7750 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7751}
7752
7753/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307754 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7755 * @hdd_ctx: HDD context
7756 *
7757 * This function sends the adaptive dwell time config configuration to the
7758 * firmware via WMA
7759 *
7760 * Return: 0 - success, < 0 - failure
7761 */
7762static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7763{
7764 QDF_STATUS status;
7765 struct adaptive_dwelltime_params dwelltime_params;
7766
7767 dwelltime_params.is_enabled =
7768 hdd_ctx->config->adaptive_dwell_mode_enabled;
7769 dwelltime_params.dwelltime_mode =
7770 hdd_ctx->config->global_adapt_dwelltime_mode;
7771 dwelltime_params.lpf_weight =
7772 hdd_ctx->config->adapt_dwell_lpf_weight;
7773 dwelltime_params.passive_mon_intval =
7774 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7775 dwelltime_params.wifi_act_threshold =
7776 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7777
7778 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7779 &dwelltime_params);
7780
7781 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7782 if (!QDF_IS_STATUS_SUCCESS(status)) {
7783 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7784 return -EAGAIN;
7785 }
7786 return 0;
7787}
7788
Arun Khandavallid4349a92016-07-25 11:10:43 +05307789#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7790/**
7791 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7792 * @hdd_ctx: HDD context
7793 *
7794 * Set auto shutdown callback to get indications from firmware to indicate
7795 * userspace to shutdown WLAN after a configured amount of inactivity.
7796 *
7797 * Return: 0 on success and errno on failure.
7798 */
7799static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7800{
7801 QDF_STATUS status;
7802
7803 if (!hdd_ctx->config->WlanAutoShutdown)
7804 return 0;
7805
7806 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7807 wlan_hdd_auto_shutdown_cb);
7808 if (status != QDF_STATUS_SUCCESS)
7809 hdd_err("Auto shutdown feature could not be enabled: %d",
7810 status);
7811
7812 return qdf_status_to_os_return(status);
7813}
7814#else
7815static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7816{
7817 return 0;
7818}
7819#endif
7820
7821/**
7822 * hdd_features_init() - Init features
7823 * @hdd_ctx: HDD context
7824 * @adapter: Primary adapter context
7825 *
7826 * Initialize features and their feature context after WLAN firmware is up.
7827 *
7828 * Return: 0 on success and errno on failure.
7829 */
7830static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7831{
7832 tSirTxPowerLimit hddtxlimit;
7833 QDF_STATUS status;
7834 int ret;
7835
7836 ENTER();
7837
7838 ret = hdd_update_country_code(hdd_ctx, adapter);
7839 if (ret) {
7840 hdd_err("Failed to update country code: %d", ret);
7841 goto out;
7842 }
7843
7844 /* FW capabilities received, Set the Dot11 mode */
7845 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07007846 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
7847 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307848
Arun Khandavallid4349a92016-07-25 11:10:43 +05307849
7850 if (hdd_ctx->config->fIsImpsEnabled)
7851 hdd_set_idle_ps_config(hdd_ctx, true);
7852 else
7853 hdd_set_idle_ps_config(hdd_ctx, false);
7854
7855 if (hdd_lro_init(hdd_ctx))
7856 hdd_err("Unable to initialize LRO in fw");
7857
7858 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7859 hdd_err("Unable to send adaptive dwelltime setting to FW");
7860
7861 ret = hdd_init_thermal_info(hdd_ctx);
7862 if (ret) {
7863 hdd_err("Error while initializing thermal information");
7864 goto deregister_frames;
7865 }
7866
7867 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7868 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7869 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7870 if (!QDF_IS_STATUS_SUCCESS(status))
7871 hdd_err("Error setting txlimit in sme: %d", status);
7872
7873 hdd_tsf_init(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307874 hdd_encrypt_decrypt_init(hdd_ctx);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307875
Arun Khandavallid4349a92016-07-25 11:10:43 +05307876 ret = hdd_register_cb(hdd_ctx);
7877 if (ret) {
7878 hdd_err("Failed to register HDD callbacks!");
7879 goto deregister_frames;
7880 }
7881
7882 if (hdd_ctx->config->dual_mac_feature_disable) {
7883 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7884 if (status != QDF_STATUS_SUCCESS) {
7885 hdd_err("Failed to disable dual mac features");
7886 goto deregister_cb;
7887 }
7888 }
7889
7890 /* register P2P Listen Offload event callback */
7891 if (wma_is_p2p_lo_capable())
7892 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7893 wlan_hdd_p2p_lo_event_callback);
7894
7895 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7896
7897 if (ret)
7898 goto deregister_cb;
7899
7900 EXIT();
7901 return 0;
7902
7903deregister_cb:
7904 hdd_deregister_cb(hdd_ctx);
7905deregister_frames:
7906 wlan_hdd_cfg80211_deregister_frames(adapter);
7907out:
7908 return -EINVAL;
7909
7910}
7911
7912
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307913/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307914 * hdd_configure_cds() - Configure cds modules
7915 * @hdd_ctx: HDD context
7916 * @adapter: Primary adapter context
7917 *
7918 * Enable Cds modules after WLAN firmware is up.
7919 *
7920 * Return: 0 on success and errno on failure.
7921 */
7922int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7923{
7924 int ret;
7925 QDF_STATUS status;
7926 /* structure of function pointers to be used by CDS */
7927 struct cds_sme_cbacks sme_cbacks;
7928
7929 ret = hdd_pre_enable_configure(hdd_ctx);
7930 if (ret) {
7931 hdd_err("Failed to pre-configure cds");
7932 goto out;
7933 }
7934
7935 /*
7936 * Start CDS which starts up the SME/MAC/HAL modules and everything
7937 * else
7938 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307939 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307940
7941 if (!QDF_IS_STATUS_SUCCESS(status)) {
7942 hdd_alert("cds_enable failed");
7943 goto out;
7944 }
7945
7946 status = hdd_post_cds_enable_config(hdd_ctx);
7947 if (!QDF_IS_STATUS_SUCCESS(status)) {
7948 hdd_alert("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007949 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307950 }
7951
7952 ret = hdd_features_init(hdd_ctx, adapter);
7953 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007954 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307955
7956 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7957 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7958 status = cds_init_policy_mgr(&sme_cbacks);
7959 if (!QDF_IS_STATUS_SUCCESS(status)) {
7960 hdd_err("Policy manager initialization failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007961 goto hdd_features_deinit;
Arun Khandavallifae92942016-08-01 13:31:08 +05307962 }
7963
7964 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007965
7966hdd_features_deinit:
7967 hdd_deregister_cb(hdd_ctx);
7968 wlan_hdd_cfg80211_deregister_frames(adapter);
7969cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307970 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007971
Arun Khandavallifae92942016-08-01 13:31:08 +05307972out:
7973 return -EINVAL;
7974}
7975
7976/**
7977 * hdd_deconfigure_cds() -De-Configure cds
7978 * @hdd_ctx: HDD context
7979 *
7980 * Deconfigure Cds modules before WLAN firmware is down.
7981 *
7982 * Return: 0 on success and errno on failure.
7983 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007984static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307985{
7986 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07007987 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307988
7989 ENTER();
7990 /* De-register the SME callbacks */
7991 hdd_deregister_cb(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307992 hdd_encrypt_decrypt_deinit(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307993
7994 /* De-init Policy Manager */
7995 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7996 hdd_err("Failed to deinit policy manager");
7997 /* Proceed and complete the clean up */
Houston Hoffman6640cf32016-10-10 16:44:29 -07007998 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307999 }
8000
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308001 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308002 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8003 hdd_err("Failed to Disable the CDS Modules! :%d",
8004 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07008005 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308006 }
8007
8008 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07008009 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308010}
8011
8012
8013/**
8014 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
8015 * @hdd_ctx: HDD context
Arun Khandavallifae92942016-08-01 13:31:08 +05308016 *
8017 * This function maintains the driver state machine it will be invoked from
8018 * exit, shutdown and con_mode change handler. Depending on the driver state
8019 * shall perform the stopping/closing of the modules.
8020 *
8021 * Return: 0 for success; non-zero for failure
8022 */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008023int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308024{
8025 void *hif_ctx;
8026 qdf_device_t qdf_ctx;
8027 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308028 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308029 p_cds_sched_context cds_sched_context = NULL;
8030
8031 ENTER();
8032
8033 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8034 if (!qdf_ctx) {
8035 hdd_err("QDF device context NULL");
8036 return -EINVAL;
8037 }
8038
8039 cds_sched_context = get_cds_sched_ctxt();
8040 if (!cds_sched_context) {
8041 hdd_err("cds scheduler context NULL");
8042 return -EINVAL;
8043 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308044 mutex_lock(&hdd_ctx->iface_change_lock);
8045 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05308046
8047 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
8048
8049 switch (hdd_ctx->driver_status) {
8050 case DRIVER_MODULES_UNINITIALIZED:
8051 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308052 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308053 case DRIVER_MODULES_CLOSED:
8054 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308055 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308056 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05308057 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308058 if (hdd_deconfigure_cds(hdd_ctx)) {
8059 hdd_alert("Failed to de-configure CDS");
8060 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308061 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308062 }
8063 hdd_info("successfully Disabled the CDS modules!");
8064 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8065 break;
8066 case DRIVER_MODULES_OPENED:
8067 hdd_info("Closing CDS modules!");
8068 break;
8069 default:
8070 hdd_err("Trying to stop wlan in a wrong state: %d",
8071 hdd_ctx->driver_status);
8072 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308073 ret = -EINVAL;
8074 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308075 }
8076
Govind Singhb048e872016-09-27 22:07:43 +05308077 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8078 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8079 hdd_err("Failed to process post CDS disable Modules! :%d",
8080 qdf_status);
8081 ret = -EINVAL;
8082 QDF_ASSERT(0);
8083 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308084 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308085 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8086 hdd_warn("Failed to stop CDS:%d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308087 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308088 QDF_ASSERT(0);
8089 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008090
Rajeev Kumarecf87ff2017-01-13 15:46:07 -08008091 ret = hdd_release_and_destroy_pdev(hdd_ctx);
8092 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308093 hdd_err("Pdev delete failed");
8094
Rajeev Kumar99e4cf62017-01-13 15:31:19 -08008095 ret = hdd_release_and_destroy_psoc(hdd_ctx);
8096 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308097 hdd_err("Psoc delete failed");
8098
Arun Khandavallifae92942016-08-01 13:31:08 +05308099 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8100 if (!hif_ctx) {
8101 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308102 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308103 }
8104
8105 hdd_hif_close(hif_ctx);
8106
8107 ol_cds_free();
8108
Arunk Khandavalli649c0092016-11-22 21:20:43 +05308109 if (!cds_is_driver_recovering() && !cds_is_driver_unloading()) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308110 ret = pld_power_off(qdf_ctx->dev);
8111 if (ret)
8112 hdd_err("CNSS power down failed put device into Low power mode:%d",
8113 ret);
8114 }
8115 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
8116
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308117done:
8118 hdd_ctx->stop_modules_in_progress = false;
8119 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308120 EXIT();
8121
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308122 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308123
8124}
8125
8126/**
8127 * hdd_iface_change_callback() - Function invoked when stop modules expires
8128 * @priv: pointer to hdd context
8129 *
8130 * This function is invoked when the timer waiting for the interface change
8131 * expires, it shall cut-down the power to wlan and stop all the modules.
8132 *
8133 * Return: void
8134 */
8135static void hdd_iface_change_callback(void *priv)
8136{
8137 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
8138 int ret;
8139 int status = wlan_hdd_validate_context(hdd_ctx);
8140
8141 if (status)
8142 return;
8143
8144 ENTER();
8145 hdd_info("Interface change timer expired close the modules!");
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008146 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308147 if (ret)
8148 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05308149 EXIT();
8150}
8151
8152/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308153 * hdd_state_info_dump() - prints state information of hdd layer
8154 * @buf: buffer pointer
8155 * @size: size of buffer to be filled
8156 *
8157 * This function is used to dump state information of hdd layer
8158 *
8159 * Return: None
8160 */
8161static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
8162{
8163 hdd_context_t *hdd_ctx;
8164 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8165 QDF_STATUS status;
8166 hdd_station_ctx_t *hdd_sta_ctx;
8167 hdd_adapter_t *adapter;
8168 uint16_t len = 0;
8169 char *buf = *buf_ptr;
8170
8171 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8172 if (!hdd_ctx) {
8173 hdd_err("Failed to get hdd context ");
8174 return;
8175 }
8176
8177 hdd_notice("size of buffer: %d", *size);
8178
8179 len += scnprintf(buf + len, *size - len,
8180 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8181 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008182 "\n is_scheduler_suspended %d",
8183 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308184
8185 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8186
8187 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8188 adapter = adapter_node->pAdapter;
8189 if (adapter->dev)
8190 len += scnprintf(buf + len, *size - len,
8191 "\n device name: %s", adapter->dev->name);
8192 len += scnprintf(buf + len, *size - len,
8193 "\n device_mode: %d", adapter->device_mode);
8194 switch (adapter->device_mode) {
8195 case QDF_STA_MODE:
8196 case QDF_P2P_CLIENT_MODE:
8197 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8198 len += scnprintf(buf + len, *size - len,
8199 "\n connState: %d",
8200 hdd_sta_ctx->conn_info.connState);
8201 break;
8202
8203 default:
8204 break;
8205 }
8206 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
8207 adapter_node = next;
8208 }
8209
8210 *size -= len;
8211 *buf_ptr += len;
8212}
8213
8214/**
8215 * hdd_register_debug_callback() - registration function for hdd layer
8216 * to print hdd state information
8217 *
8218 * Return: None
8219 */
8220static void hdd_register_debug_callback(void)
8221{
8222 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
8223}
8224
8225/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008226 * hdd_wlan_startup() - HDD init function
8227 * @dev: Pointer to the underlying device
8228 *
8229 * This is the driver startup code executed once a WLAN device has been detected
8230 *
8231 * Return: 0 for success, < 0 for failure
8232 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308233int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008234{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308235 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008236 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008237 hdd_context_t *hdd_ctx = NULL;
8238 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308239 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008240 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308241 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008242
8243 ENTER();
8244
Arun Khandavallifae92942016-08-01 13:31:08 +05308245 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008246
8247 if (IS_ERR(hdd_ctx))
8248 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008249
Arun Khandavallifae92942016-08-01 13:31:08 +05308250 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
8251 hdd_iface_change_callback, (void *)hdd_ctx);
8252
8253 mutex_init(&hdd_ctx->iface_change_lock);
8254
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008255 ret = hdd_init_netlink_services(hdd_ctx);
8256 if (ret)
8257 goto err_hdd_free_context;
8258
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07008259 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308260
Arun Khandavallifae92942016-08-01 13:31:08 +05308261 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
8262 if (ret) {
8263 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008264 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008265 }
8266
Yingying Tang80e15f32016-09-27 18:23:01 +08008267 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008268
Yingying Tang95409972016-10-20 15:16:15 +08008269 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
8270 hdd_notice("Failed to set wow pulse");
8271
Anurag Chouhan6d760662016-02-20 16:05:43 +05308272 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008273
8274 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008275 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05308276 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008277 }
8278
Prashanth Bhatta07998752016-04-28 12:35:33 -07008279 ret = hdd_wiphy_init(hdd_ctx);
8280 if (ret) {
8281 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05308282 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008283 }
8284
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05308285 if (hdd_ctx->config->enable_dp_trace)
8286 qdf_dp_trace_init();
8287
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308288 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008289 goto err_wiphy_unregister;
8290
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07008291 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08008292
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008293 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008294
Arun Khandavallifae92942016-08-01 13:31:08 +05308295 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008296
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008297 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008298 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008299 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05308300 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008301 }
8302
Arun Khandavallifae92942016-08-01 13:31:08 +05308303 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308304 if (!hif_sc) {
8305 hdd_err("HIF context is NULL");
8306 goto err_close_adapter;
8307 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008308 /*
8309 * target hw version/revision would only be retrieved after firmware
8310 * donwload
8311 */
8312 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
8313 &hdd_ctx->target_hw_revision,
8314 &hdd_ctx->target_hw_name);
8315
8316 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05308317 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008318
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008319 hdd_release_rtnl_lock();
8320 rtnl_held = false;
8321
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05308322 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8323 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08008324
8325 wlan_hdd_update_11n_mode(hdd_ctx->config);
8326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008327#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05308328 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308329 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008330 hdd_skip_acs_scan_timer_handler,
8331 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308332 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07008333 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04008334 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008335#endif
8336
Nitesh Shah61c10d92016-10-19 19:29:15 +05308337 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
8338 QDF_TIMER_TYPE_SW,
8339 wlan_hdd_change_tdls_mode,
8340 hdd_ctx);
8341
Prashanth Bhattaab004382016-10-11 16:08:11 -07008342 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008343
Jeff Johnson9afc5012016-09-23 13:56:27 -07008344 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008345
Nirav Shahbd36b062016-07-18 11:12:59 +05308346 if (hdd_ctx->rps)
8347 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07008348
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008349
8350 if (cds_is_packet_log_enabled())
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308351 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008352
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008353 ret = hdd_register_notifiers(hdd_ctx);
8354 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05308355 goto err_debugfs_exit;
8356
8357 status = wlansap_global_init();
8358 if (QDF_IS_STATUS_ERROR(status))
8359 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008360
Komal Seelam8634b772016-09-29 12:12:24 +05308361 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008362 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308363 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008364
bings612b9c42016-11-07 10:52:03 +08008365 if (hdd_enable_egap(hdd_ctx))
8366 hdd_err("enhance green ap is not enabled");
8367
Arun Khandavallifae92942016-08-01 13:31:08 +05308368 if (hdd_ctx->config->fIsImpsEnabled)
8369 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308370
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308371 if (hdd_ctx->config->sifs_burst_duration) {
8372 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
8373 hdd_ctx->config->sifs_burst_duration;
8374
8375 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
8376 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
8377 set_value, PDEV_CMD);
8378 }
8379
Arun Khandavallifae92942016-08-01 13:31:08 +05308380 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
8381 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308382
8383 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8384 status = sme_enable_disable_chanavoidind_event(
8385 hdd_ctx->hHal, 0);
8386 if (!QDF_IS_STATUS_SUCCESS(status))
8387 hdd_err("Failed to disable Chan Avoidance Indication");
8388 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008389 goto success;
8390
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008391err_debugfs_exit:
8392 hdd_debugfs_exit(adapter);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308393
8394err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008395 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008396
Arun Khandavallid4349a92016-07-25 11:10:43 +05308397 if (rtnl_held)
8398 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008399
Anurag Chouhance6a4052016-09-14 18:20:42 +05308400err_ipa_cleanup:
8401 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08008402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008403err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008404 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008405
Arun Khandavallifae92942016-08-01 13:31:08 +05308406err_stop_modules:
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008407 hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308408
8409
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008410 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308411 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008412 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308413 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008414 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008415
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008416err_exit_nl_srv:
Houston Hoffman47a4a052016-11-14 23:22:44 -08008417 hdd_green_ap_deinit(hdd_ctx);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008418 hdd_exit_netlink_services(hdd_ctx);
8419
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308420 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008421err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05308422 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
8423 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07008424 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308425 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008427 return -EIO;
8428
8429success:
8430 EXIT();
8431 return 0;
8432}
8433
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008434/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308435 * hdd_wlan_update_target_info() - update target type info
8436 * @hdd_ctx: HDD context
8437 * @context: hif context
8438 *
8439 * Update target info received from firmware in hdd context
8440 * Return:None
8441 */
8442
8443void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
8444{
8445 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
8446
8447 if (!tgt_info) {
8448 hdd_err("Target info is Null");
8449 return;
8450 }
8451
8452 hdd_ctx->target_type = tgt_info->target_type;
8453}
8454
8455/**
8456 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308457 * @hdd_ctx: HDD context
8458 *
8459 * Register the HDD callbacks to CDS/SME.
8460 *
8461 * Return: 0 for success or Error code for failure
8462 */
8463int hdd_register_cb(hdd_context_t *hdd_ctx)
8464{
8465 QDF_STATUS status;
8466 int ret = 0;
8467
8468 ENTER();
8469
8470 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
8471
8472 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
8473 hdd_send_oem_data_rsp_msg);
8474
8475 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
8476 wlan_hdd_cfg80211_fw_mem_dump_cb);
8477 if (!QDF_IS_STATUS_SUCCESS(status)) {
8478 hdd_err("Failed to register memdump callback");
8479 ret = -EINVAL;
8480 return ret;
8481 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05308482 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
8483 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308484 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
8485 sme_nan_register_callback(hdd_ctx->hHal,
8486 wlan_hdd_cfg80211_nan_callback);
8487 sme_stats_ext_register_callback(hdd_ctx->hHal,
8488 wlan_hdd_cfg80211_stats_ext_callback);
8489
8490 sme_ext_scan_register_callback(hdd_ctx->hHal,
8491 wlan_hdd_cfg80211_extscan_callback);
8492
8493 status = cds_register_sap_restart_channel_switch_cb(
8494 (void *)hdd_sap_restart_with_channel_switch);
8495 if (!QDF_IS_STATUS_SUCCESS(status)) {
8496 hdd_err("restart cb registration failed");
8497 ret = -EINVAL;
8498 return ret;
8499 }
8500
8501 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
8502 hdd_rssi_threshold_breached);
8503
8504 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
8505 hdd_get_bpf_offload_cb);
8506 if (!QDF_IS_STATUS_SUCCESS(status)) {
8507 hdd_err("set bpf offload callback failed");
8508 ret = -EINVAL;
8509 return ret;
8510 }
8511
8512 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
8513 wlan_hdd_cfg80211_link_layer_stats_callback);
8514
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05308515 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
8516 hdd_lost_link_info_cb);
8517 /* print error and not block the startup process */
8518 if (!QDF_IS_STATUS_SUCCESS(status))
8519 hdd_err("set lost link info callback failed");
8520
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308521 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
8522
8523 EXIT();
8524
8525 return ret;
8526}
8527
8528/**
8529 * hdd_deregister_cb() - De-Register HDD callbacks.
8530 * @hdd_ctx: HDD context
8531 *
8532 * De-Register the HDD callbacks to CDS/SME.
8533 *
8534 * Return: void
8535 */
8536void hdd_deregister_cb(hdd_context_t *hdd_ctx)
8537{
8538 QDF_STATUS status;
8539
8540 ENTER();
8541
8542 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
8543 if (!QDF_IS_STATUS_SUCCESS(status))
8544 hdd_err("De-register of dcc stats callback failed: %d",
8545 status);
8546
8547 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
8548 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
8549 if (!QDF_IS_STATUS_SUCCESS(status))
8550 hdd_err("De-register bpf offload callback failed: %d",
8551 status);
8552 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
8553
8554 status = cds_deregister_sap_restart_channel_switch_cb();
8555 if (!QDF_IS_STATUS_SUCCESS(status))
8556 hdd_err("De-register restart cb registration failed: %d",
8557 status);
8558
8559 sme_stats_ext_register_callback(hdd_ctx->hHal,
8560 wlan_hdd_cfg80211_stats_ext_callback);
8561
8562 sme_nan_deregister_callback(hdd_ctx->hHal);
8563 status = sme_reset_tsfcb(hdd_ctx->hHal);
8564 if (!QDF_IS_STATUS_SUCCESS(status))
8565 hdd_err("Failed to de-register tsfcb the callback:%d",
8566 status);
8567 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
8568 if (!QDF_IS_STATUS_SUCCESS(status))
8569 hdd_err("Failed to de-register the fw mem dump callback: %d",
8570 status);
8571
8572 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
8573 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
8574
8575 EXIT();
8576}
8577
8578/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008579 * hdd_softap_sta_deauth() - handle deauth req from HDD
8580 * @adapter: Pointer to the HDD
8581 * @enable: bool value
8582 *
8583 * This to take counter measure to handle deauth req from HDD
8584 *
8585 * Return: None
8586 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308587QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008588 struct tagCsrDelStaParams *pDelStaParams)
8589{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308590 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008591
8592 ENTER();
8593
Jeff Johnson34c88b72016-08-15 14:27:11 -07008594 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008595 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8596
8597 /* Ignore request to deauth bcmc station */
8598 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308599 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008600
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308601 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008602 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8603 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008604
8605 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308606 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008607}
8608
8609/**
8610 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
8611 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308612 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008613 *
8614 * This to take counter measure to handle deauth req from HDD
8615 *
8616 * Return: None
8617 */
8618void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308619 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008620{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008621 ENTER();
8622
Jeff Johnson34c88b72016-08-15 14:27:11 -07008623 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008624 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8625
8626 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308627 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008628 return;
8629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008630 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308631 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008632}
8633
8634void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
8635 bool enable)
8636{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008637 ENTER();
8638
Jeff Johnson34c88b72016-08-15 14:27:11 -07008639 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008640 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008642 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8643 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008644}
8645
8646/**
8647 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
8648 * @hdd_ctx: HDD Context
8649 *
8650 * API to find if there is any STA or P2P-Client is connected
8651 *
8652 * Return: true if connected; false otherwise
8653 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308654QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008655{
8656 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
8657}
8658
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008659/**
8660 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
8661 * @adapter: HDD adapter pointer
8662 *
8663 * This function loop through each adapter and disable roaming on each STA
8664 * device mode except the input adapter.
8665 *
8666 * Note: On the input adapter roaming is not enabled yet hence no need to
8667 * disable.
8668 *
8669 * Return: None
8670 */
8671void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8672{
8673 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8674 hdd_adapter_t *adapterIdx = NULL;
8675 hdd_adapter_list_node_t *adapterNode = NULL;
8676 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308677 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008678
8679 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8680 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008681 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008682 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008683 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008684 adapter->sessionId);
8685 /*
8686 * Loop through adapter and disable roaming for each STA device
8687 * mode except the input adapter.
8688 */
8689 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8690
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308691 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008692 adapterIdx = adapterNode->pAdapter;
8693
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008694 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008695 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008696 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008697 adapterIdx->sessionId);
8698 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8699 (adapterIdx),
8700 adapterIdx->sessionId, 0);
8701 }
8702
8703 status = hdd_get_next_adapter(hdd_ctx,
8704 adapterNode,
8705 &pNext);
8706 adapterNode = pNext;
8707 }
8708 }
8709}
8710
8711/**
8712 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8713 * @adapter: HDD adapter pointer
8714 *
8715 * This function loop through each adapter and enable roaming on each STA
8716 * device mode except the input adapter.
8717 * Note: On the input adapter no need to enable roaming because link got
8718 * disconnected on this.
8719 *
8720 * Return: None
8721 */
8722void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8723{
8724 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8725 hdd_adapter_t *adapterIdx = NULL;
8726 hdd_adapter_list_node_t *adapterNode = NULL;
8727 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308728 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008729
8730 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8731 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008732 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008733 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008734 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008735 adapter->sessionId);
8736 /*
8737 * Loop through adapter and enable roaming for each STA device
8738 * mode except the input adapter.
8739 */
8740 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8741
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308742 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008743 adapterIdx = adapterNode->pAdapter;
8744
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008745 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008746 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008747 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008748 adapterIdx->sessionId);
8749 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8750 (adapterIdx),
8751 adapterIdx->sessionId,
8752 REASON_CONNECT);
8753 }
8754
8755 status = hdd_get_next_adapter(hdd_ctx,
8756 adapterNode,
8757 &pNext);
8758 adapterNode = pNext;
8759 }
8760 }
8761}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008762
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308763void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008764{
8765 struct sk_buff *skb;
8766 struct nlmsghdr *nlh;
8767 tAniMsgHdr *ani_hdr;
8768 void *nl_data = NULL;
8769 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308770 struct radio_index_tlv *radio_info;
8771 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008772
8773 if (in_interrupt() || irqs_disabled() || in_atomic())
8774 flags = GFP_ATOMIC;
8775
8776 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8777
8778 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008779 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008780 return;
8781 }
8782
8783 nlh = (struct nlmsghdr *)skb->data;
8784 nlh->nlmsg_pid = 0; /* from kernel */
8785 nlh->nlmsg_flags = 0;
8786 nlh->nlmsg_seq = 0;
8787 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8788
8789 ani_hdr = NLMSG_DATA(nlh);
8790 ani_hdr->type = type;
8791
8792 switch (type) {
8793 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05308794 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008795 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008796 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008797 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008798 ani_hdr->length = 0;
8799 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008800 break;
8801 case WLAN_SVC_WLAN_STATUS_IND:
8802 case WLAN_SVC_WLAN_VERSION_IND:
8803 case WLAN_SVC_DFS_CAC_START_IND:
8804 case WLAN_SVC_DFS_CAC_END_IND:
8805 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8806 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8807 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008808 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308809 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008810 ani_hdr->length = len;
8811 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8812 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8813 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008814 break;
8815
8816 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008817 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008818 type);
8819 kfree_skb(skb);
8820 return;
8821 }
8822
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308823 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08008824 * Add radio index at the end of the svc event in TLV format
8825 * to maintain the backward compatibility with userspace
8826 * applications.
8827 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308828
8829 tlv_len = 0;
8830
8831 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8832 < WLAN_NL_MAX_PAYLOAD) {
8833 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8834 sizeof(*ani_hdr) + len);
8835 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8836 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8837 radio_info->radio = radio;
8838 tlv_len = sizeof(*radio_info);
8839 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8840 "Added radio index tlv - radio index %d",
8841 radio_info->radio);
8842 }
8843
8844 nlh->nlmsg_len += tlv_len;
8845 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8846
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008847 nl_srv_bcast(skb);
8848
8849 return;
8850}
8851
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008852#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8853void wlan_hdd_auto_shutdown_cb(void)
8854{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008855 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308856
8857 if (!hdd_ctx)
8858 return;
8859
Jeff Johnson28f8a772016-08-15 15:30:36 -07008860 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308861 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8862 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008863}
8864
8865void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8866{
8867 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308868 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008869 hdd_adapter_t *adapter;
8870 bool ap_connected = false, sta_connected = false;
8871 tHalHandle hal_handle;
8872
8873 hal_handle = hdd_ctx->hHal;
8874 if (hal_handle == NULL)
8875 return;
8876
8877 if (hdd_ctx->config->WlanAutoShutdown == 0)
8878 return;
8879
8880 if (enable == false) {
8881 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308882 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008883 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008884 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308885 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008886 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008887 return;
8888 }
8889
8890 /* To enable shutdown timer check conncurrency */
8891 if (cds_concurrent_open_sessions_running()) {
8892 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8893
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308894 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008895 adapter = adapterNode->pAdapter;
8896 if (adapter
8897 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008898 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008899 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8900 conn_info.connState ==
8901 eConnectionState_Associated) {
8902 sta_connected = true;
8903 break;
8904 }
8905 }
8906 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008907 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008908 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8909 bApActive == true) {
8910 ap_connected = true;
8911 break;
8912 }
8913 }
8914 status = hdd_get_next_adapter(hdd_ctx,
8915 adapterNode,
8916 &pNext);
8917 adapterNode = pNext;
8918 }
8919 }
8920
8921 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008922 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008923 return;
8924 } else {
8925 if (sme_set_auto_shutdown_timer(hal_handle,
8926 hdd_ctx->config->
8927 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308928 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008929 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008930 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008931 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008932 hdd_ctx->config->WlanAutoShutdown);
8933
8934 }
8935}
8936#endif
8937
8938hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8939 bool check_start_bss)
8940{
8941 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8942 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308943 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008944 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8945
8946 con_sap_adapter = NULL;
8947
8948 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308949 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008950 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008951 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8952 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008953 adapter != this_sap_adapter) {
8954 if (check_start_bss) {
8955 if (test_bit(SOFTAP_BSS_STARTED,
8956 &adapter->event_flags)) {
8957 con_sap_adapter = adapter;
8958 break;
8959 }
8960 } else {
8961 con_sap_adapter = adapter;
8962 break;
8963 }
8964 }
8965 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8966 adapterNode = pNext;
8967 }
8968
8969 return con_sap_adapter;
8970}
8971
8972#ifdef MSM_PLATFORM
8973void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8974{
8975 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8976
Dustin Brownfce08d12017-01-17 16:29:38 -08008977 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
8978 if (!hdd_ctx->bus_bw_timer_running) {
8979 hdd_ctx->bus_bw_timer_running = true;
8980 qdf_timer_start(&hdd_ctx->bus_bw_timer,
8981 hdd_ctx->config->busBandwidthComputeInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008982
Dustin Brownfce08d12017-01-17 16:29:38 -08008983 }
8984 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
8985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008986}
8987
8988void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8989{
8990 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308991 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008992 bool can_stop = true;
8993 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8994
Dustin Brownfce08d12017-01-17 16:29:38 -08008995 if (!hdd_ctx->bus_bw_timer_running) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008996 /* trying to stop timer, when not running is not good */
Srinivas Girigowda0ee96442016-08-17 19:10:56 -07008997 hdd_info("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008998 return;
8999 }
9000
9001 if (cds_concurrent_open_sessions_running()) {
9002 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9003
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309004 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009005 adapter = adapterNode->pAdapter;
9006 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009007 && (adapter->device_mode == QDF_STA_MODE
9008 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009009 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9010 conn_info.connState ==
9011 eConnectionState_Associated) {
9012 can_stop = false;
9013 break;
9014 }
9015 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009016 && (adapter->device_mode == QDF_SAP_MODE
9017 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009018 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
9019 true) {
9020 can_stop = false;
9021 break;
9022 }
9023 status = hdd_get_next_adapter(hdd_ctx,
9024 adapterNode,
9025 &pNext);
9026 adapterNode = pNext;
9027 }
9028 }
9029
Ravi Joshib89e7f72016-09-07 13:43:15 -07009030 if (can_stop == true) {
Chris Guoc0c95bf2016-11-10 14:28:25 +08009031 /* reset the ipa perf level */
9032 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
Dustin Brownfce08d12017-01-17 16:29:38 -08009033 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05309034 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08009035 hdd_ctx->bus_bw_timer_running = false;
9036 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Ravi Joshib89e7f72016-09-07 13:43:15 -07009037 hdd_reset_tcp_delack(hdd_ctx);
9038 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009039}
9040#endif
9041
9042/**
9043 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
9044 * and sta's operating channel.
9045 * @sta_adapter: Describe the first argument to foobar.
9046 * @ap_adapter: Describe the second argument to foobar.
9047 * @roam_profile: Roam profile of AP to which STA wants to connect.
9048 * @concurrent_chnl_same: If both SAP and STA channels are same then
9049 * set this flag to true else false.
9050 *
9051 * This function checks the sap's operating channel and sta's operating channel.
9052 * if both are same then it will return false else it will restart the sap in
9053 * sta's channel and return true.
9054 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309055 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009056 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309057QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009058 hdd_adapter_t *ap_adapter,
9059 tCsrRoamProfile *roam_profile,
9060 tScanResultHandle *scan_cache,
9061 bool *concurrent_chnl_same)
9062{
9063 hdd_ap_ctx_t *hdd_ap_ctx;
9064 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309065 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009066 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009067 *concurrent_chnl_same = true;
9068
9069 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9070 status =
9071 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
9072 roam_profile,
9073 scan_cache,
9074 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309075 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009076 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009077 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9078 if (hdd_ap_ctx->operatingChannel != channel_id) {
9079 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009080 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009081 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009082 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009083 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
9084 if (hdd_ap_ctx->operatingChannel != channel_id) {
9085 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009086 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009087 }
9088 }
9089 } else {
9090 /*
9091 * Lets handle worst case scenario here, Scan cache lookup is
9092 * failed so we have to stop the SAP to avoid any channel
9093 * discrepancy between SAP's channel and STA's channel.
9094 * Return the status as failure so caller function could know
9095 * that scan look up is failed.
9096 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07009097 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309098 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009099 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309100 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009101}
9102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009103/**
9104 * wlan_hdd_stop_sap() - This function stops bss of SAP.
9105 * @ap_adapter: SAP adapter
9106 *
9107 * This function will process the stopping of sap adapter.
9108 *
9109 * Return: None
9110 */
9111void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
9112{
9113 hdd_ap_ctx_t *hdd_ap_ctx;
9114 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309115 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009116 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117
9118 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009119 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009120 return;
9121 }
9122
9123 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9124 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309125 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009126 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309127
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009128 mutex_lock(&hdd_ctx->sap_lock);
9129 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08009130 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009131 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
9132 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009133 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309134 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309135 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009136 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309137 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08009138 qdf_stop_bss_event,
9139 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309140 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009141 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009142 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009143 return;
9144 }
9145 }
9146 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08009147 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009148 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009149 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009150 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009151 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152 }
9153 mutex_unlock(&hdd_ctx->sap_lock);
9154 return;
9155}
9156
9157/**
9158 * wlan_hdd_start_sap() - this function starts bss of SAP.
9159 * @ap_adapter: SAP adapter
9160 *
9161 * This function will process the starting of sap adapter.
9162 *
9163 * Return: None
9164 */
9165void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
9166{
9167 hdd_ap_ctx_t *hdd_ap_ctx;
9168 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309169 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009170 hdd_context_t *hdd_ctx;
9171 tsap_Config_t *sap_config;
9172
9173 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009174 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009175 return;
9176 }
9177
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009178 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07009179 hdd_err("SoftAp role has not been enabled");
9180 return;
9181 }
9182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009183 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
9184 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9185 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9186 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
9187
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309188 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009189 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009191 mutex_lock(&hdd_ctx->sap_lock);
9192 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
9193 goto end;
9194
9195 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009196 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009197 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9198 goto end;
9199 }
9200
Wei Song2f76f642016-11-18 16:32:53 +08009201 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009202 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
9203 &hdd_ap_ctx->sapConfig,
9204 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309205 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009206 goto end;
9207
Jeff Johnson28f8a772016-08-15 15:30:36 -07009208 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309209 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -08009210 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309211 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009212 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009213 goto end;
9214 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07009215 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009216 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -08009217 if (hostapd_state->bssState == BSS_START)
9218 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009219 ap_adapter->sessionId);
9220 hostapd_state->bCommit = true;
9221
9222end:
9223 mutex_unlock(&hdd_ctx->sap_lock);
9224 return;
9225}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009226
9227/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08009228 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
9229 * mac scan config
9230 * @status: Status of set antenna mode
9231 *
9232 * Callback on setting the dual mac configuration
9233 *
9234 * Return: None
9235 */
9236void wlan_hdd_soc_set_antenna_mode_cb(
9237 enum set_antenna_mode_status status)
9238{
9239 hdd_context_t *hdd_ctx;
9240
9241 hdd_info("Status: %d", status);
9242
9243 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9244 if (0 != wlan_hdd_validate_context(hdd_ctx))
9245 return;
9246
9247 /* Signal the completion of set dual mac config */
9248 complete(&hdd_ctx->set_antenna_mode_cmpl);
9249}
9250
9251/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009252 * hdd_get_fw_version() - Get FW version
9253 * @hdd_ctx: pointer to HDD context.
9254 * @major_spid: FW version - major spid.
9255 * @minor_spid: FW version - minor spid
9256 * @ssid: FW version - ssid
9257 * @crmid: FW version - crmid
9258 *
9259 * This function is called to get the firmware build version stored
9260 * as part of the HDD context
9261 *
9262 * Return: None
9263 */
9264void hdd_get_fw_version(hdd_context_t *hdd_ctx,
9265 uint32_t *major_spid, uint32_t *minor_spid,
9266 uint32_t *siid, uint32_t *crmid)
9267{
9268 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
9269 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
9270 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
9271 *crmid = hdd_ctx->target_fw_version & 0x7fff;
9272}
9273
9274#ifdef QCA_CONFIG_SMP
9275/**
9276 * wlan_hdd_get_cpu() - get cpu_index
9277 *
9278 * Return: cpu_index
9279 */
9280int wlan_hdd_get_cpu(void)
9281{
9282 int cpu_index = get_cpu();
9283 put_cpu();
9284 return cpu_index;
9285}
9286#endif
9287
9288/**
9289 * hdd_get_fwpath() - get framework path
9290 *
9291 * This function is used to get the string written by
9292 * userspace to start the wlan driver
9293 *
9294 * Return: string
9295 */
9296const char *hdd_get_fwpath(void)
9297{
9298 return fwpath.string;
9299}
9300
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009301/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009302 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009303 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009304 * This function initilizes CDS global context with the help of cds_init. This
9305 * has to be the first function called after probe to get a valid global
9306 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009307 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009308 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009309 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009310int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009311{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009312 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009313 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009314
Houston Hoffman9e06e542016-12-12 12:06:26 -08009315 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009316#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9317 wlan_logging_sock_init_svc();
9318#endif
9319
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009320 if (p_cds_context == NULL) {
9321 hdd_alert("Failed to allocate CDS context");
9322 ret = -ENOMEM;
9323 goto err_out;
9324 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009325
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009326 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309327 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009328
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009329err_out:
9330 return ret;
9331}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009332
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009333/**
9334 * hdd_deinit() - Deinitialize Driver
9335 *
9336 * This function frees CDS global context with the help of cds_deinit. This
9337 * has to be the last function call in remove callback to free the global
9338 * context.
9339 */
9340void hdd_deinit(void)
9341{
9342 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009343
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009344#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9345 wlan_logging_sock_deinit_svc();
9346#endif
9347}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009348
9349#ifdef QCA_WIFI_3_0_ADRASTEA
9350#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
9351#else
9352#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
9353#endif
9354
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009355/**
9356 * __hdd_module_init - Module init helper
9357 *
9358 * Module init helper function used by both module and static driver.
9359 *
9360 * Return: 0 for success, errno on failure
9361 */
9362static int __hdd_module_init(void)
9363{
9364 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009365
Arun Khandavallifae92942016-08-01 13:31:08 +05309366 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009367 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009368
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009369 pld_init();
9370
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309371 ret = hdd_init();
9372 if (ret) {
9373 pr_err("hdd_init failed %x\n", ret);
9374 goto err_hdd_init;
9375 }
9376
Rajeev Kumar97767a02016-11-30 11:20:40 -08009377 dispatcher_init();
9378
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309379 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009380
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009381 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009382
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009383 ret = wlan_hdd_register_driver();
9384 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07009385 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
9386 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009387 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009388 }
9389
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309390 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009391
9392 return 0;
9393out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309394 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -08009395 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309396 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009397
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309398err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009399 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009400
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009401 return ret;
9402}
9403
9404/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309405 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
9406 *
9407 * Block the unloading of the driver until the cds recovery is completed
9408 *
9409 * Return: None
9410 */
9411static void hdd_wait_for_recovery_completion(void)
9412{
9413 int retry = 0;
9414
9415 /* Wait for recovery to complete */
9416 while (cds_is_driver_recovering()) {
9417 hdd_alert("Recovery in progress; wait here!!!");
9418 msleep(1000);
9419 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
9420 hdd_alert("SSR never completed, fatal error");
9421 QDF_BUG(0);
9422 }
9423 }
9424}
9425
9426/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009427 * __hdd_module_exit - Module exit helper
9428 *
9429 * Module exit helper function used by both module and static driver.
9430 */
9431static void __hdd_module_exit(void)
9432{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05309433 int qdf_print_idx = -1;
9434
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009435 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
9436 QWLAN_VERSIONSTR);
9437
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309438 hdd_wait_for_recovery_completion();
9439
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009440 wlan_hdd_unregister_driver();
9441
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309442 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009443
Rajeev Kumar97767a02016-11-30 11:20:40 -08009444 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309445 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009446 pld_deinit();
9447
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05309448 qdf_print_idx = qdf_get_pidx();
9449 qdf_print_ctrl_cleanup(qdf_print_idx);
9450
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009451 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009452}
9453
Arun Khandavallifae92942016-08-01 13:31:08 +05309454#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009455/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309456 * wlan_boot_cb() - Wlan boot callback
9457 * @kobj: object whose directory we're creating the link in.
9458 * @attr: attribute the user is interacting with
9459 * @buff: the buffer containing the user data
9460 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009461 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309462 * This callback is invoked when the fs is ready to start the
9463 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009464 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309465 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009466 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309467static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009468 struct kobj_attribute *attr,
9469 const char *buf,
9470 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009471{
Arun Khandavallifae92942016-08-01 13:31:08 +05309472
Arun Khandavallifae92942016-08-01 13:31:08 +05309473 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009474 pr_err("%s: wlan driver already initialized\n", __func__);
9475 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +05309476 }
9477
Arun Khandavallifae92942016-08-01 13:31:08 +05309478 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009479 pr_err("%s: wlan driver initialization failed\n", __func__);
9480 return -EIO;
9481 }
9482
9483 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +05309484
9485 return count;
9486
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009487}
Arun Khandavallifae92942016-08-01 13:31:08 +05309488
9489/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009490 * hdd_sysfs_cleanup() - cleanup sysfs
9491 *
9492 * Return: None
9493 *
9494 */
9495static void hdd_sysfs_cleanup(void)
9496{
9497
9498 /* remove from group */
9499 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
9500 sysfs_remove_group(wlan_loader->boot_wlan_obj,
9501 wlan_loader->attr_group);
9502
9503 /* unlink the object from parent */
9504 kobject_del(wlan_loader->boot_wlan_obj);
9505
9506 /* free the object */
9507 kobject_put(wlan_loader->boot_wlan_obj);
9508
9509 kfree(wlan_loader->attr_group);
9510 kfree(wlan_loader);
9511
9512 wlan_loader = NULL;
9513}
9514
9515/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309516 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
9517 * ready
9518 *
9519 * This is creates the syfs entry boot_wlan. Which shall be invoked
9520 * when the filesystem is ready.
9521 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009522 * QDF API cannot be used here since this function is called even before
9523 * initializing WLAN driver.
9524 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009525 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +05309526 */
9527static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009528{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009529 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +05309530
9531 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
9532 if (!wlan_loader) {
9533 pr_err("%s: memory alloc failed\n", __func__);
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009534 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +05309535 }
9536
9537 wlan_loader->boot_wlan_obj = NULL;
9538 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
9539 GFP_KERNEL);
9540 if (!wlan_loader->attr_group) {
9541 pr_err("%s: malloc attr_group failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +05309542 goto error_return;
9543 }
9544
9545 wlan_loader->loaded_state = 0;
9546 wlan_loader->attr_group->attrs = attrs;
9547
9548 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
9549 kernel_kobj);
9550 if (!wlan_loader->boot_wlan_obj) {
9551 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +05309552 goto error_return;
9553 }
9554
9555 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
9556 wlan_loader->attr_group);
9557 if (ret) {
9558 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
9559 goto error_return;
9560 }
9561
9562 return 0;
9563
9564error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009565 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +05309566
9567 return ret;
9568}
9569
9570/**
9571 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
9572 *
9573 * Return: 0 on success or errno on failure
9574 */
9575static int wlan_deinit_sysfs(void)
9576{
Arun Khandavallifae92942016-08-01 13:31:08 +05309577 if (!wlan_loader) {
9578 hdd_alert("wlan loader context is Null!");
9579 return -EINVAL;
9580 }
9581
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009582 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009583 return 0;
9584}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009585
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009586#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +05309587
9588#ifdef MODULE
9589/**
9590 * __hdd_module_init - Module init helper
9591 *
9592 * Module init helper function used by both module and static driver.
9593 *
9594 * Return: 0 for success, errno on failure
9595 */
9596static int hdd_module_init(void)
9597{
9598 int ret = 0;
9599
9600 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9601 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9602
9603 if (__hdd_module_init()) {
9604 pr_err("%s: Failed to register handler\n", __func__);
9605 ret = -EINVAL;
9606 }
9607
9608 return ret;
9609}
9610#else
9611static int __init hdd_module_init(void)
9612{
9613 int ret = -EINVAL;
9614
9615 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009616 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +05309617 pr_err("Failed to create sysfs entry for loading wlan");
9618
9619 return ret;
9620}
9621#endif
9622
9623
9624#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009625/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009626 * hdd_module_exit() - Exit function
9627 *
9628 * This is the driver exit point (invoked when module is unloaded using rmmod)
9629 *
9630 * Return: None
9631 */
9632static void __exit hdd_module_exit(void)
9633{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009634 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009635}
Arun Khandavallifae92942016-08-01 13:31:08 +05309636#else
9637static void __exit hdd_module_exit(void)
9638{
9639 __hdd_module_exit();
9640 wlan_deinit_sysfs();
9641}
9642#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009643
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009644static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
9645{
9646 return param_set_copystring(kmessage, kp);
9647}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009648
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309649/**
9650 * is_con_mode_valid() check con mode is valid or not
9651 * @mode: global con mode
9652 *
9653 * Return: TRUE on success FALSE on failure
9654 */
9655static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
9656{
9657 switch (mode) {
9658 case QDF_GLOBAL_MONITOR_MODE:
9659 case QDF_GLOBAL_FTM_MODE:
9660 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309661 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309662 return true;
9663 default:
9664 return false;
9665 }
9666}
9667
9668/**
9669 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
9670 * @mode: global con mode
9671 *
9672 * Return: adapter mode
9673 */
9674static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
9675 enum tQDF_GLOBAL_CON_MODE mode)
9676{
9677
9678 switch (mode) {
9679 case QDF_GLOBAL_MISSION_MODE:
9680 return QDF_STA_MODE;
9681 case QDF_GLOBAL_MONITOR_MODE:
9682 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309683 case QDF_GLOBAL_EPPING_MODE:
9684 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309685 case QDF_GLOBAL_FTM_MODE:
9686 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309687 case QDF_GLOBAL_QVIT_MODE:
9688 return QDF_QVIT_MODE;
9689 default:
9690 return QDF_MAX_NO_OF_MODE;
9691 }
9692}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009693
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309694static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
9695 enum tQDF_GLOBAL_CON_MODE curr_mode)
9696{
9697 switch (curr_mode) {
9698 case QDF_GLOBAL_MISSION_MODE:
9699 case QDF_GLOBAL_MONITOR_MODE:
9700 case QDF_GLOBAL_FTM_MODE:
9701 hdd_abort_mac_scan_all_adapters(hdd_ctx);
9702 hdd_stop_all_adapters(hdd_ctx);
9703 hdd_deinit_all_adapters(hdd_ctx, false);
9704 hdd_close_all_adapters(hdd_ctx, false);
9705 break;
9706 case QDF_GLOBAL_EPPING_MODE:
9707 epping_disable();
9708 epping_close();
9709 break;
9710 default:
9711 return;
9712 }
9713}
9714
9715static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
9716 enum tQDF_GLOBAL_CON_MODE mode)
9717{
9718 hdd_adapter_t *adapter;
9719 int ret = 0;
9720 bool rtnl_held;
9721 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
9722 QDF_STATUS status;
9723
9724 if (!qdf_dev) {
9725 hdd_err("qdf device context is Null return!");
9726 return -EINVAL;
9727 }
9728
9729 rtnl_held = hdd_hold_rtnl_lock();
9730 switch (mode) {
9731 case QDF_GLOBAL_MISSION_MODE:
9732 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
9733 if (IS_ERR(adapter)) {
9734 hdd_alert("Failed to open interface, adapter is NULL");
9735 ret = -EINVAL;
9736 }
9737 break;
9738 case QDF_GLOBAL_FTM_MODE:
9739 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
9740 wlan_hdd_get_intf_addr(hdd_ctx),
9741 NET_NAME_UNKNOWN, rtnl_held);
9742 if (adapter == NULL)
9743 ret = -EINVAL;
9744 break;
9745 case QDF_GLOBAL_MONITOR_MODE:
9746 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
9747 wlan_hdd_get_intf_addr(hdd_ctx),
9748 NET_NAME_UNKNOWN, rtnl_held);
9749 if (adapter == NULL)
9750 ret = -EINVAL;
9751 break;
9752 case QDF_GLOBAL_EPPING_MODE:
9753 status = epping_open();
9754 if (status != QDF_STATUS_SUCCESS) {
9755 hdd_err("Failed to open in eeping mode: %d", status);
9756 ret = -EINVAL;
9757 break;
9758 }
9759 ret = epping_enable(qdf_dev->dev);
9760 if (ret) {
9761 hdd_err("Failed to enable in epping mode : %d", ret);
9762 epping_close();
9763 }
9764 break;
9765 default:
9766 hdd_info("Mode not supported");
9767 ret = -ENOTSUPP;
9768 break;
9769 }
9770 hdd_release_rtnl_lock();
9771 rtnl_held = false;
9772 return ret;
9773}
9774
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009775/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309776 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309777 * @kmessage: con mode name on which driver to be bring up
9778 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309779 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009780 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309781 * This function is invoked when user updates con mode using sys entry,
9782 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009783 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309784 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009785 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309786static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
9787 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009788{
9789 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309790 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309791 enum tQDF_GLOBAL_CON_MODE curr_mode;
9792 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309793
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309794 ret = wlan_hdd_validate_context(hdd_ctx);
9795 if (ret)
9796 return ret;
9797
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309798 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009799
Arun Khandavallifae92942016-08-01 13:31:08 +05309800 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009801 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05309802
Arun Khandavallifae92942016-08-01 13:31:08 +05309803
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309804
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309805 if (!(is_con_mode_valid(con_mode))) {
9806 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309807 ret = -EINVAL;
9808 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309809 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309810
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309811 curr_mode = hdd_get_conparam();
9812 if (curr_mode == con_mode) {
9813 hdd_err("curr mode: %d is same as user triggered mode %d",
9814 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309815 ret = 0;
9816 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309817 }
9818
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309819 /* Cleanup present mode before switching to new mode */
9820 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05309821
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07009822 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309823 if (ret) {
9824 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309825 goto reset_flags;
9826 }
9827
9828 hdd_set_conparam(con_mode);
9829
9830 /* Register for new con_mode & then kick_start modules again */
9831 ret = hdd_register_req_mode(hdd_ctx, con_mode);
9832 if (ret) {
9833 hdd_err("Failed to register for new mode");
9834 goto reset_flags;
9835 }
9836
9837 adapter_mode = hdd_get_adpter_mode(con_mode);
9838 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
9839 hdd_err("invalid adapter");
9840 ret = -EINVAL;
9841 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309842 }
9843
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309844 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309845 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309846 hdd_err("Failed to get adapter:%d", adapter_mode);
9847 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309848 }
9849
9850 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
9851 if (ret) {
9852 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309853 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309854 }
9855
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309856 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
9857 con_mode == QDF_GLOBAL_FTM_MODE) {
9858 if (hdd_start_adapter(adapter)) {
9859 hdd_err("Failed to start %s adapter", kmessage);
9860 ret = -EINVAL;
9861 goto reset_flags;
9862 }
Arun Khandavallifae92942016-08-01 13:31:08 +05309863 }
9864
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309865 hdd_info("Mode successfully changed to %s", kmessage);
9866 ret = 0;
9867
9868reset_flags:
9869 cds_set_load_in_progress(false);
9870 return ret;
9871}
9872
9873
9874static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
9875{
9876 int ret;
9877 hdd_context_t *hdd_ctx;
9878
9879 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9880 ret = wlan_hdd_validate_context(hdd_ctx);
9881 if (ret)
9882 return ret;
9883
9884 cds_ssr_protect(__func__);
9885 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
9886 cds_ssr_unprotect(__func__);
9887
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009888 return ret;
9889}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009890
9891/**
9892 * hdd_get_conparam() - driver exit point
9893 *
9894 * This is the driver exit point (invoked when module is unloaded using rmmod)
9895 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309896 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009897 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309898enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009899{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309900 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009901}
9902
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009903void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009904{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009905 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009906}
9907
Komal Seelamc11bb222016-01-27 18:57:10 +05309908/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309909 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9910 * @hdd_ctx: HDD context
9911 *
9912 * Cleans up the pre cac interface, if it exists
9913 *
9914 * Return: None
9915 */
9916void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9917{
9918 uint8_t session_id;
9919 QDF_STATUS status;
9920 struct hdd_adapter_s *precac_adapter;
9921
9922 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9923 if (QDF_IS_STATUS_ERROR(status)) {
9924 hdd_err("failed to get pre cac vdev id");
9925 return;
9926 }
9927
9928 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9929 if (!precac_adapter) {
9930 hdd_err("invalid pre cac adapater");
9931 return;
9932 }
9933
9934 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9935 wlan_hdd_sap_pre_cac_failure,
9936 (void *)precac_adapter);
9937 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9938
9939}
9940
9941/**
Komal Seelamec702b02016-02-24 18:42:16 +05309942 * hdd_update_ol_config - API to update ol configuration parameters
9943 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309944 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309945 * Return: void
9946 */
Komal Seelamec702b02016-02-24 18:42:16 +05309947static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309948{
Komal Seelamec702b02016-02-24 18:42:16 +05309949 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309950 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309951
Komal Seelamec702b02016-02-24 18:42:16 +05309952 if (!ol_ctx)
9953 return;
9954
9955 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9956 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9957 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9958 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -07009959 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +05309960
9961 ol_init_ini_config(ol_ctx, &cfg);
9962}
9963
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009964#ifdef FEATURE_RUNTIME_PM
9965/**
9966 * hdd_populate_runtime_cfg() - populate runtime configuration
9967 * @hdd_ctx: hdd context
9968 * @cfg: pointer to the configuration memory being populated
9969 *
9970 * Return: void
9971 */
9972static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9973 struct hif_config_info *cfg)
9974{
9975 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9976 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9977}
9978#else
9979static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9980 struct hif_config_info *cfg)
9981{
9982}
9983#endif
9984
Komal Seelamec702b02016-02-24 18:42:16 +05309985/**
9986 * hdd_update_hif_config - API to update HIF configuration parameters
9987 * @hdd_ctx: HDD Context
9988 *
9989 * Return: void
9990 */
9991static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9992{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309993 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309994 struct hif_config_info cfg;
9995
9996 if (!scn)
9997 return;
9998
9999 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010000 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053010001 hif_init_ini_config(scn, &cfg);
10002}
10003
10004/**
10005 * hdd_update_config() - Initialize driver per module ini parameters
10006 * @hdd_ctx: HDD Context
10007 *
10008 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010009 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053010010 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010011int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053010012{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010013 int ret;
10014
Komal Seelamec702b02016-02-24 18:42:16 +053010015 hdd_update_ol_config(hdd_ctx);
10016 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
10018 ret = hdd_update_cds_config_ftm(hdd_ctx);
10019 else
10020 ret = hdd_update_cds_config(hdd_ctx);
10021
10022 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053010023}
10024
Agrawal Ashish65634612016-08-18 13:24:32 +053010025/**
10026 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
10027 * @mode : cfg80211 DFS mode
10028 *
10029 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
10030 */
10031enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
10032{
10033 switch (mode) {
10034 case DFS_MODE_ENABLE:
10035 return ACS_DFS_MODE_ENABLE;
10036 break;
10037 case DFS_MODE_DISABLE:
10038 return ACS_DFS_MODE_DISABLE;
10039 break;
10040 case DFS_MODE_DEPRIORITIZE:
10041 return ACS_DFS_MODE_DEPRIORITIZE;
10042 break;
10043 default:
10044 hdd_err("ACS dfs mode is NONE");
10045 return ACS_DFS_MODE_NONE;
10046 }
10047}
10048
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053010049/**
10050 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
10051 * @hddctx: pointer to hdd context
10052 * @set_value: enable/disable
10053 *
10054 * When Host sends vendor command enable, FW will send *ONE* CA ind to
10055 * Host(even though it is duplicate). When Host send vendor command
10056 * disable,FW doesn't perform any action. Whenever any change in
10057 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
10058 *
10059 * return - 0 on success, appropriate error values on failure.
10060 */
10061int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
10062{
10063 QDF_STATUS status;
10064
10065 if (0 != wlan_hdd_validate_context(hddctx)) {
10066 return -EAGAIN;
10067 }
10068
10069 if (!hddctx->config->goptimize_chan_avoid_event) {
10070 hdd_warn("goptimize_chan_avoid_event ini param disabled");
10071 return -EINVAL;
10072 }
10073
10074 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
10075 if (!QDF_IS_STATUS_SUCCESS(status)) {
10076 hdd_err("Failed to send chan avoid command to SME");
10077 return -EINVAL;
10078 }
10079 return 0;
10080}
Agrawal Ashish65634612016-08-18 13:24:32 +053010081
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010082/**
10083 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
10084 * @value: value to set
10085 *
10086 * This function will set the passed value to roaming in progress flag.
10087 *
10088 * Return: None
10089 */
10090void hdd_set_roaming_in_progress(bool value)
10091{
10092 hdd_context_t *hdd_ctx;
10093
10094 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10095 if (!hdd_ctx) {
10096 hdd_err("HDD context is NULL");
10097 return;
10098 }
10099
10100 hdd_ctx->roaming_in_progress = value;
10101 hdd_info("Roaming in Progress set to %d", value);
10102}
10103
10104/**
10105 * hdd_is_roaming_in_progress() - check if roaming is in progress
10106 * @hdd_ctx - HDD context
10107 *
10108 * Return: true if roaming is in progress else false
10109 */
10110bool hdd_is_roaming_in_progress(void)
10111{
10112 hdd_context_t *hdd_ctx;
10113
10114 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10115 if (!hdd_ctx) {
10116 hdd_err("HDD context is NULL");
10117 return false;
10118 }
10119 return hdd_ctx->roaming_in_progress;
10120}
10121
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010122/* Register the module init/exit functions */
10123module_init(hdd_module_init);
10124module_exit(hdd_module_exit);
10125
10126MODULE_LICENSE("Dual BSD/GPL");
10127MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10128MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10129
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010130module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10131 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010132
10133module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
10134 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
10135
10136module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
10137
10138module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
10139
10140module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);