blob: fdd6390789834b9c68c891bf3081cee4d8a65d33 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
Jeff Johnson94be11c2016-08-15 15:39:25 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038/* Include Files */
39#include <wlan_hdd_includes.h>
40#include <cds_api.h>
41#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053042#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#include <linux/etherdevice.h>
44#include <linux/firmware.h>
45#include <wlan_hdd_tx_rx.h>
46#include <wni_api.h>
47#include <wlan_hdd_cfg.h>
48#include <wlan_ptt_sock_svc.h>
49#include <dbglog_host.h>
50#include <wlan_logging_sock_svc.h>
51#include <wlan_hdd_wowl.h>
52#include <wlan_hdd_misc.h>
53#include <wlan_hdd_wext.h>
54#include "wlan_hdd_trace.h"
55#include "wlan_hdd_ioctl.h"
56#include "wlan_hdd_ftm.h"
57#include "wlan_hdd_power.h"
58#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070059#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070062#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063
64#include <net/addrconf.h>
65#include <linux/wireless.h>
66#include <net/cfg80211.h>
67#include <linux/inetdevice.h>
68#include <net/addrconf.h>
69#include "wlan_hdd_cfg80211.h"
70#include "wlan_hdd_ext_scan.h"
71#include "wlan_hdd_p2p.h"
72#include <linux/rtnetlink.h>
73#include "sap_api.h"
74#include <linux/semaphore.h>
75#include <linux/ctype.h>
76#include <linux/compat.h>
77#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078#include <soc/qcom/subsystem_restart.h>
79#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080#include <wlan_hdd_hostapd.h>
81#include <wlan_hdd_softap_tx_rx.h>
82#include "cfg_api.h"
83#include "qwlan_version.h"
84#include "wma_types.h"
85#include "wlan_hdd_tdls.h"
86#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053087#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080088#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070090#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080091#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#include "wlan_hdd_nan.h"
93#include "wlan_hdd_debugfs.h"
94#include "wlan_hdd_driver_ops.h"
95#include "epping_main.h"
96#include "wlan_hdd_memdump.h"
97
98#include <wlan_hdd_ipa.h>
99#include "hif.h"
100#include "wma.h"
101#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700102#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530104#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700105#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530106#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700107#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530108#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700109#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530110#include "wlan_hdd_disa.h"
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
370 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
371 (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,
419 eCSR_SCAN_ABORT_DEFAULT);
420 rc = wait_for_completion_timeout(
421 &adapter->scan_info.abortscan_event_var,
422 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
423 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700424 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425 }
426 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700427 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 }
429 break;
430
431 default:
432 break;
433 }
434
435 return NOTIFY_DONE;
436}
437
438/**
439 * hdd_netdev_notifier_call() - netdev notifier callback function
440 * @nb: pointer to notifier block
441 * @state: state
442 * @ndev: ndev pointer
443 *
444 * Return: 0 on success, error number otherwise.
445 */
446static int hdd_netdev_notifier_call(struct notifier_block *nb,
447 unsigned long state,
448 void *ndev)
449{
450 int ret;
451
452 cds_ssr_protect(__func__);
453 ret = __hdd_netdev_notifier_call(nb, state, ndev);
454 cds_ssr_unprotect(__func__);
455
456 return ret;
457}
458
459struct notifier_block hdd_netdev_notifier = {
460 .notifier_call = hdd_netdev_notifier_call,
461};
462
463/* variable to hold the insmod parameters */
464static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800465
466/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800468
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530469/**
470 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
471 * @ch_width: NL channel width
472 *
473 * Converts the NL channel width to the driver's internal representation
474 *
475 * Return: Converted channel width. In case of non matching NL channel width,
476 * CH_WIDTH_MAX will be returned.
477 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800478enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530479{
480 switch (ch_width) {
481 case NL80211_CHAN_WIDTH_20_NOHT:
482 case NL80211_CHAN_WIDTH_20:
483 return CH_WIDTH_20MHZ;
484 case NL80211_CHAN_WIDTH_40:
485 return CH_WIDTH_40MHZ;
486 break;
487 case NL80211_CHAN_WIDTH_80:
488 return CH_WIDTH_80MHZ;
489 case NL80211_CHAN_WIDTH_80P80:
490 return CH_WIDTH_80P80MHZ;
491 case NL80211_CHAN_WIDTH_160:
492 return CH_WIDTH_160MHZ;
493 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800494 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530495 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800496 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530497 default:
498 hdd_err("Invalid channel width %d, setting to default",
499 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800500 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530501 }
502}
503
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530504/* wlan_hdd_find_opclass() - Find operating class for a channel
505 * @hal: handler to HAL
506 * @channel: channel id
507 * @bw_offset: bandwidth offset
508 *
509 * Function invokes sme api to find the operating class
510 *
511 * Return: operating class
512 */
513uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
514 uint8_t bw_offset)
515{
516 uint8_t opclass = 0;
517
518 sme_get_opclass(hal, channel, bw_offset, &opclass);
519 return opclass;
520}
521
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530523 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524 * @moduleId: Module whose trace level is being configured
525 * @bitmask: Bitmask of log levels to be enabled
526 *
527 * Called immediately after the cfg.ini is read in order to configure
528 * the desired trace levels.
529 *
530 * Return: None
531 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530532static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800533{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530534 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800535
536 /*
537 * if the bitmask is the default value, then a bitmask was not
538 * specified in cfg.ini, so leave the logging level alone (it
539 * will remain at the "compiled in" default value)
540 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530541 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 return;
543 }
544
545 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530546 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547
548 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530549 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 while (0 != bitmask) {
551 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530552 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 }
554 level++;
555 bitmask >>= 1;
556 }
557}
558
559/**
560 * wlan_hdd_validate_context() - check the HDD context
561 * @hdd_ctx: HDD context pointer
562 *
563 * Return: 0 if the context is valid. Error code otherwise
564 */
565int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
566{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530568 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569 return -ENODEV;
570 }
571
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800572 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530573 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
574 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575 return -EAGAIN;
576 }
577
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800578 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530579 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
580 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581 return -EAGAIN;
582 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530583
584 if (hdd_ctx->start_modules_in_progress ||
585 hdd_ctx->stop_modules_in_progress) {
586 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
587 (void *)_RET_IP_);
588 return -EAGAIN;
589 }
590
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 return 0;
592}
593
594void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
595{
596 hdd_adapter_t *adapter = NULL;
597 hdd_station_ctx_t *pHddStaCtx = NULL;
598 eCsrPhyMode phyMode;
599 struct hdd_config *cfg_param = NULL;
600
601 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700602 hdd_alert("HDD Context is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 return;
604 }
605
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800606 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607 if (NULL == adapter) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700608 hdd_alert("adapter is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609 return;
610 }
611
612 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
613
614 cfg_param = hdd_ctx->config;
615 if (NULL == cfg_param) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700616 hdd_alert("cfg_params not available !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 return;
618 }
619
620 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
621
622 if (!hdd_ctx->isVHT80Allowed) {
623 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
624 (eCSR_DOT11_MODE_11ac == phyMode) ||
625 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700626 hdd_notice("Setting phymode to 11n!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
628 eCSR_DOT11_MODE_11n);
629 }
630 } else {
631 /*
632 * New country Supports 11ac as well resetting value back from
633 * .ini
634 */
635 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
636 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
637 dot11Mode));
638 return;
639 }
640
641 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
642 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
643 || (eCSR_CFG_DOT11_MODE_11AC ==
644 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530645 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646
647 /* need to issue a disconnect to CSR. */
648 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530649 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650 adapter->sessionId,
651 eCSR_DISCONNECT_REASON_UNSPECIFIED);
652
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530653 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 unsigned long rc;
655
656 rc = wait_for_completion_timeout(
657 &adapter->disconnect_comp_var,
658 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
659 if (!rc)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700660 hdd_err("failure waiting for disconnect_comp_var");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 }
662 }
663}
664
665/**
666 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
667 * @hdd_adapter_t Hdd adapter.
668 *
669 * This function sets the IBSS power save config parameters to WMA
670 * which will send it to firmware if FW supports IBSS power save
671 * before vdev start.
672 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530673 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800674 * on failure.
675 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677{
678 int ret;
679 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
680
681 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700682 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530683 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 }
685
686 ret = wma_cli_set_command(adapter->sessionId,
687 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
688 hdd_ctx->config->ibssATIMWinSize,
689 VDEV_CMD);
690 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700691 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530692 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 }
694
695 ret = wma_cli_set_command(adapter->sessionId,
696 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
697 hdd_ctx->config->isIbssPowerSaveAllowed,
698 VDEV_CMD);
699 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700700 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
701 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530702 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 }
704
705 ret = wma_cli_set_command(adapter->sessionId,
706 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
707 hdd_ctx->config->
708 isIbssPowerCollapseAllowed, VDEV_CMD);
709 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700710 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
711 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530712 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 }
714
715 ret = wma_cli_set_command(adapter->sessionId,
716 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
717 hdd_ctx->config->isIbssAwakeOnTxRx,
718 VDEV_CMD);
719 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700720 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530721 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 }
723
724 ret = wma_cli_set_command(adapter->sessionId,
725 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
726 hdd_ctx->config->ibssInactivityCount,
727 VDEV_CMD);
728 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700729 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530730 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731 }
732
733 ret = wma_cli_set_command(adapter->sessionId,
734 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
735 hdd_ctx->config->ibssTxSpEndInactivityTime,
736 VDEV_CMD);
737 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700738 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
739 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530740 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800741 }
742
743 ret = wma_cli_set_command(adapter->sessionId,
744 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
745 hdd_ctx->config->ibssPsWarmupTime,
746 VDEV_CMD);
747 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700748 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
749 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530750 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751 }
752
753 ret = wma_cli_set_command(adapter->sessionId,
754 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
755 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
756 VDEV_CMD);
757 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700758 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
759 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530760 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761 }
762
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530763 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764}
765
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766#define INTF_MACADDR_MASK 0x7
767
768/**
769 * hdd_update_macaddr() - update mac address
770 * @config: hdd configuration
771 * @hw_macaddr: mac address
772 *
773 * Mac address for multiple virtual interface is found as following
774 * i) The mac address of the first interface is just the actual hw mac address.
775 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
776 * define the mac address for the remaining interfaces and locally
777 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
778 * supported virtual interfaces, right now this is 0x07 (meaning 8
779 * interface).
780 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
781 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
782 *
783 * Return: None
784 */
785void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530786 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787{
788 int8_t i;
789 uint8_t macaddr_b3, tmp_br3;
790
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530791 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530792 QDF_MAC_ADDR_SIZE);
793 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530794 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530795 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796 macaddr_b3 = config->intfMacAddr[i].bytes[3];
797 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
798 INTF_MACADDR_MASK;
799 macaddr_b3 += tmp_br3;
800
801 /* XOR-ing bit-24 of the mac address. This will give enough
802 * mac address range before collision
803 */
804 macaddr_b3 ^= (1 << 7);
805
806 /* Set locally administered bit */
807 config->intfMacAddr[i].bytes[0] |= 0x02;
808 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700809 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 MAC_ADDRESS_STR, i,
811 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
812 }
813}
814
815static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
816 struct wma_tgt_services *cfg)
817{
818 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819
820 /* Set up UAPSD */
821 config->apUapsdEnabled &= cfg->uapsd;
822
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 /* 11AC mode support */
824 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
825 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
826 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827
828 /* ARP offload: override user setting if invalid */
829 config->fhostArpOffload &= cfg->arp_offload;
830
831#ifdef FEATURE_WLAN_SCAN_PNO
832 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700833 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834 if (cfg->pno_offload)
835 config->PnoOffload = true;
836#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837#ifdef FEATURE_WLAN_TDLS
838 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530839 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
840 cfg->en_tdls_offchan;
841 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
842 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
844 config->fEnableTDLSSleepSta = true;
845 } else {
846 config->fEnableTDLSSleepSta = false;
847 }
848#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849#ifdef WLAN_FEATURE_ROAM_OFFLOAD
850 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
851#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700852 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853
854}
855
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700856/**
857 * hdd_update_vdev_nss() - sets the vdev nss
858 * @hdd_ctx: HDD context
859 *
860 * Sets the Nss per vdev type based on INI
861 *
862 * Return: None
863 */
864static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
865{
866 struct hdd_config *cfg_ini = hdd_ctx->config;
867 uint8_t max_supp_nss = 1;
868
869 if (cfg_ini->enable2x2)
870 max_supp_nss = 2;
871
872 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
873 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
874
875 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
876 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
877}
878
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
880 struct wma_tgt_ht_cap *cfg)
881{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530882 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883 uint32_t value, val32;
884 uint16_t val16;
885 struct hdd_config *pconfig = hdd_ctx->config;
886 tSirMacHTCapabilityInfo *phtCapInfo;
887 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
888 uint8_t enable_tx_stbc;
889
890 /* check and update RX STBC */
891 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
892 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
893
894 /* get the MPDU density */
895 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
896
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530897 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700898 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800899 value = 0;
900 }
901
902 /*
903 * MPDU density:
904 * override user's setting if value is larger
905 * than the one supported by target
906 */
907 if (value > cfg->mpdu_density) {
908 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
909 cfg->mpdu_density);
910
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530911 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700912 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800913 }
914
915 /* get the HT capability info */
916 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530917 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700918 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919 return;
920 }
921 val16 = (uint16_t) val32;
922 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
923
924 /* Set the LDPC capability */
925 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
926
927 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
928 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
929
930 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
931 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
932
933 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
934 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
935
936 enable_tx_stbc = pconfig->enableTxSTBC;
937
938 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
939 pconfig->enable2x2 = 1;
940 } else {
941 pconfig->enable2x2 = 0;
942 enable_tx_stbc = 0;
943
944 /* 1x1 */
945 /* Update Rx Highest Long GI data Rate */
946 if (sme_cfg_set_int(hdd_ctx->hHal,
947 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700948 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530949 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700950 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800951 }
952
953 /* Update Tx Highest Long GI data Rate */
954 if (sme_cfg_set_int
955 (hdd_ctx->hHal,
956 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700957 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530958 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700959 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800960 }
961 }
962 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
963 enable_tx_stbc = 0;
964 phtCapInfo->txSTBC = enable_tx_stbc;
965
966 val32 = val16;
967 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530968 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700969 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
971 value = SIZE_OF_SUPPORTED_MCS_SET;
972 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530973 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700974 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800975
976 if (pconfig->enable2x2) {
977 for (value = 0; value < cfg->num_rf_chains; value++)
978 mcs_set[value] =
979 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
980
981 status =
982 sme_cfg_set_str(hdd_ctx->hHal,
983 WNI_CFG_SUPPORTED_MCS_SET,
984 mcs_set,
985 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530986 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700987 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988 }
989 }
990#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
991}
992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
994 struct wma_tgt_vht_cap *cfg)
995{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530996 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997 uint32_t value = 0;
998 struct hdd_config *pconfig = hdd_ctx->config;
999 struct wiphy *wiphy = hdd_ctx->wiphy;
1000 struct ieee80211_supported_band *band_5g =
1001 wiphy->bands[IEEE80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001002 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001003
Dustin Brown5e06bd32016-10-04 12:49:10 -07001004 if (!band_5g) {
1005 hdd_info("5GHz band disabled, skipping capability population");
1006 return;
1007 }
1008
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001009 /* Get the current MPDU length */
1010 status =
1011 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1012 &value);
1013
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301014 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001015 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016 value = 0;
1017 }
1018
1019 /*
1020 * VHT max MPDU length:
1021 * override if user configured value is too high
1022 * that the target cannot support
1023 */
1024 if (value > cfg->vht_max_mpdu) {
1025 status = sme_cfg_set_int(hdd_ctx->hHal,
1026 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1027 cfg->vht_max_mpdu);
1028
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301029 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001030 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 }
1032 }
1033
1034 /* Get the current supported chan width */
1035 status = sme_cfg_get_int(hdd_ctx->hHal,
1036 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1037 &value);
1038
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301039 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001040 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001041 value = 0;
1042 }
1043
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001044 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1045 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1046
1047 if (pconfig->enable2x2)
1048 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1049
1050 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1051 QDF_STATUS_E_FAILURE) {
1052 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1053 }
1054
1055 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1056 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1057 if (pconfig->enable2x2)
1058 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1059
1060 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1061 QDF_STATUS_E_FAILURE) {
1062 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1063 }
1064
1065 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1066 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1067 if (pconfig->enable2x2)
1068 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1069
1070 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1071 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1072
1073 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1074 QDF_STATUS_E_FAILURE) {
1075 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1076 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001077 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001078 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001079 &value);
1080
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301081 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001082 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001083 value = 0;
1084 }
1085
1086 /* Set the LDPC capability */
1087 if (value && !cfg->vht_rx_ldpc) {
1088 status = sme_cfg_set_int(hdd_ctx->hHal,
1089 WNI_CFG_VHT_LDPC_CODING_CAP,
1090 cfg->vht_rx_ldpc);
1091
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301092 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001093 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001094 }
1095 }
1096
1097 /* Get current GI 80 value */
1098 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1099 &value);
1100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301101 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001102 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 value = 0;
1104 }
1105
1106 /* set the Guard interval 80MHz */
1107 if (value && !cfg->vht_short_gi_80) {
1108 status = sme_cfg_set_int(hdd_ctx->hHal,
1109 WNI_CFG_VHT_SHORT_GI_80MHZ,
1110 cfg->vht_short_gi_80);
1111
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301112 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001113 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 }
1115 }
1116
1117 /* Get current GI 160 value */
1118 status = sme_cfg_get_int(hdd_ctx->hHal,
1119 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1120 &value);
1121
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301122 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001123 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001124 value = 0;
1125 }
1126
1127 /* Get VHT TX STBC cap */
1128 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1129
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301130 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001131 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 value = 0;
1133 }
1134
1135 /* VHT TX STBC cap */
1136 if (value && !cfg->vht_tx_stbc) {
1137 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1138 cfg->vht_tx_stbc);
1139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301140 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001141 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 }
1143 }
1144
1145 /* Get VHT RX STBC cap */
1146 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1147
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301148 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001149 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150 value = 0;
1151 }
1152
1153 /* VHT RX STBC cap */
1154 if (value && !cfg->vht_rx_stbc) {
1155 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1156 cfg->vht_rx_stbc);
1157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301158 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001159 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 }
1161 }
1162
1163 /* Get VHT SU Beamformer cap */
1164 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1165 &value);
1166
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301167 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001168 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001169 value = 0;
1170 }
1171
1172 /* set VHT SU Beamformer cap */
1173 if (value && !cfg->vht_su_bformer) {
1174 status = sme_cfg_set_int(hdd_ctx->hHal,
1175 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1176 cfg->vht_su_bformer);
1177
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301178 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001179 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001180 }
1181 }
1182
1183 /* check and update SU BEAMFORMEE capabality */
1184 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1185 pconfig->enableTxBF = cfg->vht_su_bformee;
1186
1187 status = sme_cfg_set_int(hdd_ctx->hHal,
1188 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1189 pconfig->enableTxBF);
1190
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301191 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001192 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001193 }
1194
1195 /* Get VHT MU Beamformer cap */
1196 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1197 &value);
1198
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301199 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001200 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201 value = 0;
1202 }
1203
1204 /* set VHT MU Beamformer cap */
1205 if (value && !cfg->vht_mu_bformer) {
1206 status = sme_cfg_set_int(hdd_ctx->hHal,
1207 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1208 cfg->vht_mu_bformer);
1209
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301210 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001211 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212 }
1213 }
1214
1215 /* Get VHT MU Beamformee cap */
1216 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1217 &value);
1218
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301219 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001220 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 value = 0;
1222 }
1223
1224 /* set VHT MU Beamformee cap */
1225 if (value && !cfg->vht_mu_bformee) {
1226 status = sme_cfg_set_int(hdd_ctx->hHal,
1227 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1228 cfg->vht_mu_bformee);
1229
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301230 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001231 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 }
1233 }
1234
1235 /* Get VHT MAX AMPDU Len exp */
1236 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1237 &value);
1238
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301239 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001240 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001241 value = 0;
1242 }
1243
1244 /*
1245 * VHT max AMPDU len exp:
1246 * override if user configured value is too high
1247 * that the target cannot support.
1248 * Even though Rome publish ampdu_len=7, it can
1249 * only support 4 because of some h/w bug.
1250 */
1251
1252 if (value > cfg->vht_max_ampdu_len_exp) {
1253 status = sme_cfg_set_int(hdd_ctx->hHal,
1254 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1255 cfg->vht_max_ampdu_len_exp);
1256
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301257 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001258 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 }
1260 }
1261
1262 /* Get VHT TXOP PS CAP */
1263 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1264
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301265 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001266 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 value = 0;
1268 }
1269
1270 /* set VHT TXOP PS cap */
1271 if (value && !cfg->vht_txop_ps) {
1272 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1273 cfg->vht_txop_ps);
1274
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301275 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001276 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001277 }
1278 }
1279
1280 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1281 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1282 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1283 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1284 else
1285 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1286
1287
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001288 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 band_5g->vht_cap.cap |=
1290 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001291 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001292 band_5g->vht_cap.cap |=
1293 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294
1295 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1296 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1297
1298 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1299 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1300 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1301 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1302
1303 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1304 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1305
1306 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1307 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1308 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1309 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1310 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1311 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1312
1313 band_5g->vht_cap.cap |=
1314 (cfg->vht_max_ampdu_len_exp <<
1315 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1316
1317 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1318 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1319 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1320 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1321 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1322 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1323 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1324 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1325
1326 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1327 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1328
1329}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001331/**
1332 * hdd_generate_macaddr_auto() - Auto-generate mac address
1333 * @hdd_ctx: Pointer to the HDD context
1334 *
1335 * Auto-generate mac address using device serial number.
1336 * Keep the first 3 bytes of OUI as before and replace
1337 * the last 3 bytes with the lower 3 bytes of serial number.
1338 *
1339 * Return: 0 for success
1340 * Non zero failure code for errors
1341 */
1342static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1343{
1344 unsigned int serialno = 0;
1345 struct qdf_mac_addr mac_addr = {
1346 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1347 };
1348
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001349 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001350 if (serialno == 0)
1351 return -EINVAL;
1352
1353 serialno &= 0x00ffffff;
1354
1355 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1356 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1357 mac_addr.bytes[5] = serialno & 0xff;
1358
1359 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1360 return 0;
1361}
1362
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301363/**
1364 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1365 * configuration to cfg_ini in HDD
1366 * @hdd_ctx: Pointer to hdd_ctx
1367 * @cfg: target configuration
1368 *
1369 * Return: None
1370 */
1371#ifdef FEATURE_WLAN_RA_FILTERING
1372static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1373 struct wma_tgt_cfg *cfg)
1374{
1375 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1376}
1377#else
1378static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1379 struct wma_tgt_cfg *cfg)
1380{
1381}
1382#endif
1383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384void hdd_update_tgt_cfg(void *context, void *param)
1385{
1386 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1387 struct wma_tgt_cfg *cfg = param;
1388 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001389 struct cds_config_info *cds_cfg = cds_get_ini_config();
1390
1391 if (cds_cfg) {
1392 if (hdd_ctx->config->enable_sub_20_channel_width !=
1393 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1394 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1395 cds_cfg->sub_20_channel_width =
1396 WLAN_SUB_20_CH_WIDTH_NONE;
1397 } else {
1398 cds_cfg->sub_20_channel_width =
1399 hdd_ctx->config->enable_sub_20_channel_width;
1400 }
1401 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001402
1403 /* first store the INI band capability */
1404 temp_band_cap = hdd_ctx->config->nBandCapability;
1405
1406 hdd_ctx->config->nBandCapability = cfg->band_cap;
1407
1408 /* now overwrite the target band capability with INI
1409 setting if INI setting is a subset */
1410
1411 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1412 (temp_band_cap != eCSR_BAND_ALL))
1413 hdd_ctx->config->nBandCapability = temp_band_cap;
1414 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1415 (temp_band_cap != eCSR_BAND_ALL) &&
1416 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001417 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418 }
1419
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001420 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001421 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1422 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1423 }
1424
1425 /* This can be extended to other configurations like ht, vht cap... */
1426
Anurag Chouhanc5548422016-02-24 18:33:27 +05301427 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001428 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001429 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001431 static struct qdf_mac_addr default_mac_addr = {
1432 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1433 };
1434 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1435 &default_mac_addr)) {
1436 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1437 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1438 MAC_ADDRESS_STR,
1439 MAC_ADDR_ARRAY(hdd_ctx->config->
1440 intfMacAddr[0].bytes));
1441 } else {
1442 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1443 MAC_ADDRESS_STR,
1444 MAC_ADDR_ARRAY(hdd_ctx->config->
1445 intfMacAddr[0].bytes));
1446 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001447 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 }
1449
1450 hdd_ctx->target_fw_version = cfg->target_fw_version;
1451
1452 hdd_ctx->max_intf_count = cfg->max_intf_count;
1453
Jeff Johnsonc875e242016-09-23 18:12:34 -07001454 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001455 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1458 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1459
1460 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001463
1464 hdd_update_vdev_nss(hdd_ctx);
1465
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001466 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001467 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001468 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001469 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001470
1471 hdd_ctx->current_antenna_mode =
1472 (hdd_ctx->config->enable2x2 == 0x01) ?
1473 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1474 hdd_info("Init current antenna mode: %d",
1475 hdd_ctx->current_antenna_mode);
1476
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001477 hdd_info("Target BPF %d Host BPF %d",
1478 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1479 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1480 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301481 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301482
Arun Khandavallid454d422016-08-17 12:47:05 +05301483 /*
1484 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1485 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1486 * configure the STA mode wow pattern.
1487 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301488 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301489 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301490
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301491 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1492
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001493 /* Configure NAN datapath features */
1494 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495}
1496
1497/**
1498 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1499 * @context: HDD context pointer
1500 * @param: HDD radar indication pointer
1501 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001502 * This function is invoked in atomic context when a radar
1503 * is found on the SAP current operating channel and Data Tx
1504 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505 * Actions: Stop the netif Tx queues,Indicate Radar present
1506 * in HDD context for future usage.
1507 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301508 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001509 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301510bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511{
1512 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1513 struct wma_dfs_radar_ind *hdd_radar_event =
1514 (struct wma_dfs_radar_ind *)param;
1515 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1516 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301517 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301518 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301520 if (!hdd_ctx || !hdd_radar_event ||
1521 hdd_ctx->config->disableDFSChSwitch)
1522 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523
1524 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001525 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301526 /*
1527 * Application already triggered channel switch
1528 * on current channel, so return here.
1529 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301530 return false;
1531 }
1532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301534 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301536 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1537 if ((QDF_SAP_MODE == adapter->device_mode ||
1538 QDF_P2P_GO_MODE == adapter->device_mode) &&
1539 (CHANNEL_STATE_DFS ==
1540 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1542 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301543 hdd_info("tx blocked for session:%d",
1544 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 }
1546
1547 status = hdd_get_next_adapter(hdd_ctx,
1548 adapterNode,
1549 &pNext);
1550 adapterNode = pNext;
1551 }
1552 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301553
1554 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556
1557/**
1558 * hdd_is_valid_mac_address() - validate MAC address
1559 * @pMacAddr: Pointer to the input MAC address
1560 *
1561 * This function validates whether the given MAC address is valid or not
1562 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1563 * where X is the hexa decimal digit character and separated by ':'
1564 * This algorithm works even if MAC address is not separated by ':'
1565 *
1566 * This code checks given input string mac contains exactly 12 hexadecimal
1567 * digits and a separator colon : appears in the input string only after
1568 * an even number of hex digits.
1569 *
1570 * Return: 1 for valid and 0 for invalid
1571 */
1572bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1573{
1574 int xdigit = 0;
1575 int separator = 0;
1576 while (*pMacAddr) {
1577 if (isxdigit(*pMacAddr)) {
1578 xdigit++;
1579 } else if (':' == *pMacAddr) {
1580 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1581 break;
1582
1583 ++separator;
1584 } else {
1585 /* Invalid MAC found */
1586 return 0;
1587 }
1588 ++pMacAddr;
1589 }
1590 return xdigit == 12 && (separator == 5 || separator == 0);
1591}
1592
1593/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301594 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1595 * @dev: Handle to struct net_device to be updated.
1596 *
1597 * Return: None
1598 */
1599static void hdd_mon_mode_ether_setup(struct net_device *dev)
1600{
1601 dev->header_ops = NULL;
1602 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1603 dev->hard_header_len = ETH_HLEN;
1604 dev->mtu = ETH_DATA_LEN;
1605 dev->addr_len = ETH_ALEN;
1606 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1607 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1608 dev->priv_flags |= IFF_TX_SKB_SHARING;
1609
1610 memset(dev->broadcast, 0xFF, ETH_ALEN);
1611}
1612
1613/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001614 * __hdd__mon_open() - HDD Open function
1615 * @dev: Pointer to net_device structure
1616 *
1617 * This is called in response to ifconfig up
1618 *
1619 * Return: 0 for success; non-zero for failure
1620 */
1621static int __hdd_mon_open(struct net_device *dev)
1622{
1623 int ret;
1624
1625 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301626 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001627 ret = hdd_set_mon_rx_cb(dev);
1628 return ret;
1629}
1630
1631/**
1632 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1633 * @dev: Pointer to net_device structure
1634 *
1635 * This is called in response to ifconfig up
1636 *
1637 * Return: 0 for success; non-zero for failure
1638 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001639static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001640{
1641 int ret;
1642
1643 cds_ssr_protect(__func__);
1644 ret = __hdd_mon_open(dev);
1645 cds_ssr_unprotect(__func__);
1646
1647 return ret;
1648}
1649
1650/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301651 * hdd_start_adapter() - Wrapper function for device specific adapter
1652 * @adapter: pointer to HDD adapter
1653 *
1654 * This function is called to start the device specific adapter for
1655 * the mode passed in the adapter's device_mode.
1656 *
1657 * Return: 0 for success; non-zero for failure
1658 */
1659int hdd_start_adapter(hdd_adapter_t *adapter)
1660{
1661
1662 int ret;
1663 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1664
1665 ENTER_DEV(adapter->dev);
1666 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1667
1668 switch (device_mode) {
1669 case QDF_P2P_CLIENT_MODE:
1670 case QDF_P2P_DEVICE_MODE:
1671 case QDF_OCB_MODE:
1672 case QDF_STA_MODE:
1673 case QDF_MONITOR_MODE:
1674 ret = hdd_start_station_adapter(adapter);
1675 if (ret)
1676 goto err_start_adapter;
1677 break;
1678 case QDF_P2P_GO_MODE:
1679 case QDF_SAP_MODE:
1680 ret = hdd_start_ap_adapter(adapter);
1681 if (ret)
1682 goto err_start_adapter;
1683 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301684 case QDF_IBSS_MODE:
1685 /*
1686 * For IBSS interface is initialized as part of
1687 * hdd_init_station_mode()
1688 */
1689 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301690 case QDF_FTM_MODE:
1691 ret = hdd_start_ftm_adapter(adapter);
1692 if (ret)
1693 goto err_start_adapter;
1694 break;
1695 default:
1696 hdd_err("Invalid session type %d", device_mode);
1697 QDF_ASSERT(0);
1698 goto err_start_adapter;
1699 }
1700 if (hdd_set_fw_params(adapter))
1701 hdd_err("Failed to set the FW params for the adapter!");
1702
1703 /*
1704 * Action frame registered in one adapter which will
1705 * applicable to all interfaces
1706 */
1707 wlan_hdd_cfg80211_register_frames(adapter);
1708 EXIT();
1709 return 0;
1710err_start_adapter:
1711 return -EINVAL;
1712}
1713
1714/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301715 * hdd_enable_power_management() - API to Enable Power Management
1716 *
1717 * API invokes Bus Interface Layer power management functionality
1718 *
1719 * Return: None
1720 */
1721static void hdd_enable_power_management(void)
1722{
1723 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1724
1725 if (!hif_ctx) {
1726 hdd_err("Bus Interface Context is Invalid");
1727 return;
1728 }
1729
1730 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1731}
1732
1733/**
1734 * hdd_disable_power_management() - API to disable Power Management
1735 *
1736 * API disable Bus Interface Layer Power management functionality
1737 *
1738 * Return: None
1739 */
1740static void hdd_disable_power_management(void)
1741{
1742 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1743
1744 if (!hif_ctx) {
1745 hdd_err("Bus Interface Context is Invalid");
1746 return;
1747 }
1748
1749 hif_disable_power_management(hif_ctx);
1750}
1751
1752/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301753 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1754 * @hdd_ctx: HDD context
1755 * @adapter: HDD adapter
1756 * @reinit: flag to indicate from SSR or normal path
1757 *
1758 * This function maintains the driver state machine it will be invoked from
1759 * startup, reinit and change interface. Depending on the driver state shall
1760 * perform the opening of the modules.
1761 *
1762 * Return: 0 for success; non-zero for failure
1763 */
1764int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1765 bool reinit)
1766{
1767 int ret;
1768 qdf_device_t qdf_dev;
1769 QDF_STATUS status;
1770 p_cds_contextType p_cds_context;
1771 bool unint = false;
1772 void *hif_ctx;
1773
1774 ENTER();
1775
1776 p_cds_context = cds_get_global_context();
1777 if (!p_cds_context) {
1778 hdd_err("Global Context is NULL");
1779 QDF_ASSERT(0);
1780 return -EINVAL;
1781 }
1782
1783 hdd_info("start modules called in state! :%d reinit: %d",
1784 hdd_ctx->driver_status, reinit);
1785
1786 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1787 if (!qdf_dev) {
1788 hdd_err("QDF Device Context is Invalid return");
1789 return -EINVAL;
1790 }
1791
1792 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301793 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301794
1795 if (QDF_TIMER_STATE_RUNNING ==
1796 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1797
1798 hdd_set_idle_ps_config(hdd_ctx, false);
1799 hdd_info("Interface change Timer running Stop timer");
1800 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1801 }
1802
1803 switch (hdd_ctx->driver_status) {
1804 case DRIVER_MODULES_UNINITIALIZED:
1805 unint = true;
1806 /* Fall through dont add break here */
1807 case DRIVER_MODULES_CLOSED:
1808 if (!reinit && !unint) {
1809 ret = pld_power_on(qdf_dev->dev);
1810 if (ret) {
1811 hdd_err("Failed to Powerup the device: %d", ret);
1812 goto release_lock;
1813 }
1814 }
1815 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1816 qdf_dev->bus_type,
1817 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1818 HIF_ENABLE_TYPE_PROBE);
1819 if (ret) {
1820 hdd_err("Failed to open hif: %d", ret);
1821 goto power_down;
1822 }
1823
1824 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301825 if (!hif_ctx) {
1826 hdd_err("hif context is null!!");
1827 goto power_down;
1828 }
1829
Arun Khandavallifae92942016-08-01 13:31:08 +05301830 status = ol_cds_init(qdf_dev, hif_ctx);
1831 if (status != QDF_STATUS_SUCCESS) {
1832 hdd_err("No Memory to Create BMI Context :%d", status);
1833 goto hif_close;
1834 }
1835
Arun Khandavallif6246632016-08-17 17:43:06 +05301836 ret = hdd_update_config(hdd_ctx);
1837 if (ret) {
1838 hdd_err("Failed to update configuration :%d", ret);
1839 goto ol_cds_free;
1840 }
1841
Arun Khandavallifae92942016-08-01 13:31:08 +05301842 status = cds_open();
1843 if (!QDF_IS_STATUS_SUCCESS(status)) {
1844 hdd_err("Failed to Open CDS: %d", status);
1845 goto ol_cds_free;
1846 }
1847
1848 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1849
1850 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1851
1852 status = cds_pre_enable(hdd_ctx->pcds_context);
1853 if (!QDF_IS_STATUS_SUCCESS(status)) {
1854 hdd_err("Failed to pre-enable CDS: %d", status);
1855 goto close;
1856 }
1857
1858 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1859 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1860 hdd_ftm_mc_process_msg);
1861 break;
1862 }
1863 if (unint) {
1864 hdd_info("In phase-1 initialization don't enable modules");
1865 break;
1866 }
1867 /* Fall through dont add break here */
1868 case DRIVER_MODULES_OPENED:
1869 if (!adapter) {
1870 hdd_alert("adapter is Null");
1871 goto close;
1872 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05301873 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1874 hdd_err("in ftm mode, no need to configure cds modules");
1875 break;
1876 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301877 if (hdd_configure_cds(hdd_ctx, adapter)) {
1878 hdd_err("Failed to Enable cds modules");
1879 goto close;
1880 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05301881 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05301882 hdd_info("Driver Modules Successfully Enabled");
1883 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1884 break;
1885 case DRIVER_MODULES_ENABLED:
1886 hdd_info("Driver modules already Enabled");
1887 break;
1888 default:
1889 hdd_err("WLAN start invoked in wrong state! :%d\n",
1890 hdd_ctx->driver_status);
1891 goto release_lock;
1892 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301893 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301894 mutex_unlock(&hdd_ctx->iface_change_lock);
1895 EXIT();
1896 return 0;
1897
1898close:
1899 cds_close(p_cds_context);
1900
1901ol_cds_free:
1902 ol_cds_free();
1903
1904hif_close:
1905 hdd_hif_close(p_cds_context->pHIFContext);
1906power_down:
1907 if (!reinit && !unint)
1908 pld_power_off(qdf_dev->dev);
1909release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301910 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301911 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301912 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301913 return -EINVAL;
1914}
1915
1916/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001917 * __hdd_open() - HDD Open function
1918 * @dev: Pointer to net_device structure
1919 *
1920 * This is called in response to ifconfig up
1921 *
1922 * Return: 0 for success; non-zero for failure
1923 */
1924static int __hdd_open(struct net_device *dev)
1925{
1926 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1927 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1928 int ret;
1929
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001930 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301931 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301932 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933
1934 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301935 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301937
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938
Arun Khandavallifae92942016-08-01 13:31:08 +05301939 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1940 if (ret) {
1941 hdd_err("Failed to start WLAN modules return");
1942 return -ret;
1943 }
1944
1945
1946 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1947 ret = hdd_start_adapter(adapter);
1948 if (ret) {
1949 hdd_err("Failed to start adapter :%d",
1950 adapter->device_mode);
1951 return ret;
1952 }
1953 }
1954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1956 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301957 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958 /* Enable TX queues only when we are connected */
1959 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301960 WLAN_START_ALL_NETIF_QUEUE,
1961 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 }
1963
1964 return ret;
1965}
1966
Arun Khandavallifae92942016-08-01 13:31:08 +05301967
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968/**
1969 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1970 * @dev: Pointer to net_device structure
1971 *
1972 * This is called in response to ifconfig up
1973 *
1974 * Return: 0 for success; non-zero for failure
1975 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001976static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977{
1978 int ret;
1979
1980 cds_ssr_protect(__func__);
1981 ret = __hdd_open(dev);
1982 cds_ssr_unprotect(__func__);
1983
1984 return ret;
1985}
1986
1987/**
1988 * __hdd_stop() - HDD stop function
1989 * @dev: Pointer to net_device structure
1990 *
1991 * This is called in response to ifconfig down
1992 *
1993 * Return: 0 for success; non-zero for failure
1994 */
1995static int __hdd_stop(struct net_device *dev)
1996{
1997 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1998 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301999 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05302001 bool close_modules = true;
2002 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002004 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302006 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 adapter->sessionId, adapter->device_mode));
2008
2009 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302010 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012
2013 /* Nothing to be done if the interface is not opened */
2014 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002015 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 return -ENODEV;
2017 }
2018
2019 /* Make sure the interface is marked as closed */
2020 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002021 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022
2023 /*
2024 * Disable TX on the interface, after this hard_start_xmit() will not
2025 * be called on that interface
2026 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002027 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2029 WLAN_CONTROL_PATH);
2030
2031 /*
2032 * The interface is marked as down for outside world (aka kernel)
2033 * But the driver is pretty much alive inside. The driver needs to
2034 * tear down the existing connection on the netdev (session)
2035 * cleanup the data pipes and wait until the control plane is stabilized
2036 * for this interface. The call also needs to wait until the above
2037 * mentioned actions are completed before returning to the caller.
2038 * Notice that the hdd_stop_adapter is requested not to close the session
2039 * That is intentional to be able to scan if it is a STA/P2P interface
2040 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302041 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042
2043 /* DeInit the adapter. This ensures datapath cleanup as well */
2044 hdd_deinit_adapter(hdd_ctx, adapter, true);
2045
Arun Khandavallifae92942016-08-01 13:31:08 +05302046
2047 /*
2048 * Find if any iface is up. If any iface is up then can't put device to
2049 * sleep/power save mode
2050 */
2051 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2052 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2053 if (test_bit(DEVICE_IFACE_OPENED,
2054 &adapternode->pAdapter->event_flags)) {
2055 hdd_info("Still other ifaces are up cannot close modules");
2056 close_modules = false;
2057 break;
2058 }
2059 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2060 adapternode = next;
2061
2062 }
2063
2064 if (close_modules) {
2065 hdd_info("Closing all modules from the hdd_stop");
2066 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2067 hdd_ctx->config->iface_change_wait_time
2068 * 50000);
2069 }
2070
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 EXIT();
2072 return 0;
2073}
2074
2075/**
2076 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2077 * @dev: pointer to net_device structure
2078 *
2079 * This is called in response to ifconfig down
2080 *
2081 * Return: 0 for success and error number for failure
2082 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002083static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084{
2085 int ret;
2086
2087 cds_ssr_protect(__func__);
2088 ret = __hdd_stop(dev);
2089 cds_ssr_unprotect(__func__);
2090
2091 return ret;
2092}
2093
2094/**
2095 * __hdd_uninit() - HDD uninit function
2096 * @dev: Pointer to net_device structure
2097 *
2098 * This is called during the netdev unregister to uninitialize all data
2099 * associated with the device
2100 *
2101 * Return: None
2102 */
2103static void __hdd_uninit(struct net_device *dev)
2104{
2105 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2106
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002107 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002108
2109 do {
2110 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002111 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002112 break;
2113 }
2114
2115 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002116 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117 break;
2118 }
2119
2120 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002121 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 /*
2123 * we haven't validated all cases so let this go for
2124 * now
2125 */
2126 }
2127
2128 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2129
2130 /* after uninit our adapter structure will no longer be valid */
2131 adapter->dev = NULL;
2132 adapter->magic = 0;
2133 } while (0);
2134
2135 EXIT();
2136}
2137
2138/**
2139 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2140 * @dev: pointer to net_device structure
2141 *
2142 * This is called during the netdev unregister to uninitialize all data
2143 * associated with the device
2144 *
2145 * Return: none
2146 */
2147static void hdd_uninit(struct net_device *dev)
2148{
2149 cds_ssr_protect(__func__);
2150 __hdd_uninit(dev);
2151 cds_ssr_unprotect(__func__);
2152}
2153
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002154static int hdd_open_cesium_nl_sock(void)
2155{
2156#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2157 struct netlink_kernel_cfg cfg = {
2158 .groups = WLAN_NLINK_MCAST_GRP_ID,
2159 .input = NULL
2160 };
2161#endif
2162 int ret = 0;
2163
2164#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2165 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2166#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2167 THIS_MODULE,
2168#endif
2169 &cfg);
2170#else
2171 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2172 WLAN_NLINK_MCAST_GRP_ID,
2173 NULL, NULL, THIS_MODULE);
2174#endif
2175
2176 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002177 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002178 ret = -ECONNREFUSED;
2179 }
2180
2181 return ret;
2182}
2183
2184static void hdd_close_cesium_nl_sock(void)
2185{
2186 if (NULL != cesium_nl_srv_sock) {
2187 netlink_kernel_release(cesium_nl_srv_sock);
2188 cesium_nl_srv_sock = NULL;
2189 }
2190}
2191
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192/**
2193 * __hdd_set_mac_address() - set the user specified mac address
2194 * @dev: Pointer to the net device.
2195 * @addr: Pointer to the sockaddr.
2196 *
2197 * This function sets the user specified mac address using
2198 * the command ifconfig wlanX hw ether <mac adress>.
2199 *
2200 * Return: 0 for success, non zero for failure
2201 */
2202static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2203{
2204 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2205 hdd_context_t *hdd_ctx;
2206 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302207 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 int ret;
2209
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002210 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002211
2212 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2213 ret = wlan_hdd_validate_context(hdd_ctx);
2214 if (0 != ret)
2215 return ret;
2216
2217 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2218 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2219
2220 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302221 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222}
2223
2224/**
2225 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2226 * function from SSR
2227 * @dev: pointer to net_device structure
2228 * @addr: Pointer to the sockaddr
2229 *
2230 * This function sets the user specified mac address using
2231 * the command ifconfig wlanX hw ether <mac adress>.
2232 *
2233 * Return: 0 for success.
2234 */
2235static int hdd_set_mac_address(struct net_device *dev, void *addr)
2236{
2237 int ret;
2238
2239 cds_ssr_protect(__func__);
2240 ret = __hdd_set_mac_address(dev, addr);
2241 cds_ssr_unprotect(__func__);
2242
2243 return ret;
2244}
2245
2246uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2247{
2248 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302249 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002250 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2251 break;
2252 }
2253
Anurag Chouhan6d760662016-02-20 16:05:43 +05302254 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002255 return NULL;
2256
2257 hdd_ctx->config->intfAddrMask |= (1 << i);
2258 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2259}
2260
2261void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2262{
2263 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302264 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002265 if (!memcmp(releaseAddr,
2266 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2267 6)) {
2268 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2269 break;
2270 }
2271 }
2272 return;
2273}
2274
2275#ifdef WLAN_FEATURE_PACKET_FILTERING
2276/**
2277 * __hdd_set_multicast_list() - set the multicast address list
2278 * @dev: Pointer to the WLAN device.
2279 * @skb: Pointer to OS packet (sk_buff).
2280 *
2281 * This funciton sets the multicast address list.
2282 *
2283 * Return: None
2284 */
2285static void __hdd_set_multicast_list(struct net_device *dev)
2286{
2287 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2288 int mc_count;
2289 int i = 0, status;
2290 struct netdev_hw_addr *ha;
2291 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2292 static const uint8_t ipv6_router_solicitation[]
2293 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2294
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002295 ENTER_DEV(dev);
2296
Anurag Chouhan6d760662016-02-20 16:05:43 +05302297 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302298 return;
2299
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302301 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303
2304 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002305 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002306 adapter->mc_addr_list.mc_cnt = 0;
2307 } else {
2308 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302309 hdd_notice("mc_count : %u", mc_count);
2310
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Dustin Brown61269462016-09-19 13:25:45 -07002312 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
2313 WLAN_HDD_MAX_MC_ADDR_LIST);
2314 wlan_hdd_set_mc_addr_list(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 adapter->mc_addr_list.mc_cnt = 0;
2316 return;
2317 }
2318
2319 adapter->mc_addr_list.mc_cnt = mc_count;
2320
2321 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302322 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2323 i, MAC_ADDR_ARRAY(ha->addr));
2324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002325 if (i == mc_count)
2326 break;
2327 /*
2328 * Skip following addresses:
2329 * 1)IPv6 router solicitation address
2330 * 2)Any other address pattern if its set during
2331 * RXFILTER REMOVE driver command based on
2332 * addr_filter_pattern
2333 */
2334 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2335 ETH_ALEN)) ||
2336 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2337 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002338 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 MAC_ADDR_ARRAY(ha->addr));
2340 adapter->mc_addr_list.mc_cnt--;
2341 continue;
2342 }
2343
2344 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2345 ETH_ALEN);
2346 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2347 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002348 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2350 i++;
2351 }
2352 }
2353 if (hdd_ctx->config->active_mode_offload) {
2354 hdd_info("enable mc filtering");
2355 wlan_hdd_set_mc_addr_list(adapter, true);
2356 } else {
2357 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2358 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302359 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002360 return;
2361}
2362
2363/**
2364 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2365 * @dev: pointer to net_device
2366 *
2367 * Return: none
2368 */
2369static void hdd_set_multicast_list(struct net_device *dev)
2370{
2371 cds_ssr_protect(__func__);
2372 __hdd_set_multicast_list(dev);
2373 cds_ssr_unprotect(__func__);
2374}
2375#endif
2376
2377/**
2378 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2379 * @dev: Pointer to the WLAN device.
2380 * @skb: Pointer to OS packet (sk_buff).
2381 *
2382 * This function is registered with the Linux OS for network
2383 * core to decide which queue to use first.
2384 *
2385 * Return: ac, Queue Index/access category corresponding to UP in IP header
2386 */
2387static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2388#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2389 , void *accel_priv
2390#endif
2391#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2392 , select_queue_fallback_t fallback
2393#endif
2394)
2395{
2396 return hdd_wmm_select_queue(dev, skb);
2397}
2398
2399static struct net_device_ops wlan_drv_ops = {
2400 .ndo_open = hdd_open,
2401 .ndo_stop = hdd_stop,
2402 .ndo_uninit = hdd_uninit,
2403 .ndo_start_xmit = hdd_hard_start_xmit,
2404 .ndo_tx_timeout = hdd_tx_timeout,
2405 .ndo_get_stats = hdd_get_stats,
2406 .ndo_do_ioctl = hdd_ioctl,
2407 .ndo_set_mac_address = hdd_set_mac_address,
2408 .ndo_select_queue = hdd_select_queue,
2409#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411#endif
2412};
2413
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002414/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2415static struct net_device_ops wlan_mon_drv_ops = {
2416 .ndo_open = hdd_mon_open,
2417 .ndo_stop = hdd_stop,
2418 .ndo_get_stats = hdd_get_stats,
2419};
2420
2421/**
2422 * hdd_set_station_ops() - update net_device ops for monitor mode
2423 * @pWlanDev: Handle to struct net_device to be updated.
2424 * Return: None
2425 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426void hdd_set_station_ops(struct net_device *pWlanDev)
2427{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002428 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2429 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2430 else
2431 pWlanDev->netdev_ops = &wlan_drv_ops;
2432}
2433
2434/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002435 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2436 * @hdd_ctx: global hdd context
2437 * @macAddr: mac address to assign to the interface
2438 * @name: User-visible name of the interface
2439 *
2440 * hdd adapter pointer would point to the netdev->priv space, this function
2441 * would retrive the pointer, and setup the hdd adapter configuration.
2442 *
2443 * Return: the pointer to hdd adapter, otherwise NULL
2444 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2446 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002447 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448 const char *name)
2449{
2450 struct net_device *pWlanDev = NULL;
2451 hdd_adapter_t *adapter = NULL;
2452 /*
2453 * cfg80211 initialization and registration....
2454 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002455 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2456#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2457 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002459 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2460 hdd_mon_mode_ether_setup : ether_setup),
2461 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462
2463 if (pWlanDev != NULL) {
2464
2465 /* Save the pointer to the net_device in the HDD adapter */
2466 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2467
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302468 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469
2470 adapter->dev = pWlanDev;
2471 adapter->pHddCtx = hdd_ctx;
2472 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302473 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474
2475 init_completion(&adapter->session_open_comp_var);
2476 init_completion(&adapter->session_close_comp_var);
2477 init_completion(&adapter->disconnect_comp_var);
2478 init_completion(&adapter->linkup_event_var);
2479 init_completion(&adapter->cancel_rem_on_chan_var);
2480 init_completion(&adapter->rem_on_chan_ready_event);
2481 init_completion(&adapter->sta_authorized_event);
2482 init_completion(&adapter->offchannel_tx_event);
2483 init_completion(&adapter->tx_action_cnf_event);
2484#ifdef FEATURE_WLAN_TDLS
2485 init_completion(&adapter->tdls_add_station_comp);
2486 init_completion(&adapter->tdls_del_station_comp);
2487 init_completion(&adapter->tdls_mgmt_comp);
2488 init_completion(&adapter->tdls_link_establish_req_comp);
2489#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002490 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 init_completion(&adapter->change_country_code);
2492
2493
2494 init_completion(&adapter->scan_info.abortscan_event_var);
2495
2496 adapter->offloads_configured = false;
2497 adapter->isLinkUpSvcNeeded = false;
2498 adapter->higherDtimTransition = true;
2499 /* Init the net_device structure */
2500 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2501
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302502 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302504 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002505 sizeof(tSirMacAddr));
2506 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002507
2508 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2509 pWlanDev->features |=
2510 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2511 pWlanDev->features |= NETIF_F_RXCSUM;
2512
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002513 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2514
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515 hdd_set_station_ops(adapter->dev);
2516
2517 pWlanDev->destructor = free_netdev;
2518 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002519 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 adapter->wdev.wiphy = hdd_ctx->wiphy;
2521 adapter->wdev.netdev = pWlanDev;
2522 /* set pWlanDev's parent to underlying device */
2523 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2524 hdd_wmm_init(adapter);
2525 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302526 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 }
2528
2529 return adapter;
2530}
2531
Jeff Johnson590e2012016-10-05 16:16:24 -07002532static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2533 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534{
2535 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002537 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2539 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002540 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302541 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 }
2543 }
2544 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002545 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302546 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 }
2548 } else {
2549 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002550 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302551 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552 }
2553 }
2554 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2555
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302556 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557}
2558
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002559QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560{
2561 hdd_adapter_t *adapter = pContext;
2562
2563 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002564 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302565 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 }
2567
2568 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002569 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302570 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571 }
2572
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002573 /*
2574 * For NAN Data interface, the close session results in the final
2575 * indication to the userspace
2576 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002577 if (adapter->device_mode == QDF_NDI_MODE)
2578 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 /*
2583 * We can be blocked while waiting for scheduled work to be
2584 * flushed, and the adapter structure can potentially be freed, in
2585 * which case the magic will have been reset. So make sure the
2586 * magic is still good, and hence the adapter structure is still
2587 * valid, before signaling completion
2588 */
2589 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2590 complete(&adapter->session_close_comp_var);
2591
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302592 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593}
2594
Krunal Soni8c37e322016-02-03 16:08:37 -08002595/**
2596 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2597 * @adapter: pointer to device adapter
2598 * @type: type of interface
2599 *
2600 * This routine will check the mode of adapter and if it is required then it
2601 * will initialize the TDLS operations
2602 *
2603 * Return: QDF_STATUS
2604 */
2605#ifdef FEATURE_WLAN_TDLS
2606static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2607{
2608 if (QDF_IBSS_MODE != type) {
2609 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002610 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002611 return QDF_STATUS_E_FAILURE;
2612 }
2613 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2614 }
2615 return QDF_STATUS_SUCCESS;
2616}
2617#else
2618static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2619{
2620 return QDF_STATUS_SUCCESS;
2621}
2622#endif
2623
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302624QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625{
2626 struct net_device *pWlanDev = adapter->dev;
2627 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2628 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302629 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302630 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631 uint32_t type, subType;
2632 unsigned long rc;
2633 int ret_val;
2634
2635 INIT_COMPLETION(adapter->session_open_comp_var);
2636 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002637 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302639 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002640 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641 goto error_sme_open;
2642 }
2643 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302644 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2646 (uint8_t *) &adapter->macAddressCurrent,
2647 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302648 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002649 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302650 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302651 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002652 goto error_sme_open;
2653 }
2654 /* Block on a completion variable. Can't wait forever though. */
2655 rc = wait_for_completion_timeout(
2656 &adapter->session_open_comp_var,
2657 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2658 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002659 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002660 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302661 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002662 goto error_sme_open;
2663 }
2664
Naveen Rawata410c5a2016-09-19 14:22:33 -07002665 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302667 qdf_ret_status = hdd_register_wext(pWlanDev);
2668 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002669 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302670 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302671 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 goto error_register_wext;
2673 }
2674 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002675 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2677
2678 /* Set the default operation channel */
2679 pHddStaCtx->conn_info.operationChannel =
2680 hdd_ctx->config->OperatingChannel;
2681
2682 /* Make the default Auth Type as OPEN */
2683 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2684
2685 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302686 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002687 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 status, status);
2689 goto error_init_txrx;
2690 }
2691
2692 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2693
2694 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302695 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002696 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697 status, status);
2698 goto error_wmm_init;
2699 }
2700
2701 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2702
2703 ret_val = wma_cli_set_command(adapter->sessionId,
2704 WMI_PDEV_PARAM_BURST_ENABLE,
2705 hdd_ctx->config->enableSifsBurst,
2706 PDEV_CMD);
2707
2708 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002709 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 ret_val);
2711 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002712 status = hdd_check_and_init_tdls(adapter, type);
2713 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302716 status = hdd_lro_enable(hdd_ctx, adapter);
2717 if (status != QDF_STATUS_SUCCESS)
2718 goto error_lro_enable;
2719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302720 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302722error_lro_enable:
2723 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724error_tdls_init:
2725 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2726 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727error_wmm_init:
2728 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2729 hdd_deinit_tx_rx(adapter);
2730error_init_txrx:
2731 hdd_unregister_wext(pWlanDev);
2732error_register_wext:
2733 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2734 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302735 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736 adapter->sessionId,
2737 hdd_sme_close_session_callback,
2738 adapter)) {
2739 unsigned long rc;
2740
2741 /*
2742 * Block on a completion variable.
2743 * Can't wait forever though.
2744 */
2745 rc = wait_for_completion_timeout(
2746 &adapter->session_close_comp_var,
2747 msecs_to_jiffies
2748 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2749 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002750 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002751 rc);
2752 }
2753 }
2754error_sme_open:
2755 return status;
2756}
2757
2758void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2759{
2760 hdd_cfg80211_state_t *cfgState;
2761
2762 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2763
2764 if (NULL != cfgState->buf) {
2765 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 rc = wait_for_completion_timeout(
2767 &adapter->tx_action_cnf_event,
2768 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2769 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002770 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302771 /*
2772 * Inform tx status as FAILURE to upper layer and free
2773 * cfgState->buf
2774 */
2775 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 }
2777 }
2778 return;
2779}
2780
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302781/**
2782 * hdd_station_adapter_deinit() - De-initialize the station adapter
2783 * @hdd_ctx: global hdd context
2784 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07002785 * @rtnl_held: Used to indicate whether or not the caller is holding
2786 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302787 *
2788 * This function De-initializes the STA/P2P/OCB adapter.
2789 *
2790 * Return: None.
2791 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002792static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2793 hdd_adapter_t *adapter,
2794 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302795{
2796 ENTER_DEV(adapter->dev);
2797
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302798 if (adapter->dev) {
2799 if (rtnl_held)
2800 adapter->dev->wireless_handlers = NULL;
2801 else {
2802 rtnl_lock();
2803 adapter->dev->wireless_handlers = NULL;
2804 rtnl_unlock();
2805 }
2806 }
2807
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302808 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2809 hdd_deinit_tx_rx(adapter);
2810 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2811 }
2812
2813 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2814 hdd_wmm_adapter_close(adapter);
2815 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2816 }
2817
2818 hdd_cleanup_actionframe(hdd_ctx, adapter);
2819 wlan_hdd_tdls_exit(adapter);
2820
2821 EXIT();
2822}
2823
2824/**
2825 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2826 * @hdd_ctx: global hdd context
2827 * @adapter: HDD adapter
2828 * @rtnl_held: the rtnl lock hold flag
2829 * This function De-initializes the AP/P2PGo adapter.
2830 *
2831 * Return: None.
2832 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002833static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
2834 hdd_adapter_t *adapter,
2835 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302836{
2837 ENTER_DEV(adapter->dev);
2838
2839 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2840 hdd_wmm_adapter_close(adapter);
2841 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2842 }
2843
2844 hdd_cleanup_actionframe(hdd_ctx, adapter);
2845
2846 hdd_unregister_hostapd(adapter, rtnl_held);
2847
2848 EXIT();
2849}
2850
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2852 bool rtnl_held)
2853{
2854 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302855
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002857 case QDF_STA_MODE:
2858 case QDF_P2P_CLIENT_MODE:
2859 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002860 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302861 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 break;
2863 }
2864
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002865 case QDF_SAP_MODE:
2866 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867 {
2868
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302869 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 break;
2871 }
2872
2873 default:
2874 break;
2875 }
2876
2877 EXIT();
2878}
2879
Jeff Johnson590e2012016-10-05 16:16:24 -07002880static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2881 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882{
2883 struct net_device *pWlanDev = NULL;
2884
2885 if (adapter)
2886 pWlanDev = adapter->dev;
2887 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002888 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 return;
2890 }
2891
Rajeev Kumardca5f812016-02-04 17:28:06 -08002892 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05302893
2894 if (adapter->scan_info.default_scan_ies) {
2895 qdf_mem_free(adapter->scan_info.default_scan_ies);
2896 adapter->scan_info.default_scan_ies = NULL;
2897 }
2898
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899 /*
2900 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2901 * the driver is almost closed and cannot handle either control
2902 * messages or data. However, unregister_netdevice() call above will
2903 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2904 * to close the active connections (basically excites control path) which
2905 * is not right. Setting this flag helps hdd_stop() to recognize that
2906 * the interface is closed and restricts any operations on that
2907 */
2908 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2909
2910 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2911 if (rtnl_held) {
2912 unregister_netdevice(pWlanDev);
2913 } else {
2914 unregister_netdev(pWlanDev);
2915 }
2916 /*
2917 * Note that the adapter is no longer valid at this point
2918 * since the memory has been reclaimed
2919 */
2920 }
2921}
2922
Jeff Johnson590e2012016-10-05 16:16:24 -07002923static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
2924 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925{
2926 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2927 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302928 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302930 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 adapter = adapterNode->pAdapter;
2932 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302933 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302935 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 }
2937 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2938 adapterNode = pNext;
2939 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302940 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002942
Arun Khandavalli2358d522016-05-16 18:05:37 +05302943#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2944/**
2945 * hdd_set_fw_log_params() - Set log parameters to FW
2946 * @hdd_ctx: HDD Context
2947 * @adapter: HDD Adapter
2948 *
2949 * This function set the FW Debug log level based on the INI.
2950 *
2951 * Return: None
2952 */
2953static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2954 hdd_adapter_t *adapter)
2955{
2956 uint8_t count = 0, numentries = 0,
2957 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2958 uint32_t value = 0;
2959 int ret;
2960
Arun Khandavallifae92942016-08-01 13:31:08 +05302961 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
2962 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302963 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
2964 return;
2965 }
2966
Arun Khandavallifae92942016-08-01 13:31:08 +05302967 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05302968 hdd_ctx->fw_log_settings.dl_type =
2969 hdd_ctx->config->enableFwLogType;
2970 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302971 WMI_DBGLOG_TYPE,
2972 hdd_ctx->config->enableFwLogType,
2973 DBG_CMD);
2974 if (ret != 0)
2975 hdd_err("Failed to enable FW log type ret %d",
2976 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302977
2978 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05302979 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05302980 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302981 WMI_DBGLOG_LOG_LEVEL,
2982 hdd_ctx->config->enableFwLogLevel,
2983 DBG_CMD);
2984 if (ret != 0)
2985 hdd_err("Failed to enable FW log level ret %d",
2986 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302987
2988 hdd_string_to_u8_array(
2989 hdd_ctx->config->enableFwModuleLogLevel,
2990 moduleloglevel,
2991 &numentries,
2992 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2993
2994 while (count < numentries) {
2995 /*
2996 * FW module log level input string looks like
2997 * below:
2998 * gFwDebugModuleLoglevel=<FW Module ID>,
2999 * <Log Level>,...
3000 * For example:
3001 * gFwDebugModuleLoglevel=
3002 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3003 * Above input string means :
3004 * For FW module ID 1 enable log level 0
3005 * For FW module ID 2 enable log level 1
3006 * For FW module ID 3 enable log level 2
3007 * For FW module ID 4 enable log level 3
3008 * For FW module ID 5 enable log level 4
3009 * For FW module ID 6 enable log level 5
3010 * For FW module ID 7 enable log level 6
3011 */
3012
Arun Khandavallifae92942016-08-01 13:31:08 +05303013 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05303014 * Module ID * 10 + Module Log level
3015 */
3016 value = ((moduleloglevel[count] * 10) +
3017 moduleloglevel[count + 1]);
3018 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303019 WMI_DBGLOG_MOD_LOG_LEVEL,
3020 value, DBG_CMD);
3021 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303022 hdd_err("Failed to enable FW module log level %d ret %d",
3023 value, ret);
3024
3025 count += 2;
3026 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303027
Arun Khandavalli2358d522016-05-16 18:05:37 +05303028}
3029#else
3030static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3031 hdd_adapter_t *adapter)
3032{
3033}
3034
3035#endif
3036
3037/**
3038 * hdd_set_fw_params() - Set parameters to firmware
3039 * @adapter: HDD adapter
3040 *
3041 * This function Sets various parameters to fw once the
3042 * adapter is started.
3043 *
3044 * Return: 0 on success or errno on failure
3045 */
3046int hdd_set_fw_params(hdd_adapter_t *adapter)
3047{
3048 int ret;
3049 hdd_context_t *hdd_ctx;
3050
3051 ENTER_DEV(adapter->dev);
3052
3053 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3054 if (!hdd_ctx)
3055 return -EINVAL;
3056
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003057 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303058 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303059#define HDD_DTIM_1CHAIN_RX_ID 0x5
3060#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003061 /*
3062 * Disable DTIM 1 chain Rx when in 1x1,
3063 * we are passing two value
3064 * as param_id << 29 | param_value.
3065 * Below param_value = 0(disable)
3066 */
3067 ret = wma_cli_set_command(adapter->sessionId,
3068 WMI_STA_SMPS_PARAM_CMDID,
3069 HDD_DTIM_1CHAIN_RX_ID <<
3070 HDD_SMPS_PARAM_VALUE_S,
3071 VDEV_CMD);
3072 if (ret) {
3073 hdd_err("DTIM 1 chain set failed %d", ret);
3074 goto error;
3075 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303076
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003077 ret = wma_cli_set_command(adapter->sessionId,
3078 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3079 hdd_ctx->config->txchainmask1x1,
3080 PDEV_CMD);
3081 if (ret) {
3082 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3083 ret);
3084 goto error;
3085 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303086
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003087 ret = wma_cli_set_command(adapter->sessionId,
3088 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3089 hdd_ctx->config->rxchainmask1x1,
3090 PDEV_CMD);
3091 if (ret) {
3092 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3093 ret);
3094 goto error;
3095 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303096#undef HDD_DTIM_1CHAIN_RX_ID
3097#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003098 } else {
3099 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3100 }
3101
Arun Khandavallifae92942016-08-01 13:31:08 +05303102 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3103 ret = wma_cli_set_command(adapter->sessionId,
3104 WMI_PDEV_PARAM_HYST_EN,
3105 hdd_ctx->config->enableMemDeepSleep,
3106 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303107
Arun Khandavallifae92942016-08-01 13:31:08 +05303108 if (ret) {
3109 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3110 ret);
3111 goto error;
3112 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303113 }
3114
3115 hdd_set_fw_log_params(hdd_ctx, adapter);
3116
Rajeev Kumar Sirasanagandla0be56df2016-09-08 19:19:47 +05303117 ret = wma_cli_set_command(adapter->sessionId,
3118 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3119 hdd_ctx->config->rts_profile,
3120 VDEV_CMD);
3121 if (ret) {
3122 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3123 goto error;
3124 }
3125
Arun Khandavalli2358d522016-05-16 18:05:37 +05303126 EXIT();
3127 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303128
Arun Khandavalli2358d522016-05-16 18:05:37 +05303129error:
3130 return -EINVAL;
3131}
3132
Ryan Hsu07495ea2016-01-21 15:25:39 -08003133/**
3134 * hdd_open_adapter() - open and setup the hdd adatper
3135 * @hdd_ctx: global hdd context
3136 * @session_type: type of the interface to be created
3137 * @iface_name: User-visible name of the interface
3138 * @macAddr: MAC address to assign to the interface
3139 * @name_assign_type: the name of assign type of the netdev
3140 * @rtnl_held: the rtnl lock hold flag
3141 *
3142 * This function open and setup the hdd adpater according to the device
3143 * type request, assign the name, the mac address assigned, and then prepared
3144 * the hdd related parameters, queue, lock and ready to start.
3145 *
3146 * Return: the pointer of hdd adapter, otherwise NULL.
3147 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3149 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003150 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003151 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152{
3153 hdd_adapter_t *adapter = NULL;
3154 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303155 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157
Arun Khandavallifae92942016-08-01 13:31:08 +05303158 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159
3160 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3161 /*
3162 * Max limit reached on the number of vdevs configured by the
3163 * host. Return error
3164 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303165 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3166 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 return NULL;
3168 }
3169
3170 if (macAddr == NULL) {
3171 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303172 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 return NULL;
3174 }
3175 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303176 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303177 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3178 " already exists",
3179 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 return NULL;
3181 }
3182
3183 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003184 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 /* Reset locally administered bit if the device mode is STA */
3186 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3187 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003188 case QDF_P2P_CLIENT_MODE:
3189 case QDF_P2P_DEVICE_MODE:
3190 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003191 case QDF_NDI_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003192 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3193 name_assign_type,
3194 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195
3196 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303197 hdd_err("failed to allocate adapter for session %d",
3198 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199 return NULL;
3200 }
3201
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003202 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003204 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 else
3207 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3208
3209 adapter->device_mode = session_type;
3210
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303211 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003212 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303213 if (QDF_STATUS_SUCCESS != status)
3214 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303215 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217 /*
3218 * Workqueue which gets scheduled in IPv4 notification
3219 * callback
3220 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3222 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223
3224#ifdef WLAN_NS_OFFLOAD
3225 /*
3226 * Workqueue which gets scheduled in IPv6
3227 * notification callback.
3228 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3230 hdd_ipv6_notifier_work_queue);
3231#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303233 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3235 goto err_lro_cleanup;
3236 }
3237
3238 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303239 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303241 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3242 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003245
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003246 case QDF_P2P_GO_MODE:
3247 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003248 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3249 name_assign_type,
3250 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303252 hdd_alert("failed to allocate adapter for session %d",
3253 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003254 return NULL;
3255 }
3256
3257 adapter->wdev.iftype =
3258 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003259 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 NL80211_IFTYPE_P2P_GO;
3261 adapter->device_mode = session_type;
3262
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303264 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3266 goto err_free_netdev;
3267 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303268 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003269 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303270 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3271 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303274 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303275 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 return NULL;
3277 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278
3279 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3280 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3281
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303282 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003283 /* Add it to the hdd's session list. */
3284 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303285 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303287 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288 } else {
3289 pHddAdapterNode->pAdapter = adapter;
3290 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3291 }
3292 }
3293
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303294 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 if (NULL != adapter) {
3296 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3297 adapter = NULL;
3298 }
3299 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303300 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003301 }
3302 return NULL;
3303 }
3304
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303305 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003306 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003307
3308 /* Initialize the WoWL service */
3309 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003310 hdd_alert("hdd_init_wowl failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311 goto err_lro_cleanup;
3312 }
3313
3314 /* Adapter successfully added. Increment the vdev count */
3315 hdd_ctx->current_intf_count++;
3316
Jeff Johnson5880d792016-08-15 13:32:30 -07003317 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003318 hdd_ctx->current_intf_count);
3319
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003320 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 }
3322
Rajeev Kumardca5f812016-02-04 17:28:06 -08003323 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3324 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003325
3326 return adapter;
3327
3328err_lro_cleanup:
3329 hdd_lro_disable(hdd_ctx, adapter);
3330err_free_netdev:
3331 free_netdev(adapter->dev);
3332 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
3333
3334 return NULL;
3335}
3336
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303337QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003338 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339{
3340 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303341 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342
3343 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303344 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003345 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 status);
3347 return status;
3348 }
3349
3350 while (pCurrent->pAdapter != adapter) {
3351 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303352 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353 break;
3354
3355 pCurrent = pNext;
3356 }
3357 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303358 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003359 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3361
3362 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303363 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 adapterNode = NULL;
3365
3366 /* Adapter removed. Decrement vdev count */
3367 if (hdd_ctx->current_intf_count != 0)
3368 hdd_ctx->current_intf_count--;
3369
3370 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303373 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374}
3375
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003376/**
3377 * hdd_close_all_adapters - Close all open adapters
3378 * @hdd_ctx: Hdd context
3379 * rtnl_held: True if RTNL lock held
3380 *
3381 * Close all open adapters.
3382 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303383 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003384 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303385QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003386{
3387 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303388 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389
3390 ENTER();
3391
3392 do {
3393 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303394 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003396 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303397 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303399 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400
3401 EXIT();
3402
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303403 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404}
3405
3406void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3407{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303408 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409 tSirUpdateIE updateIE;
3410 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003411 case QDF_STA_MODE:
3412 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003413 {
3414 hdd_station_ctx_t *pHddStaCtx =
3415 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003416 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 break;
3418 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003419 case QDF_SAP_MODE:
3420 case QDF_P2P_GO_MODE:
3421 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003423 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 break;
3425 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003426 case QDF_FTM_MODE:
3427 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003428 default:
3429 /*
3430 * wlan_hdd_reset_prob_rspies should not have been called
3431 * for these kind of devices
3432 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003433 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003434 pHostapdAdapter->device_mode);
3435 return;
3436 }
3437
Anurag Chouhanc5548422016-02-24 18:33:27 +05303438 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003439 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3440 updateIE.ieBufferlength = 0;
3441 updateIE.pAdditionIEBuffer = NULL;
3442 updateIE.append = true;
3443 updateIE.notify = false;
3444 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3445 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303446 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003447 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003448 }
3449}
3450
Peng Xu66162de2016-02-11 17:01:20 -08003451/**
3452 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3453 * @hdd_ctx: HDD context which is already NULL validated
3454 * @adapter: HDD adapter which is already NULL validated
3455 *
3456 * Close the SME session and wait for its completion, if needed.
3457 *
3458 * Return: None
3459 */
3460static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3461 hdd_adapter_t *adapter)
3462{
3463 unsigned long rc;
3464
3465 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3466 hdd_err("session is not opened:%d", adapter->sessionId);
3467 return;
3468 }
3469
3470 INIT_COMPLETION(adapter->session_close_comp_var);
3471 if (QDF_STATUS_SUCCESS ==
3472 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3473 hdd_sme_close_session_callback,
3474 adapter)) {
3475 /*
3476 * Block on a completion variable. Can't wait
3477 * forever though.
3478 */
3479 rc = wait_for_completion_timeout(
3480 &adapter->session_close_comp_var,
3481 msecs_to_jiffies
3482 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003483 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003484 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003485 if (adapter->device_mode == QDF_NDI_MODE)
3486 hdd_ndp_session_end_handler(adapter);
3487 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303488 return;
Sandeep Puligillaada72922016-09-29 19:31:21 -07003489 }
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303490 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003491 }
3492}
3493
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303494QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495 const bool bCloseSession)
3496{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303497 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3499 union iwreq_data wrqu;
3500 tSirUpdateIE updateIE;
3501 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303502 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503
3504 ENTER();
3505
Sachin Ahuja988fd102016-09-15 17:16:25 +05303506 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003507 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3509 WLAN_CONTROL_PATH);
3510 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003511 case QDF_STA_MODE:
3512 case QDF_P2P_CLIENT_MODE:
3513 case QDF_IBSS_MODE:
3514 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003515 case QDF_NDI_MODE:
3516 if ((QDF_NDI_MODE == adapter->device_mode) ||
3517 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3519 hdd_is_connecting(
3520 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003521 INIT_COMPLETION(adapter->disconnect_comp_var);
3522 /*
3523 * For NDI do not use pWextState from sta_ctx, if needed
3524 * extract from ndi_ctx.
3525 */
3526 if (QDF_NDI_MODE == adapter->device_mode)
3527 qdf_ret_status = sme_roam_disconnect(
3528 hdd_ctx->hHal,
3529 adapter->sessionId,
3530 eCSR_DISCONNECT_REASON_NDI_DELETE);
3531 else if (pWextState->roamProfile.BSSType ==
3532 eCSR_BSS_TYPE_START_IBSS)
3533 qdf_ret_status = sme_roam_disconnect(
3534 hdd_ctx->hHal,
3535 adapter->sessionId,
3536 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003538 qdf_ret_status = sme_roam_disconnect(
3539 hdd_ctx->hHal,
3540 adapter->sessionId,
3541 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003542 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303543 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003544 rc = wait_for_completion_timeout(
3545 &adapter->disconnect_comp_var,
3546 msecs_to_jiffies
3547 (WLAN_WAIT_TIME_DISCONNECT));
3548 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003549 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003550 }
3551 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003552 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003553 }
3554 memset(&wrqu, '\0', sizeof(wrqu));
3555 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3556 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3557 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3558 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303559 }
3560 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303561 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303563 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303564 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003565
3566#ifdef WLAN_OPEN_SOURCE
3567 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3568#endif
3569
3570 hdd_deregister_tx_flow_control(adapter);
3571
3572#ifdef WLAN_NS_OFFLOAD
3573#ifdef WLAN_OPEN_SOURCE
3574 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3575#endif
3576#endif
3577
3578 /*
3579 * It is possible that the caller of this function does not
3580 * wish to close the session
3581 */
Peng Xu66162de2016-02-11 17:01:20 -08003582 if (true == bCloseSession)
3583 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 break;
3585
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003586 case QDF_SAP_MODE:
3587 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003589 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 /*
3591 * Before stopping the sap adapter, lets make sure there
3592 * is no sap restart work pending.
3593 */
3594 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003595 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003596 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003597 }
3598 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003599 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003600 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3601
3602 hdd_deregister_tx_flow_control(adapter);
3603
3604 mutex_lock(&hdd_ctx->sap_lock);
3605 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303606 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303607 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608
3609 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 status = wlansap_stop_bss(
3611 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003612
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303613 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003614 hdd_hostapd_state_t *hostapd_state =
3615 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303616 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303617 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303618 qdf_status =
3619 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303620 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621 BSS_WAIT_TIMEOUT);
3622
Anurag Chouhance0dc992016-02-16 18:18:03 +05303623 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003624 hdd_err("failure waiting for wlansap_stop_bss %d",
3625 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 }
3627 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003628 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629 }
3630 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003631 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 adapter->device_mode,
3633 adapter->sessionId);
3634
Anurag Chouhanc5548422016-02-24 18:33:27 +05303635 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003636 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637 updateIE.smeSessionId = adapter->sessionId;
3638 updateIE.ieBufferlength = 0;
3639 updateIE.pAdditionIEBuffer = NULL;
3640 updateIE.append = false;
3641 updateIE.notify = false;
3642 /* Probe bcn reset */
3643 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3644 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303645 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003646 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003647 }
3648 /* Assoc resp reset */
3649 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3650 &updateIE,
3651 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303652 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003653 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 }
3655 /* Reset WNI_CFG_PROBE_RSP Flags */
3656 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303657 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003658 adapter->sessionCtx.ap.beacon = NULL;
3659 }
3660 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003661 if (true == bCloseSession)
3662 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003663 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003664 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3666 conn_info.staId[0]);
3667 break;
3668 default:
3669 break;
3670 }
3671
3672 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303673 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674}
3675
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05303676/**
3677 * hdd_deinit_all_adapters - deinit all adapters
3678 * @hdd_ctx: HDD context
3679 * @rtnl_held: True if RTNL lock held
3680 *
3681 */
3682void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
3683{
3684 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3685 QDF_STATUS status;
3686 hdd_adapter_t *adapter;
3687
3688 ENTER();
3689
3690 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
3691
3692 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
3693 adapter = adapter_node->pAdapter;
3694 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3695 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
3696 adapter_node = next;
3697 }
3698
3699 EXIT();
3700}
3701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303702QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003703{
3704 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303705 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706 hdd_adapter_t *adapter;
3707
3708 ENTER();
3709
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303710 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3711
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003712 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3713
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303714 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 adapter = adapterNode->pAdapter;
3716 hdd_stop_adapter(hdd_ctx, adapter, true);
3717 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3718 adapterNode = pNext;
3719 }
3720
3721 EXIT();
3722
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303723 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003724}
3725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303726QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003727{
3728 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303729 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 hdd_adapter_t *adapter;
3731
3732 ENTER();
3733
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303734 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3737
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303738 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003740 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003741 wlan_hdd_netif_queue_control(adapter,
3742 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3743 WLAN_CONTROL_PATH);
3744
3745 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3746
3747 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003748 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 adapter->sessionId);
3750 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3751 hdd_wmm_adapter_close(adapter);
3752 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3753 }
3754
3755 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3756 adapterNode = pNext;
3757 }
3758
3759 EXIT();
3760
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303761 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762}
3763
Arun Khandavallifae92942016-08-01 13:31:08 +05303764/**
3765 * hdd_is_interface_up()- Checkfor interface up before ssr
3766 * @hdd_ctx: HDD context
3767 *
3768 * check if there are any wlan interfaces before SSR accordingly start
3769 * the interface.
3770 *
3771 * Return: 0 if interface was opened else false
3772 */
3773static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3774{
3775 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3776 return true;
3777 else
3778 return false;
3779}
3780
Anurag Chouhanc4092922016-09-08 15:56:11 +05303781#if defined CFG80211_CONNECT_BSS
3782#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
3783 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
Jeff Johnson590e2012016-10-05 16:16:24 -07003784static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303785struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3786 struct ieee80211_channel *channel,
3787 const u8 *bssid, const u8 *ssid,
3788 size_t ssid_len)
3789{
3790 return cfg80211_get_bss(wiphy, channel, bssid,
3791 ssid, ssid_len,
3792 WLAN_CAPABILITY_ESS,
3793 WLAN_CAPABILITY_ESS);
3794}
3795#else
Jeff Johnson590e2012016-10-05 16:16:24 -07003796static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303797struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3798 struct ieee80211_channel *channel,
3799 const u8 *bssid, const u8 *ssid,
3800 size_t ssid_len)
3801{
3802 return cfg80211_get_bss(wiphy, channel, bssid,
3803 ssid, ssid_len,
3804 IEEE80211_BSS_TYPE_ESS,
3805 IEEE80211_PRIVACY_ANY);
3806}
3807#endif
3808#endif
3809
Abhishek Singha84d3952016-09-13 13:45:05 +05303810#if defined CFG80211_CONNECT_BSS
3811/**
3812 * hdd_connect_bss() - API to send connection status to supplicant
3813 * @dev: network device
3814 * @bssid: bssid to which we want to associate
3815 * @req_ie: Request Information Element
3816 * @req_ie_len: len of the req IE
3817 * @resp_ie: Response IE
3818 * @resp_ie_len: len of ht response IE
3819 * @status: status
3820 * @gfp: Kernel Flag
3821 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
3822 *
3823 * The API is a wrapper to send connection status to supplicant
3824 *
3825 * Return: Void
3826 */
3827#if defined CFG80211_CONNECT_TIMEOUT
3828static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3829 struct cfg80211_bss *bss, const u8 *req_ie,
3830 size_t req_ie_len, const u8 *resp_ie,
3831 size_t resp_ie_len, int status, gfp_t gfp,
3832 bool connect_timeout)
3833{
3834 if (connect_timeout)
3835 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
3836 else
3837 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3838 resp_ie, resp_ie_len, status, gfp);
3839}
3840#else
3841static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3842 struct cfg80211_bss *bss, const u8 *req_ie,
3843 size_t req_ie_len, const u8 *resp_ie,
3844 size_t resp_ie_len, int status, gfp_t gfp,
3845 bool connect_timeout)
3846{
3847 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3848 resp_ie, resp_ie_len, status, gfp);
3849}
3850#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303851
3852/**
3853 * hdd_connect_result() - API to send connection status to supplicant
3854 * @dev: network device
3855 * @bssid: bssid to which we want to associate
3856 * @roam_info: information about connected bss
3857 * @req_ie: Request Information Element
3858 * @req_ie_len: len of the req IE
3859 * @resp_ie: Response IE
3860 * @resp_ie_len: len of ht response IE
3861 * @status: status
3862 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05303863 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
Anurag Chouhanc4092922016-09-08 15:56:11 +05303864 *
3865 * The API is a wrapper to send connection status to supplicant
3866 * and allow runtime suspend
3867 *
3868 * Return: Void
3869 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303870void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3871 tCsrRoamInfo *roam_info, const u8 *req_ie,
3872 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303873 size_t resp_ie_len, u16 status, gfp_t gfp,
3874 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303875{
3876 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3877 struct cfg80211_bss *bss = NULL;
3878
3879 if (WLAN_STATUS_SUCCESS == status) {
3880 struct ieee80211_channel *chan;
3881 int freq;
3882 int chan_no = roam_info->pBssDesc->channelId;
3883
3884 if (chan_no <= 14)
3885 freq = ieee80211_channel_to_frequency(chan_no,
3886 IEEE80211_BAND_2GHZ);
3887 else
3888 freq = ieee80211_channel_to_frequency(chan_no,
3889 IEEE80211_BAND_5GHZ);
3890
3891 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
3892 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
3893 roam_info->u.pConnectedProfile->SSID.ssId,
3894 roam_info->u.pConnectedProfile->SSID.length);
3895 }
Abhishek Singha84d3952016-09-13 13:45:05 +05303896 hdd_connect_bss(dev, bssid, bss, req_ie,
3897 req_ie_len, resp_ie, resp_ie_len,
3898 status, gfp, connect_timeout);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303899}
3900#else
3901void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3902 tCsrRoamInfo *roam_info, const u8 *req_ie,
3903 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303904 size_t resp_ie_len, u16 status, gfp_t gfp,
3905 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303906{
3907 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
3908 resp_ie, resp_ie_len, status, gfp);
3909}
3910#endif
3911
3912
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303913QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003914{
3915 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303916 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917 hdd_adapter_t *adapter;
3918#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303919 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920#endif
3921 eConnectionState connState;
3922
3923 ENTER();
3924
3925 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303926 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927 adapter = adapterNode->pAdapter;
3928
Arun Khandavallifae92942016-08-01 13:31:08 +05303929 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05303930 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05303931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003932 hdd_wmm_init(adapter);
3933
3934 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003935 case QDF_STA_MODE:
3936 case QDF_P2P_CLIENT_MODE:
3937 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938
3939 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3940 ->conn_info.connState;
3941
3942 hdd_init_station_mode(adapter);
3943 /* Open the gates for HDD to receive Wext commands */
3944 adapter->isLinkUpSvcNeeded = false;
3945 adapter->scan_info.mScanPending = false;
3946
3947 /* Indicate disconnect event to supplicant if associated previously */
3948 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003949 eConnectionState_IbssConnected == connState ||
3950 eConnectionState_NotConnected == connState ||
3951 eConnectionState_IbssDisconnected == connState ||
3952 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003953 union iwreq_data wrqu;
3954 memset(&wrqu, '\0', sizeof(wrqu));
3955 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3956 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3957 wireless_send_event(adapter->dev, SIOCGIWAP,
3958 &wrqu, NULL);
3959 adapter->sessionCtx.station.
3960 hdd_ReassocScenario = false;
3961
3962 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05303963 wlan_hdd_cfg80211_indicate_disconnect(
3964 adapter->dev, false,
3965 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966 } else if (eConnectionState_Connecting == connState) {
3967 /*
3968 * Indicate connect failure to supplicant if we were in the
3969 * process of connecting
3970 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303971 hdd_connect_result(adapter->dev, NULL, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003972 NULL, 0, NULL, 0,
3973 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Abhishek Singha84d3952016-09-13 13:45:05 +05303974 GFP_KERNEL, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 }
3976
3977 hdd_register_tx_flow_control(adapter,
3978 hdd_tx_resume_timer_expired_handler,
3979 hdd_tx_resume_cb);
3980
3981 break;
3982
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003983 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003984 /* softAP can handle SSR */
3985 break;
3986
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003987 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07003989 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3991#else
Jeff Johnson5880d792016-08-15 13:32:30 -07003992 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993 /* event supplicant to restart */
3994 cfg80211_del_sta(adapter->dev,
3995 (const u8 *)&bcastMac.bytes[0],
3996 GFP_KERNEL);
3997#endif
3998 break;
3999
4000 default:
4001 break;
4002 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304003get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004004 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4005 adapterNode = pNext;
4006 }
4007
4008 EXIT();
4009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304010 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011}
4012
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304013QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004014 hdd_adapter_list_node_t **padapterNode)
4015{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304016 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004017 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304018 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4019 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004020 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 return status;
4022}
4023
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304024QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025 hdd_adapter_list_node_t *adapterNode,
4026 hdd_adapter_list_node_t **pNextAdapterNode)
4027{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304028 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004029 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304030 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4031 (qdf_list_node_t *) adapterNode,
4032 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004034 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035 return status;
4036}
4037
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304038QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039 hdd_adapter_list_node_t *adapterNode)
4040{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304041 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004042 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304043 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004044 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004045 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046 return status;
4047}
4048
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304049QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004050 hdd_adapter_list_node_t **padapterNode)
4051{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304052 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004053 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304054 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4055 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004056 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 return status;
4058}
4059
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304060QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 hdd_adapter_list_node_t *adapterNode)
4062{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304063 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004064 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304065 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4066 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004067 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004068 return status;
4069}
4070
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304071QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072 hdd_adapter_list_node_t *adapterNode)
4073{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304074 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004075 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304076 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4077 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004078 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079 return status;
4080}
4081
4082hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4083 tSirMacAddr macAddr)
4084{
4085 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4086 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304087 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004088
4089 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304091 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 adapter = adapterNode->pAdapter;
4093
4094 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304095 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004096 macAddr, sizeof(tSirMacAddr))) {
4097 return adapter;
4098 }
4099 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4100 adapterNode = pNext;
4101 }
4102
4103 return NULL;
4104
4105}
4106
4107hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4108 uint32_t vdev_id)
4109{
4110 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4111 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304112 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304114 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304116 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004117 adapter = adapterNode->pAdapter;
4118
4119 if (adapter->sessionId == vdev_id)
4120 return adapter;
4121
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304122 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4124 adapterNode = pNext;
4125 }
4126
Jeff Johnson5880d792016-08-15 13:32:30 -07004127 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128
4129 return NULL;
4130}
4131
Abhishek Singh7996eb72015-12-30 17:24:02 +05304132/**
4133 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4134 * the sessionid
4135 * @hdd_ctx: hdd context.
4136 * @sme_session_id: sme session is for the adapter to get.
4137 *
4138 * This function is used to get the adapter with provided session id
4139 *
4140 * Return: adapter pointer if found
4141 *
4142 */
4143hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4144 uint32_t sme_session_id)
4145{
4146 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4147 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304148 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304149
4150
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304151 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304152
4153 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304154 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304155 adapter = adapter_node->pAdapter;
4156
4157 if (adapter &&
4158 adapter->sessionId == sme_session_id)
4159 return adapter;
4160
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304161 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304162 hdd_get_next_adapter(hdd_ctx,
4163 adapter_node, &next);
4164 adapter_node = next;
4165 }
4166 return NULL;
4167}
4168
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004169/**
4170 * hdd_get_adapter() - to get adapter matching the mode
4171 * @hdd_ctx: hdd context
4172 * @mode: adapter mode
4173 *
4174 * This routine will return the pointer to adapter matching
4175 * with the passed mode.
4176 *
4177 * Return: pointer to adapter or null
4178 */
4179hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4180 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004181{
4182 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4183 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304184 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004185
4186 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4187
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304188 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189 adapter = adapterNode->pAdapter;
4190
4191 if (adapter && (mode == adapter->device_mode))
4192 return adapter;
4193
4194 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4195 adapterNode = pNext;
4196 }
4197
4198 return NULL;
4199
4200}
4201
4202/**
4203 * hdd_get_operating_channel() - return operating channel of the device mode
4204 * @hdd_ctx: Pointer to the HDD context.
4205 * @mode: Device mode for which operating channel is required.
4206 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004207 * QDF_STA_MODE,
4208 * QDF_P2P_CLIENT_MODE,
4209 * QDF_SAP_MODE,
4210 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211 *
4212 * This API returns the operating channel of the requested device mode
4213 *
4214 * Return: channel number. "0" id the requested device is not found OR it is
4215 * not connected.
4216 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004217uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4218 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219{
4220 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304221 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 hdd_adapter_t *adapter;
4223 uint8_t operatingChannel = 0;
4224
4225 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4226
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304227 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004228 adapter = adapterNode->pAdapter;
4229
4230 if (mode == adapter->device_mode) {
4231 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004232 case QDF_STA_MODE:
4233 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004234 if (hdd_conn_is_connected
4235 (WLAN_HDD_GET_STATION_CTX_PTR
4236 (adapter))) {
4237 operatingChannel =
4238 (WLAN_HDD_GET_STATION_CTX_PTR
4239 (adapter))->conn_info.
4240 operationChannel;
4241 }
4242 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004243 case QDF_SAP_MODE:
4244 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 /* softap connection info */
4246 if (test_bit
4247 (SOFTAP_BSS_STARTED,
4248 &adapter->event_flags))
4249 operatingChannel =
4250 (WLAN_HDD_GET_AP_CTX_PTR
4251 (adapter))->operatingChannel;
4252 break;
4253 default:
4254 break;
4255 }
4256
4257 break; /* Found the device of interest. break the loop */
4258 }
4259
4260 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4261 adapterNode = pNext;
4262 }
4263 return operatingChannel;
4264}
4265
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304266static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 hdd_ctx)
4268{
4269 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304270 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004271 hdd_adapter_t *adapter;
4272
4273 ENTER();
4274
4275 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4276
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304277 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004279 if ((adapter->device_mode == QDF_STA_MODE) ||
4280 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4281 (adapter->device_mode == QDF_IBSS_MODE) ||
4282 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4283 (adapter->device_mode == QDF_SAP_MODE) ||
4284 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285 wlan_hdd_cfg80211_deregister_frames(adapter);
4286 hdd_unregister_wext(adapter->dev);
4287 }
4288 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4289 adapterNode = pNext;
4290 }
4291
4292 EXIT();
4293
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304294 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004295}
4296
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304297QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298{
4299 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304300 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 hdd_adapter_t *adapter;
4302
4303 ENTER();
4304
4305 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4306
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304307 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004309 if ((adapter->device_mode == QDF_STA_MODE) ||
4310 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4311 (adapter->device_mode == QDF_IBSS_MODE) ||
4312 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4313 (adapter->device_mode == QDF_SAP_MODE) ||
4314 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004315 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4316 eCSR_SCAN_ABORT_DEFAULT);
4317 }
4318 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4319 adapterNode = pNext;
4320 }
4321
4322 EXIT();
4323
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304324 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325}
4326
4327#ifdef WLAN_NS_OFFLOAD
4328/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004329 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004330 * @hdd_ctx: Pointer to hdd context
4331 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004332 * Unregister for IPv6 address change notifications.
4333 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 * Return: None
4335 */
4336static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4337{
4338 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4339
4340 return;
4341}
4342
4343/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004344 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 * @hdd_ctx: Pointer to hdd context
4346 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004347 * Register for IPv6 address change notifications.
4348 *
4349 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004350 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004351static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004352{
4353 int ret;
4354
4355 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4356 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004357 if (ret) {
4358 hdd_err("Failed to register IPv6 notifier: %d", ret);
4359 goto out;
4360 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004362 hdd_info("Registered IPv6 notifier");
4363out:
4364 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365}
4366#else
4367/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004368 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 * @hdd_ctx: Pointer to hdd context
4370 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004371 * Unregister for IPv6 address change notifications.
4372 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 * Return: None
4374 */
4375static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4376{
4377}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004380 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381 * @hdd_ctx: Pointer to hdd context
4382 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004383 * Register for IPv6 address change notifications.
4384 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385 * Return: None
4386 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004387static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004389 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390}
4391#endif
4392
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304393#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4394/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004395 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304396 * @hdd_ctx: HDD context
4397 *
4398 * Activates the logging service
4399 *
4400 * Return: Zero in case of success, negative value otherwise
4401 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004402static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304403{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004404 int ret;
4405 struct hdd_config *config = hdd_ctx->config;
4406
4407 if (!config->wlanLoggingEnable)
4408 return 0;
4409
4410 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4411 config->wlanLoggingNumBuf);
4412 if (ret)
4413 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4414 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304415}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004416
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304417/**
4418 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4419 * @hdd_ctx: HDD context
4420 *
4421 * Deactivates the logging service
4422 *
4423 * Return: 0 on deactivating the logging service
4424 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004425static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304426{
4427 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4428 return wlan_logging_sock_deactivate_svc();
4429
4430 return 0;
4431}
4432#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004433static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304434{
4435 return 0;
4436}
4437
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004438static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304439{
4440 return 0;
4441}
4442#endif
4443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004445 * hdd_register_notifiers - Register netdev notifiers.
4446 * @hdd_ctx: HDD context
4447 *
4448 * Register netdev notifiers like IPv4 and IPv6.
4449 *
4450 * Return: 0 on success and errno on failure
4451 */
4452static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4453{
4454 int ret;
4455
4456 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4457 if (ret) {
4458 hdd_err("register_netdevice_notifier failed: %d", ret);
4459 goto out;
4460 }
4461
4462 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4463 if (ret)
4464 goto unregister_notifier;
4465
4466 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4467 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4468 if (ret) {
4469 hdd_err("Failed to register IPv4 notifier: %d", ret);
4470 goto unregister_ip6_notifier;
4471 }
4472
4473 return 0;
4474
4475unregister_ip6_notifier:
4476 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4477unregister_notifier:
4478 unregister_netdevice_notifier(&hdd_netdev_notifier);
4479out:
4480 return ret;
4481
4482}
4483
4484/**
4485 * hdd_unregister_notifiers - Unregister netdev notifiers.
4486 * @hdd_ctx: HDD context
4487 *
4488 * Unregister netdev notifiers like IPv4 and IPv6.
4489 *
4490 * Return: None.
4491 */
4492static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4493{
4494 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4495
4496 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4497
4498 unregister_netdevice_notifier(&hdd_netdev_notifier);
4499}
4500
4501/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004502 * hdd_exit_netlink_services - Exit netlink services
4503 * @hdd_ctx: HDD context
4504 *
4505 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4506 * nl service.
4507 *
4508 * Return: None.
4509 */
4510static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4511{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004512 hdd_close_cesium_nl_sock();
4513
4514 ptt_sock_deactivate_svc();
4515
4516 nl_srv_exit();
4517}
4518
4519/**
4520 * hdd_init_netlink_services- Init netlink services
4521 * @hdd_ctx: HDD context
4522 *
4523 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4524 * nl service.
4525 *
4526 * Return: 0 on success and errno on failure.
4527 */
4528static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4529{
4530 int ret;
4531
Ryan Hsuceddceb2016-04-28 10:20:14 -07004532 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004533 if (ret) {
4534 hdd_alert("nl_srv_init failed: %d", ret);
4535 goto out;
4536 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004537 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004538
4539 ret = oem_activate_service(hdd_ctx);
4540 if (ret) {
4541 hdd_alert("oem_activate_service failed: %d", ret);
4542 goto err_nl_srv;
4543 }
4544
4545 ret = ptt_sock_activate_svc();
4546 if (ret) {
4547 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4548 goto err_nl_srv;
4549 }
4550
4551 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004552 if (ret)
4553 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004554
4555 ret = cnss_diag_activate_service();
4556 if (ret) {
4557 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4558 goto err_close_cesium;
4559 }
4560
4561 return 0;
4562
4563err_close_cesium:
4564 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004565 ptt_sock_deactivate_svc();
4566err_nl_srv:
4567 nl_srv_exit();
4568out:
4569 return ret;
4570}
4571
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004572#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4573/**
4574 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4575 * @hdd_ctx: HDD context.
4576 *
4577 * Destroy RX wakelock.
4578 *
4579 * Return: None.
4580 */
4581static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4582{
4583 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4584}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004585
4586/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004587 * hdd_rx_wake_lock_create() - Create RX wakelock
4588 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004589 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004590 * Create RX wakelock.
4591 *
4592 * Return: None.
4593 */
4594static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4595{
4596 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4597}
4598#else
4599static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { }
4600static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { }
4601#endif
4602
4603/**
4604 * hdd_roc_context_init() - Init ROC context
4605 * @hdd_ctx: HDD context.
4606 *
4607 * Initialize ROC context.
4608 *
4609 * Return: 0 on success and errno on failure.
4610 */
4611static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4612{
4613 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4614 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4615
4616 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4617
4618 return 0;
4619}
4620
4621/**
4622 * hdd_roc_context_destroy() - Destroy ROC context
4623 * @hdd_ctx: HDD context.
4624 *
4625 * Destroy roc list and flush the pending roc work.
4626 *
4627 * Return: None.
4628 */
4629static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4630{
4631 flush_delayed_work(&hdd_ctx->roc_req_work);
4632 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4633}
4634
4635/**
4636 * hdd_context_destroy() - Destroy HDD context
4637 * @hdd_ctx: HDD context to be destroyed.
4638 *
4639 * Free config and HDD context as well as destroy all the resources.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004640 *
4641 * Return: None
4642 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004643static void hdd_context_destroy(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004644{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304645 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004646 hdd_logging_sock_deactivate_svc(hdd_ctx);
4647
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004648 hdd_roc_context_destroy(hdd_ctx);
4649
4650 hdd_sap_context_destroy(hdd_ctx);
4651
4652 hdd_rx_wake_lock_destroy(hdd_ctx);
4653
4654 hdd_tdls_context_destroy(hdd_ctx);
4655
4656 hdd_scan_context_destroy(hdd_ctx);
4657
4658 qdf_list_destroy(&hdd_ctx->hddAdapters);
4659
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304660 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004661 hdd_ctx->config = NULL;
4662
4663 wiphy_free(hdd_ctx->wiphy);
4664}
4665
4666/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667 * hdd_wlan_exit() - HDD WLAN exit function
4668 * @hdd_ctx: Pointer to the HDD Context
4669 *
4670 * This is the driver exit point (invoked during rmmod)
4671 *
4672 * Return: None
4673 */
Jeff Johnson590e2012016-10-05 16:16:24 -07004674static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675{
4676 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304677 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004678 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304679 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680
4681 ENTER();
4682
Arun Khandavallifae92942016-08-01 13:31:08 +05304683 if (QDF_TIMER_STATE_RUNNING ==
4684 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4685 hdd_info("Stpp interface change timer");
4686 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004687 }
4688
Arun Khandavallifae92942016-08-01 13:31:08 +05304689 if (!QDF_IS_STATUS_SUCCESS
4690 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4691 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004692
Arun Khandavallifae92942016-08-01 13:31:08 +05304693
4694 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004695
4696#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05304697 if (QDF_TIMER_STATE_RUNNING ==
4698 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
4699 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Ravi Joshib89e7f72016-09-07 13:43:15 -07004700 hdd_reset_tcp_delack(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 }
4702
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304703 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304704 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004705 hdd_err("Cannot deallocate Bus bandwidth timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 }
4707#endif
4708
4709#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304710 if (QDF_TIMER_STATE_RUNNING ==
4711 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4712 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 }
4714
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304715 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304716 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004717 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718 }
4719#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720
Arun Khandavallifae92942016-08-01 13:31:08 +05304721 mutex_lock(&hdd_ctx->iface_change_lock);
4722 driver_status = hdd_ctx->driver_status;
4723 mutex_unlock(&hdd_ctx->iface_change_lock);
4724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725 /*
4726 * Powersave Offload Case
4727 * Disable Idle Power Save Mode
4728 */
4729 hdd_set_idle_ps_config(hdd_ctx, false);
4730
Arun Khandavallifae92942016-08-01 13:31:08 +05304731 if (driver_status != DRIVER_MODULES_CLOSED) {
4732 hdd_unregister_wext_all_adapters(hdd_ctx);
4733 /*
4734 * Cancel any outstanding scan requests. We are about to close
4735 * all of our adapters, but an adapter structure is what SME
4736 * passes back to our callback function. Hence if there
4737 * are any outstanding scan requests then there is a
4738 * race condition between when the adapter is closed and
4739 * when the callback is invoked. We try to resolve that
4740 * race condition here by canceling any outstanding scans
4741 * before we close the adapters.
4742 * Note that the scans may be cancelled in an asynchronous
4743 * manner, so ideally there needs to be some kind of
4744 * synchronization. Rather than introduce a new
4745 * synchronization here, we will utilize the fact that we are
4746 * about to Request Full Power, and since that is synchronized,
4747 * the expectation is that by the time Request Full Power has
4748 * completed, all scans will be cancelled
4749 */
4750 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4751 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004752 }
4753
Arun Khandavallifae92942016-08-01 13:31:08 +05304754 hdd_wlan_stop_modules(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 /*
4756 * Close the scheduler before calling cds_close to make sure no thread
4757 * is scheduled after the each module close is called i.e after all the
4758 * data structures are freed.
4759 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304760 qdf_status = cds_sched_close(p_cds_context);
4761 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004762 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304763 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004765
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304766 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4767 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4768 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4769
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 /*
4771 * Close CDS
4772 * This frees pMac(HAL) context. There should not be any call
4773 * that requires pMac access after this.
4774 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07004776 hdd_green_ap_deinit(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004777
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004778 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779
4780 hdd_ipa_cleanup(hdd_ctx);
4781
4782 /* Free up RoC request queue and flush workqueue */
4783 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004784
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05304785 hdd_encrypt_decrypt_deinit(hdd_ctx);
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304786 wlansap_global_deinit();
Nirav Shahed34b212016-04-25 10:59:16 +05304787 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004788 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304789 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004790
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07004791 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004792
Arun Khandavallifae92942016-08-01 13:31:08 +05304793 hdd_exit_netlink_services(hdd_ctx);
4794 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004795 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004796}
4797
4798void __hdd_wlan_exit(void)
4799{
4800 hdd_context_t *hdd_ctx;
4801
4802 ENTER();
4803
Anurag Chouhan6d760662016-02-20 16:05:43 +05304804 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004805 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004806 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 EXIT();
4808 return;
4809 }
4810
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004811 /* Check IPA HW Pipe shutdown */
4812 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4813
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004814 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05304815 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004816
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004817 /* Do all the cleanup before deregistering the driver */
4818 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 EXIT();
4821}
4822
4823#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4824void hdd_skip_acs_scan_timer_handler(void *data)
4825{
4826 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4827
Jeff Johnson760350b2016-08-15 14:01:52 -07004828 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004829 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4830
4831 if (!hdd_ctx->hHal)
4832 return;
4833 sme_scan_flush_result(hdd_ctx->hHal);
4834}
4835#endif
4836
4837#ifdef QCA_HT_2040_COEX
4838/**
4839 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4840 * @adapter: pointer to adapter
4841 * @staId: station id
4842 * @macAddrSTA: station MAC address
4843 * @channel_type: channel type
4844 *
4845 * This function notifies FW with HT20/HT40 mode
4846 *
4847 * Return: 0 if successful, error number otherwise
4848 */
4849int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304850 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851{
4852 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304853 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 hdd_context_t *hdd_ctx = NULL;
4855
4856 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4857
4858 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304859 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 if (!hdd_ctx->hHal)
4863 return -EINVAL;
4864
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304865 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304867 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004868 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004869 return -EINVAL;
4870 }
4871
4872 return 0;
4873}
4874#endif
4875
4876/**
4877 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4878 * @state: state
4879 *
4880 * This function notifies FW with modem power status
4881 *
4882 * Return: 0 if successful, error number otherwise
4883 */
4884int hdd_wlan_notify_modem_power_state(int state)
4885{
4886 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304887 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 hdd_context_t *hdd_ctx;
4889
Anurag Chouhan6d760662016-02-20 16:05:43 +05304890 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304892 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 if (!hdd_ctx->hHal)
4896 return -EINVAL;
4897
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304898 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4899 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004900 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 state);
4902 return -EINVAL;
4903 }
4904 return 0;
4905}
4906
4907/**
4908 *
4909 * hdd_post_cds_enable_config() - HDD post cds start config helper
4910 * @adapter - Pointer to the HDD
4911 *
4912 * Return: None
4913 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304914QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004915{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304916 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917
4918 /*
4919 * Send ready indication to the HDD. This will kick off the MAC
4920 * into a 'running' state and should kick off an initial scan.
4921 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304922 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4923 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004924 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
4925 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304926 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 }
4928
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304929 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930}
4931
4932/* wake lock APIs for HDD */
4933void hdd_prevent_suspend(uint32_t reason)
4934{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304935 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004936}
4937
4938void hdd_allow_suspend(uint32_t reason)
4939{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304940 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941}
4942
4943void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
4944{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05304945 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
4946 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947}
4948
4949/**
4950 * hdd_exchange_version_and_caps() - exchange version and capability with target
4951 * @hdd_ctx: Pointer to HDD context
4952 *
4953 * This is the HDD function to exchange version and capability information
4954 * between Host and Target
4955 *
4956 * This function gets reported version of FW.
4957 * It also finds the version of target headers used to compile the host;
4958 * It compares the above two and prints a warning if they are different;
4959 * It gets the SW and HW version string;
4960 * Finally, it exchanges capabilities between host and target i.e. host
4961 * and target exchange a msg indicating the features they support through a
4962 * bitmap
4963 *
4964 * Return: None
4965 */
4966void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4967{
4968
4969 tSirVersionType versionCompiled;
4970 tSirVersionType versionReported;
4971 tSirVersionString versionString;
4972 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304973 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004974
4975 memset(&versionCompiled, 0, sizeof(versionCompiled));
4976 memset(&versionReported, 0, sizeof(versionReported));
4977
4978 /* retrieve and display WCNSS version information */
4979 do {
4980
4981 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4982 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304983 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004984 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004985 break;
4986 }
4987
4988 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4989 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304990 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004991 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004992 break;
4993 }
4994
4995 if ((versionCompiled.major != versionReported.major) ||
4996 (versionCompiled.minor != versionReported.minor) ||
4997 (versionCompiled.version != versionReported.version) ||
4998 (versionCompiled.revision != versionReported.revision)) {
4999 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5000 "Host expected %u.%u.%u.%u\n",
5001 WLAN_MODULE_NAME,
5002 (int)versionReported.major,
5003 (int)versionReported.minor,
5004 (int)versionReported.version,
5005 (int)versionReported.revision,
5006 (int)versionCompiled.major,
5007 (int)versionCompiled.minor,
5008 (int)versionCompiled.version,
5009 (int)versionCompiled.revision);
5010 } else {
5011 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5012 WLAN_MODULE_NAME,
5013 (int)versionReported.major,
5014 (int)versionReported.minor,
5015 (int)versionReported.version,
5016 (int)versionReported.revision);
5017 }
5018
5019 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5020 versionString,
5021 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305022 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005023 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024 break;
5025 }
5026
5027 pr_info("%s: WCNSS software version %s\n",
5028 WLAN_MODULE_NAME, versionString);
5029
5030 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5031 versionString,
5032 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305033 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005034 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005035 break;
5036 }
5037
5038 pr_info("%s: WCNSS hardware version %s\n",
5039 WLAN_MODULE_NAME, versionString);
5040
5041 /*
5042 * 1.Check if FW version is greater than 0.1.1.0. Only then
5043 * send host-FW capability exchange message
5044 * 2.Host-FW capability exchange message is only present on
5045 * target 1.1 so send the message only if it the target is 1.1
5046 * minor numbers for different target branches:
5047 * 0 -> (1.0)Mainline Build
5048 * 1 -> (1.1)Mainline Build
5049 * 2->(1.04) Stability Build
5050 */
5051 if (((versionReported.major > 0) || (versionReported.minor > 1)
5052 || ((versionReported.minor >= 1)
5053 && (versionReported.version >= 1)))
5054 && ((versionReported.major == 1)
5055 && (versionReported.minor >= 1)))
5056 fwFeatCapsMsgSupported = 1;
5057
5058 if (fwFeatCapsMsgSupported) {
5059 /*
5060 * Indicate if IBSS heartbeat monitoring needs to be
5061 * offloaded
5062 */
5063 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5064 sme_disable_feature_capablity
5065 (IBSS_HEARTBEAT_OFFLOAD);
5066 }
5067
5068 sme_feature_caps_exchange(hdd_ctx->hHal);
5069 }
5070
5071 } while (0);
5072
5073}
5074
5075/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305076QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005077{
5078 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5079 hdd_ctx->reg.cc_src);
5080}
5081
5082/**
5083 * hdd_is_5g_supported() - check if hardware supports 5GHz
5084 * @hdd_ctx: Pointer to the hdd context
5085 *
5086 * HDD function to know if hardware supports 5GHz
5087 *
5088 * Return: true if hardware supports 5GHz
5089 */
5090bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5091{
5092 /*
5093 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5094 * then hardware support 5Ghz.
5095 */
5096 return true;
5097}
5098
Amar Singhale4f28ee2015-10-21 14:36:56 -07005099static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005100{
5101 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005102 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005103
5104 wiphy = hdd_ctx->wiphy;
5105
5106 /*
5107 * The channel information in
5108 * wiphy needs to be initialized before wiphy registration
5109 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005110 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5111 if (ret_val) {
5112 hdd_alert("regulatory init failed");
5113 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005114 }
5115
5116#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5117 wiphy->wowlan = &wowlan_support_reg_init;
5118#else
5119 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5120 WIPHY_WOWLAN_MAGIC_PKT |
5121 WIPHY_WOWLAN_DISCONNECT |
5122 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5123 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5124 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5125 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5126 WIPHY_WOWLAN_RFKILL_RELEASE;
5127
5128 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5129 WOW_MAX_FILTERS_PER_LIST);
5130 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5131 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5132#endif
5133
5134 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005135 ret_val = wlan_hdd_cfg80211_register(wiphy);
5136 if (0 > ret_val)
5137 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005138
Amar Singhale4f28ee2015-10-21 14:36:56 -07005139 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005140}
5141
Ravi Joshie2331e82015-07-01 18:18:54 -07005142/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005143 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005144 * @hdd_ctx - handle to hdd context
5145 * @tx_packets - transmit packet count
5146 * @rx_packets - receive packet count
5147 *
5148 * The function controls the bus bandwidth and dynamic control of
5149 * tcp delayed ack configuration
5150 *
5151 * Returns: None
5152 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005153#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005154static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5155 const uint64_t tx_packets,
5156 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005157{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005158 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005159 uint64_t temp_rx = 0;
5160 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005161 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005162 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5163 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005164 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005167 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005169 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005170 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005171 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005172 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005173 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174
Mohit Khannae71e2262015-11-10 09:37:24 -08005175 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5176 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177
5178 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005179 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5180 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005182 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305183 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305184 if (hdd_ctx->hbw_requested) {
5185 pld_remove_pm_qos(hdd_ctx->parent_dev);
5186 hdd_ctx->hbw_requested = false;
5187 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305188 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005189 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305190 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305191 if (!hdd_ctx->hbw_requested) {
5192 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5193 hdd_ctx->hbw_requested = true;
5194 }
5195
Nirav Shah3bbfa512016-05-12 16:43:49 +05305196 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005197 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305198 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005199 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005201
5202 /* fine-tuning parameters for RX Flows */
5203 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 hdd_ctx->prev_rx = rx_packets;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005206 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh &&
5207 (hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH &&
5208 ++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
Mohit Khannae71e2262015-11-10 09:37:24 -08005209 next_rx_level = WLAN_SVC_TP_HIGH;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005210 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005211 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005212 hdd_ctx->rx_high_ind_cnt = 0;
5213 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214
Mohit Khannae71e2262015-11-10 09:37:24 -08005215 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5216 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217
5218 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005219 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 next_rx_level, temp_rx);
5221 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005222 /* Send throughput indication only if it is enabled.
5223 * Disabling tcp_del_ack will revert the tcp stack behavior
5224 * to default delayed ack. Note that this will disable the
5225 * dynamic delayed ack mechanism across the system
5226 */
5227 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305228 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5229 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 &next_rx_level,
5231 sizeof(next_rx_level));
5232 }
5233
Mohit Khannae71e2262015-11-10 09:37:24 -08005234 /* fine-tuning parameters for TX Flows */
5235 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5236 hdd_ctx->prev_tx = tx_packets;
5237 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5238 next_tx_level = WLAN_SVC_TP_HIGH;
5239 else
5240 next_tx_level = WLAN_SVC_TP_LOW;
5241
5242 if (hdd_ctx->cur_tx_level != next_tx_level) {
5243 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5244 next_tx_level, temp_tx);
5245 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305246 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5247 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005248 &next_tx_level,
5249 sizeof(next_tx_level));
5250 }
5251
5252 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5253 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005254 hdd_ctx->hdd_txrx_hist_idx++;
5255 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256}
5257
5258#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
5259static void hdd_bus_bw_compute_cbk(void *priv)
5260{
5261 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
5262 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305263 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305264 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5265 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 uint64_t total_tx = 0, total_rx = 0;
5267 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305268 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305269 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005270 bool connected = false;
5271 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5272
5273 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305274 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 status =
5276 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5277
5278 if (adapterNode->pAdapter == NULL)
5279 continue;
5280 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305281 /*
5282 * Validate magic so we don't end up accessing
5283 * an invalid adapter.
5284 */
5285 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5286 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005288 if ((adapter->device_mode == QDF_STA_MODE ||
5289 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005290 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5291 != eConnectionState_Associated) {
5292
5293 continue;
5294 }
5295
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005296 if ((adapter->device_mode == QDF_SAP_MODE ||
5297 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005298 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5299
5300 continue;
5301 }
5302
5303 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5304 adapter->prev_tx_packets);
5305 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5306 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305307
5308 if (adapter->device_mode == QDF_SAP_MODE ||
5309 adapter->device_mode == QDF_P2P_GO_MODE ||
5310 adapter->device_mode == QDF_IBSS_MODE) {
5311
5312 ret = ol_get_intra_bss_fwd_pkts_count(
5313 adapter->sessionId,
5314 &fwd_tx_packets, &fwd_rx_packets);
5315 if (ret == A_OK) {
5316 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5317 fwd_tx_packets,
5318 adapter->prev_fwd_tx_packets);
5319 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5320 fwd_tx_packets,
5321 adapter->prev_fwd_rx_packets);
5322 }
5323 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324
5325 total_rx += adapter->stats.rx_packets;
5326 total_tx += adapter->stats.tx_packets;
5327
5328 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5329 adapter->prev_tx_packets = adapter->stats.tx_packets;
5330 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305331 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5332 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005333 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5334 connected = true;
5335 }
5336
5337 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5338 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5339 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5340 rx_packets;
5341 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5342 tx_packets;
5343
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305344 /* add intra bss forwarded tx and rx packets */
5345 tx_packets += fwd_tx_packets_diff;
5346 rx_packets += fwd_rx_packets_diff;
5347
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5349 tx_packets += (uint64_t)ipa_tx_packets;
5350 rx_packets += (uint64_t)ipa_rx_packets;
5351
5352 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005353 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 return;
5355 }
5356
Yuanyuan Liu13738502016-04-06 17:41:37 -07005357 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005358
5359 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5360 hdd_ipa_uc_stat_request(adapter, 2);
5361
Anurag Chouhan210db072016-02-22 18:42:15 +05305362 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 hdd_ctx->config->busBandwidthComputeInterval);
5364}
5365#endif
5366
5367/**
Nirav Shahed34b212016-04-25 10:59:16 +05305368 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5369 * @hdd_ctx: hdd context
5370 *
5371 * Return: 0 for success or error code
5372 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005373static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305374{
5375 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5376 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5377 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005378 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305379 return -ENOMEM;
5380 }
5381 return 0;
5382}
5383
5384/**
5385 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5386 * @hdd_ctx: hdd context
5387 *
5388 * Return: none
5389 */
5390void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5391{
5392 if (hdd_ctx->hdd_txrx_hist) {
5393 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5394 hdd_ctx->hdd_txrx_hist = NULL;
5395 }
5396}
5397
Nirav Shahda008342016-05-17 18:50:40 +05305398static uint8_t *convert_level_to_string(uint32_t level)
5399{
5400 switch (level) {
5401 /* initialize the wlan sub system */
5402 case WLAN_SVC_TP_NONE:
5403 return "NONE";
5404 case WLAN_SVC_TP_LOW:
5405 return "LOW";
5406 case WLAN_SVC_TP_MEDIUM:
5407 return "MED";
5408 case WLAN_SVC_TP_HIGH:
5409 return "HIGH";
5410 default:
5411 return "INVAL";
5412 }
5413}
5414
Nirav Shahed34b212016-04-25 10:59:16 +05305415
5416/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5418 * @hdd_ctx: hdd context
5419 *
5420 * Return: none
5421 */
5422void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5423{
5424 int i;
5425
5426#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005427 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305428 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005429 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 hdd_ctx->config->busBandwidthHighThreshold,
5431 hdd_ctx->config->busBandwidthMediumThreshold,
5432 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005433 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305434 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005435 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005436 hdd_ctx->config->tcpDelackThresholdHigh,
5437 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005438 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305439 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440#endif
5441
Jeff Johnson760350b2016-08-15 14:01:52 -07005442 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305443 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5444
Jeff Johnson760350b2016-08-15 14:01:52 -07005445 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 -08005446
5447 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005448 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5450 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5451 hdd_ctx->hdd_txrx_hist[i].total_tx,
5452 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305453 convert_level_to_string(
5454 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5455 convert_level_to_string(
5456 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5457 convert_level_to_string(
5458 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005459 }
5460 return;
5461}
5462
5463/**
5464 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5465 * @hdd_ctx: hdd context
5466 *
5467 * Return: none
5468 */
5469void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5470{
5471 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305472 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5473 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474}
5475
5476/**
5477 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5478 * @pHddCtx: hdd context
5479 *
5480 * Return: none
5481 */
5482void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5483{
5484
5485 hdd_adapter_t *adapter = NULL;
5486 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305487 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305489 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005490
5491 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305492 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 adapter = adapter_node->pAdapter;
5494
Jeff Johnson760350b2016-08-15 14:01:52 -07005495 hdd_err("\nNetif queue operation statistics:");
5496 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305497 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005498 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305499 curr_time = qdf_system_ticks();
5500 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305501 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305502 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305503 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305504 unpause = adapter->total_unpause_time;
5505 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305506 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305507 pause = adapter->total_pause_time;
5508 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005509 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305510 qdf_system_ticks_to_msecs(total),
5511 qdf_system_ticks_to_msecs(pause),
5512 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005513 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514
Nirav Shahda008342016-05-17 18:50:40 +05305515 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5516 qdf_time_t pause_delta = 0;
5517
5518 if (adapter->pause_map & (1 << i))
5519 pause_delta = delta;
5520
Jeff Johnson760350b2016-08-15 14:01:52 -07005521 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 hdd_reason_type_to_string(i),
5523 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305524 adapter->queue_oper_stats[i].unpause_count,
5525 qdf_system_ticks_to_msecs(
5526 adapter->queue_oper_stats[i].total_pause_time +
5527 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 }
5529
Jeff Johnson760350b2016-08-15 14:01:52 -07005530 hdd_err("\nNetif queue operation history:");
5531 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305532 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5533
Jeff Johnson760350b2016-08-15 14:01:52 -07005534 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535
5536 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005537 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305538 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005539 adapter->queue_oper_history[i].time),
5540 hdd_action_type_to_string(
5541 adapter->queue_oper_history[i].netif_action),
5542 hdd_reason_type_to_string(
5543 adapter->queue_oper_history[i].netif_reason),
5544 adapter->queue_oper_history[i].pause_map);
5545 }
5546
5547 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5548 adapter_node = next;
5549 }
5550
5551
5552}
5553
5554/**
5555 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5556 * @hdd_ctx: hdd context
5557 *
5558 * Return: none
5559 */
5560void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5561{
5562 hdd_adapter_t *adapter = NULL;
5563 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305564 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565
5566 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305567 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005568 adapter = adapter_node->pAdapter;
5569
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305570 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305572 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305574 adapter->history_index = 0;
5575 adapter->start_time = adapter->last_time = qdf_system_ticks();
5576 adapter->total_pause_time = 0;
5577 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005578 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5579 adapter_node = next;
5580 }
5581}
5582
5583/**
5584 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5585 * @halHandle: Hal handle
5586 * @pContext: Pointer to the context
5587 * @sessionId: Session ID
5588 * @scanId: Scan ID
5589 * @status: Status
5590 *
5591 * This is the callback to be executed when 11d scan is completed to flush out
5592 * the scan results
5593 *
5594 * 11d scan is done during driver load and is a passive scan on all
5595 * channels supported by the device, 11d scans may find some APs on
5596 * frequencies which are forbidden to be used in the regulatory domain
5597 * the device is operating in. If these APs are notified to the supplicant
5598 * it may try to connect to these APs, thus flush out all the scan results
5599 * which are present in SME after 11d scan is done.
5600 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305601 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305603static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604 uint8_t sessionId, uint32_t scanId,
5605 eCsrScanStatus status)
5606{
5607 ENTER();
5608
5609 sme_scan_flush_result(halHandle);
5610
5611 EXIT();
5612
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305613 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614}
5615
5616#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5617/**
5618 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5619 * @hdd_ctx: hdd global context
5620 *
5621 * Return: none
5622 */
5623static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5624{
5625 uint8_t i;
5626
5627 mutex_init(&hdd_ctx->op_ctx.op_lock);
5628 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5629 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5630 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5631 }
5632}
5633#else
5634static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5635{
5636}
5637#endif
5638
5639#ifdef WLAN_FEATURE_FASTPATH
5640/**
5641 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5642 * @hdd_cfg: hdd config
5643 * @context: lower layer context
5644 *
5645 * Return: none
5646 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305647void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005648 void *context)
5649{
5650 if (hdd_cfg->fastpath_enable)
5651 hif_enable_fastpath(context);
5652}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653#endif
5654
Yuanyuan Liu13738502016-04-06 17:41:37 -07005655#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656/**
5657 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005658 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005659 * @level: thermal level
5660 *
5661 * Change IPA data path to SW path when the thermal throttle level greater
5662 * than 0, and restore the original data path when throttle level is 0
5663 *
5664 * Return: none
5665 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005666static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005668 hdd_context_t *hdd_ctx = context;
5669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005670 /* Change IPA to SW path when throttle level greater than 0 */
5671 if (level > THROTTLE_LEVEL_0)
5672 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5673 else
5674 /* restore original concurrency mode */
5675 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5676}
5677
5678/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305679 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5680 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305681 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305683 * Get a safe channel to restart SAP. PCL already takes into account the
5684 * unsafe channels. So, the PCL is validated with the ACS range to provide
5685 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305687 * Return: Channel number to restart SAP in case of success. In case of any
5688 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305690static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5691 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305693 struct sir_pcl_list pcl;
5694 QDF_STATUS status;
5695 uint32_t i, j;
5696 tHalHandle *hal_handle;
5697 hdd_context_t *hdd_ctx;
5698 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305700 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5701 if (!hdd_ctx) {
5702 hdd_err("invalid HDD context");
5703 return INVALID_CHANNEL_ID;
5704 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005705
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305706 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5707 if (!hal_handle) {
5708 hdd_err("invalid HAL handle");
5709 return INVALID_CHANNEL_ID;
5710 }
5711
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305712 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5713 pcl.pcl_list, &pcl.pcl_len,
5714 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5715 if (QDF_IS_STATUS_ERROR(status)) {
5716 hdd_err("Get PCL failed");
5717 return INVALID_CHANNEL_ID;
5718 }
5719
5720 if (!pcl.pcl_len) {
5721 hdd_alert("pcl length is zero. this is not expected");
5722 return INVALID_CHANNEL_ID;
5723 }
5724
5725 hdd_info("start:%d end:%d",
5726 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5727 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5728
5729 /* PCL already takes unsafe channel into account */
5730 for (i = 0; i < pcl.pcl_len; i++) {
5731 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5732 if ((pcl.pcl_list[i] >=
5733 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5734 (pcl.pcl_list[i] <=
5735 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5736 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5737 return pcl.pcl_list[i];
5738 }
5739 }
5740
5741 hdd_info("no safe channel from PCL found in ACS range");
5742
5743 /* Try for safe channel from all valid channel */
5744 pcl.pcl_len = MAX_NUM_CHAN;
5745 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5746 &pcl.pcl_len);
5747 if (QDF_IS_STATUS_ERROR(status)) {
5748 hdd_err("error in getting valid channel list");
5749 return INVALID_CHANNEL_ID;
5750 }
5751
5752 for (i = 0; i < pcl.pcl_len; i++) {
5753 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5754 found = false;
5755 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
5756 if (cds_chan_to_freq(pcl.pcl_list[i]) ==
5757 hdd_ctx->unsafe_channel_list[j]) {
5758 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5759 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005760 break;
5761 }
5762 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305763
5764 if (found)
5765 continue;
5766
5767 if ((pcl.pcl_list[i] >=
5768 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5769 (pcl.pcl_list[i] <=
5770 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5771 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5772 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005773 }
5774 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305775
5776 return INVALID_CHANNEL_ID;
5777}
5778
5779/**
5780 * hdd_restart_sap() - Restarts SAP on the given channel
5781 * @adapter: AP adapter
5782 * @channel: Channel
5783 *
5784 * Restarts the SAP interface by invoking the function which executes the
5785 * callback to perform channel switch using (E)CSA.
5786 *
5787 * Return: None
5788 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005789static void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305790{
5791 hdd_ap_ctx_t *hdd_ap_ctx;
5792 tHalHandle *hal_handle;
5793
5794 if (!adapter) {
5795 hdd_err("invalid adapter");
5796 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305798
5799 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5800
5801 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5802 if (!hal_handle) {
5803 hdd_err("invalid HAL handle");
5804 return;
5805 }
5806
5807 hdd_ap_ctx->sapConfig.channel = channel;
5808 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5809 hdd_ap_ctx->sapConfig.ch_width_orig;
5810
5811 hdd_info("chan:%d width:%d",
5812 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5813
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005814 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305815 hdd_ap_ctx->sapConfig.sec_ch,
5816 &hdd_ap_ctx->sapConfig.ch_params);
5817
5818 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819}
Agrawal Ashish467dde42016-09-08 18:44:22 +05305820/**
5821 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
5822 * @hdd_ctx: hdd context pointer
5823 *
5824 * hdd_unsafe_channel_restart_sap check all unsafe channel list
5825 * and if ACS is enabled, driver will ask userspace to restart the
5826 * sap. User space on LTE coex indication restart driver.
5827 *
5828 * Return - none
5829 */
5830void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
5831{
5832 QDF_STATUS status;
5833 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
5834 hdd_adapter_t *adapter_temp;
5835 uint32_t i;
5836 bool found = false;
5837 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838
Agrawal Ashish467dde42016-09-08 18:44:22 +05305839 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
5840 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5841 adapter_temp = adapter_node->pAdapter;
5842
5843 if (!adapter_temp) {
5844 hdd_err("adapter is NULL, moving to next one");
5845 goto next_adapater;
5846 }
5847
5848 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
5849 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
5850 hdd_info("skip device mode:%d acs:%d",
5851 adapter_temp->device_mode,
5852 adapter_temp->sessionCtx.ap.sapConfig.
5853 acs_cfg.acs_mode);
5854 goto next_adapater;
5855 }
5856
5857 found = false;
5858 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
5859 if (cds_chan_to_freq(
5860 adapter_temp->sessionCtx.ap.operatingChannel) ==
5861 hdd_ctxt->unsafe_channel_list[i]) {
5862 found = true;
5863 hdd_info("operating ch:%d is unsafe",
5864 adapter_temp->sessionCtx.ap.operatingChannel);
5865 break;
5866 }
5867 }
5868
5869 if (!found) {
5870 hdd_info("ch:%d is safe. no need to change channel",
5871 adapter_temp->sessionCtx.ap.operatingChannel);
5872 goto next_adapater;
5873 }
5874
5875 restart_chan =
5876 hdd_get_safe_channel_from_pcl_and_acs_range(
5877 adapter_temp);
5878 if (!restart_chan) {
5879 hdd_alert("fail to restart SAP");
5880 } else {
5881 hdd_info("sending coex indication");
5882 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
5883 WLAN_SVC_LTE_COEX_IND, NULL, 0);
5884 hdd_restart_sap(adapter_temp, restart_chan);
5885 }
5886
5887next_adapater:
5888 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
5889 adapter_node = next;
5890 }
5891}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005892/**
5893 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
5894 * @adapter: HDD adapter pointer
5895 * @indParam: Channel avoid notification parameter
5896 *
5897 * Avoid channel notification from FW handler.
5898 * FW will send un-safe channel list to avoid over wrapping.
5899 * hostapd should not use notified channel
5900 *
5901 * Return: None
5902 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05305903void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005904{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 hdd_context_t *hdd_ctxt;
5906 tSirChAvoidIndType *ch_avoid_indi;
5907 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08005908 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
5909 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005910 uint16_t start_channel;
5911 uint16_t end_channel;
5912 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 tHddAvoidFreqList hdd_avoid_freq_list;
5914 uint32_t i;
5915
5916 /* Basic sanity */
5917 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005918 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 return;
5920 }
5921
5922 hdd_ctxt = (hdd_context_t *) hdd_context;
5923 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
5924 cds_context = hdd_ctxt->pcds_context;
5925
5926 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07005927 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 ch_avoid_indi->avoid_range_count);
5929
5930 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305931 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005932 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
5933 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
5934 ch_avoid_indi->avoid_freq_range[i].start_freq;
5935 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
5936 ch_avoid_indi->avoid_freq_range[i].end_freq;
5937 }
5938 hdd_avoid_freq_list.avoidFreqRangeCount =
5939 ch_avoid_indi->avoid_range_count;
5940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 /* clear existing unsafe channel cache */
5942 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305943 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005944 sizeof(hdd_ctxt->unsafe_channel_list));
5945
5946 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
5947 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08005948 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005949 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950 break;
5951 }
5952
5953 start_channel = ieee80211_frequency_to_channel(
5954 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
5955 end_channel = ieee80211_frequency_to_channel(
5956 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07005957 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005958 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
5959 start_channel,
5960 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
5961 end_channel);
5962
5963 /* do not process frequency bands that are not mapped to
5964 * predefined channels
5965 */
5966 if (start_channel == 0 || end_channel == 0)
5967 continue;
5968
Amar Singhalb8d4f152016-02-10 10:21:43 -08005969 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5970 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005971 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972 ch_avoid_indi->avoid_freq_range[
5973 range_loop].start_freq) {
5974 start_channel_idx = channel_loop;
5975 break;
5976 }
5977 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08005978 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5979 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005980 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005981 ch_avoid_indi->avoid_freq_range[
5982 range_loop].end_freq) {
5983 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07005984 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005985 ch_avoid_indi->avoid_freq_range[
5986 range_loop].end_freq)
5987 end_channel_idx--;
5988 break;
5989 }
5990 }
5991
Amar Singhalb8d4f152016-02-10 10:21:43 -08005992 if (start_channel_idx == INVALID_CHANNEL ||
5993 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005994 continue;
5995
5996 for (channel_loop = start_channel_idx; channel_loop <=
5997 end_channel_idx; channel_loop++) {
5998 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07005999 hdd_ctxt->unsafe_channel_count++] =
6000 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006001 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006002 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006003 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006004 break;
6005 }
6006 }
6007 }
6008
Jeff Johnson34c88b72016-08-15 14:27:11 -07006009 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006010 hdd_ctxt->unsafe_channel_count);
6011
Yuanyuan Liu13738502016-04-06 17:41:37 -07006012 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6013 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006014 hdd_ctxt->unsafe_channel_count)) {
6015 hdd_err("Failed to set unsafe channel");
6016
6017 /* clear existing unsafe channel cache */
6018 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306019 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020 sizeof(hdd_ctxt->unsafe_channel_list));
6021
6022 return;
6023 }
6024
6025 for (channel_loop = 0;
6026 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006027 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006028 hdd_ctxt->unsafe_channel_list[channel_loop]);
6029 }
6030
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306031 /*
6032 * first update the unsafe channel list to the platform driver and
6033 * send the avoid freq event to the application
6034 */
6035 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6036
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306037 if (!hdd_ctxt->unsafe_channel_count) {
6038 hdd_info("no unsafe channels - not restarting SAP");
6039 return;
6040 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306041 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006042 return;
6043}
6044
6045/**
6046 * hdd_init_channel_avoidance() - Initialize channel avoidance
6047 * @hdd_ctx: HDD global context
6048 *
6049 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006050 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 * down to the lower layers. Then subscribe to subsequent channel
6052 * avoidance events.
6053 *
6054 * Return: None
6055 */
6056static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6057{
6058 uint16_t unsafe_channel_count;
6059 int index;
6060
Yuanyuan Liu13738502016-04-06 17:41:37 -07006061 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6062 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006063 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006064 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006065
Jeff Johnson34c88b72016-08-15 14:27:11 -07006066 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006067 hdd_ctx->unsafe_channel_count);
6068
Anurag Chouhan6d760662016-02-20 16:05:43 +05306069 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006070 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006071
6072 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006073 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006074 hdd_ctx->unsafe_channel_list[index]);
6075
6076 }
6077
6078 /* Plug in avoid channel notification callback */
6079 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6080}
6081#else
6082static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6083{
6084}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006085static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006086{
6087}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006088#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006089
6090/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006091 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6092 * user space
6093 * @frame_ind: Management frame data to be informed.
6094 *
6095 * This function is used to indicate management frame to
6096 * user space
6097 *
6098 * Return: None
6099 *
6100 */
6101void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6102{
6103 hdd_context_t *hdd_ctx = NULL;
6104 hdd_adapter_t *adapter = NULL;
6105 void *cds_context = NULL;
6106 int i;
6107
6108 /* Get the global VOSS context.*/
6109 cds_context = cds_get_global_context();
6110 if (!cds_context) {
6111 hdd_err("Global CDS context is Null");
6112 return;
6113 }
6114 /* Get the HDD context.*/
6115 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6116
6117 if (0 != wlan_hdd_validate_context(hdd_ctx))
6118 return;
6119
6120 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6121 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6122 adapter =
6123 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6124 if (adapter)
6125 break;
6126 }
6127 } else {
6128 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6129 frame_ind->sessionId);
6130 }
6131
6132 if ((NULL != adapter) &&
6133 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6134 __hdd_indicate_mgmt_frame(adapter,
6135 frame_ind->frame_len,
6136 frame_ind->frameBuf,
6137 frame_ind->frameType,
6138 frame_ind->rxChan,
6139 frame_ind->rxRssi);
6140 return;
6141}
6142
6143/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006144 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6145 * @hdd_ctx: HDD context
6146 *
6147 * Disables all the dual mac features like DBS, Agile DFS etc.
6148 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306149 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006150 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306151static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006152{
6153 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306154 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006155
6156 if (!hdd_ctx) {
6157 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306158 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159 }
6160
6161 cfg.scan_config = 0;
6162 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306163 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006164
6165 hdd_debug("Disabling all dual mac features...");
6166
6167 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306168 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006169 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6170 return status;
6171 }
6172
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306173 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174}
6175
6176/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006177 * hdd_override_ini_config - Override INI config
6178 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006179 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006180 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006181 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006182 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006183 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006184static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006185{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006186
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006187 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6188 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6189 hdd_notice("Module enable_dfs_chan_scan set to %d",
6190 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006191 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006192 if (0 == enable_11d || 1 == enable_11d) {
6193 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6194 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006195 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006196}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006197
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006198/**
6199 * hdd_set_trace_level_for_each - Set trace level for each INI config
6200 * @hdd_ctx - HDD context
6201 *
6202 * Set trace level for each module based on INI config.
6203 *
6204 * Return: None
6205 */
6206static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6207{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306208 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6209 hdd_ctx->config->qdf_trace_enable_wdi);
6210 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6211 hdd_ctx->config->qdf_trace_enable_hdd);
6212 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6213 hdd_ctx->config->qdf_trace_enable_sme);
6214 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6215 hdd_ctx->config->qdf_trace_enable_pe);
6216 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6217 hdd_ctx->config->qdf_trace_enable_wma);
6218 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6219 hdd_ctx->config->qdf_trace_enable_sys);
6220 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6221 hdd_ctx->config->qdf_trace_enable_qdf);
6222 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6223 hdd_ctx->config->qdf_trace_enable_sap);
6224 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6225 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6226 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6227 hdd_ctx->config->qdf_trace_enable_bmi);
6228 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6229 hdd_ctx->config->qdf_trace_enable_cfg);
6230 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6231 hdd_ctx->config->qdf_trace_enable_epping);
6232 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6233 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6234 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306235 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306236 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6237 hdd_ctx->config->qdf_trace_enable_htc);
6238 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6239 hdd_ctx->config->qdf_trace_enable_hif);
6240 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6241 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6242 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6243 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006245 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006246}
6247
6248/**
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006249 * hdd_context_deinit() - Deinitialize HDD context
6250 * @hdd_ctx: HDD context.
6251 *
6252 * Deinitialize HDD context along with all the feature specific contexts but
6253 * do not free hdd context itself. Caller of this API is supposed to free
6254 * HDD context.
6255 *
6256 * return: 0 on success and errno on failure.
6257 */
6258static int hdd_context_deinit(hdd_context_t *hdd_ctx)
6259{
6260 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
6261
6262 hdd_roc_context_destroy(hdd_ctx);
6263
6264 hdd_sap_context_destroy(hdd_ctx);
6265
6266 hdd_rx_wake_lock_destroy(hdd_ctx);
6267
6268 hdd_tdls_context_destroy(hdd_ctx);
6269
6270 hdd_scan_context_destroy(hdd_ctx);
6271
6272 qdf_list_destroy(&hdd_ctx->hddAdapters);
6273
6274 return 0;
6275}
6276
6277
6278/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006279 * hdd_context_init() - Initialize HDD context
6280 * @hdd_ctx: HDD context.
6281 *
6282 * Initialize HDD context along with all the feature specific contexts.
6283 *
6284 * return: 0 on success and errno on failure.
6285 */
6286static int hdd_context_init(hdd_context_t *hdd_ctx)
6287{
6288 int ret;
6289
6290 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6291 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6292
6293 hdd_init_ll_stats_ctx();
6294
6295 init_completion(&hdd_ctx->mc_sus_event_var);
6296 init_completion(&hdd_ctx->ready_to_suspend);
6297
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306298 hdd_init_bpf_completion();
6299
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006300 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306301 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006302 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306303
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006304 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6305
6306 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6307
6308 ret = hdd_scan_context_init(hdd_ctx);
6309 if (ret)
6310 goto list_destroy;
6311
6312 hdd_tdls_context_init(hdd_ctx);
6313
6314 hdd_rx_wake_lock_create(hdd_ctx);
6315
6316 ret = hdd_sap_context_init(hdd_ctx);
6317 if (ret)
6318 goto scan_destroy;
6319
6320 ret = hdd_roc_context_init(hdd_ctx);
6321 if (ret)
6322 goto sap_destroy;
6323
6324 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6325
6326 hdd_init_offloaded_packets_ctx(hdd_ctx);
6327
6328 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6329 hdd_ctx->config);
6330 if (ret)
6331 goto roc_destroy;
6332
6333 return 0;
6334
6335roc_destroy:
6336 hdd_roc_context_destroy(hdd_ctx);
6337
6338sap_destroy:
6339 hdd_sap_context_destroy(hdd_ctx);
6340
6341scan_destroy:
6342 hdd_scan_context_destroy(hdd_ctx);
6343 hdd_rx_wake_lock_destroy(hdd_ctx);
6344 hdd_tdls_context_destroy(hdd_ctx);
6345
6346list_destroy:
6347 qdf_list_destroy(&hdd_ctx->hddAdapters);
6348 return ret;
6349}
6350
6351/**
6352 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306353 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006354 *
6355 * Allocate and initialize HDD context. HDD context is allocated as part of
6356 * wiphy allocation and then context is initialized.
6357 *
6358 * Return: HDD context on success and ERR_PTR on failure
6359 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006360static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006361{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306362 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006363 int ret = 0;
6364 hdd_context_t *hdd_ctx;
6365 v_CONTEXT_t p_cds_context;
6366
6367 ENTER();
6368
6369 p_cds_context = cds_get_global_context();
6370 if (p_cds_context == NULL) {
6371 hdd_alert("Failed to get CDS global context");
6372 ret = -EINVAL;
6373 goto err_out;
6374 }
6375
6376 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6377
6378 if (hdd_ctx == NULL) {
6379 ret = -ENOMEM;
6380 goto err_out;
6381 }
6382
6383 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006384 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006385
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306386 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006387 if (hdd_ctx->config == NULL) {
6388 hdd_alert("Failed to alloc memory for HDD config!");
6389 ret = -ENOMEM;
6390 goto err_free_hdd_context;
6391 }
6392
6393 /* Read and parse the qcom_cfg.ini file */
6394 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306395 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306396 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006397 WLAN_INI_FILE);
6398 ret = -EINVAL;
6399 goto err_free_config;
6400 }
6401
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006402 hdd_ctx->configuredMcastBcastFilter =
6403 hdd_ctx->config->mcastBcastFilterSetting;
6404
6405 hdd_notice("Setting configuredMcastBcastFilter: %d",
6406 hdd_ctx->config->mcastBcastFilterSetting);
6407
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306408 if (hdd_ctx->config->fhostNSOffload)
6409 hdd_ctx->ns_offload_enable = true;
6410
Abhishek Singh5ea86532016-04-27 14:10:53 +05306411 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6412
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006413 hdd_override_ini_config(hdd_ctx);
6414
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006415 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006416
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006417 ret = hdd_context_init(hdd_ctx);
6418
6419 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006420 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006421
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006422
Yuanyuan Liu13738502016-04-06 17:41:37 -07006423 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6424 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006425
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006426
6427 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306428 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006429
Anurag Chouhan6d760662016-02-20 16:05:43 +05306430 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006431 goto skip_multicast_logging;
6432
6433 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6434
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006435 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6436 if (ret)
6437 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05306438
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006439 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6440 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306441 goto err_free_histogram;
6442
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006443
6444 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306445 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006446 * levels of the code need not be set when the logger thread
6447 * is not enabled.
6448 */
6449 if (cds_is_multicast_logging())
6450 wlan_logging_set_log_level();
6451
6452skip_multicast_logging:
6453 hdd_set_trace_level_for_each(hdd_ctx);
6454
6455 return hdd_ctx;
6456
Nirav Shahed34b212016-04-25 10:59:16 +05306457err_free_histogram:
6458 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6459
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006460err_deinit_hdd_context:
6461 hdd_context_deinit(hdd_ctx);
6462
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006463err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306464 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006465
6466err_free_hdd_context:
6467 wiphy_free(hdd_ctx->wiphy);
6468
6469err_out:
6470 return ERR_PTR(ret);
6471}
6472
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006473#ifdef WLAN_OPEN_P2P_INTERFACE
6474/**
6475 * hdd_open_p2p_interface - Open P2P interface
6476 * @hdd_ctx: HDD context
6477 * @rtnl_held: True if RTNL lock held
6478 *
6479 * Open P2P interface during probe. This function called to open the P2P
6480 * interface at probe along with STA interface.
6481 *
6482 * Return: 0 on success and errno on failure
6483 */
6484static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6485{
6486 hdd_adapter_t *adapter;
6487 uint8_t *p2p_dev_addr;
6488
6489 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6490 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306491 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006492 hdd_ctx->config->intfMacAddr[0].bytes,
6493 sizeof(tSirMacAddr));
6494
6495 /*
6496 * Generate the P2P Device Address. This consists of
6497 * the device's primary MAC address with the locally
6498 * administered bit set.
6499 */
6500 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6501 } else {
6502 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6503 if (p2p_dev_addr == NULL) {
6504 hdd_alert("Failed to allocate mac_address for p2p_device");
6505 return -ENOSPC;
6506 }
6507
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306508 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306509 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006510 }
6511
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006512 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006513 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006514 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006515
6516 if (NULL == adapter) {
6517 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6518 return -ENOSPC;
6519 }
6520
6521 return 0;
6522}
6523#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306524static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006525 bool rtnl_held)
6526{
6527 return 0;
6528}
6529#endif
6530
6531/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306532 * hdd_start_station_adapter()- Start the Station Adapter
6533 * @adapter: HDD adapter
6534 *
6535 * This function initializes the adapter for the station mode.
6536 *
6537 * Return: 0 on success or errno on failure.
6538 */
6539int hdd_start_station_adapter(hdd_adapter_t *adapter)
6540{
6541 QDF_STATUS status;
6542
6543 ENTER_DEV(adapter->dev);
6544
6545 status = hdd_init_station_mode(adapter);
6546
6547 if (QDF_STATUS_SUCCESS != status) {
6548 hdd_err("Error Initializing station mode: %d", status);
6549 return qdf_status_to_os_return(status);
6550 }
6551
Arun Khandavallifae92942016-08-01 13:31:08 +05306552 hdd_register_tx_flow_control(adapter,
6553 hdd_tx_resume_timer_expired_handler,
6554 hdd_tx_resume_cb);
6555
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306556 EXIT();
6557 return 0;
6558}
6559
6560/**
6561 * hdd_start_ap_adapter()- Start AP Adapter
6562 * @adapter: HDD adapter
6563 *
6564 * This function initializes the adapter for the AP mode.
6565 *
6566 * Return: 0 on success errno on failure.
6567 */
6568int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6569{
6570 QDF_STATUS status;
6571
6572 ENTER();
6573
6574 status = hdd_init_ap_mode(adapter);
6575
6576 if (QDF_STATUS_SUCCESS != status) {
6577 hdd_err("Error Initializing the AP mode: %d", status);
6578 return qdf_status_to_os_return(status);
6579 }
6580
Arun Khandavallifae92942016-08-01 13:31:08 +05306581 hdd_register_tx_flow_control(adapter,
6582 hdd_softap_tx_resume_timer_expired_handler,
6583 hdd_softap_tx_resume_cb);
6584
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306585 EXIT();
6586 return 0;
6587}
6588
6589/**
6590 * hdd_start_ftm_adapter()- Start FTM adapter
6591 * @adapter: HDD adapter
6592 *
6593 * This function initializes the adapter for the FTM mode.
6594 *
6595 * Return: 0 on success or errno on failure.
6596 */
6597int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6598{
6599 QDF_STATUS qdf_status;
6600
6601 ENTER_DEV(adapter->dev);
6602
6603 qdf_status = hdd_init_tx_rx(adapter);
6604
6605 if (QDF_STATUS_SUCCESS != qdf_status) {
6606 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6607 return qdf_status_to_os_return(qdf_status);
6608 }
6609
6610 return 0;
6611 EXIT();
6612}
6613
6614/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006615 * hdd_open_interfaces - Open all required interfaces
6616 * hdd_ctx: HDD context
6617 * rtnl_held: True if RTNL lock is held
6618 *
6619 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6620 *
6621 * Return: Primary adapter on success and PTR_ERR on failure
6622 */
6623static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6624 bool rtnl_held)
6625{
6626 hdd_adapter_t *adapter = NULL;
6627 hdd_adapter_t *adapter_11p = NULL;
6628 int ret;
6629
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006630 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306631 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006632 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006633 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006634 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006635
6636 if (adapter == NULL)
6637 return ERR_PTR(-ENOSPC);
6638
6639 return adapter;
6640 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006641 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006642 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006643 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006644
6645 if (adapter == NULL)
6646 return ERR_PTR(-ENOSPC);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006647 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6648 if (ret)
6649 goto err_close_adapter;
6650
6651 /* Open 802.11p Interface */
6652 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006653 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006654 "wlanocb%d",
6655 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006656 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006657 if (adapter_11p == NULL) {
6658 hdd_err("Failed to open 802.11p interface");
6659 goto err_close_adapter;
6660 }
6661 }
6662
6663 return adapter;
6664
6665err_close_adapter:
6666 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6667 return ERR_PTR(ret);
6668}
6669
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006670/**
6671 * hdd_update_country_code - Update country code
6672 * @hdd_ctx: HDD context
6673 * @adapter: Primary adapter context
6674 *
6675 * Update country code based on module parameter country_code at SME and wait
6676 * for the settings to take effect.
6677 *
6678 * Return: 0 on success and errno on failure
6679 */
6680static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6681 hdd_adapter_t *adapter)
6682{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306683 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006684 int ret = 0;
6685 unsigned long rc;
6686
6687 if (country_code == NULL)
6688 return 0;
6689
6690 INIT_COMPLETION(adapter->change_country_code);
6691
6692 status = sme_change_country_code(hdd_ctx->hHal,
6693 wlan_hdd_change_country_code_callback,
6694 country_code, adapter,
6695 hdd_ctx->pcds_context, eSIR_TRUE,
6696 eSIR_TRUE);
6697
6698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306699 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006700 hdd_err("SME Change Country code from module param fail ret=%d",
6701 ret);
6702 return -EINVAL;
6703 }
6704
6705 rc = wait_for_completion_timeout(&adapter->change_country_code,
6706 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6707 if (!rc) {
6708 hdd_err("SME while setting country code timed out");
6709 ret = -ETIMEDOUT;
6710 }
6711
6712 return ret;
6713}
6714
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306715#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6716/**
6717 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6718 * @cds_cfg: CDS Configuration
6719 * @hdd_ctx: Pointer to hdd context
6720 *
6721 * Return: none
6722 */
6723static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6724 *cds_cfg,
6725 hdd_context_t *hdd_ctx)
6726{
6727 cds_cfg->tx_flow_stop_queue_th =
6728 hdd_ctx->config->TxFlowStopQueueThreshold;
6729 cds_cfg->tx_flow_start_queue_offset =
6730 hdd_ctx->config->TxFlowStartQueueOffset;
6731}
6732#else
6733static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6734 *cds_cfg,
6735 hdd_context_t *hdd_ctx)
6736{
6737}
6738#endif
6739
6740#ifdef FEATURE_WLAN_RA_FILTERING
6741/**
6742 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6743 * @cds_cfg: CDS Configuration
6744 * @hdd_ctx: Pointer to hdd context
6745 *
6746 * Return: none
6747 */
6748inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6749 hdd_context_t *hdd_ctx)
6750{
6751 cds_cfg->ra_ratelimit_interval =
6752 hdd_ctx->config->RArateLimitInterval;
6753 cds_cfg->is_ra_ratelimit_enabled =
6754 hdd_ctx->config->IsRArateLimitEnabled;
6755}
6756#else
6757inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6758 hdd_context_t *hdd_ctx)
6759{
6760}
6761#endif
6762
6763/**
6764 * hdd_update_cds_config() - API to update cds configuration parameters
6765 * @hdd_ctx: HDD Context
6766 *
6767 * Return: 0 for Success, errno on failure
6768 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006769static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306770{
6771 struct cds_config_info *cds_cfg;
6772
6773 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6774 if (!cds_cfg) {
6775 hdd_err("failed to allocate cds config");
6776 return -ENOMEM;
6777 }
6778
6779 qdf_mem_zero(cds_cfg, sizeof(*cds_cfg));
6780
6781 /* UMA is supported in hardware for performing the
6782 * frame translation 802.11 <-> 802.3
6783 */
6784 cds_cfg->frame_xln_reqd = 1;
6785 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
6786 cds_cfg->powersave_offload_enabled =
6787 hdd_ctx->config->enablePowersaveOffload;
6788 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
6789 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
6790 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
6791 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
6792 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
6793
6794 /* Here ol_ini_info is used to store ini status of arp offload
6795 * ns offload and others. Currently 1st bit is used for arp
6796 * off load and 2nd bit for ns offload currently, rest bits are unused
6797 */
6798 if (hdd_ctx->config->fhostArpOffload)
6799 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
6800 if (hdd_ctx->config->fhostNSOffload)
6801 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
6802
6803 /*
6804 * Copy the DFS Phyerr Filtering Offload status.
6805 * This parameter reflects the value of the
6806 * dfs_phyerr_filter_offload flag as set in the ini.
6807 */
6808 cds_cfg->dfs_phyerr_filter_offload =
6809 hdd_ctx->config->fDfsPhyerrFilterOffload;
6810 if (hdd_ctx->config->ssdp)
6811 cds_cfg->ssdp = hdd_ctx->config->ssdp;
6812
6813 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
6814 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
6815
6816 cds_cfg->ap_maxoffload_reorderbuffs =
6817 hdd_ctx->config->apMaxOffloadReorderBuffs;
6818
6819 cds_cfg->ap_disable_intrabss_fwd =
6820 hdd_ctx->config->apDisableIntraBssFwd;
6821
6822 cds_cfg->dfs_pri_multiplier =
6823 hdd_ctx->config->dfsRadarPriMultiplier;
6824 cds_cfg->reorder_offload =
6825 hdd_ctx->config->reorderOffloadSupport;
6826
6827 /* IPA micro controller data path offload resource config item */
6828 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
6829 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
6830 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
6831 cds_cfg->uc_rxind_ringcount =
6832 hdd_ctx->config->IpaUcRxIndRingCount;
6833 cds_cfg->uc_tx_partition_base =
6834 hdd_ctx->config->IpaUcTxPartitionBase;
6835 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
6836
6837 cds_cfg->ip_tcp_udp_checksum_offload =
6838 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05306839 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306840 cds_cfg->ce_classify_enabled =
6841 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07006842 cds_cfg->bpf_packet_filter_enable =
6843 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306844 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
6845 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
6846 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07006847 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07006848 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306849
6850 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
6851 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
6852 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07006853 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306854 cds_init_ini_config(cds_cfg);
6855 return 0;
6856}
6857
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006858/**
6859 * hdd_init_thermal_info - Initialize thermal level
6860 * @hdd_ctx: HDD context
6861 *
6862 * Initialize thermal level at SME layer and set the thermal level callback
6863 * which would be called when a configured thermal threshold is hit.
6864 *
6865 * Return: 0 on success and errno on failure
6866 */
6867static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
6868{
6869 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306870 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006871
6872 thermal_param.smeThermalMgmtEnabled =
6873 hdd_ctx->config->thermalMitigationEnable;
6874 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
6875
Poddar, Siddarth83905022016-04-16 17:56:08 -07006876 thermal_param.sme_throttle_duty_cycle_tbl[0] =
6877 hdd_ctx->config->throttle_dutycycle_level0;
6878 thermal_param.sme_throttle_duty_cycle_tbl[1] =
6879 hdd_ctx->config->throttle_dutycycle_level1;
6880 thermal_param.sme_throttle_duty_cycle_tbl[2] =
6881 hdd_ctx->config->throttle_dutycycle_level2;
6882 thermal_param.sme_throttle_duty_cycle_tbl[3] =
6883 hdd_ctx->config->throttle_dutycycle_level3;
6884
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006885 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
6886 hdd_ctx->config->thermalTempMinLevel0;
6887 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
6888 hdd_ctx->config->thermalTempMaxLevel0;
6889 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
6890 hdd_ctx->config->thermalTempMinLevel1;
6891 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
6892 hdd_ctx->config->thermalTempMaxLevel1;
6893 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
6894 hdd_ctx->config->thermalTempMinLevel2;
6895 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
6896 hdd_ctx->config->thermalTempMaxLevel2;
6897 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
6898 hdd_ctx->config->thermalTempMinLevel3;
6899 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
6900 hdd_ctx->config->thermalTempMaxLevel3;
6901
6902 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
6903
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306904 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05306905 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006906
6907 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
6908 hdd_set_thermal_level_cb);
6909
6910 return 0;
6911
6912}
6913
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006914#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
6915/**
6916 * hdd_hold_rtnl_lock - Hold RTNL lock
6917 *
6918 * Hold RTNL lock
6919 *
6920 * Return: True if held and false otherwise
6921 */
6922static inline bool hdd_hold_rtnl_lock(void)
6923{
6924 rtnl_lock();
6925 return true;
6926}
6927
6928/**
6929 * hdd_release_rtnl_lock - Release RTNL lock
6930 *
6931 * Release RTNL lock
6932 *
6933 * Return: None
6934 */
6935static inline void hdd_release_rtnl_lock(void)
6936{
6937 rtnl_unlock();
6938}
6939#else
6940static inline bool hdd_hold_rtnl_lock(void) { return false; }
6941static inline void hdd_release_rtnl_lock(void) { }
6942#endif
6943
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006944#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006945
6946/**
6947 * hdd_process_pktlog_command() - process pktlog command
6948 * @hdd_ctx: hdd context
6949 * @set_value: value set by user
6950 *
6951 * Return: 0 for success or error.
6952 */
6953int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value)
6954{
6955 int ret;
6956 bool enable;
6957 uint8_t user_triggered = 0;
6958
6959 ret = wlan_hdd_validate_context(hdd_ctx);
6960 if (0 != ret)
6961 return ret;
6962
6963 hdd_info("set pktlog %d", set_value);
6964
6965 if (set_value > 2) {
6966 hdd_err("invalid pktlog value %d", set_value);
6967 return -EINVAL;
6968 }
6969
6970 /*
6971 * set_value = 0 then disable packetlog
6972 * set_value = 1 enable packetlog forcefully
6973 * set_vlaue = 2 then disable packetlog if disabled through ini or
6974 * enable packetlog with AUTO type.
6975 */
6976 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
6977 true : false;
6978
6979 if (1 == set_value) {
6980 enable = true;
6981 user_triggered = 1;
6982 }
6983
6984 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered);
6985}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006986/**
6987 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
6988 * @hdd_ctx: HDD context
6989 * @enable: Flag to enable/disable
6990 *
6991 * Return: 0 on success; error number otherwise
6992 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006993int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
6994 uint8_t user_triggered)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006995{
6996 struct sir_wifi_start_log start_log;
6997 QDF_STATUS status;
6998
6999 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7000 start_log.verbose_level =
7001 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007002 start_log.ini_triggered = cds_is_packet_log_enabled();
7003 start_log.user_triggered = user_triggered;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307004 /*
7005 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7006 * commands. Host uses this flag to decide whether to send pktlog
7007 * disable command to fw without sending pktlog enable command
7008 * previously. For eg, If vendor sends pktlog disable command without
7009 * sending pktlog enable command, then host discards the packet
7010 * but for iwpriv command, host will send it to fw.
7011 */
7012 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007013 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7014 if (!QDF_IS_STATUS_SUCCESS(status)) {
7015 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7016 EXIT();
7017 return -EINVAL;
7018 }
7019
7020 return 0;
7021}
7022#endif /* REMOVE_PKT_LOG */
7023
7024
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307025#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7026/**
7027 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7028 * switch without restart
7029 *
7030 * Registers callback function to change the operating channel of SAP by using
7031 * channel switch announcements instead of restarting SAP.
7032 *
7033 * Return: QDF_STATUS
7034 */
7035QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7036{
7037 QDF_STATUS status;
7038
7039 status = cds_register_sap_restart_channel_switch_cb(
7040 (void *)hdd_sap_restart_with_channel_switch);
7041 if (!QDF_IS_STATUS_SUCCESS(status))
7042 hdd_err("restart cb registration failed");
7043
7044 return status;
7045}
7046#endif
7047
Komal Seelam92fff912016-03-24 11:51:41 +05307048#ifdef CONFIG_CNSS
7049/**
7050 * hdd_get_cnss_wlan_mac_buff() - API to query platform driver for MAC address
7051 * @dev: Device Pointer
7052 * @num: Number of Valid Mac address
7053 *
7054 * Return: Pointer to MAC address buffer
7055 */
7056static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
7057{
7058 return cnss_common_get_wlan_mac_address(dev, num);
7059}
7060#else
7061static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
7062{
7063 *num = 0;
7064 return NULL;
7065}
7066#endif
7067
7068/**
7069 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7070 * @hdd_ctx: HDD Context
7071 * @num: Number of random mac addresses needed
7072 *
7073 * Generate random addresses using bit manipulation on the base mac address
7074 *
7075 * Return: None
7076 */
7077static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7078{
7079 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7080 uint32_t iter;
7081 struct hdd_config *ini = hdd_ctx->config;
7082 uint8_t *buf = NULL;
7083 uint8_t macaddr_b3, tmp_br3;
7084 uint8_t *src = ini->intfMacAddr[0].bytes;
7085
7086 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
7087 buf = ini->intfMacAddr[iter].bytes;
7088 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7089 macaddr_b3 = buf[3];
7090 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7091 INTF_MACADDR_MASK;
7092 macaddr_b3 += tmp_br3;
7093 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7094 buf[0] |= 0x02;
7095 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007096 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307097 }
7098}
7099
7100/**
7101 * hdd_cnss_wlan_mac() - API to get mac addresses from cnss platform driver
7102 * @hdd_ctx: HDD Context
7103 *
7104 * API to get mac addresses from platform driver and update the driver
7105 * structures and configure FW with the base mac address.
7106 * Return: int
7107 */
7108static int hdd_cnss_wlan_mac(hdd_context_t *hdd_ctx)
7109{
7110 uint32_t no_of_mac_addr, iter;
7111 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7112 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7113 uint8_t *addr, *buf;
7114 struct device *dev = hdd_ctx->parent_dev;
7115 struct hdd_config *ini = hdd_ctx->config;
7116 tSirMacAddr mac_addr;
7117 QDF_STATUS status;
7118
7119 addr = hdd_get_cnss_wlan_mac_buff(dev, &no_of_mac_addr);
7120
7121 if (no_of_mac_addr == 0 || !addr) {
7122 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7123 return -EINVAL;
7124 }
7125
7126 if (no_of_mac_addr > max_mac_addr)
7127 no_of_mac_addr = max_mac_addr;
7128
7129 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7130
7131 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7132 buf = ini->intfMacAddr[iter].bytes;
7133 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007134 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307135 }
7136
7137 status = sme_set_custom_mac_addr(mac_addr);
7138
7139 if (!QDF_IS_STATUS_SUCCESS(status))
7140 return -EAGAIN;
7141 if (no_of_mac_addr < max_mac_addr)
7142 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7143 no_of_mac_addr);
7144 return 0;
7145}
7146
7147/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007148 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7149 * @hdd_ctx: HDD Context
7150 *
7151 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7152 * will generate its own MAC and update it to FW.
7153 *
7154 * Return: 0 for success
7155 * Non-zero error code for failure
7156 */
7157static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7158{
7159 tSirMacAddr customMacAddr;
7160 QDF_STATUS status;
7161
7162 qdf_mem_copy(&customMacAddr,
7163 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7164 sizeof(tSirMacAddr));
7165 status = sme_set_custom_mac_addr(customMacAddr);
7166 if (!QDF_IS_STATUS_SUCCESS(status))
7167 return -EAGAIN;
7168 return 0;
7169}
7170
7171/**
Komal Seelam92fff912016-03-24 11:51:41 +05307172 * hdd_initialize_mac_address() - API to get wlan mac addresses
7173 * @hdd_ctx: HDD Context
7174 *
7175 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
7176 * is provisioned with mac addresses, driver uses it, else it will use
7177 * wlan_mac.bin to update HW MAC addresses.
7178 *
7179 * Return: None
7180 */
7181static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
7182{
7183 QDF_STATUS status;
7184 int ret;
7185
7186 ret = hdd_cnss_wlan_mac(hdd_ctx);
7187 if (ret == 0)
7188 return;
7189
7190 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7191
7192 status = hdd_update_mac_config(hdd_ctx);
7193
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007194 if (QDF_IS_STATUS_SUCCESS(status))
7195 return;
7196
7197 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
7198
7199 if (hdd_ctx->update_mac_addr_to_fw)
7200 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
7201
7202 if (ret != 0) {
7203 hdd_err("MAC address out-of-sync, ret:%d", ret);
7204 QDF_ASSERT(ret);
7205 }
Komal Seelam92fff912016-03-24 11:51:41 +05307206}
7207
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007208/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007209 * hdd_tsf_init() - Initialize the TSF synchronization interface
7210 * @hdd_ctx: HDD global context
7211 *
7212 * When TSF synchronization via GPIO is supported by the driver and
7213 * has been enabled in the configuration file, this function plumbs
7214 * the GPIO value down to firmware via SME.
7215 *
7216 * Return: None
7217 */
7218#ifdef WLAN_FEATURE_TSF
7219static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7220{
7221 QDF_STATUS status;
7222
7223 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7224 return;
7225
7226 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7227 hdd_ctx->config->tsf_gpio_pin);
7228 if (!QDF_IS_STATUS_SUCCESS(status))
7229 hdd_err("Set tsf GPIO failed, status: %d", status);
7230}
7231#else
7232static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7233{
7234}
7235#endif
7236
7237/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007238 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7239 * @hdd_ctx: HDD context
7240 *
7241 * Pre configurations to be done at lower layer before calling cds enable.
7242 *
7243 * Return: 0 on success and errno on failure.
7244 */
7245static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7246{
7247 int ret;
7248 QDF_STATUS status;
7249 tSirRetStatus hal_status;
7250
7251 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
7252
7253 /*
7254 * Set 802.11p config
7255 * TODO-OCB: This has been temporarily added here to ensure this
7256 * parameter is set in CSR when we init the channel list. This should
7257 * be removed once the 5.9 GHz channels are added to the regulatory
7258 * domain.
7259 */
7260 hdd_set_dot11p_config(hdd_ctx);
7261
7262 /*
7263 * Note that the cds_pre_enable() sequence triggers the cfg download.
7264 * The cfg download must occur before we update the SME config
7265 * since the SME config operation must access the cfg database
7266 */
7267 status = hdd_set_sme_config(hdd_ctx);
7268
7269 if (QDF_STATUS_SUCCESS != status) {
7270 hdd_alert("Failed hdd_set_sme_config: %d", status);
7271 ret = qdf_status_to_os_return(status);
7272 goto out;
7273 }
7274
7275 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7276 hdd_ctx->config->tx_chain_mask_1ss,
7277 PDEV_CMD);
7278 if (0 != ret) {
7279 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7280 goto out;
7281 }
7282
7283 hdd_program_country_code(hdd_ctx);
7284
7285 status = hdd_set_sme_chan_list(hdd_ctx);
7286 if (status != QDF_STATUS_SUCCESS) {
7287 hdd_alert("Failed to init channel list: %d", status);
7288 ret = qdf_status_to_os_return(status);
7289 goto out;
7290 }
7291
7292 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07007293 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07007294 hdd_alert("config update failed");
7295 ret = -EINVAL;
7296 goto out;
7297 }
7298
Komal Seelam92fff912016-03-24 11:51:41 +05307299 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007300
7301 /*
7302 * Set the MAC Address Currently this is used by HAL to add self sta.
7303 * Remove this once self sta is added as part of session open.
7304 */
7305 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7306 hdd_ctx->config->intfMacAddr[0].bytes,
7307 sizeof(hdd_ctx->config->intfMacAddr[0]));
7308
7309 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7310 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7311 hal_status, hal_status);
7312 ret = -EINVAL;
7313 goto out;
7314 }
7315
7316 hdd_init_channel_avoidance(hdd_ctx);
7317
7318out:
7319 return ret;
7320}
7321
7322/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007323 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7324 * @context_ptr - hdd context pointer
7325 * @event_ptr - event structure pointer
7326 *
7327 * This is the p2p listen offload stop event handler, it sends vendor
7328 * event back to supplicant to notify the stop reason.
7329 *
7330 * Return: None
7331 */
7332static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7333 void *event_ptr)
7334{
7335 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7336 struct sir_p2p_lo_event *evt = event_ptr;
7337 struct sk_buff *vendor_event;
7338
7339 ENTER();
7340
7341 if (hdd_ctx == NULL) {
7342 hdd_err("Invalid HDD context pointer");
7343 return;
7344 }
7345
7346 vendor_event =
7347 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7348 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7349 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7350 GFP_KERNEL);
7351
7352 if (!vendor_event) {
7353 hdd_err("cfg80211_vendor_event_alloc failed");
7354 return;
7355 }
7356
7357 if (nla_put_u32(vendor_event,
7358 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7359 evt->reason_code)) {
7360 hdd_err("nla put failed");
7361 kfree_skb(vendor_event);
7362 return;
7363 }
7364
7365 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7366}
7367
7368/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307369 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7370 * @hdd_ctx: HDD context
7371 *
7372 * This function sends the adaptive dwell time config configuration to the
7373 * firmware via WMA
7374 *
7375 * Return: 0 - success, < 0 - failure
7376 */
7377static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7378{
7379 QDF_STATUS status;
7380 struct adaptive_dwelltime_params dwelltime_params;
7381
7382 dwelltime_params.is_enabled =
7383 hdd_ctx->config->adaptive_dwell_mode_enabled;
7384 dwelltime_params.dwelltime_mode =
7385 hdd_ctx->config->global_adapt_dwelltime_mode;
7386 dwelltime_params.lpf_weight =
7387 hdd_ctx->config->adapt_dwell_lpf_weight;
7388 dwelltime_params.passive_mon_intval =
7389 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7390 dwelltime_params.wifi_act_threshold =
7391 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7392
7393 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7394 &dwelltime_params);
7395
7396 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7397 if (!QDF_IS_STATUS_SUCCESS(status)) {
7398 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7399 return -EAGAIN;
7400 }
7401 return 0;
7402}
7403
Arun Khandavallid4349a92016-07-25 11:10:43 +05307404#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7405/**
7406 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7407 * @hdd_ctx: HDD context
7408 *
7409 * Set auto shutdown callback to get indications from firmware to indicate
7410 * userspace to shutdown WLAN after a configured amount of inactivity.
7411 *
7412 * Return: 0 on success and errno on failure.
7413 */
7414static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7415{
7416 QDF_STATUS status;
7417
7418 if (!hdd_ctx->config->WlanAutoShutdown)
7419 return 0;
7420
7421 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7422 wlan_hdd_auto_shutdown_cb);
7423 if (status != QDF_STATUS_SUCCESS)
7424 hdd_err("Auto shutdown feature could not be enabled: %d",
7425 status);
7426
7427 return qdf_status_to_os_return(status);
7428}
7429#else
7430static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7431{
7432 return 0;
7433}
7434#endif
7435
7436/**
7437 * hdd_features_init() - Init features
7438 * @hdd_ctx: HDD context
7439 * @adapter: Primary adapter context
7440 *
7441 * Initialize features and their feature context after WLAN firmware is up.
7442 *
7443 * Return: 0 on success and errno on failure.
7444 */
7445static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7446{
7447 tSirTxPowerLimit hddtxlimit;
7448 QDF_STATUS status;
7449 int ret;
7450
7451 ENTER();
7452
7453 ret = hdd_update_country_code(hdd_ctx, adapter);
7454 if (ret) {
7455 hdd_err("Failed to update country code: %d", ret);
7456 goto out;
7457 }
7458
7459 /* FW capabilities received, Set the Dot11 mode */
7460 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07007461 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
7462 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307463
Arun Khandavallid4349a92016-07-25 11:10:43 +05307464
7465 if (hdd_ctx->config->fIsImpsEnabled)
7466 hdd_set_idle_ps_config(hdd_ctx, true);
7467 else
7468 hdd_set_idle_ps_config(hdd_ctx, false);
7469
7470 if (hdd_lro_init(hdd_ctx))
7471 hdd_err("Unable to initialize LRO in fw");
7472
7473 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7474 hdd_err("Unable to send adaptive dwelltime setting to FW");
7475
7476 ret = hdd_init_thermal_info(hdd_ctx);
7477 if (ret) {
7478 hdd_err("Error while initializing thermal information");
7479 goto deregister_frames;
7480 }
7481
7482 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7483 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7484 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7485 if (!QDF_IS_STATUS_SUCCESS(status))
7486 hdd_err("Error setting txlimit in sme: %d", status);
7487
7488 hdd_tsf_init(hdd_ctx);
7489
Arun Khandavallid4349a92016-07-25 11:10:43 +05307490 ret = hdd_register_cb(hdd_ctx);
7491 if (ret) {
7492 hdd_err("Failed to register HDD callbacks!");
7493 goto deregister_frames;
7494 }
7495
7496 if (hdd_ctx->config->dual_mac_feature_disable) {
7497 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7498 if (status != QDF_STATUS_SUCCESS) {
7499 hdd_err("Failed to disable dual mac features");
7500 goto deregister_cb;
7501 }
7502 }
7503
7504 /* register P2P Listen Offload event callback */
7505 if (wma_is_p2p_lo_capable())
7506 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7507 wlan_hdd_p2p_lo_event_callback);
7508
7509 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7510
7511 if (ret)
7512 goto deregister_cb;
7513
7514 EXIT();
7515 return 0;
7516
7517deregister_cb:
7518 hdd_deregister_cb(hdd_ctx);
7519deregister_frames:
7520 wlan_hdd_cfg80211_deregister_frames(adapter);
7521out:
7522 return -EINVAL;
7523
7524}
7525
7526
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307527/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307528 * hdd_configure_cds() - Configure cds modules
7529 * @hdd_ctx: HDD context
7530 * @adapter: Primary adapter context
7531 *
7532 * Enable Cds modules after WLAN firmware is up.
7533 *
7534 * Return: 0 on success and errno on failure.
7535 */
7536int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7537{
7538 int ret;
7539 QDF_STATUS status;
7540 /* structure of function pointers to be used by CDS */
7541 struct cds_sme_cbacks sme_cbacks;
7542
7543 ret = hdd_pre_enable_configure(hdd_ctx);
7544 if (ret) {
7545 hdd_err("Failed to pre-configure cds");
7546 goto out;
7547 }
7548
7549 /*
7550 * Start CDS which starts up the SME/MAC/HAL modules and everything
7551 * else
7552 */
7553 status = cds_enable(hdd_ctx->pcds_context);
7554
7555 if (!QDF_IS_STATUS_SUCCESS(status)) {
7556 hdd_alert("cds_enable failed");
7557 goto out;
7558 }
7559
7560 status = hdd_post_cds_enable_config(hdd_ctx);
7561 if (!QDF_IS_STATUS_SUCCESS(status)) {
7562 hdd_alert("hdd_post_cds_enable_config failed");
7563 goto out;
7564 }
7565
7566 ret = hdd_features_init(hdd_ctx, adapter);
7567 if (ret)
7568 goto out;
7569
7570 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7571 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7572 status = cds_init_policy_mgr(&sme_cbacks);
7573 if (!QDF_IS_STATUS_SUCCESS(status)) {
7574 hdd_err("Policy manager initialization failed");
7575 goto out;
7576 }
7577
7578 return 0;
7579out:
7580 return -EINVAL;
7581}
7582
7583/**
7584 * hdd_deconfigure_cds() -De-Configure cds
7585 * @hdd_ctx: HDD context
7586 *
7587 * Deconfigure Cds modules before WLAN firmware is down.
7588 *
7589 * Return: 0 on success and errno on failure.
7590 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007591static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307592{
7593 QDF_STATUS qdf_status;
7594
7595 ENTER();
7596 /* De-register the SME callbacks */
7597 hdd_deregister_cb(hdd_ctx);
7598
7599 /* De-init Policy Manager */
7600 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7601 hdd_err("Failed to deinit policy manager");
7602 /* Proceed and complete the clean up */
7603 return -EINVAL;
7604 }
7605
7606 qdf_status = cds_disable(hdd_ctx->pcds_context);
7607 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7608 hdd_err("Failed to Disable the CDS Modules! :%d",
7609 qdf_status);
7610 return -EINVAL;
7611 }
7612
7613 EXIT();
7614 return 0;
7615}
7616
7617
7618/**
7619 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7620 * @hdd_ctx: HDD context
7621 * @shutdown: flag to indicate from SSR or normal path
7622 *
7623 * This function maintains the driver state machine it will be invoked from
7624 * exit, shutdown and con_mode change handler. Depending on the driver state
7625 * shall perform the stopping/closing of the modules.
7626 *
7627 * Return: 0 for success; non-zero for failure
7628 */
7629int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
7630{
7631 void *hif_ctx;
7632 qdf_device_t qdf_ctx;
7633 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307634 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307635 p_cds_sched_context cds_sched_context = NULL;
7636
7637 ENTER();
7638
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307639
Arun Khandavallifae92942016-08-01 13:31:08 +05307640 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7641 if (!qdf_ctx) {
7642 hdd_err("QDF device context NULL");
7643 return -EINVAL;
7644 }
7645
7646 cds_sched_context = get_cds_sched_ctxt();
7647 if (!cds_sched_context) {
7648 hdd_err("cds scheduler context NULL");
7649 return -EINVAL;
7650 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307651 mutex_lock(&hdd_ctx->iface_change_lock);
7652 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307653
7654 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7655
7656 switch (hdd_ctx->driver_status) {
7657 case DRIVER_MODULES_UNINITIALIZED:
7658 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307659 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307660 case DRIVER_MODULES_CLOSED:
7661 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307662 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307663 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05307664 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05307665 if (hdd_deconfigure_cds(hdd_ctx)) {
7666 hdd_alert("Failed to de-configure CDS");
7667 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307668 ret = -EINVAL;
7669 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307670 }
7671 hdd_info("successfully Disabled the CDS modules!");
7672 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7673 break;
7674 case DRIVER_MODULES_OPENED:
7675 hdd_info("Closing CDS modules!");
7676 break;
7677 default:
7678 hdd_err("Trying to stop wlan in a wrong state: %d",
7679 hdd_ctx->driver_status);
7680 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307681 ret = -EINVAL;
7682 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307683 }
7684
7685 qdf_status = cds_close(hdd_ctx->pcds_context);
7686 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7687 hdd_warn("Failed to stop CDS:%d", qdf_status);
7688 QDF_ASSERT(0);
7689 }
7690 /* Clean up message queues of TX, RX and MC thread */
7691 cds_sched_flush_mc_mqs(cds_sched_context);
7692
7693 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
7694 if (!hif_ctx) {
7695 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307696 ret = -EINVAL;
7697 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307698 }
7699
7700 hdd_hif_close(hif_ctx);
7701
7702 ol_cds_free();
7703
7704 if (!shutdown) {
7705 ret = pld_power_off(qdf_ctx->dev);
7706 if (ret)
7707 hdd_err("CNSS power down failed put device into Low power mode:%d",
7708 ret);
7709 }
7710 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
7711
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307712done:
7713 hdd_ctx->stop_modules_in_progress = false;
7714 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05307715 EXIT();
7716
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307717 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307718
7719}
7720
7721/**
7722 * hdd_iface_change_callback() - Function invoked when stop modules expires
7723 * @priv: pointer to hdd context
7724 *
7725 * This function is invoked when the timer waiting for the interface change
7726 * expires, it shall cut-down the power to wlan and stop all the modules.
7727 *
7728 * Return: void
7729 */
7730static void hdd_iface_change_callback(void *priv)
7731{
7732 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
7733 int ret;
7734 int status = wlan_hdd_validate_context(hdd_ctx);
7735
7736 if (status)
7737 return;
7738
7739 ENTER();
7740 hdd_info("Interface change timer expired close the modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05307741 ret = hdd_wlan_stop_modules(hdd_ctx, false);
7742 if (ret)
7743 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05307744 EXIT();
7745}
7746
7747/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05307748 * hdd_state_info_dump() - prints state information of hdd layer
7749 * @buf: buffer pointer
7750 * @size: size of buffer to be filled
7751 *
7752 * This function is used to dump state information of hdd layer
7753 *
7754 * Return: None
7755 */
7756static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
7757{
7758 hdd_context_t *hdd_ctx;
7759 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7760 QDF_STATUS status;
7761 hdd_station_ctx_t *hdd_sta_ctx;
7762 hdd_adapter_t *adapter;
7763 uint16_t len = 0;
7764 char *buf = *buf_ptr;
7765
7766 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7767 if (!hdd_ctx) {
7768 hdd_err("Failed to get hdd context ");
7769 return;
7770 }
7771
7772 hdd_notice("size of buffer: %d", *size);
7773
7774 len += scnprintf(buf + len, *size - len,
7775 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
7776 len += scnprintf(buf + len, *size - len,
7777 "\n isMcThreadSuspended %d",
7778 hdd_ctx->isMcThreadSuspended);
7779
7780 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7781
7782 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7783 adapter = adapter_node->pAdapter;
7784 if (adapter->dev)
7785 len += scnprintf(buf + len, *size - len,
7786 "\n device name: %s", adapter->dev->name);
7787 len += scnprintf(buf + len, *size - len,
7788 "\n device_mode: %d", adapter->device_mode);
7789 switch (adapter->device_mode) {
7790 case QDF_STA_MODE:
7791 case QDF_P2P_CLIENT_MODE:
7792 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
7793 len += scnprintf(buf + len, *size - len,
7794 "\n connState: %d",
7795 hdd_sta_ctx->conn_info.connState);
7796 break;
7797
7798 default:
7799 break;
7800 }
7801 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
7802 adapter_node = next;
7803 }
7804
7805 *size -= len;
7806 *buf_ptr += len;
7807}
7808
7809/**
7810 * hdd_register_debug_callback() - registration function for hdd layer
7811 * to print hdd state information
7812 *
7813 * Return: None
7814 */
7815static void hdd_register_debug_callback(void)
7816{
7817 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
7818}
7819
7820/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007821 * hdd_wlan_startup() - HDD init function
7822 * @dev: Pointer to the underlying device
7823 *
7824 * This is the driver startup code executed once a WLAN device has been detected
7825 *
7826 * Return: 0 for success, < 0 for failure
7827 */
Arun Khandavallifae92942016-08-01 13:31:08 +05307828int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007829{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307830 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007831 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007832 hdd_context_t *hdd_ctx = NULL;
7833 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307834 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007835 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05307836 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007837
7838 ENTER();
7839
Arun Khandavallifae92942016-08-01 13:31:08 +05307840 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007841
7842 if (IS_ERR(hdd_ctx))
7843 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007844
Arun Khandavallifae92942016-08-01 13:31:08 +05307845 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
7846 hdd_iface_change_callback, (void *)hdd_ctx);
7847
7848 mutex_init(&hdd_ctx->iface_change_lock);
7849
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007850 ret = hdd_init_netlink_services(hdd_ctx);
7851 if (ret)
7852 goto err_hdd_free_context;
7853
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07007854 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307855
Arun Khandavallifae92942016-08-01 13:31:08 +05307856 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
7857 if (ret) {
7858 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007859 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007860 }
7861
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007862 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007863
Anurag Chouhan6d760662016-02-20 16:05:43 +05307864 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007865
7866 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007867 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05307868 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007869 }
7870
Prashanth Bhatta07998752016-04-28 12:35:33 -07007871 ret = hdd_wiphy_init(hdd_ctx);
7872 if (ret) {
7873 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05307874 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007875 }
7876
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05307877 if (hdd_ctx->config->enable_dp_trace)
7878 qdf_dp_trace_init();
7879
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307880 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007881 goto err_wiphy_unregister;
7882
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08007883
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007884 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007885
Arun Khandavallifae92942016-08-01 13:31:08 +05307886
7887 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007888
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007889 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007890 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007891 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05307892 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007893 }
7894
Arun Khandavallifae92942016-08-01 13:31:08 +05307895 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Anurag Chouhance6a4052016-09-14 18:20:42 +05307896 if (!hif_sc) {
7897 hdd_err("HIF context is NULL");
7898 goto err_close_adapter;
7899 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007900 /*
7901 * target hw version/revision would only be retrieved after firmware
7902 * donwload
7903 */
7904 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
7905 &hdd_ctx->target_hw_revision,
7906 &hdd_ctx->target_hw_name);
7907
7908 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05307909 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007910
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007911 hdd_release_rtnl_lock();
7912 rtnl_held = false;
7913
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05307914 if (hdd_ctx->config->enable_go_cts2self_for_sta)
7915 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007916#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05307917 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307918 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007919 hdd_skip_acs_scan_timer_handler,
7920 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307921 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07007922 hdd_err("Failed to init ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007923#endif
7924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007925#ifdef MSM_PLATFORM
7926 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05307927 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307928 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007929 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
7930#endif
7931
Jeff Johnson9afc5012016-09-23 13:56:27 -07007932 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007933
Nirav Shahbd36b062016-07-18 11:12:59 +05307934 if (hdd_ctx->rps)
7935 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07007936
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007937
7938 if (cds_is_packet_log_enabled())
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007939 hdd_pktlog_enable_disable(hdd_ctx, true, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007940
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007941 ret = hdd_register_notifiers(hdd_ctx);
7942 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05307943 goto err_debugfs_exit;
7944
7945 status = wlansap_global_init();
7946 if (QDF_IS_STATUS_ERROR(status))
7947 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007948
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007949 memdump_init();
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05307950 hdd_encrypt_decrypt_init(hdd_ctx);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05307951 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007952
Arun Khandavallifae92942016-08-01 13:31:08 +05307953 if (hdd_ctx->config->fIsImpsEnabled)
7954 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307955
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05307956 if (hdd_ctx->config->sifs_burst_duration) {
7957 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
7958 hdd_ctx->config->sifs_burst_duration;
7959
7960 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
7961 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
7962 set_value, PDEV_CMD);
7963 }
7964
Arun Khandavallifae92942016-08-01 13:31:08 +05307965 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
7966 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05307967
7968 if (hdd_ctx->config->goptimize_chan_avoid_event) {
7969 status = sme_enable_disable_chanavoidind_event(
7970 hdd_ctx->hHal, 0);
7971 if (!QDF_IS_STATUS_SUCCESS(status))
7972 hdd_err("Failed to disable Chan Avoidance Indication");
7973 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007974 goto success;
7975
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007976err_debugfs_exit:
7977 hdd_debugfs_exit(adapter);
Anurag Chouhance6a4052016-09-14 18:20:42 +05307978
7979err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007980 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007981
Arun Khandavallid4349a92016-07-25 11:10:43 +05307982 if (rtnl_held)
7983 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007984
Anurag Chouhance6a4052016-09-14 18:20:42 +05307985err_ipa_cleanup:
7986 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08007987
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007988err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007989 wiphy_unregister(hdd_ctx->wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05307990 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007991
Arun Khandavallifae92942016-08-01 13:31:08 +05307992err_stop_modules:
7993 hdd_wlan_stop_modules(hdd_ctx, false);
7994
7995
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007996 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307997 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007998 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307999 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008000 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008001
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008002err_exit_nl_srv:
8003 hdd_exit_netlink_services(hdd_ctx);
8004
8005 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
8006 hdd_err("Failed to deinit policy manager");
8007 /* Proceed and complete the clean up */
8008 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308009 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008010err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05308011 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
8012 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07008013 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308014 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008015
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008016 return -EIO;
8017
8018success:
8019 EXIT();
8020 return 0;
8021}
8022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008023/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308024 * hdd_wlan_update_target_info() - update target type info
8025 * @hdd_ctx: HDD context
8026 * @context: hif context
8027 *
8028 * Update target info received from firmware in hdd context
8029 * Return:None
8030 */
8031
8032void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
8033{
8034 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
8035
8036 if (!tgt_info) {
8037 hdd_err("Target info is Null");
8038 return;
8039 }
8040
8041 hdd_ctx->target_type = tgt_info->target_type;
8042}
8043
8044/**
8045 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308046 * @hdd_ctx: HDD context
8047 *
8048 * Register the HDD callbacks to CDS/SME.
8049 *
8050 * Return: 0 for success or Error code for failure
8051 */
8052int hdd_register_cb(hdd_context_t *hdd_ctx)
8053{
8054 QDF_STATUS status;
8055 int ret = 0;
8056
8057 ENTER();
8058
8059 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
8060
8061 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
8062 hdd_send_oem_data_rsp_msg);
8063
8064 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
8065 wlan_hdd_cfg80211_fw_mem_dump_cb);
8066 if (!QDF_IS_STATUS_SUCCESS(status)) {
8067 hdd_err("Failed to register memdump callback");
8068 ret = -EINVAL;
8069 return ret;
8070 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05308071 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
8072 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308073 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
8074 sme_nan_register_callback(hdd_ctx->hHal,
8075 wlan_hdd_cfg80211_nan_callback);
8076 sme_stats_ext_register_callback(hdd_ctx->hHal,
8077 wlan_hdd_cfg80211_stats_ext_callback);
8078
8079 sme_ext_scan_register_callback(hdd_ctx->hHal,
8080 wlan_hdd_cfg80211_extscan_callback);
8081
8082 status = cds_register_sap_restart_channel_switch_cb(
8083 (void *)hdd_sap_restart_with_channel_switch);
8084 if (!QDF_IS_STATUS_SUCCESS(status)) {
8085 hdd_err("restart cb registration failed");
8086 ret = -EINVAL;
8087 return ret;
8088 }
8089
8090 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
8091 hdd_rssi_threshold_breached);
8092
8093 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
8094 hdd_get_bpf_offload_cb);
8095 if (!QDF_IS_STATUS_SUCCESS(status)) {
8096 hdd_err("set bpf offload callback failed");
8097 ret = -EINVAL;
8098 return ret;
8099 }
8100
8101 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
8102 wlan_hdd_cfg80211_link_layer_stats_callback);
8103
8104 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
8105
8106 EXIT();
8107
8108 return ret;
8109}
8110
8111/**
8112 * hdd_deregister_cb() - De-Register HDD callbacks.
8113 * @hdd_ctx: HDD context
8114 *
8115 * De-Register the HDD callbacks to CDS/SME.
8116 *
8117 * Return: void
8118 */
8119void hdd_deregister_cb(hdd_context_t *hdd_ctx)
8120{
8121 QDF_STATUS status;
8122
8123 ENTER();
8124
8125 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
8126 if (!QDF_IS_STATUS_SUCCESS(status))
8127 hdd_err("De-register of dcc stats callback failed: %d",
8128 status);
8129
8130 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
8131 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
8132 if (!QDF_IS_STATUS_SUCCESS(status))
8133 hdd_err("De-register bpf offload callback failed: %d",
8134 status);
8135 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
8136
8137 status = cds_deregister_sap_restart_channel_switch_cb();
8138 if (!QDF_IS_STATUS_SUCCESS(status))
8139 hdd_err("De-register restart cb registration failed: %d",
8140 status);
8141
8142 sme_stats_ext_register_callback(hdd_ctx->hHal,
8143 wlan_hdd_cfg80211_stats_ext_callback);
8144
8145 sme_nan_deregister_callback(hdd_ctx->hHal);
8146 status = sme_reset_tsfcb(hdd_ctx->hHal);
8147 if (!QDF_IS_STATUS_SUCCESS(status))
8148 hdd_err("Failed to de-register tsfcb the callback:%d",
8149 status);
8150 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
8151 if (!QDF_IS_STATUS_SUCCESS(status))
8152 hdd_err("Failed to de-register the fw mem dump callback: %d",
8153 status);
8154
8155 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
8156 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
8157
8158 EXIT();
8159}
8160
8161/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008162 * hdd_softap_sta_deauth() - handle deauth req from HDD
8163 * @adapter: Pointer to the HDD
8164 * @enable: bool value
8165 *
8166 * This to take counter measure to handle deauth req from HDD
8167 *
8168 * Return: None
8169 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308170QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008171 struct tagCsrDelStaParams *pDelStaParams)
8172{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308173 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008174
8175 ENTER();
8176
Jeff Johnson34c88b72016-08-15 14:27:11 -07008177 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008178 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8179
8180 /* Ignore request to deauth bcmc station */
8181 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308182 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008183
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308184 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008185 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8186 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008187
8188 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308189 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008190}
8191
8192/**
8193 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
8194 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308195 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008196 *
8197 * This to take counter measure to handle deauth req from HDD
8198 *
8199 * Return: None
8200 */
8201void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308202 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008203{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008204 ENTER();
8205
Jeff Johnson34c88b72016-08-15 14:27:11 -07008206 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008207 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8208
8209 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308210 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008211 return;
8212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008213 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308214 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008215}
8216
8217void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
8218 bool enable)
8219{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008220 ENTER();
8221
Jeff Johnson34c88b72016-08-15 14:27:11 -07008222 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008223 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008225 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8226 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008227}
8228
8229/**
8230 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
8231 * @hdd_ctx: HDD Context
8232 *
8233 * API to find if there is any STA or P2P-Client is connected
8234 *
8235 * Return: true if connected; false otherwise
8236 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308237QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008238{
8239 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
8240}
8241
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008242/**
8243 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
8244 * @adapter: HDD adapter pointer
8245 *
8246 * This function loop through each adapter and disable roaming on each STA
8247 * device mode except the input adapter.
8248 *
8249 * Note: On the input adapter roaming is not enabled yet hence no need to
8250 * disable.
8251 *
8252 * Return: None
8253 */
8254void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8255{
8256 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8257 hdd_adapter_t *adapterIdx = NULL;
8258 hdd_adapter_list_node_t *adapterNode = NULL;
8259 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308260 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008261
8262 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8263 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008264 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008265 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008266 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008267 adapter->sessionId);
8268 /*
8269 * Loop through adapter and disable roaming for each STA device
8270 * mode except the input adapter.
8271 */
8272 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8273
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308274 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008275 adapterIdx = adapterNode->pAdapter;
8276
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008277 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008278 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008279 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008280 adapterIdx->sessionId);
8281 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8282 (adapterIdx),
8283 adapterIdx->sessionId, 0);
8284 }
8285
8286 status = hdd_get_next_adapter(hdd_ctx,
8287 adapterNode,
8288 &pNext);
8289 adapterNode = pNext;
8290 }
8291 }
8292}
8293
8294/**
8295 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8296 * @adapter: HDD adapter pointer
8297 *
8298 * This function loop through each adapter and enable roaming on each STA
8299 * device mode except the input adapter.
8300 * Note: On the input adapter no need to enable roaming because link got
8301 * disconnected on this.
8302 *
8303 * Return: None
8304 */
8305void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8306{
8307 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8308 hdd_adapter_t *adapterIdx = NULL;
8309 hdd_adapter_list_node_t *adapterNode = NULL;
8310 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308311 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008312
8313 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8314 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008315 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008316 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008317 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008318 adapter->sessionId);
8319 /*
8320 * Loop through adapter and enable roaming for each STA device
8321 * mode except the input adapter.
8322 */
8323 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8324
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308325 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008326 adapterIdx = adapterNode->pAdapter;
8327
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008328 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008329 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008330 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008331 adapterIdx->sessionId);
8332 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8333 (adapterIdx),
8334 adapterIdx->sessionId,
8335 REASON_CONNECT);
8336 }
8337
8338 status = hdd_get_next_adapter(hdd_ctx,
8339 adapterNode,
8340 &pNext);
8341 adapterNode = pNext;
8342 }
8343 }
8344}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008345
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308346void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008347{
8348 struct sk_buff *skb;
8349 struct nlmsghdr *nlh;
8350 tAniMsgHdr *ani_hdr;
8351 void *nl_data = NULL;
8352 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308353 struct radio_index_tlv *radio_info;
8354 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008355
8356 if (in_interrupt() || irqs_disabled() || in_atomic())
8357 flags = GFP_ATOMIC;
8358
8359 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8360
8361 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008362 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008363 return;
8364 }
8365
8366 nlh = (struct nlmsghdr *)skb->data;
8367 nlh->nlmsg_pid = 0; /* from kernel */
8368 nlh->nlmsg_flags = 0;
8369 nlh->nlmsg_seq = 0;
8370 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8371
8372 ani_hdr = NLMSG_DATA(nlh);
8373 ani_hdr->type = type;
8374
8375 switch (type) {
8376 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05308377 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008378 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008379 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008380 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008381 ani_hdr->length = 0;
8382 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8383 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8384 break;
8385 case WLAN_SVC_WLAN_STATUS_IND:
8386 case WLAN_SVC_WLAN_VERSION_IND:
8387 case WLAN_SVC_DFS_CAC_START_IND:
8388 case WLAN_SVC_DFS_CAC_END_IND:
8389 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8390 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8391 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008392 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308393 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008394 ani_hdr->length = len;
8395 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8396 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8397 memcpy(nl_data, data, len);
8398 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
8399 break;
8400
8401 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008402 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008403 type);
8404 kfree_skb(skb);
8405 return;
8406 }
8407
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308408 /*
8409 * Add radio index at the end of the svc event in TLV format to maintain
8410 * the backward compatibility with userspace applications.
8411 */
8412
8413 tlv_len = 0;
8414
8415 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8416 < WLAN_NL_MAX_PAYLOAD) {
8417 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8418 sizeof(*ani_hdr) + len);
8419 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8420 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8421 radio_info->radio = radio;
8422 tlv_len = sizeof(*radio_info);
8423 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8424 "Added radio index tlv - radio index %d",
8425 radio_info->radio);
8426 }
8427
8428 nlh->nlmsg_len += tlv_len;
8429 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008431 nl_srv_bcast(skb);
8432
8433 return;
8434}
8435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008436#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8437void wlan_hdd_auto_shutdown_cb(void)
8438{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008439 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308440
8441 if (!hdd_ctx)
8442 return;
8443
Jeff Johnson28f8a772016-08-15 15:30:36 -07008444 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308445 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8446 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008447}
8448
8449void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8450{
8451 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308452 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008453 hdd_adapter_t *adapter;
8454 bool ap_connected = false, sta_connected = false;
8455 tHalHandle hal_handle;
8456
8457 hal_handle = hdd_ctx->hHal;
8458 if (hal_handle == NULL)
8459 return;
8460
8461 if (hdd_ctx->config->WlanAutoShutdown == 0)
8462 return;
8463
8464 if (enable == false) {
8465 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308466 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008467 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008468 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308469 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008470 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008471 return;
8472 }
8473
8474 /* To enable shutdown timer check conncurrency */
8475 if (cds_concurrent_open_sessions_running()) {
8476 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8477
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308478 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008479 adapter = adapterNode->pAdapter;
8480 if (adapter
8481 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008482 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008483 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8484 conn_info.connState ==
8485 eConnectionState_Associated) {
8486 sta_connected = true;
8487 break;
8488 }
8489 }
8490 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008491 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008492 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8493 bApActive == true) {
8494 ap_connected = true;
8495 break;
8496 }
8497 }
8498 status = hdd_get_next_adapter(hdd_ctx,
8499 adapterNode,
8500 &pNext);
8501 adapterNode = pNext;
8502 }
8503 }
8504
8505 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008506 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008507 return;
8508 } else {
8509 if (sme_set_auto_shutdown_timer(hal_handle,
8510 hdd_ctx->config->
8511 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308512 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008513 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008514 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008515 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008516 hdd_ctx->config->WlanAutoShutdown);
8517
8518 }
8519}
8520#endif
8521
8522hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8523 bool check_start_bss)
8524{
8525 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8526 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308527 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008528 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8529
8530 con_sap_adapter = NULL;
8531
8532 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308533 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008534 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008535 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8536 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008537 adapter != this_sap_adapter) {
8538 if (check_start_bss) {
8539 if (test_bit(SOFTAP_BSS_STARTED,
8540 &adapter->event_flags)) {
8541 con_sap_adapter = adapter;
8542 break;
8543 }
8544 } else {
8545 con_sap_adapter = adapter;
8546 break;
8547 }
8548 }
8549 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8550 adapterNode = pNext;
8551 }
8552
8553 return con_sap_adapter;
8554}
8555
8556#ifdef MSM_PLATFORM
8557void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8558{
8559 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8560
Anurag Chouhan210db072016-02-22 18:42:15 +05308561 if (QDF_TIMER_STATE_RUNNING ==
8562 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563 return;
8564
Anurag Chouhan210db072016-02-22 18:42:15 +05308565 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008566 hdd_ctx->config->busBandwidthComputeInterval);
8567}
8568
8569void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8570{
8571 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308572 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008573 bool can_stop = true;
8574 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8575
Anurag Chouhan210db072016-02-22 18:42:15 +05308576 if (QDF_TIMER_STATE_RUNNING !=
8577 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008578 /* trying to stop timer, when not running is not good */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008579 hdd_err("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008580 return;
8581 }
8582
8583 if (cds_concurrent_open_sessions_running()) {
8584 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8585
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308586 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008587 adapter = adapterNode->pAdapter;
8588 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008589 && (adapter->device_mode == QDF_STA_MODE
8590 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008591 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8592 conn_info.connState ==
8593 eConnectionState_Associated) {
8594 can_stop = false;
8595 break;
8596 }
8597 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008598 && (adapter->device_mode == QDF_SAP_MODE
8599 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008600 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8601 true) {
8602 can_stop = false;
8603 break;
8604 }
8605 status = hdd_get_next_adapter(hdd_ctx,
8606 adapterNode,
8607 &pNext);
8608 adapterNode = pNext;
8609 }
8610 }
8611
Ravi Joshib89e7f72016-09-07 13:43:15 -07008612 if (can_stop == true) {
Anurag Chouhan210db072016-02-22 18:42:15 +05308613 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Ravi Joshib89e7f72016-09-07 13:43:15 -07008614 hdd_reset_tcp_delack(hdd_ctx);
8615 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008616}
8617#endif
8618
8619/**
8620 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8621 * and sta's operating channel.
8622 * @sta_adapter: Describe the first argument to foobar.
8623 * @ap_adapter: Describe the second argument to foobar.
8624 * @roam_profile: Roam profile of AP to which STA wants to connect.
8625 * @concurrent_chnl_same: If both SAP and STA channels are same then
8626 * set this flag to true else false.
8627 *
8628 * This function checks the sap's operating channel and sta's operating channel.
8629 * if both are same then it will return false else it will restart the sap in
8630 * sta's channel and return true.
8631 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308632 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008633 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308634QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008635 hdd_adapter_t *ap_adapter,
8636 tCsrRoamProfile *roam_profile,
8637 tScanResultHandle *scan_cache,
8638 bool *concurrent_chnl_same)
8639{
8640 hdd_ap_ctx_t *hdd_ap_ctx;
8641 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308642 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008643 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008644 *concurrent_chnl_same = true;
8645
8646 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8647 status =
8648 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8649 roam_profile,
8650 scan_cache,
8651 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308652 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008653 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008654 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8655 if (hdd_ap_ctx->operatingChannel != channel_id) {
8656 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008657 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008658 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008659 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008660 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8661 if (hdd_ap_ctx->operatingChannel != channel_id) {
8662 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008663 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008664 }
8665 }
8666 } else {
8667 /*
8668 * Lets handle worst case scenario here, Scan cache lookup is
8669 * failed so we have to stop the SAP to avoid any channel
8670 * discrepancy between SAP's channel and STA's channel.
8671 * Return the status as failure so caller function could know
8672 * that scan look up is failed.
8673 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008674 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308675 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008676 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308677 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008678}
8679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008680/**
8681 * wlan_hdd_stop_sap() - This function stops bss of SAP.
8682 * @ap_adapter: SAP adapter
8683 *
8684 * This function will process the stopping of sap adapter.
8685 *
8686 * Return: None
8687 */
8688void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
8689{
8690 hdd_ap_ctx_t *hdd_ap_ctx;
8691 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308692 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008693 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008694
8695 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008696 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008697 return;
8698 }
8699
8700 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8701 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308702 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008703 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008705 mutex_lock(&hdd_ctx->sap_lock);
8706 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08008707 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008708 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
8709 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008710 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308711 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308712 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008713 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05308714 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308715 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008716 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308717 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008718 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008719 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008720 return;
8721 }
8722 }
8723 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008724 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008725 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008726 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008727 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008728 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008729 }
8730 mutex_unlock(&hdd_ctx->sap_lock);
8731 return;
8732}
8733
8734/**
8735 * wlan_hdd_start_sap() - this function starts bss of SAP.
8736 * @ap_adapter: SAP adapter
8737 *
8738 * This function will process the starting of sap adapter.
8739 *
8740 * Return: None
8741 */
8742void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
8743{
8744 hdd_ap_ctx_t *hdd_ap_ctx;
8745 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308746 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008747 hdd_context_t *hdd_ctx;
8748 tsap_Config_t *sap_config;
8749
8750 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008751 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008752 return;
8753 }
8754
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008755 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07008756 hdd_err("SoftAp role has not been enabled");
8757 return;
8758 }
8759
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008760 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
8761 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8762 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8763 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
8764
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308765 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008766 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308767
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008768 mutex_lock(&hdd_ctx->sap_lock);
8769 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
8770 goto end;
8771
8772 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008773 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008774 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
8775 goto end;
8776 }
8777
8778 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
8779 &hdd_ap_ctx->sapConfig,
8780 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308781 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008782 goto end;
8783
Jeff Johnson28f8a772016-08-15 15:30:36 -07008784 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308785 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008786 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308787 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008788 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008789 goto end;
8790 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07008791 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008792 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008793 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008794 ap_adapter->sessionId);
8795 hostapd_state->bCommit = true;
8796
8797end:
8798 mutex_unlock(&hdd_ctx->sap_lock);
8799 return;
8800}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008801
8802/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08008803 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
8804 * mac scan config
8805 * @status: Status of set antenna mode
8806 *
8807 * Callback on setting the dual mac configuration
8808 *
8809 * Return: None
8810 */
8811void wlan_hdd_soc_set_antenna_mode_cb(
8812 enum set_antenna_mode_status status)
8813{
8814 hdd_context_t *hdd_ctx;
8815
8816 hdd_info("Status: %d", status);
8817
8818 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8819 if (0 != wlan_hdd_validate_context(hdd_ctx))
8820 return;
8821
8822 /* Signal the completion of set dual mac config */
8823 complete(&hdd_ctx->set_antenna_mode_cmpl);
8824}
8825
8826/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008827 * hdd_get_fw_version() - Get FW version
8828 * @hdd_ctx: pointer to HDD context.
8829 * @major_spid: FW version - major spid.
8830 * @minor_spid: FW version - minor spid
8831 * @ssid: FW version - ssid
8832 * @crmid: FW version - crmid
8833 *
8834 * This function is called to get the firmware build version stored
8835 * as part of the HDD context
8836 *
8837 * Return: None
8838 */
8839void hdd_get_fw_version(hdd_context_t *hdd_ctx,
8840 uint32_t *major_spid, uint32_t *minor_spid,
8841 uint32_t *siid, uint32_t *crmid)
8842{
8843 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
8844 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
8845 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
8846 *crmid = hdd_ctx->target_fw_version & 0x7fff;
8847}
8848
8849#ifdef QCA_CONFIG_SMP
8850/**
8851 * wlan_hdd_get_cpu() - get cpu_index
8852 *
8853 * Return: cpu_index
8854 */
8855int wlan_hdd_get_cpu(void)
8856{
8857 int cpu_index = get_cpu();
8858 put_cpu();
8859 return cpu_index;
8860}
8861#endif
8862
8863/**
8864 * hdd_get_fwpath() - get framework path
8865 *
8866 * This function is used to get the string written by
8867 * userspace to start the wlan driver
8868 *
8869 * Return: string
8870 */
8871const char *hdd_get_fwpath(void)
8872{
8873 return fwpath.string;
8874}
8875
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008876/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008877 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008878 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008879 * This function initilizes CDS global context with the help of cds_init. This
8880 * has to be the first function called after probe to get a valid global
8881 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008882 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008883 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008884 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008885int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008886{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008887 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008888 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008889
8890#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8891 wlan_logging_sock_init_svc();
8892#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008893 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008894
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008895 if (p_cds_context == NULL) {
8896 hdd_alert("Failed to allocate CDS context");
8897 ret = -ENOMEM;
8898 goto err_out;
8899 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008900
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008901 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308902 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008903
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008904err_out:
8905 return ret;
8906}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008907
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008908/**
8909 * hdd_deinit() - Deinitialize Driver
8910 *
8911 * This function frees CDS global context with the help of cds_deinit. This
8912 * has to be the last function call in remove callback to free the global
8913 * context.
8914 */
8915void hdd_deinit(void)
8916{
8917 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008918
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008919#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8920 wlan_logging_sock_deinit_svc();
8921#endif
8922}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008923
8924#ifdef QCA_WIFI_3_0_ADRASTEA
8925#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
8926#else
8927#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
8928#endif
8929
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008930/**
8931 * __hdd_module_init - Module init helper
8932 *
8933 * Module init helper function used by both module and static driver.
8934 *
8935 * Return: 0 for success, errno on failure
8936 */
8937static int __hdd_module_init(void)
8938{
8939 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008940
Arun Khandavallifae92942016-08-01 13:31:08 +05308941 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008942 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008943
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008944 pld_init();
8945
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308946 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008947
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008948 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008949
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008950 ret = wlan_hdd_register_driver();
8951 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07008952 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
8953 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008954 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008955 }
8956
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308957 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008958
8959 return 0;
8960out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308961 qdf_wake_lock_destroy(&wlan_wake_lock);
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008962 pld_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008963 return ret;
8964}
8965
8966/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05308967 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
8968 *
8969 * Block the unloading of the driver until the cds recovery is completed
8970 *
8971 * Return: None
8972 */
8973static void hdd_wait_for_recovery_completion(void)
8974{
8975 int retry = 0;
8976
8977 /* Wait for recovery to complete */
8978 while (cds_is_driver_recovering()) {
8979 hdd_alert("Recovery in progress; wait here!!!");
8980 msleep(1000);
8981 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8982 hdd_alert("SSR never completed, fatal error");
8983 QDF_BUG(0);
8984 }
8985 }
8986}
8987
8988/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008989 * __hdd_module_exit - Module exit helper
8990 *
8991 * Module exit helper function used by both module and static driver.
8992 */
8993static void __hdd_module_exit(void)
8994{
8995 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
8996 QWLAN_VERSIONSTR);
8997
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05308998 hdd_wait_for_recovery_completion();
8999
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009000 wlan_hdd_unregister_driver();
9001
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309002 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009003
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009004 pld_deinit();
9005
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009006 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009007}
9008
Arun Khandavallifae92942016-08-01 13:31:08 +05309009#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009010/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309011 * wlan_boot_cb() - Wlan boot callback
9012 * @kobj: object whose directory we're creating the link in.
9013 * @attr: attribute the user is interacting with
9014 * @buff: the buffer containing the user data
9015 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009016 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309017 * This callback is invoked when the fs is ready to start the
9018 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009019 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309020 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009021 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309022static ssize_t wlan_boot_cb(struct kobject *kobj,
9023 struct kobj_attribute *attr,
9024 const char *buf,
9025 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009026{
Arun Khandavallifae92942016-08-01 13:31:08 +05309027
9028 int ret = 0;
9029
9030 if (wlan_loader->loaded_state) {
9031 pr_info("Wlan driver already initialized");
9032 return 0;
9033 }
9034
9035
9036 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9037 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9038
9039 if (__hdd_module_init()) {
9040 pr_err("%s: Failed to register handler\n", __func__);
9041 ret = -EINVAL;
9042 } else
9043 wlan_loader->loaded_state = MODULE_INITIALIZED;
9044
9045 return count;
9046
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009047}
Arun Khandavallifae92942016-08-01 13:31:08 +05309048
9049/**
9050 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
9051 * ready
9052 *
9053 * This is creates the syfs entry boot_wlan. Which shall be invoked
9054 * when the filesystem is ready.
9055 *
9056 * Return: None
9057 */
9058static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009059{
Arun Khandavallifae92942016-08-01 13:31:08 +05309060 int ret = -EINVAL;
9061
9062 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
9063 if (!wlan_loader) {
9064 pr_err("%s: memory alloc failed\n", __func__);
9065 ret = -ENOMEM;
9066 return ret;
9067 }
9068
9069 wlan_loader->boot_wlan_obj = NULL;
9070 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
9071 GFP_KERNEL);
9072 if (!wlan_loader->attr_group) {
9073 pr_err("%s: malloc attr_group failed\n", __func__);
9074 ret = -ENOMEM;
9075 goto error_return;
9076 }
9077
9078 wlan_loader->loaded_state = 0;
9079 wlan_loader->attr_group->attrs = attrs;
9080
9081 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
9082 kernel_kobj);
9083 if (!wlan_loader->boot_wlan_obj) {
9084 pr_err("%s: sysfs create and add failed\n", __func__);
9085 ret = -ENOMEM;
9086 goto error_return;
9087 }
9088
9089 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
9090 wlan_loader->attr_group);
9091 if (ret) {
9092 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
9093 goto error_return;
9094 }
9095
9096 return 0;
9097
9098error_return:
9099
9100 if (wlan_loader->boot_wlan_obj) {
9101 kobject_del(wlan_loader->boot_wlan_obj);
9102 wlan_loader->boot_wlan_obj = NULL;
9103 }
9104
9105 return ret;
9106}
9107
9108/**
9109 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
9110 *
9111 * Return: 0 on success or errno on failure
9112 */
9113static int wlan_deinit_sysfs(void)
9114{
9115
9116 if (!wlan_loader) {
9117 hdd_alert("wlan loader context is Null!");
9118 return -EINVAL;
9119 }
9120
9121 if (wlan_loader->boot_wlan_obj) {
9122 sysfs_remove_group(wlan_loader->boot_wlan_obj,
9123 wlan_loader->attr_group);
9124 kobject_del(wlan_loader->boot_wlan_obj);
9125 wlan_loader->boot_wlan_obj = NULL;
9126 }
9127
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009128 return 0;
9129}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009130
Arun Khandavallifae92942016-08-01 13:31:08 +05309131#endif
9132
9133#ifdef MODULE
9134/**
9135 * __hdd_module_init - Module init helper
9136 *
9137 * Module init helper function used by both module and static driver.
9138 *
9139 * Return: 0 for success, errno on failure
9140 */
9141static int hdd_module_init(void)
9142{
9143 int ret = 0;
9144
9145 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9146 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9147
9148 if (__hdd_module_init()) {
9149 pr_err("%s: Failed to register handler\n", __func__);
9150 ret = -EINVAL;
9151 }
9152
9153 return ret;
9154}
9155#else
9156static int __init hdd_module_init(void)
9157{
9158 int ret = -EINVAL;
9159
9160 ret = wlan_init_sysfs();
9161 if (!ret)
9162 pr_err("Failed to create sysfs entry for loading wlan");
9163
9164 return ret;
9165}
9166#endif
9167
9168
9169#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009170/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009171 * hdd_module_exit() - Exit function
9172 *
9173 * This is the driver exit point (invoked when module is unloaded using rmmod)
9174 *
9175 * Return: None
9176 */
9177static void __exit hdd_module_exit(void)
9178{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009179 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009180}
Arun Khandavallifae92942016-08-01 13:31:08 +05309181#else
9182static void __exit hdd_module_exit(void)
9183{
9184 __hdd_module_exit();
9185 wlan_deinit_sysfs();
9186}
9187#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009188
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009189static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
9190{
9191 return param_set_copystring(kmessage, kp);
9192}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009193
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309194/**
9195 * is_con_mode_valid() check con mode is valid or not
9196 * @mode: global con mode
9197 *
9198 * Return: TRUE on success FALSE on failure
9199 */
9200static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
9201{
9202 switch (mode) {
9203 case QDF_GLOBAL_MONITOR_MODE:
9204 case QDF_GLOBAL_FTM_MODE:
9205 case QDF_GLOBAL_EPPING_MODE:
9206 return true;
9207 default:
9208 return false;
9209 }
9210}
9211
9212/**
9213 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
9214 * @mode: global con mode
9215 *
9216 * Return: adapter mode
9217 */
9218static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
9219 enum tQDF_GLOBAL_CON_MODE mode)
9220{
9221
9222 switch (mode) {
9223 case QDF_GLOBAL_MISSION_MODE:
9224 return QDF_STA_MODE;
9225 case QDF_GLOBAL_MONITOR_MODE:
9226 return QDF_MONITOR_MODE;
9227 case QDF_GLOBAL_FTM_MODE:
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05309228 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309229 case QDF_GLOBAL_EPPING_MODE:
9230 return QDF_EPPING_MODE;
9231 case QDF_GLOBAL_QVIT_MODE:
9232 return QDF_QVIT_MODE;
9233 default:
9234 return QDF_MAX_NO_OF_MODE;
9235 }
9236}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009237
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009238/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009239 * con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309240 * @kmessage: con mode name on which driver to be bring up
9241 * @kp: The associated kernel parameter
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009242 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309243 * This function is invoked when user updates con mode using sys entry,
9244 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009245 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309246 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009247 */
9248static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
9249{
9250 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309251 hdd_context_t *hdd_ctx;
9252 hdd_adapter_t *adapter;
9253 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309254 enum tQDF_GLOBAL_CON_MODE curr_mode;
9255 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavallifae92942016-08-01 13:31:08 +05309256 QDF_STATUS status;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009257
Arun Khandavallifae92942016-08-01 13:31:08 +05309258 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009259 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05309260
9261 if (!qdf_dev) {
9262 hdd_err("qdf device context is Null return!");
9263 return -EINVAL;
9264 }
9265
9266 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9267 if (!hdd_ctx) {
9268 hdd_err("Hdd context Null return!");
9269 return -EINVAL;
9270 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309271
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309272 if (!(is_con_mode_valid(con_mode))) {
9273 hdd_err("invlaid con_mode %d", con_mode);
9274 return -EINVAL;
9275 }
9276 curr_mode = hdd_get_conparam();
9277 if (curr_mode == con_mode) {
9278 hdd_err("curr mode: %d is same as user triggered mode %d",
9279 curr_mode, con_mode);
9280 return 0;
9281 }
9282
9283 adapter_mode = hdd_get_adpter_mode(curr_mode);
9284 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
9285 hdd_err("invalid adapter");
9286 return -EINVAL;
9287 }
9288
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05309289 hdd_stop_all_adapters(hdd_ctx);
9290 hdd_deinit_all_adapters(hdd_ctx, false);
9291
Arun Khandavallifae92942016-08-01 13:31:08 +05309292 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309293 if (ret) {
9294 hdd_err("Stop wlan modules failed");
9295 return -EINVAL;
9296 }
9297
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309298 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309299 if (!adapter) {
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309300 hdd_err("Failed to get adapter, mode: %d", curr_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309301 return -EINVAL;
9302 }
9303
9304 if (con_mode == QDF_GLOBAL_FTM_MODE) {
9305 adapter->device_mode = QDF_FTM_MODE;
9306 hdd_set_conparam(QDF_GLOBAL_FTM_MODE);
9307 } else if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
9308 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9309 adapter->device_mode = QDF_MONITOR_MODE;
9310 hdd_set_conparam(QDF_GLOBAL_MONITOR_MODE);
9311 hdd_set_station_ops(adapter->dev);
9312 } else if (con_mode == QDF_GLOBAL_EPPING_MODE) {
9313 hdd_set_conparam(QDF_GLOBAL_EPPING_MODE);
9314 status = epping_open();
9315 if (status != QDF_STATUS_SUCCESS) {
9316 hdd_err("Failed to open in eeping mode: %d", status);
9317 return -EINVAL;
9318 }
9319 ret = epping_enable(qdf_dev->dev);
9320 if (ret) {
9321 hdd_err("Failed to enable in epping mode : %d", ret);
9322 epping_close();
9323 return -EINVAL;
9324 }
9325 hdd_info("epping mode successfully enabled");
9326 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05309327 }
9328
9329 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
9330 if (ret) {
9331 hdd_err("Start wlan modules failed: %d", ret);
9332 return -EINVAL;
9333 }
9334
9335 if (hdd_start_adapter(adapter)) {
9336 hdd_err("Failed to start %s adapter", kmessage);
9337 return -EINVAL;
9338 } else {
9339 hdd_info("Mode successfully changed to %s", kmessage);
9340 ret = 0;
9341 }
9342
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009343 return ret;
9344}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009345
9346/**
9347 * hdd_get_conparam() - driver exit point
9348 *
9349 * This is the driver exit point (invoked when module is unloaded using rmmod)
9350 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309351 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009352 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309353enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009354{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309355 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009356}
9357
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009358void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009359{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009360 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009361}
9362
Komal Seelamc11bb222016-01-27 18:57:10 +05309363/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309364 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9365 * @hdd_ctx: HDD context
9366 *
9367 * Cleans up the pre cac interface, if it exists
9368 *
9369 * Return: None
9370 */
9371void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9372{
9373 uint8_t session_id;
9374 QDF_STATUS status;
9375 struct hdd_adapter_s *precac_adapter;
9376
9377 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9378 if (QDF_IS_STATUS_ERROR(status)) {
9379 hdd_err("failed to get pre cac vdev id");
9380 return;
9381 }
9382
9383 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9384 if (!precac_adapter) {
9385 hdd_err("invalid pre cac adapater");
9386 return;
9387 }
9388
9389 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9390 wlan_hdd_sap_pre_cac_failure,
9391 (void *)precac_adapter);
9392 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9393
9394}
9395
9396/**
Komal Seelamec702b02016-02-24 18:42:16 +05309397 * hdd_update_ol_config - API to update ol configuration parameters
9398 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309399 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309400 * Return: void
9401 */
Komal Seelamec702b02016-02-24 18:42:16 +05309402static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309403{
Komal Seelamec702b02016-02-24 18:42:16 +05309404 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309405 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309406
Komal Seelamec702b02016-02-24 18:42:16 +05309407 if (!ol_ctx)
9408 return;
9409
9410 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9411 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9412 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9413 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -07009414 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +05309415
9416 ol_init_ini_config(ol_ctx, &cfg);
9417}
9418
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009419#ifdef FEATURE_RUNTIME_PM
9420/**
9421 * hdd_populate_runtime_cfg() - populate runtime configuration
9422 * @hdd_ctx: hdd context
9423 * @cfg: pointer to the configuration memory being populated
9424 *
9425 * Return: void
9426 */
9427static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9428 struct hif_config_info *cfg)
9429{
9430 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9431 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9432}
9433#else
9434static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9435 struct hif_config_info *cfg)
9436{
9437}
9438#endif
9439
Komal Seelamec702b02016-02-24 18:42:16 +05309440/**
9441 * hdd_update_hif_config - API to update HIF configuration parameters
9442 * @hdd_ctx: HDD Context
9443 *
9444 * Return: void
9445 */
9446static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9447{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309448 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309449 struct hif_config_info cfg;
9450
9451 if (!scn)
9452 return;
9453
9454 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009455 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05309456 hif_init_ini_config(scn, &cfg);
9457}
9458
9459/**
9460 * hdd_update_config() - Initialize driver per module ini parameters
9461 * @hdd_ctx: HDD Context
9462 *
9463 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309464 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05309465 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309466int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05309467{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309468 int ret;
9469
Komal Seelamec702b02016-02-24 18:42:16 +05309470 hdd_update_ol_config(hdd_ctx);
9471 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309472 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
9473 ret = hdd_update_cds_config_ftm(hdd_ctx);
9474 else
9475 ret = hdd_update_cds_config(hdd_ctx);
9476
9477 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05309478}
9479
Agrawal Ashish65634612016-08-18 13:24:32 +05309480/**
9481 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
9482 * @mode : cfg80211 DFS mode
9483 *
9484 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
9485 */
9486enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
9487{
9488 switch (mode) {
9489 case DFS_MODE_ENABLE:
9490 return ACS_DFS_MODE_ENABLE;
9491 break;
9492 case DFS_MODE_DISABLE:
9493 return ACS_DFS_MODE_DISABLE;
9494 break;
9495 case DFS_MODE_DEPRIORITIZE:
9496 return ACS_DFS_MODE_DEPRIORITIZE;
9497 break;
9498 default:
9499 hdd_err("ACS dfs mode is NONE");
9500 return ACS_DFS_MODE_NONE;
9501 }
9502}
9503
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309504/**
9505 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
9506 * @hddctx: pointer to hdd context
9507 * @set_value: enable/disable
9508 *
9509 * When Host sends vendor command enable, FW will send *ONE* CA ind to
9510 * Host(even though it is duplicate). When Host send vendor command
9511 * disable,FW doesn't perform any action. Whenever any change in
9512 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
9513 *
9514 * return - 0 on success, appropriate error values on failure.
9515 */
9516int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
9517{
9518 QDF_STATUS status;
9519
9520 if (0 != wlan_hdd_validate_context(hddctx)) {
9521 return -EAGAIN;
9522 }
9523
9524 if (!hddctx->config->goptimize_chan_avoid_event) {
9525 hdd_warn("goptimize_chan_avoid_event ini param disabled");
9526 return -EINVAL;
9527 }
9528
9529 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
9530 if (!QDF_IS_STATUS_SUCCESS(status)) {
9531 hdd_err("Failed to send chan avoid command to SME");
9532 return -EINVAL;
9533 }
9534 return 0;
9535}
Agrawal Ashish65634612016-08-18 13:24:32 +05309536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009537/* Register the module init/exit functions */
9538module_init(hdd_module_init);
9539module_exit(hdd_module_exit);
9540
9541MODULE_LICENSE("Dual BSD/GPL");
9542MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9543MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9544
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009545module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9546 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009547
9548module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
9549 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
9550
9551module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
9552
9553module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
9554
9555module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);