blob: a287ac4f3fcf1b3c3630beae05c2994c7456d1d6 [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
Naveen Rawat286def52016-09-23 15:38:02 -07001964 /* Enable carrier and transmit queues for NDI */
1965 if (WLAN_HDD_IS_NDI(adapter)) {
1966 hdd_notice("Enabling Tx Queues");
1967 wlan_hdd_netif_queue_control(adapter,
1968 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
1969 WLAN_CONTROL_PATH);
1970 }
1971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 return ret;
1973}
1974
Arun Khandavallifae92942016-08-01 13:31:08 +05301975
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976/**
1977 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1978 * @dev: Pointer to net_device structure
1979 *
1980 * This is called in response to ifconfig up
1981 *
1982 * Return: 0 for success; non-zero for failure
1983 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001984static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985{
1986 int ret;
1987
1988 cds_ssr_protect(__func__);
1989 ret = __hdd_open(dev);
1990 cds_ssr_unprotect(__func__);
1991
1992 return ret;
1993}
1994
1995/**
1996 * __hdd_stop() - HDD stop function
1997 * @dev: Pointer to net_device structure
1998 *
1999 * This is called in response to ifconfig down
2000 *
2001 * Return: 0 for success; non-zero for failure
2002 */
2003static int __hdd_stop(struct net_device *dev)
2004{
2005 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2006 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05302007 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05302009 bool close_modules = true;
2010 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002012 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302014 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 adapter->sessionId, adapter->device_mode));
2016
2017 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302018 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002019 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020
2021 /* Nothing to be done if the interface is not opened */
2022 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002023 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 return -ENODEV;
2025 }
2026
2027 /* Make sure the interface is marked as closed */
2028 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002029 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002030
2031 /*
2032 * Disable TX on the interface, after this hard_start_xmit() will not
2033 * be called on that interface
2034 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002035 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002036 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2037 WLAN_CONTROL_PATH);
2038
2039 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002040 * NAN data interface is different in some sense. The traffic on NDI is
2041 * bursty in nature and depends on the need to transfer. The service
2042 * layer may down the interface after the usage and up again when
2043 * required. In some sense, the NDI is expected to be available
2044 * (like SAP) iface until NDI delete request is issued by the service
2045 * layer. Skip BSS termination and adapter deletion for NAN Data
2046 * interface (NDI).
2047 */
2048 if (WLAN_HDD_IS_NDI(adapter))
2049 return 0;
2050
2051 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 * The interface is marked as down for outside world (aka kernel)
2053 * But the driver is pretty much alive inside. The driver needs to
2054 * tear down the existing connection on the netdev (session)
2055 * cleanup the data pipes and wait until the control plane is stabilized
2056 * for this interface. The call also needs to wait until the above
2057 * mentioned actions are completed before returning to the caller.
2058 * Notice that the hdd_stop_adapter is requested not to close the session
2059 * That is intentional to be able to scan if it is a STA/P2P interface
2060 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302061 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062
2063 /* DeInit the adapter. This ensures datapath cleanup as well */
2064 hdd_deinit_adapter(hdd_ctx, adapter, true);
2065
Arun Khandavallifae92942016-08-01 13:31:08 +05302066
2067 /*
2068 * Find if any iface is up. If any iface is up then can't put device to
2069 * sleep/power save mode
2070 */
2071 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2072 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2073 if (test_bit(DEVICE_IFACE_OPENED,
2074 &adapternode->pAdapter->event_flags)) {
2075 hdd_info("Still other ifaces are up cannot close modules");
2076 close_modules = false;
2077 break;
2078 }
2079 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2080 adapternode = next;
2081
2082 }
2083
2084 if (close_modules) {
2085 hdd_info("Closing all modules from the hdd_stop");
2086 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2087 hdd_ctx->config->iface_change_wait_time
2088 * 50000);
2089 }
2090
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002091 EXIT();
2092 return 0;
2093}
2094
2095/**
2096 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2097 * @dev: pointer to net_device structure
2098 *
2099 * This is called in response to ifconfig down
2100 *
2101 * Return: 0 for success and error number for failure
2102 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002103static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002104{
2105 int ret;
2106
2107 cds_ssr_protect(__func__);
2108 ret = __hdd_stop(dev);
2109 cds_ssr_unprotect(__func__);
2110
2111 return ret;
2112}
2113
2114/**
2115 * __hdd_uninit() - HDD uninit function
2116 * @dev: Pointer to net_device structure
2117 *
2118 * This is called during the netdev unregister to uninitialize all data
2119 * associated with the device
2120 *
2121 * Return: None
2122 */
2123static void __hdd_uninit(struct net_device *dev)
2124{
2125 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2126
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002127 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002128
2129 do {
2130 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002131 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002132 break;
2133 }
2134
2135 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002136 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002137 break;
2138 }
2139
2140 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002141 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142 /*
2143 * we haven't validated all cases so let this go for
2144 * now
2145 */
2146 }
2147
2148 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2149
2150 /* after uninit our adapter structure will no longer be valid */
2151 adapter->dev = NULL;
2152 adapter->magic = 0;
2153 } while (0);
2154
2155 EXIT();
2156}
2157
2158/**
2159 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2160 * @dev: pointer to net_device structure
2161 *
2162 * This is called during the netdev unregister to uninitialize all data
2163 * associated with the device
2164 *
2165 * Return: none
2166 */
2167static void hdd_uninit(struct net_device *dev)
2168{
2169 cds_ssr_protect(__func__);
2170 __hdd_uninit(dev);
2171 cds_ssr_unprotect(__func__);
2172}
2173
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002174static int hdd_open_cesium_nl_sock(void)
2175{
2176#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2177 struct netlink_kernel_cfg cfg = {
2178 .groups = WLAN_NLINK_MCAST_GRP_ID,
2179 .input = NULL
2180 };
2181#endif
2182 int ret = 0;
2183
2184#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2185 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2186#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2187 THIS_MODULE,
2188#endif
2189 &cfg);
2190#else
2191 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2192 WLAN_NLINK_MCAST_GRP_ID,
2193 NULL, NULL, THIS_MODULE);
2194#endif
2195
2196 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002197 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002198 ret = -ECONNREFUSED;
2199 }
2200
2201 return ret;
2202}
2203
2204static void hdd_close_cesium_nl_sock(void)
2205{
2206 if (NULL != cesium_nl_srv_sock) {
2207 netlink_kernel_release(cesium_nl_srv_sock);
2208 cesium_nl_srv_sock = NULL;
2209 }
2210}
2211
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212/**
2213 * __hdd_set_mac_address() - set the user specified mac address
2214 * @dev: Pointer to the net device.
2215 * @addr: Pointer to the sockaddr.
2216 *
2217 * This function sets the user specified mac address using
2218 * the command ifconfig wlanX hw ether <mac adress>.
2219 *
2220 * Return: 0 for success, non zero for failure
2221 */
2222static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2223{
2224 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2225 hdd_context_t *hdd_ctx;
2226 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302227 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228 int ret;
2229
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002230 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002231
2232 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2233 ret = wlan_hdd_validate_context(hdd_ctx);
2234 if (0 != ret)
2235 return ret;
2236
2237 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2238 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2239
2240 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302241 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002242}
2243
2244/**
2245 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2246 * function from SSR
2247 * @dev: pointer to net_device structure
2248 * @addr: Pointer to the sockaddr
2249 *
2250 * This function sets the user specified mac address using
2251 * the command ifconfig wlanX hw ether <mac adress>.
2252 *
2253 * Return: 0 for success.
2254 */
2255static int hdd_set_mac_address(struct net_device *dev, void *addr)
2256{
2257 int ret;
2258
2259 cds_ssr_protect(__func__);
2260 ret = __hdd_set_mac_address(dev, addr);
2261 cds_ssr_unprotect(__func__);
2262
2263 return ret;
2264}
2265
2266uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2267{
2268 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302269 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2271 break;
2272 }
2273
Anurag Chouhan6d760662016-02-20 16:05:43 +05302274 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 return NULL;
2276
2277 hdd_ctx->config->intfAddrMask |= (1 << i);
2278 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2279}
2280
2281void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2282{
2283 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302284 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 if (!memcmp(releaseAddr,
2286 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2287 6)) {
2288 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2289 break;
2290 }
2291 }
2292 return;
2293}
2294
2295#ifdef WLAN_FEATURE_PACKET_FILTERING
2296/**
2297 * __hdd_set_multicast_list() - set the multicast address list
2298 * @dev: Pointer to the WLAN device.
2299 * @skb: Pointer to OS packet (sk_buff).
2300 *
2301 * This funciton sets the multicast address list.
2302 *
2303 * Return: None
2304 */
2305static void __hdd_set_multicast_list(struct net_device *dev)
2306{
2307 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2308 int mc_count;
2309 int i = 0, status;
2310 struct netdev_hw_addr *ha;
2311 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2312 static const uint8_t ipv6_router_solicitation[]
2313 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2314
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002315 ENTER_DEV(dev);
2316
Anurag Chouhan6d760662016-02-20 16:05:43 +05302317 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302318 return;
2319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002320 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302321 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002322 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323
2324 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002325 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 adapter->mc_addr_list.mc_cnt = 0;
2327 } else {
2328 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302329 hdd_notice("mc_count : %u", mc_count);
2330
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Dustin Brown61269462016-09-19 13:25:45 -07002332 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
2333 WLAN_HDD_MAX_MC_ADDR_LIST);
2334 wlan_hdd_set_mc_addr_list(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 adapter->mc_addr_list.mc_cnt = 0;
2336 return;
2337 }
2338
2339 adapter->mc_addr_list.mc_cnt = mc_count;
2340
2341 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302342 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2343 i, MAC_ADDR_ARRAY(ha->addr));
2344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002345 if (i == mc_count)
2346 break;
2347 /*
2348 * Skip following addresses:
2349 * 1)IPv6 router solicitation address
2350 * 2)Any other address pattern if its set during
2351 * RXFILTER REMOVE driver command based on
2352 * addr_filter_pattern
2353 */
2354 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2355 ETH_ALEN)) ||
2356 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2357 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002358 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002359 MAC_ADDR_ARRAY(ha->addr));
2360 adapter->mc_addr_list.mc_cnt--;
2361 continue;
2362 }
2363
2364 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2365 ETH_ALEN);
2366 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2367 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002368 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002369 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2370 i++;
2371 }
2372 }
2373 if (hdd_ctx->config->active_mode_offload) {
2374 hdd_info("enable mc filtering");
2375 wlan_hdd_set_mc_addr_list(adapter, true);
2376 } else {
2377 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2378 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302379 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 return;
2381}
2382
2383/**
2384 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2385 * @dev: pointer to net_device
2386 *
2387 * Return: none
2388 */
2389static void hdd_set_multicast_list(struct net_device *dev)
2390{
2391 cds_ssr_protect(__func__);
2392 __hdd_set_multicast_list(dev);
2393 cds_ssr_unprotect(__func__);
2394}
2395#endif
2396
2397/**
2398 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2399 * @dev: Pointer to the WLAN device.
2400 * @skb: Pointer to OS packet (sk_buff).
2401 *
2402 * This function is registered with the Linux OS for network
2403 * core to decide which queue to use first.
2404 *
2405 * Return: ac, Queue Index/access category corresponding to UP in IP header
2406 */
2407static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2408#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2409 , void *accel_priv
2410#endif
2411#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2412 , select_queue_fallback_t fallback
2413#endif
2414)
2415{
2416 return hdd_wmm_select_queue(dev, skb);
2417}
2418
2419static struct net_device_ops wlan_drv_ops = {
2420 .ndo_open = hdd_open,
2421 .ndo_stop = hdd_stop,
2422 .ndo_uninit = hdd_uninit,
2423 .ndo_start_xmit = hdd_hard_start_xmit,
2424 .ndo_tx_timeout = hdd_tx_timeout,
2425 .ndo_get_stats = hdd_get_stats,
2426 .ndo_do_ioctl = hdd_ioctl,
2427 .ndo_set_mac_address = hdd_set_mac_address,
2428 .ndo_select_queue = hdd_select_queue,
2429#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002430 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431#endif
2432};
2433
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002434/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2435static struct net_device_ops wlan_mon_drv_ops = {
2436 .ndo_open = hdd_mon_open,
2437 .ndo_stop = hdd_stop,
2438 .ndo_get_stats = hdd_get_stats,
2439};
2440
2441/**
2442 * hdd_set_station_ops() - update net_device ops for monitor mode
2443 * @pWlanDev: Handle to struct net_device to be updated.
2444 * Return: None
2445 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446void hdd_set_station_ops(struct net_device *pWlanDev)
2447{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002448 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2449 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2450 else
2451 pWlanDev->netdev_ops = &wlan_drv_ops;
2452}
2453
Komal Seelama89be8d2016-09-29 11:09:26 +05302454#ifdef FEATURE_RUNTIME_PM
2455static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2456{
2457 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2458
2459 ctx->connect = qdf_runtime_lock_init("connect");
2460}
2461
2462static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2463{
2464 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2465
2466 qdf_runtime_lock_deinit(ctx->connect);
2467 ctx->connect = NULL;
2468}
2469#else /* FEATURE_RUNTIME_PM */
2470static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2471static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2472#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002473/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002474 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2475 * @hdd_ctx: global hdd context
2476 * @macAddr: mac address to assign to the interface
2477 * @name: User-visible name of the interface
2478 *
2479 * hdd adapter pointer would point to the netdev->priv space, this function
2480 * would retrive the pointer, and setup the hdd adapter configuration.
2481 *
2482 * Return: the pointer to hdd adapter, otherwise NULL
2483 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2485 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002486 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 const char *name)
2488{
2489 struct net_device *pWlanDev = NULL;
2490 hdd_adapter_t *adapter = NULL;
2491 /*
2492 * cfg80211 initialization and registration....
2493 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002494 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2495#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2496 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002498 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2499 hdd_mon_mode_ether_setup : ether_setup),
2500 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501
2502 if (pWlanDev != NULL) {
2503
2504 /* Save the pointer to the net_device in the HDD adapter */
2505 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2506
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302507 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508
2509 adapter->dev = pWlanDev;
2510 adapter->pHddCtx = hdd_ctx;
2511 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302512 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002513
2514 init_completion(&adapter->session_open_comp_var);
2515 init_completion(&adapter->session_close_comp_var);
2516 init_completion(&adapter->disconnect_comp_var);
2517 init_completion(&adapter->linkup_event_var);
2518 init_completion(&adapter->cancel_rem_on_chan_var);
2519 init_completion(&adapter->rem_on_chan_ready_event);
2520 init_completion(&adapter->sta_authorized_event);
2521 init_completion(&adapter->offchannel_tx_event);
2522 init_completion(&adapter->tx_action_cnf_event);
2523#ifdef FEATURE_WLAN_TDLS
2524 init_completion(&adapter->tdls_add_station_comp);
2525 init_completion(&adapter->tdls_del_station_comp);
2526 init_completion(&adapter->tdls_mgmt_comp);
2527 init_completion(&adapter->tdls_link_establish_req_comp);
2528#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002529 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002530 init_completion(&adapter->change_country_code);
2531
2532
2533 init_completion(&adapter->scan_info.abortscan_event_var);
2534
2535 adapter->offloads_configured = false;
2536 adapter->isLinkUpSvcNeeded = false;
2537 adapter->higherDtimTransition = true;
2538 /* Init the net_device structure */
2539 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2540
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302541 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302543 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 sizeof(tSirMacAddr));
2545 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546
2547 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2548 pWlanDev->features |=
2549 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2550 pWlanDev->features |= NETIF_F_RXCSUM;
2551
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002552 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 hdd_set_station_ops(adapter->dev);
2555
2556 pWlanDev->destructor = free_netdev;
2557 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002558 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 adapter->wdev.wiphy = hdd_ctx->wiphy;
2560 adapter->wdev.netdev = pWlanDev;
2561 /* set pWlanDev's parent to underlying device */
2562 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2563 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302564 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302566 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 }
2568
2569 return adapter;
2570}
2571
Jeff Johnson590e2012016-10-05 16:16:24 -07002572static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2573 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574{
2575 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002576
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002577 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2579 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002580 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302581 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 }
2583 }
2584 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002585 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302586 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587 }
2588 } else {
2589 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002590 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302591 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 }
2593 }
2594 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2595
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302596 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597}
2598
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002599QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600{
2601 hdd_adapter_t *adapter = pContext;
2602
2603 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002604 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302605 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 }
2607
2608 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002609 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302610 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611 }
2612
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002613 /*
2614 * For NAN Data interface, the close session results in the final
2615 * indication to the userspace
2616 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002617 if (adapter->device_mode == QDF_NDI_MODE)
2618 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002619
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2621
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002622 /*
2623 * We can be blocked while waiting for scheduled work to be
2624 * flushed, and the adapter structure can potentially be freed, in
2625 * which case the magic will have been reset. So make sure the
2626 * magic is still good, and hence the adapter structure is still
2627 * valid, before signaling completion
2628 */
2629 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2630 complete(&adapter->session_close_comp_var);
2631
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302632 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633}
2634
Krunal Soni8c37e322016-02-03 16:08:37 -08002635/**
2636 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2637 * @adapter: pointer to device adapter
2638 * @type: type of interface
2639 *
2640 * This routine will check the mode of adapter and if it is required then it
2641 * will initialize the TDLS operations
2642 *
2643 * Return: QDF_STATUS
2644 */
2645#ifdef FEATURE_WLAN_TDLS
2646static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2647{
2648 if (QDF_IBSS_MODE != type) {
2649 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002650 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002651 return QDF_STATUS_E_FAILURE;
2652 }
2653 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2654 }
2655 return QDF_STATUS_SUCCESS;
2656}
2657#else
2658static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2659{
2660 return QDF_STATUS_SUCCESS;
2661}
2662#endif
2663
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302664QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665{
2666 struct net_device *pWlanDev = adapter->dev;
2667 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2668 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302669 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302670 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 uint32_t type, subType;
2672 unsigned long rc;
2673 int ret_val;
2674
2675 INIT_COMPLETION(adapter->session_open_comp_var);
2676 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002677 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302679 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002680 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 goto error_sme_open;
2682 }
2683 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302684 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2686 (uint8_t *) &adapter->macAddressCurrent,
2687 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302688 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002689 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302690 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302691 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 goto error_sme_open;
2693 }
2694 /* Block on a completion variable. Can't wait forever though. */
2695 rc = wait_for_completion_timeout(
2696 &adapter->session_open_comp_var,
2697 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2698 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002699 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302701 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 goto error_sme_open;
2703 }
2704
Naveen Rawata410c5a2016-09-19 14:22:33 -07002705 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302707 qdf_ret_status = hdd_register_wext(pWlanDev);
2708 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002709 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302710 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302711 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002712 goto error_register_wext;
2713 }
2714 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002715 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2717
2718 /* Set the default operation channel */
2719 pHddStaCtx->conn_info.operationChannel =
2720 hdd_ctx->config->OperatingChannel;
2721
2722 /* Make the default Auth Type as OPEN */
2723 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2724
2725 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302726 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002727 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728 status, status);
2729 goto error_init_txrx;
2730 }
2731
2732 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2733
2734 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302735 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002736 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737 status, status);
2738 goto error_wmm_init;
2739 }
2740
2741 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2742
2743 ret_val = wma_cli_set_command(adapter->sessionId,
2744 WMI_PDEV_PARAM_BURST_ENABLE,
2745 hdd_ctx->config->enableSifsBurst,
2746 PDEV_CMD);
2747
2748 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002749 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 ret_val);
2751 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002752 status = hdd_check_and_init_tdls(adapter, type);
2753 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302756 status = hdd_lro_enable(hdd_ctx, adapter);
2757 if (status != QDF_STATUS_SUCCESS)
2758 goto error_lro_enable;
2759
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302760 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302762error_lro_enable:
2763 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764error_tdls_init:
2765 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2766 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767error_wmm_init:
2768 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2769 hdd_deinit_tx_rx(adapter);
2770error_init_txrx:
2771 hdd_unregister_wext(pWlanDev);
2772error_register_wext:
2773 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2774 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302775 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 adapter->sessionId,
2777 hdd_sme_close_session_callback,
2778 adapter)) {
2779 unsigned long rc;
2780
2781 /*
2782 * Block on a completion variable.
2783 * Can't wait forever though.
2784 */
2785 rc = wait_for_completion_timeout(
2786 &adapter->session_close_comp_var,
2787 msecs_to_jiffies
2788 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2789 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002790 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 rc);
2792 }
2793 }
2794error_sme_open:
2795 return status;
2796}
2797
2798void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2799{
2800 hdd_cfg80211_state_t *cfgState;
2801
2802 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2803
2804 if (NULL != cfgState->buf) {
2805 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 rc = wait_for_completion_timeout(
2807 &adapter->tx_action_cnf_event,
2808 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2809 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002810 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302811 /*
2812 * Inform tx status as FAILURE to upper layer and free
2813 * cfgState->buf
2814 */
2815 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 }
2817 }
2818 return;
2819}
2820
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302821/**
2822 * hdd_station_adapter_deinit() - De-initialize the station adapter
2823 * @hdd_ctx: global hdd context
2824 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07002825 * @rtnl_held: Used to indicate whether or not the caller is holding
2826 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302827 *
2828 * This function De-initializes the STA/P2P/OCB adapter.
2829 *
2830 * Return: None.
2831 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002832static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2833 hdd_adapter_t *adapter,
2834 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302835{
2836 ENTER_DEV(adapter->dev);
2837
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302838 if (adapter->dev) {
2839 if (rtnl_held)
2840 adapter->dev->wireless_handlers = NULL;
2841 else {
2842 rtnl_lock();
2843 adapter->dev->wireless_handlers = NULL;
2844 rtnl_unlock();
2845 }
2846 }
2847
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302848 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2849 hdd_deinit_tx_rx(adapter);
2850 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2851 }
2852
2853 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2854 hdd_wmm_adapter_close(adapter);
2855 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2856 }
2857
2858 hdd_cleanup_actionframe(hdd_ctx, adapter);
2859 wlan_hdd_tdls_exit(adapter);
2860
2861 EXIT();
2862}
2863
2864/**
2865 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2866 * @hdd_ctx: global hdd context
2867 * @adapter: HDD adapter
2868 * @rtnl_held: the rtnl lock hold flag
2869 * This function De-initializes the AP/P2PGo adapter.
2870 *
2871 * Return: None.
2872 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002873static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
2874 hdd_adapter_t *adapter,
2875 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302876{
2877 ENTER_DEV(adapter->dev);
2878
2879 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2880 hdd_wmm_adapter_close(adapter);
2881 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2882 }
2883
2884 hdd_cleanup_actionframe(hdd_ctx, adapter);
2885
2886 hdd_unregister_hostapd(adapter, rtnl_held);
2887
2888 EXIT();
2889}
2890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2892 bool rtnl_held)
2893{
2894 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002897 case QDF_STA_MODE:
2898 case QDF_P2P_CLIENT_MODE:
2899 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302901 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902 break;
2903 }
2904
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002905 case QDF_SAP_MODE:
2906 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 {
2908
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302909 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 break;
2911 }
2912
2913 default:
2914 break;
2915 }
2916
2917 EXIT();
2918}
2919
Jeff Johnson590e2012016-10-05 16:16:24 -07002920static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2921 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922{
2923 struct net_device *pWlanDev = NULL;
2924
2925 if (adapter)
2926 pWlanDev = adapter->dev;
2927 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002928 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 return;
2930 }
2931
Rajeev Kumardca5f812016-02-04 17:28:06 -08002932 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05302933
2934 if (adapter->scan_info.default_scan_ies) {
2935 qdf_mem_free(adapter->scan_info.default_scan_ies);
2936 adapter->scan_info.default_scan_ies = NULL;
2937 }
2938
Komal Seelama89be8d2016-09-29 11:09:26 +05302939 hdd_adapter_runtime_suspend_denit(adapter);
2940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 /*
2942 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2943 * the driver is almost closed and cannot handle either control
2944 * messages or data. However, unregister_netdevice() call above will
2945 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2946 * to close the active connections (basically excites control path) which
2947 * is not right. Setting this flag helps hdd_stop() to recognize that
2948 * the interface is closed and restricts any operations on that
2949 */
2950 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2951
2952 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2953 if (rtnl_held) {
2954 unregister_netdevice(pWlanDev);
2955 } else {
2956 unregister_netdev(pWlanDev);
2957 }
2958 /*
2959 * Note that the adapter is no longer valid at this point
2960 * since the memory has been reclaimed
2961 */
2962 }
2963}
2964
Jeff Johnson590e2012016-10-05 16:16:24 -07002965static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
2966 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967{
2968 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2969 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302970 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302972 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 adapter = adapterNode->pAdapter;
2974 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302975 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302977 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978 }
2979 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2980 adapterNode = pNext;
2981 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302982 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002983}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002984
Arun Khandavalli2358d522016-05-16 18:05:37 +05302985#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2986/**
2987 * hdd_set_fw_log_params() - Set log parameters to FW
2988 * @hdd_ctx: HDD Context
2989 * @adapter: HDD Adapter
2990 *
2991 * This function set the FW Debug log level based on the INI.
2992 *
2993 * Return: None
2994 */
2995static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2996 hdd_adapter_t *adapter)
2997{
2998 uint8_t count = 0, numentries = 0,
2999 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3000 uint32_t value = 0;
3001 int ret;
3002
Arun Khandavallifae92942016-08-01 13:31:08 +05303003 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3004 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303005 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
3006 return;
3007 }
3008
Arun Khandavallifae92942016-08-01 13:31:08 +05303009 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303010 hdd_ctx->fw_log_settings.dl_type =
3011 hdd_ctx->config->enableFwLogType;
3012 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303013 WMI_DBGLOG_TYPE,
3014 hdd_ctx->config->enableFwLogType,
3015 DBG_CMD);
3016 if (ret != 0)
3017 hdd_err("Failed to enable FW log type ret %d",
3018 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303019
3020 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303021 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303022 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303023 WMI_DBGLOG_LOG_LEVEL,
3024 hdd_ctx->config->enableFwLogLevel,
3025 DBG_CMD);
3026 if (ret != 0)
3027 hdd_err("Failed to enable FW log level ret %d",
3028 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303029
3030 hdd_string_to_u8_array(
3031 hdd_ctx->config->enableFwModuleLogLevel,
3032 moduleloglevel,
3033 &numentries,
3034 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3035
3036 while (count < numentries) {
3037 /*
3038 * FW module log level input string looks like
3039 * below:
3040 * gFwDebugModuleLoglevel=<FW Module ID>,
3041 * <Log Level>,...
3042 * For example:
3043 * gFwDebugModuleLoglevel=
3044 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3045 * Above input string means :
3046 * For FW module ID 1 enable log level 0
3047 * For FW module ID 2 enable log level 1
3048 * For FW module ID 3 enable log level 2
3049 * For FW module ID 4 enable log level 3
3050 * For FW module ID 5 enable log level 4
3051 * For FW module ID 6 enable log level 5
3052 * For FW module ID 7 enable log level 6
3053 */
3054
Arun Khandavallifae92942016-08-01 13:31:08 +05303055 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05303056 * Module ID * 10 + Module Log level
3057 */
3058 value = ((moduleloglevel[count] * 10) +
3059 moduleloglevel[count + 1]);
3060 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303061 WMI_DBGLOG_MOD_LOG_LEVEL,
3062 value, DBG_CMD);
3063 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303064 hdd_err("Failed to enable FW module log level %d ret %d",
3065 value, ret);
3066
3067 count += 2;
3068 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303069
Arun Khandavalli2358d522016-05-16 18:05:37 +05303070}
3071#else
3072static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3073 hdd_adapter_t *adapter)
3074{
3075}
3076
3077#endif
3078
3079/**
3080 * hdd_set_fw_params() - Set parameters to firmware
3081 * @adapter: HDD adapter
3082 *
3083 * This function Sets various parameters to fw once the
3084 * adapter is started.
3085 *
3086 * Return: 0 on success or errno on failure
3087 */
3088int hdd_set_fw_params(hdd_adapter_t *adapter)
3089{
3090 int ret;
3091 hdd_context_t *hdd_ctx;
3092
3093 ENTER_DEV(adapter->dev);
3094
3095 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3096 if (!hdd_ctx)
3097 return -EINVAL;
3098
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003099 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303100 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303101#define HDD_DTIM_1CHAIN_RX_ID 0x5
3102#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003103 /*
3104 * Disable DTIM 1 chain Rx when in 1x1,
3105 * we are passing two value
3106 * as param_id << 29 | param_value.
3107 * Below param_value = 0(disable)
3108 */
3109 ret = wma_cli_set_command(adapter->sessionId,
3110 WMI_STA_SMPS_PARAM_CMDID,
3111 HDD_DTIM_1CHAIN_RX_ID <<
3112 HDD_SMPS_PARAM_VALUE_S,
3113 VDEV_CMD);
3114 if (ret) {
3115 hdd_err("DTIM 1 chain set failed %d", ret);
3116 goto error;
3117 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303118
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003119 ret = wma_cli_set_command(adapter->sessionId,
3120 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3121 hdd_ctx->config->txchainmask1x1,
3122 PDEV_CMD);
3123 if (ret) {
3124 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3125 ret);
3126 goto error;
3127 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303128
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003129 ret = wma_cli_set_command(adapter->sessionId,
3130 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3131 hdd_ctx->config->rxchainmask1x1,
3132 PDEV_CMD);
3133 if (ret) {
3134 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3135 ret);
3136 goto error;
3137 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303138#undef HDD_DTIM_1CHAIN_RX_ID
3139#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003140 } else {
3141 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3142 }
3143
Arun Khandavallifae92942016-08-01 13:31:08 +05303144 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3145 ret = wma_cli_set_command(adapter->sessionId,
3146 WMI_PDEV_PARAM_HYST_EN,
3147 hdd_ctx->config->enableMemDeepSleep,
3148 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303149
Arun Khandavallifae92942016-08-01 13:31:08 +05303150 if (ret) {
3151 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3152 ret);
3153 goto error;
3154 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303155 }
3156
3157 hdd_set_fw_log_params(hdd_ctx, adapter);
3158
Rajeev Kumar Sirasanagandla0be56df2016-09-08 19:19:47 +05303159 ret = wma_cli_set_command(adapter->sessionId,
3160 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3161 hdd_ctx->config->rts_profile,
3162 VDEV_CMD);
3163 if (ret) {
3164 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3165 goto error;
3166 }
3167
Arun Khandavalli2358d522016-05-16 18:05:37 +05303168 EXIT();
3169 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303170
Arun Khandavalli2358d522016-05-16 18:05:37 +05303171error:
3172 return -EINVAL;
3173}
3174
Ryan Hsu07495ea2016-01-21 15:25:39 -08003175/**
3176 * hdd_open_adapter() - open and setup the hdd adatper
3177 * @hdd_ctx: global hdd context
3178 * @session_type: type of the interface to be created
3179 * @iface_name: User-visible name of the interface
3180 * @macAddr: MAC address to assign to the interface
3181 * @name_assign_type: the name of assign type of the netdev
3182 * @rtnl_held: the rtnl lock hold flag
3183 *
3184 * This function open and setup the hdd adpater according to the device
3185 * type request, assign the name, the mac address assigned, and then prepared
3186 * the hdd related parameters, queue, lock and ready to start.
3187 *
3188 * Return: the pointer of hdd adapter, otherwise NULL.
3189 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3191 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003192 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003193 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194{
3195 hdd_adapter_t *adapter = NULL;
3196 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303197 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199
Arun Khandavallifae92942016-08-01 13:31:08 +05303200 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201
3202 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3203 /*
3204 * Max limit reached on the number of vdevs configured by the
3205 * host. Return error
3206 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303207 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3208 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209 return NULL;
3210 }
3211
3212 if (macAddr == NULL) {
3213 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303214 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 return NULL;
3216 }
3217 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303218 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303219 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3220 " already exists",
3221 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 return NULL;
3223 }
3224
3225 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003226 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227 /* Reset locally administered bit if the device mode is STA */
3228 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3229 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003230 case QDF_P2P_CLIENT_MODE:
3231 case QDF_P2P_DEVICE_MODE:
3232 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003233 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303234 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003235 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3236 name_assign_type,
3237 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238
3239 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303240 hdd_err("failed to allocate adapter for session %d",
3241 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242 return NULL;
3243 }
3244
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003245 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003247 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303249 else if (QDF_MONITOR_MODE == session_type)
3250 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251 else
3252 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3253
3254 adapter->device_mode = session_type;
3255
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303256 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003257 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303258 if (QDF_STATUS_SUCCESS != status)
3259 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303260 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003262 /*
3263 * Workqueue which gets scheduled in IPv4 notification
3264 * callback
3265 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3267 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003268
3269#ifdef WLAN_NS_OFFLOAD
3270 /*
3271 * Workqueue which gets scheduled in IPv6
3272 * notification callback.
3273 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3275 hdd_ipv6_notifier_work_queue);
3276#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303278 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3280 goto err_lro_cleanup;
3281 }
3282
3283 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303284 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303286 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3287 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303289
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003291 case QDF_P2P_GO_MODE:
3292 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003293 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3294 name_assign_type,
3295 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003296 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303297 hdd_alert("failed to allocate adapter for session %d",
3298 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 return NULL;
3300 }
3301
3302 adapter->wdev.iftype =
3303 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003304 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305 NL80211_IFTYPE_P2P_GO;
3306 adapter->device_mode = session_type;
3307
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303309 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3311 goto err_free_netdev;
3312 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303313 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303315 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3316 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303318 case QDF_FTM_MODE:
3319 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3320 name_assign_type,
3321 "wlan0");
3322 if (NULL == adapter) {
3323 hdd_err("Failed to allocate adapter for FTM mode");
3324 return NULL;
3325 }
3326 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3327 adapter->device_mode = session_type;
3328 status = hdd_register_interface(adapter, rtnl_held);
3329 if (QDF_STATUS_SUCCESS != status) {
3330 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3331 goto err_free_netdev;
3332 }
3333 /* Stop the Interface TX queue. */
3334 hdd_info("Disabling queues");
3335 wlan_hdd_netif_queue_control(adapter,
3336 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3337 WLAN_CONTROL_PATH);
3338 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303340 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303341 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342 return NULL;
3343 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344
3345 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3346 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3347
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303348 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349 /* Add it to the hdd's session list. */
3350 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303351 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303353 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 } else {
3355 pHddAdapterNode->pAdapter = adapter;
3356 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3357 }
3358 }
3359
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303360 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003361 if (NULL != adapter) {
3362 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3363 adapter = NULL;
3364 }
3365 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303366 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367 }
3368 return NULL;
3369 }
3370
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003372 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373
3374 /* Initialize the WoWL service */
3375 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003376 hdd_alert("hdd_init_wowl failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 goto err_lro_cleanup;
3378 }
3379
3380 /* Adapter successfully added. Increment the vdev count */
3381 hdd_ctx->current_intf_count++;
3382
Jeff Johnson5880d792016-08-15 13:32:30 -07003383 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003384 hdd_ctx->current_intf_count);
3385
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003386 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387 }
3388
Rajeev Kumardca5f812016-02-04 17:28:06 -08003389 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3390 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391
3392 return adapter;
3393
3394err_lro_cleanup:
3395 hdd_lro_disable(hdd_ctx, adapter);
3396err_free_netdev:
3397 free_netdev(adapter->dev);
3398 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
3399
3400 return NULL;
3401}
3402
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303403QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003404 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003405{
3406 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303407 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003408
3409 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303410 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003411 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003412 status);
3413 return status;
3414 }
3415
3416 while (pCurrent->pAdapter != adapter) {
3417 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303418 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 break;
3420
3421 pCurrent = pNext;
3422 }
3423 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303424 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003425 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003426 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3427
3428 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303429 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 adapterNode = NULL;
3431
3432 /* Adapter removed. Decrement vdev count */
3433 if (hdd_ctx->current_intf_count != 0)
3434 hdd_ctx->current_intf_count--;
3435
3436 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303437 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303439
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303440 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003441}
3442
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003443/**
3444 * hdd_close_all_adapters - Close all open adapters
3445 * @hdd_ctx: Hdd context
3446 * rtnl_held: True if RTNL lock held
3447 *
3448 * Close all open adapters.
3449 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303450 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003451 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303452QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003453{
3454 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303455 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456
3457 ENTER();
3458
3459 do {
3460 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303461 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303462 wlan_hdd_release_intf_addr(hdd_ctx,
3463 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003464 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003465 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303466 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303467 /* Adapter removed. Decrement vdev count */
3468 if (hdd_ctx->current_intf_count != 0)
3469 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303471 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472
3473 EXIT();
3474
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303475 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476}
3477
3478void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3479{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303480 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 tSirUpdateIE updateIE;
3482 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003483 case QDF_STA_MODE:
3484 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485 {
3486 hdd_station_ctx_t *pHddStaCtx =
3487 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003488 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 break;
3490 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003491 case QDF_SAP_MODE:
3492 case QDF_P2P_GO_MODE:
3493 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003494 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003495 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003496 break;
3497 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003498 case QDF_FTM_MODE:
3499 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 default:
3501 /*
3502 * wlan_hdd_reset_prob_rspies should not have been called
3503 * for these kind of devices
3504 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003505 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506 pHostapdAdapter->device_mode);
3507 return;
3508 }
3509
Anurag Chouhanc5548422016-02-24 18:33:27 +05303510 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3512 updateIE.ieBufferlength = 0;
3513 updateIE.pAdditionIEBuffer = NULL;
3514 updateIE.append = true;
3515 updateIE.notify = false;
3516 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3517 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303518 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003519 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 }
3521}
3522
Peng Xu66162de2016-02-11 17:01:20 -08003523/**
3524 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3525 * @hdd_ctx: HDD context which is already NULL validated
3526 * @adapter: HDD adapter which is already NULL validated
3527 *
3528 * Close the SME session and wait for its completion, if needed.
3529 *
3530 * Return: None
3531 */
3532static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3533 hdd_adapter_t *adapter)
3534{
3535 unsigned long rc;
3536
3537 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3538 hdd_err("session is not opened:%d", adapter->sessionId);
3539 return;
3540 }
3541
3542 INIT_COMPLETION(adapter->session_close_comp_var);
3543 if (QDF_STATUS_SUCCESS ==
3544 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3545 hdd_sme_close_session_callback,
3546 adapter)) {
3547 /*
3548 * Block on a completion variable. Can't wait
3549 * forever though.
3550 */
3551 rc = wait_for_completion_timeout(
3552 &adapter->session_close_comp_var,
3553 msecs_to_jiffies
3554 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003555 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003556 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003557 if (adapter->device_mode == QDF_NDI_MODE)
3558 hdd_ndp_session_end_handler(adapter);
3559 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303560 return;
Sandeep Puligillaada72922016-09-29 19:31:21 -07003561 }
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303562 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003563 }
3564}
3565
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303566QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003567 const bool bCloseSession)
3568{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303569 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3571 union iwreq_data wrqu;
3572 tSirUpdateIE updateIE;
3573 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303574 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003575
3576 ENTER();
3577
Sachin Ahuja988fd102016-09-15 17:16:25 +05303578 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003579 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3581 WLAN_CONTROL_PATH);
3582 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003583 case QDF_STA_MODE:
3584 case QDF_P2P_CLIENT_MODE:
3585 case QDF_IBSS_MODE:
3586 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003587 case QDF_NDI_MODE:
3588 if ((QDF_NDI_MODE == adapter->device_mode) ||
3589 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3591 hdd_is_connecting(
3592 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003593 INIT_COMPLETION(adapter->disconnect_comp_var);
3594 /*
3595 * For NDI do not use pWextState from sta_ctx, if needed
3596 * extract from ndi_ctx.
3597 */
3598 if (QDF_NDI_MODE == adapter->device_mode)
3599 qdf_ret_status = sme_roam_disconnect(
3600 hdd_ctx->hHal,
3601 adapter->sessionId,
3602 eCSR_DISCONNECT_REASON_NDI_DELETE);
3603 else if (pWextState->roamProfile.BSSType ==
3604 eCSR_BSS_TYPE_START_IBSS)
3605 qdf_ret_status = sme_roam_disconnect(
3606 hdd_ctx->hHal,
3607 adapter->sessionId,
3608 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003610 qdf_ret_status = sme_roam_disconnect(
3611 hdd_ctx->hHal,
3612 adapter->sessionId,
3613 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003614 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303615 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 rc = wait_for_completion_timeout(
3617 &adapter->disconnect_comp_var,
3618 msecs_to_jiffies
3619 (WLAN_WAIT_TIME_DISCONNECT));
3620 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003621 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622 }
3623 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003624 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 }
3626 memset(&wrqu, '\0', sizeof(wrqu));
3627 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3628 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3629 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3630 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303631 }
3632 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303633 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303635 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303636 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637
3638#ifdef WLAN_OPEN_SOURCE
3639 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3640#endif
3641
3642 hdd_deregister_tx_flow_control(adapter);
3643
3644#ifdef WLAN_NS_OFFLOAD
3645#ifdef WLAN_OPEN_SOURCE
3646 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3647#endif
3648#endif
3649
3650 /*
3651 * It is possible that the caller of this function does not
3652 * wish to close the session
3653 */
Peng Xu66162de2016-02-11 17:01:20 -08003654 if (true == bCloseSession)
3655 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 break;
3657
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003658 case QDF_SAP_MODE:
3659 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003660 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003661 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 /*
3663 * Before stopping the sap adapter, lets make sure there
3664 * is no sap restart work pending.
3665 */
3666 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003667 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003668 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669 }
3670 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003671 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3673
3674 hdd_deregister_tx_flow_control(adapter);
3675
3676 mutex_lock(&hdd_ctx->sap_lock);
3677 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303678 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303679 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680
3681 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682 status = wlansap_stop_bss(
3683 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003684
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303685 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 hdd_hostapd_state_t *hostapd_state =
3687 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303688 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303689 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303690 qdf_status =
3691 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303692 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003693 BSS_WAIT_TIMEOUT);
3694
Anurag Chouhance0dc992016-02-16 18:18:03 +05303695 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003696 hdd_err("failure waiting for wlansap_stop_bss %d",
3697 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 }
3699 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003700 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 }
3702 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003703 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704 adapter->device_mode,
3705 adapter->sessionId);
3706
Anurag Chouhanc5548422016-02-24 18:33:27 +05303707 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003708 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 updateIE.smeSessionId = adapter->sessionId;
3710 updateIE.ieBufferlength = 0;
3711 updateIE.pAdditionIEBuffer = NULL;
3712 updateIE.append = false;
3713 updateIE.notify = false;
3714 /* Probe bcn reset */
3715 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3716 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303717 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003718 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003719 }
3720 /* Assoc resp reset */
3721 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3722 &updateIE,
3723 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303724 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003725 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 }
3727 /* Reset WNI_CFG_PROBE_RSP Flags */
3728 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303729 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 adapter->sessionCtx.ap.beacon = NULL;
3731 }
3732 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003733 if (true == bCloseSession)
3734 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003736 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3738 conn_info.staId[0]);
3739 break;
3740 default:
3741 break;
3742 }
3743
3744 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303745 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003746}
3747
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05303748/**
3749 * hdd_deinit_all_adapters - deinit all adapters
3750 * @hdd_ctx: HDD context
3751 * @rtnl_held: True if RTNL lock held
3752 *
3753 */
3754void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
3755{
3756 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3757 QDF_STATUS status;
3758 hdd_adapter_t *adapter;
3759
3760 ENTER();
3761
3762 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
3763
3764 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
3765 adapter = adapter_node->pAdapter;
3766 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3767 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
3768 adapter_node = next;
3769 }
3770
3771 EXIT();
3772}
3773
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303774QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775{
3776 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303777 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 hdd_adapter_t *adapter;
3779
3780 ENTER();
3781
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303782 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3783
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003784 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3785
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303786 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 adapter = adapterNode->pAdapter;
3788 hdd_stop_adapter(hdd_ctx, adapter, true);
3789 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3790 adapterNode = pNext;
3791 }
3792
3793 EXIT();
3794
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303795 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796}
3797
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303798QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003799{
3800 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303801 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003802 hdd_adapter_t *adapter;
3803
3804 ENTER();
3805
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303806 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3809
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303810 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003812 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 wlan_hdd_netif_queue_control(adapter,
3814 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3815 WLAN_CONTROL_PATH);
3816
3817 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3818
3819 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003820 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821 adapter->sessionId);
3822 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3823 hdd_wmm_adapter_close(adapter);
3824 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3825 }
3826
3827 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3828 adapterNode = pNext;
3829 }
3830
3831 EXIT();
3832
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303833 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834}
3835
Arun Khandavallifae92942016-08-01 13:31:08 +05303836/**
3837 * hdd_is_interface_up()- Checkfor interface up before ssr
3838 * @hdd_ctx: HDD context
3839 *
3840 * check if there are any wlan interfaces before SSR accordingly start
3841 * the interface.
3842 *
3843 * Return: 0 if interface was opened else false
3844 */
3845static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3846{
3847 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3848 return true;
3849 else
3850 return false;
3851}
3852
Anurag Chouhanc4092922016-09-08 15:56:11 +05303853#if defined CFG80211_CONNECT_BSS
3854#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
3855 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
Jeff Johnson590e2012016-10-05 16:16:24 -07003856static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303857struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3858 struct ieee80211_channel *channel,
3859 const u8 *bssid, const u8 *ssid,
3860 size_t ssid_len)
3861{
3862 return cfg80211_get_bss(wiphy, channel, bssid,
3863 ssid, ssid_len,
3864 WLAN_CAPABILITY_ESS,
3865 WLAN_CAPABILITY_ESS);
3866}
3867#else
Jeff Johnson590e2012016-10-05 16:16:24 -07003868static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303869struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3870 struct ieee80211_channel *channel,
3871 const u8 *bssid, const u8 *ssid,
3872 size_t ssid_len)
3873{
3874 return cfg80211_get_bss(wiphy, channel, bssid,
3875 ssid, ssid_len,
3876 IEEE80211_BSS_TYPE_ESS,
3877 IEEE80211_PRIVACY_ANY);
3878}
3879#endif
3880#endif
3881
Abhishek Singha84d3952016-09-13 13:45:05 +05303882#if defined CFG80211_CONNECT_BSS
3883/**
3884 * hdd_connect_bss() - API to send connection status to supplicant
3885 * @dev: network device
3886 * @bssid: bssid to which we want to associate
3887 * @req_ie: Request Information Element
3888 * @req_ie_len: len of the req IE
3889 * @resp_ie: Response IE
3890 * @resp_ie_len: len of ht response IE
3891 * @status: status
3892 * @gfp: Kernel Flag
3893 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
3894 *
3895 * The API is a wrapper to send connection status to supplicant
3896 *
3897 * Return: Void
3898 */
3899#if defined CFG80211_CONNECT_TIMEOUT
3900static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3901 struct cfg80211_bss *bss, const u8 *req_ie,
3902 size_t req_ie_len, const u8 *resp_ie,
3903 size_t resp_ie_len, int status, gfp_t gfp,
3904 bool connect_timeout)
3905{
3906 if (connect_timeout)
3907 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
3908 else
3909 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3910 resp_ie, resp_ie_len, status, gfp);
3911}
3912#else
3913static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3914 struct cfg80211_bss *bss, const u8 *req_ie,
3915 size_t req_ie_len, const u8 *resp_ie,
3916 size_t resp_ie_len, int status, gfp_t gfp,
3917 bool connect_timeout)
3918{
3919 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3920 resp_ie, resp_ie_len, status, gfp);
3921}
3922#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303923
3924/**
3925 * hdd_connect_result() - API to send connection status to supplicant
3926 * @dev: network device
3927 * @bssid: bssid to which we want to associate
3928 * @roam_info: information about connected bss
3929 * @req_ie: Request Information Element
3930 * @req_ie_len: len of the req IE
3931 * @resp_ie: Response IE
3932 * @resp_ie_len: len of ht response IE
3933 * @status: status
3934 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05303935 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
Anurag Chouhanc4092922016-09-08 15:56:11 +05303936 *
3937 * The API is a wrapper to send connection status to supplicant
3938 * and allow runtime suspend
3939 *
3940 * Return: Void
3941 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303942void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3943 tCsrRoamInfo *roam_info, const u8 *req_ie,
3944 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303945 size_t resp_ie_len, u16 status, gfp_t gfp,
3946 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303947{
3948 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3949 struct cfg80211_bss *bss = NULL;
3950
3951 if (WLAN_STATUS_SUCCESS == status) {
3952 struct ieee80211_channel *chan;
3953 int freq;
3954 int chan_no = roam_info->pBssDesc->channelId;
3955
3956 if (chan_no <= 14)
3957 freq = ieee80211_channel_to_frequency(chan_no,
3958 IEEE80211_BAND_2GHZ);
3959 else
3960 freq = ieee80211_channel_to_frequency(chan_no,
3961 IEEE80211_BAND_5GHZ);
3962
3963 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
3964 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
3965 roam_info->u.pConnectedProfile->SSID.ssId,
3966 roam_info->u.pConnectedProfile->SSID.length);
3967 }
Komal Seelama89be8d2016-09-29 11:09:26 +05303968
Abhishek Singha84d3952016-09-13 13:45:05 +05303969 hdd_connect_bss(dev, bssid, bss, req_ie,
3970 req_ie_len, resp_ie, resp_ie_len,
3971 status, gfp, connect_timeout);
Komal Seelama89be8d2016-09-29 11:09:26 +05303972
3973 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303974}
3975#else
3976void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3977 tCsrRoamInfo *roam_info, const u8 *req_ie,
3978 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303979 size_t resp_ie_len, u16 status, gfp_t gfp,
3980 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303981{
Komal Seelama89be8d2016-09-29 11:09:26 +05303982 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3983
Anurag Chouhanc4092922016-09-08 15:56:11 +05303984 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
3985 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05303986 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303987}
3988#endif
3989
3990
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303991QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992{
3993 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303994 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 hdd_adapter_t *adapter;
3996#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303997 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998#endif
3999 eConnectionState connState;
4000
4001 ENTER();
4002
4003 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304004 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005 adapter = adapterNode->pAdapter;
4006
Arun Khandavallifae92942016-08-01 13:31:08 +05304007 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304008 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010 hdd_wmm_init(adapter);
4011
4012 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004013 case QDF_STA_MODE:
4014 case QDF_P2P_CLIENT_MODE:
4015 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004016
4017 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4018 ->conn_info.connState;
4019
4020 hdd_init_station_mode(adapter);
4021 /* Open the gates for HDD to receive Wext commands */
4022 adapter->isLinkUpSvcNeeded = false;
4023 adapter->scan_info.mScanPending = false;
4024
4025 /* Indicate disconnect event to supplicant if associated previously */
4026 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004027 eConnectionState_IbssConnected == connState ||
4028 eConnectionState_NotConnected == connState ||
4029 eConnectionState_IbssDisconnected == connState ||
4030 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 union iwreq_data wrqu;
4032 memset(&wrqu, '\0', sizeof(wrqu));
4033 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4034 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4035 wireless_send_event(adapter->dev, SIOCGIWAP,
4036 &wrqu, NULL);
4037 adapter->sessionCtx.station.
4038 hdd_ReassocScenario = false;
4039
4040 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304041 wlan_hdd_cfg80211_indicate_disconnect(
4042 adapter->dev, false,
4043 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004044 } else if (eConnectionState_Connecting == connState) {
4045 /*
4046 * Indicate connect failure to supplicant if we were in the
4047 * process of connecting
4048 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304049 hdd_connect_result(adapter->dev, NULL, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004050 NULL, 0, NULL, 0,
4051 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Abhishek Singha84d3952016-09-13 13:45:05 +05304052 GFP_KERNEL, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053 }
4054
4055 hdd_register_tx_flow_control(adapter,
4056 hdd_tx_resume_timer_expired_handler,
4057 hdd_tx_resume_cb);
4058
4059 break;
4060
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004061 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062 /* softAP can handle SSR */
4063 break;
4064
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004065 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07004067 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004068 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4069#else
Jeff Johnson5880d792016-08-15 13:32:30 -07004070 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071 /* event supplicant to restart */
4072 cfg80211_del_sta(adapter->dev,
4073 (const u8 *)&bcastMac.bytes[0],
4074 GFP_KERNEL);
4075#endif
4076 break;
4077
4078 default:
4079 break;
4080 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304081get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4083 adapterNode = pNext;
4084 }
4085
4086 EXIT();
4087
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304088 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004089}
4090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304091QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 hdd_adapter_list_node_t **padapterNode)
4093{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304094 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004095 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304096 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4097 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004098 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004099 return status;
4100}
4101
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304102QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004103 hdd_adapter_list_node_t *adapterNode,
4104 hdd_adapter_list_node_t **pNextAdapterNode)
4105{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304106 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004107 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304108 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4109 (qdf_list_node_t *) adapterNode,
4110 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004112 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113 return status;
4114}
4115
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304116QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004117 hdd_adapter_list_node_t *adapterNode)
4118{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304119 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004120 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304121 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004123 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 return status;
4125}
4126
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304127QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128 hdd_adapter_list_node_t **padapterNode)
4129{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304130 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004131 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304132 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4133 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004134 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 return status;
4136}
4137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304138QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 hdd_adapter_list_node_t *adapterNode)
4140{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304141 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004142 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304143 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4144 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004145 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146 return status;
4147}
4148
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304149QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 hdd_adapter_list_node_t *adapterNode)
4151{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304152 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004153 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304154 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4155 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004156 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 return status;
4158}
4159
4160hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4161 tSirMacAddr macAddr)
4162{
4163 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4164 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304165 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004166
4167 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4168
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304169 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 adapter = adapterNode->pAdapter;
4171
4172 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304173 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174 macAddr, sizeof(tSirMacAddr))) {
4175 return adapter;
4176 }
4177 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4178 adapterNode = pNext;
4179 }
4180
4181 return NULL;
4182
4183}
4184
4185hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4186 uint32_t vdev_id)
4187{
4188 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4189 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304190 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304192 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004193
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304194 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195 adapter = adapterNode->pAdapter;
4196
4197 if (adapter->sessionId == vdev_id)
4198 return adapter;
4199
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304200 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004201 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4202 adapterNode = pNext;
4203 }
4204
Jeff Johnson5880d792016-08-15 13:32:30 -07004205 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004206
4207 return NULL;
4208}
4209
Abhishek Singh7996eb72015-12-30 17:24:02 +05304210/**
4211 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4212 * the sessionid
4213 * @hdd_ctx: hdd context.
4214 * @sme_session_id: sme session is for the adapter to get.
4215 *
4216 * This function is used to get the adapter with provided session id
4217 *
4218 * Return: adapter pointer if found
4219 *
4220 */
4221hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4222 uint32_t sme_session_id)
4223{
4224 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4225 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304226 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304227
4228
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304229 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304230
4231 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304232 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304233 adapter = adapter_node->pAdapter;
4234
4235 if (adapter &&
4236 adapter->sessionId == sme_session_id)
4237 return adapter;
4238
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304239 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304240 hdd_get_next_adapter(hdd_ctx,
4241 adapter_node, &next);
4242 adapter_node = next;
4243 }
4244 return NULL;
4245}
4246
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004247/**
4248 * hdd_get_adapter() - to get adapter matching the mode
4249 * @hdd_ctx: hdd context
4250 * @mode: adapter mode
4251 *
4252 * This routine will return the pointer to adapter matching
4253 * with the passed mode.
4254 *
4255 * Return: pointer to adapter or null
4256 */
4257hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4258 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259{
4260 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4261 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304262 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263
4264 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4265
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304266 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 adapter = adapterNode->pAdapter;
4268
4269 if (adapter && (mode == adapter->device_mode))
4270 return adapter;
4271
4272 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4273 adapterNode = pNext;
4274 }
4275
4276 return NULL;
4277
4278}
4279
4280/**
4281 * hdd_get_operating_channel() - return operating channel of the device mode
4282 * @hdd_ctx: Pointer to the HDD context.
4283 * @mode: Device mode for which operating channel is required.
4284 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004285 * QDF_STA_MODE,
4286 * QDF_P2P_CLIENT_MODE,
4287 * QDF_SAP_MODE,
4288 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289 *
4290 * This API returns the operating channel of the requested device mode
4291 *
4292 * Return: channel number. "0" id the requested device is not found OR it is
4293 * not connected.
4294 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004295uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4296 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297{
4298 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304299 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004300 hdd_adapter_t *adapter;
4301 uint8_t operatingChannel = 0;
4302
4303 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4304
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304305 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004306 adapter = adapterNode->pAdapter;
4307
4308 if (mode == adapter->device_mode) {
4309 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004310 case QDF_STA_MODE:
4311 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 if (hdd_conn_is_connected
4313 (WLAN_HDD_GET_STATION_CTX_PTR
4314 (adapter))) {
4315 operatingChannel =
4316 (WLAN_HDD_GET_STATION_CTX_PTR
4317 (adapter))->conn_info.
4318 operationChannel;
4319 }
4320 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004321 case QDF_SAP_MODE:
4322 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323 /* softap connection info */
4324 if (test_bit
4325 (SOFTAP_BSS_STARTED,
4326 &adapter->event_flags))
4327 operatingChannel =
4328 (WLAN_HDD_GET_AP_CTX_PTR
4329 (adapter))->operatingChannel;
4330 break;
4331 default:
4332 break;
4333 }
4334
4335 break; /* Found the device of interest. break the loop */
4336 }
4337
4338 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4339 adapterNode = pNext;
4340 }
4341 return operatingChannel;
4342}
4343
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304344static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 hdd_ctx)
4346{
4347 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304348 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 hdd_adapter_t *adapter;
4350
4351 ENTER();
4352
4353 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4354
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304355 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004357 if ((adapter->device_mode == QDF_STA_MODE) ||
4358 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4359 (adapter->device_mode == QDF_IBSS_MODE) ||
4360 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4361 (adapter->device_mode == QDF_SAP_MODE) ||
4362 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363 wlan_hdd_cfg80211_deregister_frames(adapter);
4364 hdd_unregister_wext(adapter->dev);
4365 }
4366 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4367 adapterNode = pNext;
4368 }
4369
4370 EXIT();
4371
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304372 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373}
4374
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304375QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376{
4377 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304378 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 hdd_adapter_t *adapter;
4380
4381 ENTER();
4382
4383 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4384
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304385 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004387 if ((adapter->device_mode == QDF_STA_MODE) ||
4388 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4389 (adapter->device_mode == QDF_IBSS_MODE) ||
4390 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4391 (adapter->device_mode == QDF_SAP_MODE) ||
4392 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4394 eCSR_SCAN_ABORT_DEFAULT);
4395 }
4396 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4397 adapterNode = pNext;
4398 }
4399
4400 EXIT();
4401
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304402 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403}
4404
4405#ifdef WLAN_NS_OFFLOAD
4406/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004407 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 * @hdd_ctx: Pointer to hdd context
4409 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004410 * Unregister for IPv6 address change notifications.
4411 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004412 * Return: None
4413 */
4414static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4415{
4416 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4417
4418 return;
4419}
4420
4421/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004422 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423 * @hdd_ctx: Pointer to hdd context
4424 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004425 * Register for IPv6 address change notifications.
4426 *
4427 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004429static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430{
4431 int ret;
4432
4433 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4434 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004435 if (ret) {
4436 hdd_err("Failed to register IPv6 notifier: %d", ret);
4437 goto out;
4438 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004440 hdd_info("Registered IPv6 notifier");
4441out:
4442 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443}
4444#else
4445/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004446 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 * @hdd_ctx: Pointer to hdd context
4448 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004449 * Unregister for IPv6 address change notifications.
4450 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451 * Return: None
4452 */
4453static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4454{
4455}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004458 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459 * @hdd_ctx: Pointer to hdd context
4460 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004461 * Register for IPv6 address change notifications.
4462 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 * Return: None
4464 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004465static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004466{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004467 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004468}
4469#endif
4470
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304471#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4472/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004473 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304474 * @hdd_ctx: HDD context
4475 *
4476 * Activates the logging service
4477 *
4478 * Return: Zero in case of success, negative value otherwise
4479 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004480static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304481{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004482 int ret;
4483 struct hdd_config *config = hdd_ctx->config;
4484
4485 if (!config->wlanLoggingEnable)
4486 return 0;
4487
4488 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4489 config->wlanLoggingNumBuf);
4490 if (ret)
4491 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4492 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304493}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004494
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304495/**
4496 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4497 * @hdd_ctx: HDD context
4498 *
4499 * Deactivates the logging service
4500 *
4501 * Return: 0 on deactivating the logging service
4502 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004503static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304504{
4505 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4506 return wlan_logging_sock_deactivate_svc();
4507
4508 return 0;
4509}
4510#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004511static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304512{
4513 return 0;
4514}
4515
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004516static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304517{
4518 return 0;
4519}
4520#endif
4521
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004523 * hdd_register_notifiers - Register netdev notifiers.
4524 * @hdd_ctx: HDD context
4525 *
4526 * Register netdev notifiers like IPv4 and IPv6.
4527 *
4528 * Return: 0 on success and errno on failure
4529 */
4530static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4531{
4532 int ret;
4533
4534 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4535 if (ret) {
4536 hdd_err("register_netdevice_notifier failed: %d", ret);
4537 goto out;
4538 }
4539
4540 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4541 if (ret)
4542 goto unregister_notifier;
4543
4544 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4545 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4546 if (ret) {
4547 hdd_err("Failed to register IPv4 notifier: %d", ret);
4548 goto unregister_ip6_notifier;
4549 }
4550
4551 return 0;
4552
4553unregister_ip6_notifier:
4554 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4555unregister_notifier:
4556 unregister_netdevice_notifier(&hdd_netdev_notifier);
4557out:
4558 return ret;
4559
4560}
4561
4562/**
4563 * hdd_unregister_notifiers - Unregister netdev notifiers.
4564 * @hdd_ctx: HDD context
4565 *
4566 * Unregister netdev notifiers like IPv4 and IPv6.
4567 *
4568 * Return: None.
4569 */
4570static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4571{
4572 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4573
4574 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4575
4576 unregister_netdevice_notifier(&hdd_netdev_notifier);
4577}
4578
4579/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004580 * hdd_exit_netlink_services - Exit netlink services
4581 * @hdd_ctx: HDD context
4582 *
4583 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4584 * nl service.
4585 *
4586 * Return: None.
4587 */
4588static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4589{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004590 hdd_close_cesium_nl_sock();
4591
4592 ptt_sock_deactivate_svc();
4593
4594 nl_srv_exit();
4595}
4596
4597/**
4598 * hdd_init_netlink_services- Init netlink services
4599 * @hdd_ctx: HDD context
4600 *
4601 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4602 * nl service.
4603 *
4604 * Return: 0 on success and errno on failure.
4605 */
4606static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4607{
4608 int ret;
4609
Ryan Hsuceddceb2016-04-28 10:20:14 -07004610 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004611 if (ret) {
4612 hdd_alert("nl_srv_init failed: %d", ret);
4613 goto out;
4614 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004615 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004616
4617 ret = oem_activate_service(hdd_ctx);
4618 if (ret) {
4619 hdd_alert("oem_activate_service failed: %d", ret);
4620 goto err_nl_srv;
4621 }
4622
4623 ret = ptt_sock_activate_svc();
4624 if (ret) {
4625 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4626 goto err_nl_srv;
4627 }
4628
4629 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004630 if (ret)
4631 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004632
4633 ret = cnss_diag_activate_service();
4634 if (ret) {
4635 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4636 goto err_close_cesium;
4637 }
4638
4639 return 0;
4640
4641err_close_cesium:
4642 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004643 ptt_sock_deactivate_svc();
4644err_nl_srv:
4645 nl_srv_exit();
4646out:
4647 return ret;
4648}
4649
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004650#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4651/**
4652 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4653 * @hdd_ctx: HDD context.
4654 *
4655 * Destroy RX wakelock.
4656 *
4657 * Return: None.
4658 */
4659static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4660{
4661 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4662}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004663
4664/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004665 * hdd_rx_wake_lock_create() - Create RX wakelock
4666 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004667 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004668 * Create RX wakelock.
4669 *
4670 * Return: None.
4671 */
4672static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4673{
4674 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4675}
4676#else
4677static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { }
4678static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { }
4679#endif
4680
4681/**
4682 * hdd_roc_context_init() - Init ROC context
4683 * @hdd_ctx: HDD context.
4684 *
4685 * Initialize ROC context.
4686 *
4687 * Return: 0 on success and errno on failure.
4688 */
4689static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4690{
4691 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4692 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4693
4694 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4695
4696 return 0;
4697}
4698
4699/**
4700 * hdd_roc_context_destroy() - Destroy ROC context
4701 * @hdd_ctx: HDD context.
4702 *
4703 * Destroy roc list and flush the pending roc work.
4704 *
4705 * Return: None.
4706 */
4707static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4708{
4709 flush_delayed_work(&hdd_ctx->roc_req_work);
4710 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4711}
4712
4713/**
4714 * hdd_context_destroy() - Destroy HDD context
4715 * @hdd_ctx: HDD context to be destroyed.
4716 *
4717 * Free config and HDD context as well as destroy all the resources.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004718 *
4719 * Return: None
4720 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004721static void hdd_context_destroy(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004722{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304723 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004724 hdd_logging_sock_deactivate_svc(hdd_ctx);
4725
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004726 hdd_roc_context_destroy(hdd_ctx);
4727
4728 hdd_sap_context_destroy(hdd_ctx);
4729
4730 hdd_rx_wake_lock_destroy(hdd_ctx);
4731
4732 hdd_tdls_context_destroy(hdd_ctx);
4733
4734 hdd_scan_context_destroy(hdd_ctx);
4735
4736 qdf_list_destroy(&hdd_ctx->hddAdapters);
4737
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304738 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004739 hdd_ctx->config = NULL;
4740
4741 wiphy_free(hdd_ctx->wiphy);
4742}
4743
4744/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004745 * hdd_wlan_exit() - HDD WLAN exit function
4746 * @hdd_ctx: Pointer to the HDD Context
4747 *
4748 * This is the driver exit point (invoked during rmmod)
4749 *
4750 * Return: None
4751 */
Jeff Johnson590e2012016-10-05 16:16:24 -07004752static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753{
4754 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304755 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004756 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304757 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758
4759 ENTER();
4760
Arun Khandavallifae92942016-08-01 13:31:08 +05304761 if (QDF_TIMER_STATE_RUNNING ==
4762 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4763 hdd_info("Stpp interface change timer");
4764 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004765 }
4766
Arun Khandavallifae92942016-08-01 13:31:08 +05304767 if (!QDF_IS_STATUS_SUCCESS
4768 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4769 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004770
Arun Khandavallifae92942016-08-01 13:31:08 +05304771
4772 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004773
Prashanth Bhattaab004382016-10-11 16:08:11 -07004774 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775
4776#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304777 if (QDF_TIMER_STATE_RUNNING ==
4778 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4779 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004780 }
4781
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304782 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304783 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004784 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004785 }
4786#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004787
Arun Khandavallifae92942016-08-01 13:31:08 +05304788 mutex_lock(&hdd_ctx->iface_change_lock);
4789 driver_status = hdd_ctx->driver_status;
4790 mutex_unlock(&hdd_ctx->iface_change_lock);
4791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792 /*
4793 * Powersave Offload Case
4794 * Disable Idle Power Save Mode
4795 */
4796 hdd_set_idle_ps_config(hdd_ctx, false);
4797
Arun Khandavallifae92942016-08-01 13:31:08 +05304798 if (driver_status != DRIVER_MODULES_CLOSED) {
4799 hdd_unregister_wext_all_adapters(hdd_ctx);
4800 /*
4801 * Cancel any outstanding scan requests. We are about to close
4802 * all of our adapters, but an adapter structure is what SME
4803 * passes back to our callback function. Hence if there
4804 * are any outstanding scan requests then there is a
4805 * race condition between when the adapter is closed and
4806 * when the callback is invoked. We try to resolve that
4807 * race condition here by canceling any outstanding scans
4808 * before we close the adapters.
4809 * Note that the scans may be cancelled in an asynchronous
4810 * manner, so ideally there needs to be some kind of
4811 * synchronization. Rather than introduce a new
4812 * synchronization here, we will utilize the fact that we are
4813 * about to Request Full Power, and since that is synchronized,
4814 * the expectation is that by the time Request Full Power has
4815 * completed, all scans will be cancelled
4816 */
4817 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4818 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 }
4820
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07004821 hdd_wlan_stop_modules(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004822 /*
4823 * Close the scheduler before calling cds_close to make sure no thread
4824 * is scheduled after the each module close is called i.e after all the
4825 * data structures are freed.
4826 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304827 qdf_status = cds_sched_close(p_cds_context);
4828 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004829 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304830 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304833 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4834 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4835 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 /*
4838 * Close CDS
4839 * This frees pMac(HAL) context. There should not be any call
4840 * that requires pMac access after this.
4841 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07004843 hdd_green_ap_deinit(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004844
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004845 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004846
4847 hdd_ipa_cleanup(hdd_ctx);
4848
4849 /* Free up RoC request queue and flush workqueue */
4850 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304852 wlansap_global_deinit();
Nirav Shahed34b212016-04-25 10:59:16 +05304853 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304855 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004856
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07004857 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004858
Arun Khandavallifae92942016-08-01 13:31:08 +05304859 hdd_exit_netlink_services(hdd_ctx);
4860 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004861 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862}
4863
4864void __hdd_wlan_exit(void)
4865{
4866 hdd_context_t *hdd_ctx;
4867
4868 ENTER();
4869
Anurag Chouhan6d760662016-02-20 16:05:43 +05304870 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004872 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 EXIT();
4874 return;
4875 }
4876
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004877 /* Check IPA HW Pipe shutdown */
4878 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4879
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004880 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05304881 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004882
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004883 /* Do all the cleanup before deregistering the driver */
4884 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886 EXIT();
4887}
4888
4889#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4890void hdd_skip_acs_scan_timer_handler(void *data)
4891{
4892 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4893
Jeff Johnson760350b2016-08-15 14:01:52 -07004894 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4896
4897 if (!hdd_ctx->hHal)
4898 return;
4899 sme_scan_flush_result(hdd_ctx->hHal);
4900}
4901#endif
4902
4903#ifdef QCA_HT_2040_COEX
4904/**
4905 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4906 * @adapter: pointer to adapter
4907 * @staId: station id
4908 * @macAddrSTA: station MAC address
4909 * @channel_type: channel type
4910 *
4911 * This function notifies FW with HT20/HT40 mode
4912 *
4913 * Return: 0 if successful, error number otherwise
4914 */
4915int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304916 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917{
4918 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304919 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920 hdd_context_t *hdd_ctx = NULL;
4921
4922 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4923
4924 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304925 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004926 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 if (!hdd_ctx->hHal)
4929 return -EINVAL;
4930
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304931 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304933 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004934 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 return -EINVAL;
4936 }
4937
4938 return 0;
4939}
4940#endif
4941
4942/**
4943 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4944 * @state: state
4945 *
4946 * This function notifies FW with modem power status
4947 *
4948 * Return: 0 if successful, error number otherwise
4949 */
4950int hdd_wlan_notify_modem_power_state(int state)
4951{
4952 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304953 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004954 hdd_context_t *hdd_ctx;
4955
Anurag Chouhan6d760662016-02-20 16:05:43 +05304956 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004957 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304958 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304960
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004961 if (!hdd_ctx->hHal)
4962 return -EINVAL;
4963
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304964 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4965 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004966 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004967 state);
4968 return -EINVAL;
4969 }
4970 return 0;
4971}
4972
4973/**
4974 *
4975 * hdd_post_cds_enable_config() - HDD post cds start config helper
4976 * @adapter - Pointer to the HDD
4977 *
4978 * Return: None
4979 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304980QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304982 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983
4984 /*
4985 * Send ready indication to the HDD. This will kick off the MAC
4986 * into a 'running' state and should kick off an initial scan.
4987 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304988 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4989 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004990 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
4991 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304992 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993 }
4994
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304995 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004996}
4997
4998/* wake lock APIs for HDD */
4999void hdd_prevent_suspend(uint32_t reason)
5000{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305001 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002}
5003
5004void hdd_allow_suspend(uint32_t reason)
5005{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305006 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007}
5008
5009void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5010{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305011 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5012 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013}
5014
5015/**
5016 * hdd_exchange_version_and_caps() - exchange version and capability with target
5017 * @hdd_ctx: Pointer to HDD context
5018 *
5019 * This is the HDD function to exchange version and capability information
5020 * between Host and Target
5021 *
5022 * This function gets reported version of FW.
5023 * It also finds the version of target headers used to compile the host;
5024 * It compares the above two and prints a warning if they are different;
5025 * It gets the SW and HW version string;
5026 * Finally, it exchanges capabilities between host and target i.e. host
5027 * and target exchange a msg indicating the features they support through a
5028 * bitmap
5029 *
5030 * Return: None
5031 */
5032void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5033{
5034
5035 tSirVersionType versionCompiled;
5036 tSirVersionType versionReported;
5037 tSirVersionString versionString;
5038 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305039 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005040
5041 memset(&versionCompiled, 0, sizeof(versionCompiled));
5042 memset(&versionReported, 0, sizeof(versionReported));
5043
5044 /* retrieve and display WCNSS version information */
5045 do {
5046
5047 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5048 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305049 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005050 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005051 break;
5052 }
5053
5054 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5055 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305056 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005057 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 break;
5059 }
5060
5061 if ((versionCompiled.major != versionReported.major) ||
5062 (versionCompiled.minor != versionReported.minor) ||
5063 (versionCompiled.version != versionReported.version) ||
5064 (versionCompiled.revision != versionReported.revision)) {
5065 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5066 "Host expected %u.%u.%u.%u\n",
5067 WLAN_MODULE_NAME,
5068 (int)versionReported.major,
5069 (int)versionReported.minor,
5070 (int)versionReported.version,
5071 (int)versionReported.revision,
5072 (int)versionCompiled.major,
5073 (int)versionCompiled.minor,
5074 (int)versionCompiled.version,
5075 (int)versionCompiled.revision);
5076 } else {
5077 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5078 WLAN_MODULE_NAME,
5079 (int)versionReported.major,
5080 (int)versionReported.minor,
5081 (int)versionReported.version,
5082 (int)versionReported.revision);
5083 }
5084
5085 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5086 versionString,
5087 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305088 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005089 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005090 break;
5091 }
5092
5093 pr_info("%s: WCNSS software version %s\n",
5094 WLAN_MODULE_NAME, versionString);
5095
5096 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5097 versionString,
5098 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305099 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005100 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005101 break;
5102 }
5103
5104 pr_info("%s: WCNSS hardware version %s\n",
5105 WLAN_MODULE_NAME, versionString);
5106
5107 /*
5108 * 1.Check if FW version is greater than 0.1.1.0. Only then
5109 * send host-FW capability exchange message
5110 * 2.Host-FW capability exchange message is only present on
5111 * target 1.1 so send the message only if it the target is 1.1
5112 * minor numbers for different target branches:
5113 * 0 -> (1.0)Mainline Build
5114 * 1 -> (1.1)Mainline Build
5115 * 2->(1.04) Stability Build
5116 */
5117 if (((versionReported.major > 0) || (versionReported.minor > 1)
5118 || ((versionReported.minor >= 1)
5119 && (versionReported.version >= 1)))
5120 && ((versionReported.major == 1)
5121 && (versionReported.minor >= 1)))
5122 fwFeatCapsMsgSupported = 1;
5123
5124 if (fwFeatCapsMsgSupported) {
5125 /*
5126 * Indicate if IBSS heartbeat monitoring needs to be
5127 * offloaded
5128 */
5129 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5130 sme_disable_feature_capablity
5131 (IBSS_HEARTBEAT_OFFLOAD);
5132 }
5133
5134 sme_feature_caps_exchange(hdd_ctx->hHal);
5135 }
5136
5137 } while (0);
5138
5139}
5140
5141/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305142QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143{
5144 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5145 hdd_ctx->reg.cc_src);
5146}
5147
5148/**
5149 * hdd_is_5g_supported() - check if hardware supports 5GHz
5150 * @hdd_ctx: Pointer to the hdd context
5151 *
5152 * HDD function to know if hardware supports 5GHz
5153 *
5154 * Return: true if hardware supports 5GHz
5155 */
5156bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5157{
5158 /*
5159 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5160 * then hardware support 5Ghz.
5161 */
5162 return true;
5163}
5164
Amar Singhale4f28ee2015-10-21 14:36:56 -07005165static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166{
5167 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005168 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005169
5170 wiphy = hdd_ctx->wiphy;
5171
5172 /*
5173 * The channel information in
5174 * wiphy needs to be initialized before wiphy registration
5175 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005176 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5177 if (ret_val) {
5178 hdd_alert("regulatory init failed");
5179 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005180 }
5181
5182#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5183 wiphy->wowlan = &wowlan_support_reg_init;
5184#else
5185 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5186 WIPHY_WOWLAN_MAGIC_PKT |
5187 WIPHY_WOWLAN_DISCONNECT |
5188 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5189 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5190 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5191 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5192 WIPHY_WOWLAN_RFKILL_RELEASE;
5193
5194 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5195 WOW_MAX_FILTERS_PER_LIST);
5196 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5197 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5198#endif
5199
5200 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005201 ret_val = wlan_hdd_cfg80211_register(wiphy);
5202 if (0 > ret_val)
5203 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005204
Amar Singhale4f28ee2015-10-21 14:36:56 -07005205 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206}
5207
Ravi Joshie2331e82015-07-01 18:18:54 -07005208/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005209 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005210 * @hdd_ctx - handle to hdd context
5211 * @tx_packets - transmit packet count
5212 * @rx_packets - receive packet count
5213 *
5214 * The function controls the bus bandwidth and dynamic control of
5215 * tcp delayed ack configuration
5216 *
5217 * Returns: None
5218 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005219#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005220static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5221 const uint64_t tx_packets,
5222 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005225 uint64_t temp_rx = 0;
5226 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005227 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005228 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5229 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005230 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005233 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005235 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005236 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005237 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005238 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005239 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005240
Mohit Khannae71e2262015-11-10 09:37:24 -08005241 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5242 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
5244 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005245 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5246 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005248 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305249 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305250 if (hdd_ctx->hbw_requested) {
5251 pld_remove_pm_qos(hdd_ctx->parent_dev);
5252 hdd_ctx->hbw_requested = false;
5253 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305254 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005255 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305256 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305257 if (!hdd_ctx->hbw_requested) {
5258 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5259 hdd_ctx->hbw_requested = true;
5260 }
5261
Nirav Shah3bbfa512016-05-12 16:43:49 +05305262 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005263 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305264 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005265 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005267
5268 /* fine-tuning parameters for RX Flows */
5269 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5270
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005271 hdd_ctx->prev_rx = rx_packets;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005272 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh &&
5273 (hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH &&
5274 ++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
Mohit Khannae71e2262015-11-10 09:37:24 -08005275 next_rx_level = WLAN_SVC_TP_HIGH;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005276 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005277 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005278 hdd_ctx->rx_high_ind_cnt = 0;
5279 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280
Mohit Khannae71e2262015-11-10 09:37:24 -08005281 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5282 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283
5284 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005285 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 next_rx_level, temp_rx);
5287 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005288 /* Send throughput indication only if it is enabled.
5289 * Disabling tcp_del_ack will revert the tcp stack behavior
5290 * to default delayed ack. Note that this will disable the
5291 * dynamic delayed ack mechanism across the system
5292 */
5293 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305294 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5295 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005296 &next_rx_level,
5297 sizeof(next_rx_level));
5298 }
5299
Mohit Khannae71e2262015-11-10 09:37:24 -08005300 /* fine-tuning parameters for TX Flows */
5301 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5302 hdd_ctx->prev_tx = tx_packets;
5303 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5304 next_tx_level = WLAN_SVC_TP_HIGH;
5305 else
5306 next_tx_level = WLAN_SVC_TP_LOW;
5307
5308 if (hdd_ctx->cur_tx_level != next_tx_level) {
5309 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5310 next_tx_level, temp_tx);
5311 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305312 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5313 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005314 &next_tx_level,
5315 sizeof(next_tx_level));
5316 }
5317
5318 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5319 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320 hdd_ctx->hdd_txrx_hist_idx++;
5321 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322}
5323
5324#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
5325static void hdd_bus_bw_compute_cbk(void *priv)
5326{
5327 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
5328 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305329 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305330 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5331 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 uint64_t total_tx = 0, total_rx = 0;
5333 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305334 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305335 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 bool connected = false;
5337 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5338
Prashanth Bhattaab004382016-10-11 16:08:11 -07005339 if (wlan_hdd_validate_context(hdd_ctx))
5340 return;
5341
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305343 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344 status =
5345 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5346
5347 if (adapterNode->pAdapter == NULL)
5348 continue;
5349 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305350 /*
5351 * Validate magic so we don't end up accessing
5352 * an invalid adapter.
5353 */
5354 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5355 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005357 if ((adapter->device_mode == QDF_STA_MODE ||
5358 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5360 != eConnectionState_Associated) {
5361
5362 continue;
5363 }
5364
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005365 if ((adapter->device_mode == QDF_SAP_MODE ||
5366 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5368
5369 continue;
5370 }
5371
5372 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5373 adapter->prev_tx_packets);
5374 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5375 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305376
5377 if (adapter->device_mode == QDF_SAP_MODE ||
5378 adapter->device_mode == QDF_P2P_GO_MODE ||
5379 adapter->device_mode == QDF_IBSS_MODE) {
5380
5381 ret = ol_get_intra_bss_fwd_pkts_count(
5382 adapter->sessionId,
5383 &fwd_tx_packets, &fwd_rx_packets);
5384 if (ret == A_OK) {
5385 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5386 fwd_tx_packets,
5387 adapter->prev_fwd_tx_packets);
5388 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5389 fwd_tx_packets,
5390 adapter->prev_fwd_rx_packets);
5391 }
5392 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005393
5394 total_rx += adapter->stats.rx_packets;
5395 total_tx += adapter->stats.tx_packets;
5396
5397 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5398 adapter->prev_tx_packets = adapter->stats.tx_packets;
5399 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305400 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5401 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5403 connected = true;
5404 }
5405
5406 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5407 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5408 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5409 rx_packets;
5410 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5411 tx_packets;
5412
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305413 /* add intra bss forwarded tx and rx packets */
5414 tx_packets += fwd_tx_packets_diff;
5415 rx_packets += fwd_rx_packets_diff;
5416
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5418 tx_packets += (uint64_t)ipa_tx_packets;
5419 rx_packets += (uint64_t)ipa_rx_packets;
5420
5421 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005422 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423 return;
5424 }
5425
Yuanyuan Liu13738502016-04-06 17:41:37 -07005426 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427
5428 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5429 hdd_ipa_uc_stat_request(adapter, 2);
5430
Anurag Chouhan210db072016-02-22 18:42:15 +05305431 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432 hdd_ctx->config->busBandwidthComputeInterval);
5433}
Prashanth Bhattaab004382016-10-11 16:08:11 -07005434
5435int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
5436{
5437 spin_lock_init(&hdd_ctx->bus_bw_lock);
5438
5439 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
5440 QDF_TIMER_TYPE_SW,
5441 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5442
5443 return 0;
5444}
5445
5446void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
5447{
5448 if (qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer) ==
5449 QDF_TIMER_STATE_RUNNING)
5450 hdd_reset_tcp_delack(hdd_ctx);
5451
5452 qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer);
5453}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454#endif
5455
5456/**
Nirav Shahed34b212016-04-25 10:59:16 +05305457 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5458 * @hdd_ctx: hdd context
5459 *
5460 * Return: 0 for success or error code
5461 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005462static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305463{
5464 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5465 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5466 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005467 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305468 return -ENOMEM;
5469 }
5470 return 0;
5471}
5472
5473/**
5474 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5475 * @hdd_ctx: hdd context
5476 *
5477 * Return: none
5478 */
5479void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5480{
5481 if (hdd_ctx->hdd_txrx_hist) {
5482 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5483 hdd_ctx->hdd_txrx_hist = NULL;
5484 }
5485}
5486
Nirav Shahda008342016-05-17 18:50:40 +05305487static uint8_t *convert_level_to_string(uint32_t level)
5488{
5489 switch (level) {
5490 /* initialize the wlan sub system */
5491 case WLAN_SVC_TP_NONE:
5492 return "NONE";
5493 case WLAN_SVC_TP_LOW:
5494 return "LOW";
5495 case WLAN_SVC_TP_MEDIUM:
5496 return "MED";
5497 case WLAN_SVC_TP_HIGH:
5498 return "HIGH";
5499 default:
5500 return "INVAL";
5501 }
5502}
5503
Nirav Shahed34b212016-04-25 10:59:16 +05305504
5505/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5507 * @hdd_ctx: hdd context
5508 *
5509 * Return: none
5510 */
5511void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5512{
5513 int i;
5514
5515#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005516 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305517 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005518 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005519 hdd_ctx->config->busBandwidthHighThreshold,
5520 hdd_ctx->config->busBandwidthMediumThreshold,
5521 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005522 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305523 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005524 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 hdd_ctx->config->tcpDelackThresholdHigh,
5526 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005527 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305528 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005529#endif
5530
Jeff Johnson760350b2016-08-15 14:01:52 -07005531 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305532 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5533
Jeff Johnson760350b2016-08-15 14:01:52 -07005534 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 -08005535
5536 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005537 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5539 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5540 hdd_ctx->hdd_txrx_hist[i].total_tx,
5541 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305542 convert_level_to_string(
5543 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5544 convert_level_to_string(
5545 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5546 convert_level_to_string(
5547 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 }
5549 return;
5550}
5551
5552/**
5553 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5554 * @hdd_ctx: hdd context
5555 *
5556 * Return: none
5557 */
5558void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5559{
5560 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305561 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5562 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005563}
5564
5565/**
5566 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5567 * @pHddCtx: hdd context
5568 *
5569 * Return: none
5570 */
5571void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5572{
5573
5574 hdd_adapter_t *adapter = NULL;
5575 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305576 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305578 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579
5580 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305581 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 adapter = adapter_node->pAdapter;
5583
Jeff Johnson760350b2016-08-15 14:01:52 -07005584 hdd_err("\nNetif queue operation statistics:");
5585 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305586 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005587 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305588 curr_time = qdf_system_ticks();
5589 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305590 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305591 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305592 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305593 unpause = adapter->total_unpause_time;
5594 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305595 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305596 pause = adapter->total_pause_time;
5597 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005598 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305599 qdf_system_ticks_to_msecs(total),
5600 qdf_system_ticks_to_msecs(pause),
5601 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005602 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005603
Nirav Shahda008342016-05-17 18:50:40 +05305604 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5605 qdf_time_t pause_delta = 0;
5606
5607 if (adapter->pause_map & (1 << i))
5608 pause_delta = delta;
5609
Jeff Johnson760350b2016-08-15 14:01:52 -07005610 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611 hdd_reason_type_to_string(i),
5612 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305613 adapter->queue_oper_stats[i].unpause_count,
5614 qdf_system_ticks_to_msecs(
5615 adapter->queue_oper_stats[i].total_pause_time +
5616 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005617 }
5618
Jeff Johnson760350b2016-08-15 14:01:52 -07005619 hdd_err("\nNetif queue operation history:");
5620 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305621 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5622
Jeff Johnson760350b2016-08-15 14:01:52 -07005623 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624
5625 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005626 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305627 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005628 adapter->queue_oper_history[i].time),
5629 hdd_action_type_to_string(
5630 adapter->queue_oper_history[i].netif_action),
5631 hdd_reason_type_to_string(
5632 adapter->queue_oper_history[i].netif_reason),
5633 adapter->queue_oper_history[i].pause_map);
5634 }
5635
5636 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5637 adapter_node = next;
5638 }
5639
5640
5641}
5642
5643/**
5644 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5645 * @hdd_ctx: hdd context
5646 *
5647 * Return: none
5648 */
5649void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5650{
5651 hdd_adapter_t *adapter = NULL;
5652 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305653 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654
5655 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305656 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005657 adapter = adapter_node->pAdapter;
5658
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305659 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305661 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005662 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305663 adapter->history_index = 0;
5664 adapter->start_time = adapter->last_time = qdf_system_ticks();
5665 adapter->total_pause_time = 0;
5666 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5668 adapter_node = next;
5669 }
5670}
5671
5672/**
5673 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5674 * @halHandle: Hal handle
5675 * @pContext: Pointer to the context
5676 * @sessionId: Session ID
5677 * @scanId: Scan ID
5678 * @status: Status
5679 *
5680 * This is the callback to be executed when 11d scan is completed to flush out
5681 * the scan results
5682 *
5683 * 11d scan is done during driver load and is a passive scan on all
5684 * channels supported by the device, 11d scans may find some APs on
5685 * frequencies which are forbidden to be used in the regulatory domain
5686 * the device is operating in. If these APs are notified to the supplicant
5687 * it may try to connect to these APs, thus flush out all the scan results
5688 * which are present in SME after 11d scan is done.
5689 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305690 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305692static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005693 uint8_t sessionId, uint32_t scanId,
5694 eCsrScanStatus status)
5695{
5696 ENTER();
5697
5698 sme_scan_flush_result(halHandle);
5699
5700 EXIT();
5701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305702 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005703}
5704
5705#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5706/**
5707 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5708 * @hdd_ctx: hdd global context
5709 *
5710 * Return: none
5711 */
5712static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5713{
5714 uint8_t i;
5715
5716 mutex_init(&hdd_ctx->op_ctx.op_lock);
5717 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5718 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5719 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5720 }
5721}
5722#else
5723static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5724{
5725}
5726#endif
5727
5728#ifdef WLAN_FEATURE_FASTPATH
5729/**
5730 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5731 * @hdd_cfg: hdd config
5732 * @context: lower layer context
5733 *
5734 * Return: none
5735 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305736void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005737 void *context)
5738{
5739 if (hdd_cfg->fastpath_enable)
5740 hif_enable_fastpath(context);
5741}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742#endif
5743
Yuanyuan Liu13738502016-04-06 17:41:37 -07005744#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005745/**
5746 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005747 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005748 * @level: thermal level
5749 *
5750 * Change IPA data path to SW path when the thermal throttle level greater
5751 * than 0, and restore the original data path when throttle level is 0
5752 *
5753 * Return: none
5754 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005755static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005757 hdd_context_t *hdd_ctx = context;
5758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 /* Change IPA to SW path when throttle level greater than 0 */
5760 if (level > THROTTLE_LEVEL_0)
5761 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5762 else
5763 /* restore original concurrency mode */
5764 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5765}
5766
5767/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305768 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5769 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305770 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305772 * Get a safe channel to restart SAP. PCL already takes into account the
5773 * unsafe channels. So, the PCL is validated with the ACS range to provide
5774 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005775 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305776 * Return: Channel number to restart SAP in case of success. In case of any
5777 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305779static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5780 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005781{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305782 struct sir_pcl_list pcl;
5783 QDF_STATUS status;
5784 uint32_t i, j;
5785 tHalHandle *hal_handle;
5786 hdd_context_t *hdd_ctx;
5787 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305789 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5790 if (!hdd_ctx) {
5791 hdd_err("invalid HDD context");
5792 return INVALID_CHANNEL_ID;
5793 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305795 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5796 if (!hal_handle) {
5797 hdd_err("invalid HAL handle");
5798 return INVALID_CHANNEL_ID;
5799 }
5800
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305801 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5802 pcl.pcl_list, &pcl.pcl_len,
5803 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5804 if (QDF_IS_STATUS_ERROR(status)) {
5805 hdd_err("Get PCL failed");
5806 return INVALID_CHANNEL_ID;
5807 }
5808
5809 if (!pcl.pcl_len) {
5810 hdd_alert("pcl length is zero. this is not expected");
5811 return INVALID_CHANNEL_ID;
5812 }
5813
5814 hdd_info("start:%d end:%d",
5815 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5816 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5817
5818 /* PCL already takes unsafe channel into account */
5819 for (i = 0; i < pcl.pcl_len; i++) {
5820 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5821 if ((pcl.pcl_list[i] >=
5822 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5823 (pcl.pcl_list[i] <=
5824 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5825 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5826 return pcl.pcl_list[i];
5827 }
5828 }
5829
5830 hdd_info("no safe channel from PCL found in ACS range");
5831
5832 /* Try for safe channel from all valid channel */
5833 pcl.pcl_len = MAX_NUM_CHAN;
5834 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5835 &pcl.pcl_len);
5836 if (QDF_IS_STATUS_ERROR(status)) {
5837 hdd_err("error in getting valid channel list");
5838 return INVALID_CHANNEL_ID;
5839 }
5840
5841 for (i = 0; i < pcl.pcl_len; i++) {
5842 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5843 found = false;
5844 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07005845 if (pcl.pcl_list[i] ==
5846 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305847 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5848 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849 break;
5850 }
5851 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305852
5853 if (found)
5854 continue;
5855
5856 if ((pcl.pcl_list[i] >=
5857 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5858 (pcl.pcl_list[i] <=
5859 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5860 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5861 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 }
5863 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305864
5865 return INVALID_CHANNEL_ID;
5866}
5867
5868/**
5869 * hdd_restart_sap() - Restarts SAP on the given channel
5870 * @adapter: AP adapter
5871 * @channel: Channel
5872 *
5873 * Restarts the SAP interface by invoking the function which executes the
5874 * callback to perform channel switch using (E)CSA.
5875 *
5876 * Return: None
5877 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005878static void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305879{
5880 hdd_ap_ctx_t *hdd_ap_ctx;
5881 tHalHandle *hal_handle;
5882
5883 if (!adapter) {
5884 hdd_err("invalid adapter");
5885 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005886 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305887
5888 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5889
5890 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5891 if (!hal_handle) {
5892 hdd_err("invalid HAL handle");
5893 return;
5894 }
5895
5896 hdd_ap_ctx->sapConfig.channel = channel;
5897 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5898 hdd_ap_ctx->sapConfig.ch_width_orig;
5899
5900 hdd_info("chan:%d width:%d",
5901 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5902
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005903 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305904 hdd_ap_ctx->sapConfig.sec_ch,
5905 &hdd_ap_ctx->sapConfig.ch_params);
5906
5907 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005908}
Agrawal Ashish467dde42016-09-08 18:44:22 +05305909/**
5910 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
5911 * @hdd_ctx: hdd context pointer
5912 *
5913 * hdd_unsafe_channel_restart_sap check all unsafe channel list
5914 * and if ACS is enabled, driver will ask userspace to restart the
5915 * sap. User space on LTE coex indication restart driver.
5916 *
5917 * Return - none
5918 */
5919void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
5920{
5921 QDF_STATUS status;
5922 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
5923 hdd_adapter_t *adapter_temp;
5924 uint32_t i;
5925 bool found = false;
5926 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927
Agrawal Ashish467dde42016-09-08 18:44:22 +05305928 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
5929 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5930 adapter_temp = adapter_node->pAdapter;
5931
5932 if (!adapter_temp) {
5933 hdd_err("adapter is NULL, moving to next one");
5934 goto next_adapater;
5935 }
5936
5937 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
5938 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
5939 hdd_info("skip device mode:%d acs:%d",
5940 adapter_temp->device_mode,
5941 adapter_temp->sessionCtx.ap.sapConfig.
5942 acs_cfg.acs_mode);
5943 goto next_adapater;
5944 }
5945
5946 found = false;
5947 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07005948 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05305949 hdd_ctxt->unsafe_channel_list[i]) {
5950 found = true;
5951 hdd_info("operating ch:%d is unsafe",
5952 adapter_temp->sessionCtx.ap.operatingChannel);
5953 break;
5954 }
5955 }
5956
5957 if (!found) {
5958 hdd_info("ch:%d is safe. no need to change channel",
5959 adapter_temp->sessionCtx.ap.operatingChannel);
5960 goto next_adapater;
5961 }
5962
5963 restart_chan =
5964 hdd_get_safe_channel_from_pcl_and_acs_range(
5965 adapter_temp);
5966 if (!restart_chan) {
5967 hdd_alert("fail to restart SAP");
5968 } else {
5969 hdd_info("sending coex indication");
5970 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
5971 WLAN_SVC_LTE_COEX_IND, NULL, 0);
5972 hdd_restart_sap(adapter_temp, restart_chan);
5973 }
5974
5975next_adapater:
5976 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
5977 adapter_node = next;
5978 }
5979}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980/**
5981 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
5982 * @adapter: HDD adapter pointer
5983 * @indParam: Channel avoid notification parameter
5984 *
5985 * Avoid channel notification from FW handler.
5986 * FW will send un-safe channel list to avoid over wrapping.
5987 * hostapd should not use notified channel
5988 *
5989 * Return: None
5990 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05305991void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005992{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993 hdd_context_t *hdd_ctxt;
5994 tSirChAvoidIndType *ch_avoid_indi;
5995 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08005996 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
5997 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005998 uint16_t start_channel;
5999 uint16_t end_channel;
6000 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006001 tHddAvoidFreqList hdd_avoid_freq_list;
6002 uint32_t i;
6003
6004 /* Basic sanity */
6005 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006006 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006007 return;
6008 }
6009
6010 hdd_ctxt = (hdd_context_t *) hdd_context;
6011 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6012 cds_context = hdd_ctxt->pcds_context;
6013
6014 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006015 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006016 ch_avoid_indi->avoid_range_count);
6017
6018 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306019 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6021 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6022 ch_avoid_indi->avoid_freq_range[i].start_freq;
6023 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6024 ch_avoid_indi->avoid_freq_range[i].end_freq;
6025 }
6026 hdd_avoid_freq_list.avoidFreqRangeCount =
6027 ch_avoid_indi->avoid_range_count;
6028
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006029 /* clear existing unsafe channel cache */
6030 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306031 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006032 sizeof(hdd_ctxt->unsafe_channel_list));
6033
6034 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6035 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006036 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006037 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006038 break;
6039 }
6040
6041 start_channel = ieee80211_frequency_to_channel(
6042 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6043 end_channel = ieee80211_frequency_to_channel(
6044 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006045 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6047 start_channel,
6048 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6049 end_channel);
6050
6051 /* do not process frequency bands that are not mapped to
6052 * predefined channels
6053 */
6054 if (start_channel == 0 || end_channel == 0)
6055 continue;
6056
Amar Singhalb8d4f152016-02-10 10:21:43 -08006057 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6058 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006059 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006060 ch_avoid_indi->avoid_freq_range[
6061 range_loop].start_freq) {
6062 start_channel_idx = channel_loop;
6063 break;
6064 }
6065 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006066 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6067 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006068 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006069 ch_avoid_indi->avoid_freq_range[
6070 range_loop].end_freq) {
6071 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006072 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073 ch_avoid_indi->avoid_freq_range[
6074 range_loop].end_freq)
6075 end_channel_idx--;
6076 break;
6077 }
6078 }
6079
Amar Singhalb8d4f152016-02-10 10:21:43 -08006080 if (start_channel_idx == INVALID_CHANNEL ||
6081 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006082 continue;
6083
6084 for (channel_loop = start_channel_idx; channel_loop <=
6085 end_channel_idx; channel_loop++) {
6086 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006087 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006088 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006089 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006090 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006091 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006092 break;
6093 }
6094 }
6095 }
6096
Jeff Johnson34c88b72016-08-15 14:27:11 -07006097 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098 hdd_ctxt->unsafe_channel_count);
6099
Yuanyuan Liu13738502016-04-06 17:41:37 -07006100 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6101 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006102 hdd_ctxt->unsafe_channel_count)) {
6103 hdd_err("Failed to set unsafe channel");
6104
6105 /* clear existing unsafe channel cache */
6106 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306107 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006108 sizeof(hdd_ctxt->unsafe_channel_list));
6109
6110 return;
6111 }
6112
6113 for (channel_loop = 0;
6114 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006115 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006116 hdd_ctxt->unsafe_channel_list[channel_loop]);
6117 }
6118
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306119 /*
6120 * first update the unsafe channel list to the platform driver and
6121 * send the avoid freq event to the application
6122 */
6123 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6124
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306125 if (!hdd_ctxt->unsafe_channel_count) {
6126 hdd_info("no unsafe channels - not restarting SAP");
6127 return;
6128 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306129 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006130 return;
6131}
6132
6133/**
6134 * hdd_init_channel_avoidance() - Initialize channel avoidance
6135 * @hdd_ctx: HDD global context
6136 *
6137 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006138 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006139 * down to the lower layers. Then subscribe to subsequent channel
6140 * avoidance events.
6141 *
6142 * Return: None
6143 */
6144static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6145{
6146 uint16_t unsafe_channel_count;
6147 int index;
6148
Yuanyuan Liu13738502016-04-06 17:41:37 -07006149 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6150 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006151 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006152 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006153
Jeff Johnson34c88b72016-08-15 14:27:11 -07006154 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006155 hdd_ctx->unsafe_channel_count);
6156
Anurag Chouhan6d760662016-02-20 16:05:43 +05306157 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006158 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159
6160 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006161 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006162 hdd_ctx->unsafe_channel_list[index]);
6163
6164 }
6165
6166 /* Plug in avoid channel notification callback */
6167 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6168}
6169#else
6170static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6171{
6172}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006173static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174{
6175}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006176#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006177
6178/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006179 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6180 * user space
6181 * @frame_ind: Management frame data to be informed.
6182 *
6183 * This function is used to indicate management frame to
6184 * user space
6185 *
6186 * Return: None
6187 *
6188 */
6189void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6190{
6191 hdd_context_t *hdd_ctx = NULL;
6192 hdd_adapter_t *adapter = NULL;
6193 void *cds_context = NULL;
6194 int i;
6195
6196 /* Get the global VOSS context.*/
6197 cds_context = cds_get_global_context();
6198 if (!cds_context) {
6199 hdd_err("Global CDS context is Null");
6200 return;
6201 }
6202 /* Get the HDD context.*/
6203 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6204
6205 if (0 != wlan_hdd_validate_context(hdd_ctx))
6206 return;
6207
6208 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6209 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6210 adapter =
6211 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6212 if (adapter)
6213 break;
6214 }
6215 } else {
6216 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6217 frame_ind->sessionId);
6218 }
6219
6220 if ((NULL != adapter) &&
6221 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6222 __hdd_indicate_mgmt_frame(adapter,
6223 frame_ind->frame_len,
6224 frame_ind->frameBuf,
6225 frame_ind->frameType,
6226 frame_ind->rxChan,
6227 frame_ind->rxRssi);
6228 return;
6229}
6230
6231/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006232 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6233 * @hdd_ctx: HDD context
6234 *
6235 * Disables all the dual mac features like DBS, Agile DFS etc.
6236 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306237 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006238 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306239static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006240{
6241 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306242 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006243
6244 if (!hdd_ctx) {
6245 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306246 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006247 }
6248
6249 cfg.scan_config = 0;
6250 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306251 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252
6253 hdd_debug("Disabling all dual mac features...");
6254
6255 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306256 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006257 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6258 return status;
6259 }
6260
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306261 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006262}
6263
6264/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006265 * hdd_override_ini_config - Override INI config
6266 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006268 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006269 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006270 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006271 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006272static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006273{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006274
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006275 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6276 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6277 hdd_notice("Module enable_dfs_chan_scan set to %d",
6278 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006279 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006280 if (0 == enable_11d || 1 == enable_11d) {
6281 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6282 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006283 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006284}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006285
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006286/**
6287 * hdd_set_trace_level_for_each - Set trace level for each INI config
6288 * @hdd_ctx - HDD context
6289 *
6290 * Set trace level for each module based on INI config.
6291 *
6292 * Return: None
6293 */
6294static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6295{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306296 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6297 hdd_ctx->config->qdf_trace_enable_wdi);
6298 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6299 hdd_ctx->config->qdf_trace_enable_hdd);
6300 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6301 hdd_ctx->config->qdf_trace_enable_sme);
6302 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6303 hdd_ctx->config->qdf_trace_enable_pe);
6304 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6305 hdd_ctx->config->qdf_trace_enable_wma);
6306 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6307 hdd_ctx->config->qdf_trace_enable_sys);
6308 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6309 hdd_ctx->config->qdf_trace_enable_qdf);
6310 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6311 hdd_ctx->config->qdf_trace_enable_sap);
6312 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6313 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6314 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6315 hdd_ctx->config->qdf_trace_enable_bmi);
6316 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6317 hdd_ctx->config->qdf_trace_enable_cfg);
6318 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6319 hdd_ctx->config->qdf_trace_enable_epping);
6320 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6321 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6322 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306323 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306324 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6325 hdd_ctx->config->qdf_trace_enable_htc);
6326 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6327 hdd_ctx->config->qdf_trace_enable_hif);
6328 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6329 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6330 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6331 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006333 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006334}
6335
6336/**
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006337 * hdd_context_deinit() - Deinitialize HDD context
6338 * @hdd_ctx: HDD context.
6339 *
6340 * Deinitialize HDD context along with all the feature specific contexts but
6341 * do not free hdd context itself. Caller of this API is supposed to free
6342 * HDD context.
6343 *
6344 * return: 0 on success and errno on failure.
6345 */
6346static int hdd_context_deinit(hdd_context_t *hdd_ctx)
6347{
6348 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
6349
6350 hdd_roc_context_destroy(hdd_ctx);
6351
6352 hdd_sap_context_destroy(hdd_ctx);
6353
6354 hdd_rx_wake_lock_destroy(hdd_ctx);
6355
6356 hdd_tdls_context_destroy(hdd_ctx);
6357
6358 hdd_scan_context_destroy(hdd_ctx);
6359
6360 qdf_list_destroy(&hdd_ctx->hddAdapters);
6361
6362 return 0;
6363}
6364
6365
6366/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006367 * hdd_context_init() - Initialize HDD context
6368 * @hdd_ctx: HDD context.
6369 *
6370 * Initialize HDD context along with all the feature specific contexts.
6371 *
6372 * return: 0 on success and errno on failure.
6373 */
6374static int hdd_context_init(hdd_context_t *hdd_ctx)
6375{
6376 int ret;
6377
6378 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6379 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6380
6381 hdd_init_ll_stats_ctx();
6382
6383 init_completion(&hdd_ctx->mc_sus_event_var);
6384 init_completion(&hdd_ctx->ready_to_suspend);
6385
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306386 hdd_init_bpf_completion();
6387
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006388 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306389 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006390 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306391
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006392 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6393
6394 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6395
6396 ret = hdd_scan_context_init(hdd_ctx);
6397 if (ret)
6398 goto list_destroy;
6399
6400 hdd_tdls_context_init(hdd_ctx);
6401
6402 hdd_rx_wake_lock_create(hdd_ctx);
6403
6404 ret = hdd_sap_context_init(hdd_ctx);
6405 if (ret)
6406 goto scan_destroy;
6407
6408 ret = hdd_roc_context_init(hdd_ctx);
6409 if (ret)
6410 goto sap_destroy;
6411
6412 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6413
6414 hdd_init_offloaded_packets_ctx(hdd_ctx);
6415
6416 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6417 hdd_ctx->config);
6418 if (ret)
6419 goto roc_destroy;
6420
6421 return 0;
6422
6423roc_destroy:
6424 hdd_roc_context_destroy(hdd_ctx);
6425
6426sap_destroy:
6427 hdd_sap_context_destroy(hdd_ctx);
6428
6429scan_destroy:
6430 hdd_scan_context_destroy(hdd_ctx);
6431 hdd_rx_wake_lock_destroy(hdd_ctx);
6432 hdd_tdls_context_destroy(hdd_ctx);
6433
6434list_destroy:
6435 qdf_list_destroy(&hdd_ctx->hddAdapters);
6436 return ret;
6437}
6438
6439/**
6440 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306441 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006442 *
6443 * Allocate and initialize HDD context. HDD context is allocated as part of
6444 * wiphy allocation and then context is initialized.
6445 *
6446 * Return: HDD context on success and ERR_PTR on failure
6447 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006448static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006449{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306450 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006451 int ret = 0;
6452 hdd_context_t *hdd_ctx;
6453 v_CONTEXT_t p_cds_context;
6454
6455 ENTER();
6456
6457 p_cds_context = cds_get_global_context();
6458 if (p_cds_context == NULL) {
6459 hdd_alert("Failed to get CDS global context");
6460 ret = -EINVAL;
6461 goto err_out;
6462 }
6463
6464 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6465
6466 if (hdd_ctx == NULL) {
6467 ret = -ENOMEM;
6468 goto err_out;
6469 }
6470
6471 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006472 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006473
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306474 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006475 if (hdd_ctx->config == NULL) {
6476 hdd_alert("Failed to alloc memory for HDD config!");
6477 ret = -ENOMEM;
6478 goto err_free_hdd_context;
6479 }
6480
6481 /* Read and parse the qcom_cfg.ini file */
6482 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306483 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306484 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006485 WLAN_INI_FILE);
6486 ret = -EINVAL;
6487 goto err_free_config;
6488 }
6489
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006490 hdd_ctx->configuredMcastBcastFilter =
6491 hdd_ctx->config->mcastBcastFilterSetting;
6492
6493 hdd_notice("Setting configuredMcastBcastFilter: %d",
6494 hdd_ctx->config->mcastBcastFilterSetting);
6495
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306496 if (hdd_ctx->config->fhostNSOffload)
6497 hdd_ctx->ns_offload_enable = true;
6498
Abhishek Singh5ea86532016-04-27 14:10:53 +05306499 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6500
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006501 hdd_override_ini_config(hdd_ctx);
6502
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006503 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006504
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006505 ret = hdd_context_init(hdd_ctx);
6506
6507 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006508 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006509
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006510
Yuanyuan Liu13738502016-04-06 17:41:37 -07006511 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6512 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006513
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006514
6515 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306516 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006517
Anurag Chouhan6d760662016-02-20 16:05:43 +05306518 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006519 goto skip_multicast_logging;
6520
6521 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6522
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006523 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6524 if (ret)
6525 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05306526
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006527 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6528 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306529 goto err_free_histogram;
6530
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006531
6532 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306533 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006534 * levels of the code need not be set when the logger thread
6535 * is not enabled.
6536 */
6537 if (cds_is_multicast_logging())
6538 wlan_logging_set_log_level();
6539
6540skip_multicast_logging:
6541 hdd_set_trace_level_for_each(hdd_ctx);
6542
6543 return hdd_ctx;
6544
Nirav Shahed34b212016-04-25 10:59:16 +05306545err_free_histogram:
6546 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6547
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006548err_deinit_hdd_context:
6549 hdd_context_deinit(hdd_ctx);
6550
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006551err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306552 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006553
6554err_free_hdd_context:
6555 wiphy_free(hdd_ctx->wiphy);
6556
6557err_out:
6558 return ERR_PTR(ret);
6559}
6560
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006561#ifdef WLAN_OPEN_P2P_INTERFACE
6562/**
6563 * hdd_open_p2p_interface - Open P2P interface
6564 * @hdd_ctx: HDD context
6565 * @rtnl_held: True if RTNL lock held
6566 *
6567 * Open P2P interface during probe. This function called to open the P2P
6568 * interface at probe along with STA interface.
6569 *
6570 * Return: 0 on success and errno on failure
6571 */
6572static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6573{
6574 hdd_adapter_t *adapter;
6575 uint8_t *p2p_dev_addr;
6576
6577 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6578 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306579 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006580 hdd_ctx->config->intfMacAddr[0].bytes,
6581 sizeof(tSirMacAddr));
6582
6583 /*
6584 * Generate the P2P Device Address. This consists of
6585 * the device's primary MAC address with the locally
6586 * administered bit set.
6587 */
6588 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6589 } else {
6590 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6591 if (p2p_dev_addr == NULL) {
6592 hdd_alert("Failed to allocate mac_address for p2p_device");
6593 return -ENOSPC;
6594 }
6595
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306596 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306597 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006598 }
6599
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006600 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006601 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006602 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006603
6604 if (NULL == adapter) {
6605 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6606 return -ENOSPC;
6607 }
6608
6609 return 0;
6610}
6611#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306612static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006613 bool rtnl_held)
6614{
6615 return 0;
6616}
6617#endif
6618
6619/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306620 * hdd_start_station_adapter()- Start the Station Adapter
6621 * @adapter: HDD adapter
6622 *
6623 * This function initializes the adapter for the station mode.
6624 *
6625 * Return: 0 on success or errno on failure.
6626 */
6627int hdd_start_station_adapter(hdd_adapter_t *adapter)
6628{
6629 QDF_STATUS status;
6630
6631 ENTER_DEV(adapter->dev);
6632
6633 status = hdd_init_station_mode(adapter);
6634
6635 if (QDF_STATUS_SUCCESS != status) {
6636 hdd_err("Error Initializing station mode: %d", status);
6637 return qdf_status_to_os_return(status);
6638 }
6639
Arun Khandavallifae92942016-08-01 13:31:08 +05306640 hdd_register_tx_flow_control(adapter,
6641 hdd_tx_resume_timer_expired_handler,
6642 hdd_tx_resume_cb);
6643
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306644 EXIT();
6645 return 0;
6646}
6647
6648/**
6649 * hdd_start_ap_adapter()- Start AP Adapter
6650 * @adapter: HDD adapter
6651 *
6652 * This function initializes the adapter for the AP mode.
6653 *
6654 * Return: 0 on success errno on failure.
6655 */
6656int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6657{
6658 QDF_STATUS status;
6659
6660 ENTER();
6661
6662 status = hdd_init_ap_mode(adapter);
6663
6664 if (QDF_STATUS_SUCCESS != status) {
6665 hdd_err("Error Initializing the AP mode: %d", status);
6666 return qdf_status_to_os_return(status);
6667 }
6668
Arun Khandavallifae92942016-08-01 13:31:08 +05306669 hdd_register_tx_flow_control(adapter,
6670 hdd_softap_tx_resume_timer_expired_handler,
6671 hdd_softap_tx_resume_cb);
6672
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306673 EXIT();
6674 return 0;
6675}
6676
6677/**
6678 * hdd_start_ftm_adapter()- Start FTM adapter
6679 * @adapter: HDD adapter
6680 *
6681 * This function initializes the adapter for the FTM mode.
6682 *
6683 * Return: 0 on success or errno on failure.
6684 */
6685int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6686{
6687 QDF_STATUS qdf_status;
6688
6689 ENTER_DEV(adapter->dev);
6690
6691 qdf_status = hdd_init_tx_rx(adapter);
6692
6693 if (QDF_STATUS_SUCCESS != qdf_status) {
6694 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6695 return qdf_status_to_os_return(qdf_status);
6696 }
6697
6698 return 0;
6699 EXIT();
6700}
6701
6702/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006703 * hdd_open_interfaces - Open all required interfaces
6704 * hdd_ctx: HDD context
6705 * rtnl_held: True if RTNL lock is held
6706 *
6707 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6708 *
6709 * Return: Primary adapter on success and PTR_ERR on failure
6710 */
6711static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6712 bool rtnl_held)
6713{
6714 hdd_adapter_t *adapter = NULL;
6715 hdd_adapter_t *adapter_11p = NULL;
6716 int ret;
6717
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006718 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306719 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006720 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006721 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006722 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006723
6724 if (adapter == NULL)
6725 return ERR_PTR(-ENOSPC);
6726
6727 return adapter;
6728 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006729 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006730 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006731 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006732
6733 if (adapter == NULL)
6734 return ERR_PTR(-ENOSPC);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006735 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6736 if (ret)
6737 goto err_close_adapter;
6738
6739 /* Open 802.11p Interface */
6740 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006741 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006742 "wlanocb%d",
6743 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006744 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006745 if (adapter_11p == NULL) {
6746 hdd_err("Failed to open 802.11p interface");
6747 goto err_close_adapter;
6748 }
6749 }
6750
6751 return adapter;
6752
6753err_close_adapter:
6754 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6755 return ERR_PTR(ret);
6756}
6757
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006758/**
6759 * hdd_update_country_code - Update country code
6760 * @hdd_ctx: HDD context
6761 * @adapter: Primary adapter context
6762 *
6763 * Update country code based on module parameter country_code at SME and wait
6764 * for the settings to take effect.
6765 *
6766 * Return: 0 on success and errno on failure
6767 */
6768static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6769 hdd_adapter_t *adapter)
6770{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306771 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006772 int ret = 0;
6773 unsigned long rc;
6774
6775 if (country_code == NULL)
6776 return 0;
6777
6778 INIT_COMPLETION(adapter->change_country_code);
6779
6780 status = sme_change_country_code(hdd_ctx->hHal,
6781 wlan_hdd_change_country_code_callback,
6782 country_code, adapter,
6783 hdd_ctx->pcds_context, eSIR_TRUE,
6784 eSIR_TRUE);
6785
6786
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306787 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006788 hdd_err("SME Change Country code from module param fail ret=%d",
6789 ret);
6790 return -EINVAL;
6791 }
6792
6793 rc = wait_for_completion_timeout(&adapter->change_country_code,
6794 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6795 if (!rc) {
6796 hdd_err("SME while setting country code timed out");
6797 ret = -ETIMEDOUT;
6798 }
6799
6800 return ret;
6801}
6802
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306803#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6804/**
6805 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6806 * @cds_cfg: CDS Configuration
6807 * @hdd_ctx: Pointer to hdd context
6808 *
6809 * Return: none
6810 */
6811static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6812 *cds_cfg,
6813 hdd_context_t *hdd_ctx)
6814{
6815 cds_cfg->tx_flow_stop_queue_th =
6816 hdd_ctx->config->TxFlowStopQueueThreshold;
6817 cds_cfg->tx_flow_start_queue_offset =
6818 hdd_ctx->config->TxFlowStartQueueOffset;
6819}
6820#else
6821static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6822 *cds_cfg,
6823 hdd_context_t *hdd_ctx)
6824{
6825}
6826#endif
6827
6828#ifdef FEATURE_WLAN_RA_FILTERING
6829/**
6830 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6831 * @cds_cfg: CDS Configuration
6832 * @hdd_ctx: Pointer to hdd context
6833 *
6834 * Return: none
6835 */
6836inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6837 hdd_context_t *hdd_ctx)
6838{
6839 cds_cfg->ra_ratelimit_interval =
6840 hdd_ctx->config->RArateLimitInterval;
6841 cds_cfg->is_ra_ratelimit_enabled =
6842 hdd_ctx->config->IsRArateLimitEnabled;
6843}
6844#else
6845inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6846 hdd_context_t *hdd_ctx)
6847{
6848}
6849#endif
6850
6851/**
6852 * hdd_update_cds_config() - API to update cds configuration parameters
6853 * @hdd_ctx: HDD Context
6854 *
6855 * Return: 0 for Success, errno on failure
6856 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006857static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306858{
6859 struct cds_config_info *cds_cfg;
6860
6861 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6862 if (!cds_cfg) {
6863 hdd_err("failed to allocate cds config");
6864 return -ENOMEM;
6865 }
6866
6867 qdf_mem_zero(cds_cfg, sizeof(*cds_cfg));
6868
6869 /* UMA is supported in hardware for performing the
6870 * frame translation 802.11 <-> 802.3
6871 */
6872 cds_cfg->frame_xln_reqd = 1;
6873 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
6874 cds_cfg->powersave_offload_enabled =
6875 hdd_ctx->config->enablePowersaveOffload;
6876 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
6877 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
6878 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
6879 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
6880 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
6881
6882 /* Here ol_ini_info is used to store ini status of arp offload
6883 * ns offload and others. Currently 1st bit is used for arp
6884 * off load and 2nd bit for ns offload currently, rest bits are unused
6885 */
6886 if (hdd_ctx->config->fhostArpOffload)
6887 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
6888 if (hdd_ctx->config->fhostNSOffload)
6889 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
6890
6891 /*
6892 * Copy the DFS Phyerr Filtering Offload status.
6893 * This parameter reflects the value of the
6894 * dfs_phyerr_filter_offload flag as set in the ini.
6895 */
6896 cds_cfg->dfs_phyerr_filter_offload =
6897 hdd_ctx->config->fDfsPhyerrFilterOffload;
6898 if (hdd_ctx->config->ssdp)
6899 cds_cfg->ssdp = hdd_ctx->config->ssdp;
6900
6901 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
6902 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
6903
6904 cds_cfg->ap_maxoffload_reorderbuffs =
6905 hdd_ctx->config->apMaxOffloadReorderBuffs;
6906
6907 cds_cfg->ap_disable_intrabss_fwd =
6908 hdd_ctx->config->apDisableIntraBssFwd;
6909
6910 cds_cfg->dfs_pri_multiplier =
6911 hdd_ctx->config->dfsRadarPriMultiplier;
6912 cds_cfg->reorder_offload =
6913 hdd_ctx->config->reorderOffloadSupport;
6914
6915 /* IPA micro controller data path offload resource config item */
6916 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
6917 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
6918 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
6919 cds_cfg->uc_rxind_ringcount =
6920 hdd_ctx->config->IpaUcRxIndRingCount;
6921 cds_cfg->uc_tx_partition_base =
6922 hdd_ctx->config->IpaUcTxPartitionBase;
6923 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
6924
6925 cds_cfg->ip_tcp_udp_checksum_offload =
6926 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05306927 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306928 cds_cfg->ce_classify_enabled =
6929 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07006930 cds_cfg->bpf_packet_filter_enable =
6931 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306932 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
6933 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
6934 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07006935 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07006936 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306937
6938 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
6939 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
6940 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07006941 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306942 cds_init_ini_config(cds_cfg);
6943 return 0;
6944}
6945
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006946/**
6947 * hdd_init_thermal_info - Initialize thermal level
6948 * @hdd_ctx: HDD context
6949 *
6950 * Initialize thermal level at SME layer and set the thermal level callback
6951 * which would be called when a configured thermal threshold is hit.
6952 *
6953 * Return: 0 on success and errno on failure
6954 */
6955static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
6956{
6957 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306958 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006959
6960 thermal_param.smeThermalMgmtEnabled =
6961 hdd_ctx->config->thermalMitigationEnable;
6962 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
6963
Poddar, Siddarth83905022016-04-16 17:56:08 -07006964 thermal_param.sme_throttle_duty_cycle_tbl[0] =
6965 hdd_ctx->config->throttle_dutycycle_level0;
6966 thermal_param.sme_throttle_duty_cycle_tbl[1] =
6967 hdd_ctx->config->throttle_dutycycle_level1;
6968 thermal_param.sme_throttle_duty_cycle_tbl[2] =
6969 hdd_ctx->config->throttle_dutycycle_level2;
6970 thermal_param.sme_throttle_duty_cycle_tbl[3] =
6971 hdd_ctx->config->throttle_dutycycle_level3;
6972
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006973 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
6974 hdd_ctx->config->thermalTempMinLevel0;
6975 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
6976 hdd_ctx->config->thermalTempMaxLevel0;
6977 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
6978 hdd_ctx->config->thermalTempMinLevel1;
6979 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
6980 hdd_ctx->config->thermalTempMaxLevel1;
6981 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
6982 hdd_ctx->config->thermalTempMinLevel2;
6983 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
6984 hdd_ctx->config->thermalTempMaxLevel2;
6985 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
6986 hdd_ctx->config->thermalTempMinLevel3;
6987 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
6988 hdd_ctx->config->thermalTempMaxLevel3;
6989
6990 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
6991
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306992 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05306993 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006994
6995 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
6996 hdd_set_thermal_level_cb);
6997
6998 return 0;
6999
7000}
7001
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007002#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7003/**
7004 * hdd_hold_rtnl_lock - Hold RTNL lock
7005 *
7006 * Hold RTNL lock
7007 *
7008 * Return: True if held and false otherwise
7009 */
7010static inline bool hdd_hold_rtnl_lock(void)
7011{
7012 rtnl_lock();
7013 return true;
7014}
7015
7016/**
7017 * hdd_release_rtnl_lock - Release RTNL lock
7018 *
7019 * Release RTNL lock
7020 *
7021 * Return: None
7022 */
7023static inline void hdd_release_rtnl_lock(void)
7024{
7025 rtnl_unlock();
7026}
7027#else
7028static inline bool hdd_hold_rtnl_lock(void) { return false; }
7029static inline void hdd_release_rtnl_lock(void) { }
7030#endif
7031
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007032#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007033
7034/**
7035 * hdd_process_pktlog_command() - process pktlog command
7036 * @hdd_ctx: hdd context
7037 * @set_value: value set by user
7038 *
7039 * Return: 0 for success or error.
7040 */
7041int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value)
7042{
7043 int ret;
7044 bool enable;
7045 uint8_t user_triggered = 0;
7046
7047 ret = wlan_hdd_validate_context(hdd_ctx);
7048 if (0 != ret)
7049 return ret;
7050
7051 hdd_info("set pktlog %d", set_value);
7052
7053 if (set_value > 2) {
7054 hdd_err("invalid pktlog value %d", set_value);
7055 return -EINVAL;
7056 }
7057
7058 /*
7059 * set_value = 0 then disable packetlog
7060 * set_value = 1 enable packetlog forcefully
7061 * set_vlaue = 2 then disable packetlog if disabled through ini or
7062 * enable packetlog with AUTO type.
7063 */
7064 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
7065 true : false;
7066
7067 if (1 == set_value) {
7068 enable = true;
7069 user_triggered = 1;
7070 }
7071
7072 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered);
7073}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007074/**
7075 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
7076 * @hdd_ctx: HDD context
7077 * @enable: Flag to enable/disable
7078 *
7079 * Return: 0 on success; error number otherwise
7080 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007081int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
7082 uint8_t user_triggered)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007083{
7084 struct sir_wifi_start_log start_log;
7085 QDF_STATUS status;
7086
7087 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7088 start_log.verbose_level =
7089 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007090 start_log.ini_triggered = cds_is_packet_log_enabled();
7091 start_log.user_triggered = user_triggered;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307092 /*
7093 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7094 * commands. Host uses this flag to decide whether to send pktlog
7095 * disable command to fw without sending pktlog enable command
7096 * previously. For eg, If vendor sends pktlog disable command without
7097 * sending pktlog enable command, then host discards the packet
7098 * but for iwpriv command, host will send it to fw.
7099 */
7100 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007101 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7102 if (!QDF_IS_STATUS_SUCCESS(status)) {
7103 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7104 EXIT();
7105 return -EINVAL;
7106 }
7107
7108 return 0;
7109}
7110#endif /* REMOVE_PKT_LOG */
7111
7112
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307113#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7114/**
7115 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7116 * switch without restart
7117 *
7118 * Registers callback function to change the operating channel of SAP by using
7119 * channel switch announcements instead of restarting SAP.
7120 *
7121 * Return: QDF_STATUS
7122 */
7123QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7124{
7125 QDF_STATUS status;
7126
7127 status = cds_register_sap_restart_channel_switch_cb(
7128 (void *)hdd_sap_restart_with_channel_switch);
7129 if (!QDF_IS_STATUS_SUCCESS(status))
7130 hdd_err("restart cb registration failed");
7131
7132 return status;
7133}
7134#endif
7135
Komal Seelam92fff912016-03-24 11:51:41 +05307136#ifdef CONFIG_CNSS
7137/**
7138 * hdd_get_cnss_wlan_mac_buff() - API to query platform driver for MAC address
7139 * @dev: Device Pointer
7140 * @num: Number of Valid Mac address
7141 *
7142 * Return: Pointer to MAC address buffer
7143 */
7144static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
7145{
7146 return cnss_common_get_wlan_mac_address(dev, num);
7147}
7148#else
7149static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
7150{
7151 *num = 0;
7152 return NULL;
7153}
7154#endif
7155
7156/**
7157 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7158 * @hdd_ctx: HDD Context
7159 * @num: Number of random mac addresses needed
7160 *
7161 * Generate random addresses using bit manipulation on the base mac address
7162 *
7163 * Return: None
7164 */
7165static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7166{
7167 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7168 uint32_t iter;
7169 struct hdd_config *ini = hdd_ctx->config;
7170 uint8_t *buf = NULL;
7171 uint8_t macaddr_b3, tmp_br3;
7172 uint8_t *src = ini->intfMacAddr[0].bytes;
7173
7174 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
7175 buf = ini->intfMacAddr[iter].bytes;
7176 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7177 macaddr_b3 = buf[3];
7178 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7179 INTF_MACADDR_MASK;
7180 macaddr_b3 += tmp_br3;
7181 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7182 buf[0] |= 0x02;
7183 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007184 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307185 }
7186}
7187
7188/**
7189 * hdd_cnss_wlan_mac() - API to get mac addresses from cnss platform driver
7190 * @hdd_ctx: HDD Context
7191 *
7192 * API to get mac addresses from platform driver and update the driver
7193 * structures and configure FW with the base mac address.
7194 * Return: int
7195 */
7196static int hdd_cnss_wlan_mac(hdd_context_t *hdd_ctx)
7197{
7198 uint32_t no_of_mac_addr, iter;
7199 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7200 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7201 uint8_t *addr, *buf;
7202 struct device *dev = hdd_ctx->parent_dev;
7203 struct hdd_config *ini = hdd_ctx->config;
7204 tSirMacAddr mac_addr;
7205 QDF_STATUS status;
7206
7207 addr = hdd_get_cnss_wlan_mac_buff(dev, &no_of_mac_addr);
7208
7209 if (no_of_mac_addr == 0 || !addr) {
7210 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7211 return -EINVAL;
7212 }
7213
7214 if (no_of_mac_addr > max_mac_addr)
7215 no_of_mac_addr = max_mac_addr;
7216
7217 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7218
7219 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7220 buf = ini->intfMacAddr[iter].bytes;
7221 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007222 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307223 }
7224
7225 status = sme_set_custom_mac_addr(mac_addr);
7226
7227 if (!QDF_IS_STATUS_SUCCESS(status))
7228 return -EAGAIN;
7229 if (no_of_mac_addr < max_mac_addr)
7230 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7231 no_of_mac_addr);
7232 return 0;
7233}
7234
7235/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007236 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7237 * @hdd_ctx: HDD Context
7238 *
7239 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7240 * will generate its own MAC and update it to FW.
7241 *
7242 * Return: 0 for success
7243 * Non-zero error code for failure
7244 */
7245static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7246{
7247 tSirMacAddr customMacAddr;
7248 QDF_STATUS status;
7249
7250 qdf_mem_copy(&customMacAddr,
7251 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7252 sizeof(tSirMacAddr));
7253 status = sme_set_custom_mac_addr(customMacAddr);
7254 if (!QDF_IS_STATUS_SUCCESS(status))
7255 return -EAGAIN;
7256 return 0;
7257}
7258
7259/**
Komal Seelam92fff912016-03-24 11:51:41 +05307260 * hdd_initialize_mac_address() - API to get wlan mac addresses
7261 * @hdd_ctx: HDD Context
7262 *
7263 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
7264 * is provisioned with mac addresses, driver uses it, else it will use
7265 * wlan_mac.bin to update HW MAC addresses.
7266 *
7267 * Return: None
7268 */
7269static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
7270{
7271 QDF_STATUS status;
7272 int ret;
7273
7274 ret = hdd_cnss_wlan_mac(hdd_ctx);
7275 if (ret == 0)
7276 return;
7277
7278 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7279
7280 status = hdd_update_mac_config(hdd_ctx);
7281
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007282 if (QDF_IS_STATUS_SUCCESS(status))
7283 return;
7284
7285 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
7286
7287 if (hdd_ctx->update_mac_addr_to_fw)
7288 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
7289
7290 if (ret != 0) {
7291 hdd_err("MAC address out-of-sync, ret:%d", ret);
7292 QDF_ASSERT(ret);
7293 }
Komal Seelam92fff912016-03-24 11:51:41 +05307294}
7295
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007296/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007297 * hdd_tsf_init() - Initialize the TSF synchronization interface
7298 * @hdd_ctx: HDD global context
7299 *
7300 * When TSF synchronization via GPIO is supported by the driver and
7301 * has been enabled in the configuration file, this function plumbs
7302 * the GPIO value down to firmware via SME.
7303 *
7304 * Return: None
7305 */
7306#ifdef WLAN_FEATURE_TSF
7307static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7308{
7309 QDF_STATUS status;
7310
7311 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7312 return;
7313
7314 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7315 hdd_ctx->config->tsf_gpio_pin);
7316 if (!QDF_IS_STATUS_SUCCESS(status))
7317 hdd_err("Set tsf GPIO failed, status: %d", status);
7318}
7319#else
7320static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7321{
7322}
7323#endif
7324
7325/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007326 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7327 * @hdd_ctx: HDD context
7328 *
7329 * Pre configurations to be done at lower layer before calling cds enable.
7330 *
7331 * Return: 0 on success and errno on failure.
7332 */
7333static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7334{
7335 int ret;
7336 QDF_STATUS status;
7337 tSirRetStatus hal_status;
7338
7339 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
7340
7341 /*
7342 * Set 802.11p config
7343 * TODO-OCB: This has been temporarily added here to ensure this
7344 * parameter is set in CSR when we init the channel list. This should
7345 * be removed once the 5.9 GHz channels are added to the regulatory
7346 * domain.
7347 */
7348 hdd_set_dot11p_config(hdd_ctx);
7349
7350 /*
7351 * Note that the cds_pre_enable() sequence triggers the cfg download.
7352 * The cfg download must occur before we update the SME config
7353 * since the SME config operation must access the cfg database
7354 */
7355 status = hdd_set_sme_config(hdd_ctx);
7356
7357 if (QDF_STATUS_SUCCESS != status) {
7358 hdd_alert("Failed hdd_set_sme_config: %d", status);
7359 ret = qdf_status_to_os_return(status);
7360 goto out;
7361 }
7362
7363 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7364 hdd_ctx->config->tx_chain_mask_1ss,
7365 PDEV_CMD);
7366 if (0 != ret) {
7367 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7368 goto out;
7369 }
7370
7371 hdd_program_country_code(hdd_ctx);
7372
7373 status = hdd_set_sme_chan_list(hdd_ctx);
7374 if (status != QDF_STATUS_SUCCESS) {
7375 hdd_alert("Failed to init channel list: %d", status);
7376 ret = qdf_status_to_os_return(status);
7377 goto out;
7378 }
7379
7380 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07007381 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07007382 hdd_alert("config update failed");
7383 ret = -EINVAL;
7384 goto out;
7385 }
7386
Komal Seelam92fff912016-03-24 11:51:41 +05307387 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007388
7389 /*
7390 * Set the MAC Address Currently this is used by HAL to add self sta.
7391 * Remove this once self sta is added as part of session open.
7392 */
7393 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7394 hdd_ctx->config->intfMacAddr[0].bytes,
7395 sizeof(hdd_ctx->config->intfMacAddr[0]));
7396
7397 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7398 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7399 hal_status, hal_status);
7400 ret = -EINVAL;
7401 goto out;
7402 }
7403
7404 hdd_init_channel_avoidance(hdd_ctx);
7405
7406out:
7407 return ret;
7408}
7409
7410/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007411 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7412 * @context_ptr - hdd context pointer
7413 * @event_ptr - event structure pointer
7414 *
7415 * This is the p2p listen offload stop event handler, it sends vendor
7416 * event back to supplicant to notify the stop reason.
7417 *
7418 * Return: None
7419 */
7420static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7421 void *event_ptr)
7422{
7423 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7424 struct sir_p2p_lo_event *evt = event_ptr;
7425 struct sk_buff *vendor_event;
7426
7427 ENTER();
7428
7429 if (hdd_ctx == NULL) {
7430 hdd_err("Invalid HDD context pointer");
7431 return;
7432 }
7433
7434 vendor_event =
7435 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7436 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7437 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7438 GFP_KERNEL);
7439
7440 if (!vendor_event) {
7441 hdd_err("cfg80211_vendor_event_alloc failed");
7442 return;
7443 }
7444
7445 if (nla_put_u32(vendor_event,
7446 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7447 evt->reason_code)) {
7448 hdd_err("nla put failed");
7449 kfree_skb(vendor_event);
7450 return;
7451 }
7452
7453 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7454}
7455
7456/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307457 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7458 * @hdd_ctx: HDD context
7459 *
7460 * This function sends the adaptive dwell time config configuration to the
7461 * firmware via WMA
7462 *
7463 * Return: 0 - success, < 0 - failure
7464 */
7465static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7466{
7467 QDF_STATUS status;
7468 struct adaptive_dwelltime_params dwelltime_params;
7469
7470 dwelltime_params.is_enabled =
7471 hdd_ctx->config->adaptive_dwell_mode_enabled;
7472 dwelltime_params.dwelltime_mode =
7473 hdd_ctx->config->global_adapt_dwelltime_mode;
7474 dwelltime_params.lpf_weight =
7475 hdd_ctx->config->adapt_dwell_lpf_weight;
7476 dwelltime_params.passive_mon_intval =
7477 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7478 dwelltime_params.wifi_act_threshold =
7479 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7480
7481 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7482 &dwelltime_params);
7483
7484 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7485 if (!QDF_IS_STATUS_SUCCESS(status)) {
7486 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7487 return -EAGAIN;
7488 }
7489 return 0;
7490}
7491
Arun Khandavallid4349a92016-07-25 11:10:43 +05307492#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7493/**
7494 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7495 * @hdd_ctx: HDD context
7496 *
7497 * Set auto shutdown callback to get indications from firmware to indicate
7498 * userspace to shutdown WLAN after a configured amount of inactivity.
7499 *
7500 * Return: 0 on success and errno on failure.
7501 */
7502static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7503{
7504 QDF_STATUS status;
7505
7506 if (!hdd_ctx->config->WlanAutoShutdown)
7507 return 0;
7508
7509 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7510 wlan_hdd_auto_shutdown_cb);
7511 if (status != QDF_STATUS_SUCCESS)
7512 hdd_err("Auto shutdown feature could not be enabled: %d",
7513 status);
7514
7515 return qdf_status_to_os_return(status);
7516}
7517#else
7518static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7519{
7520 return 0;
7521}
7522#endif
7523
7524/**
7525 * hdd_features_init() - Init features
7526 * @hdd_ctx: HDD context
7527 * @adapter: Primary adapter context
7528 *
7529 * Initialize features and their feature context after WLAN firmware is up.
7530 *
7531 * Return: 0 on success and errno on failure.
7532 */
7533static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7534{
7535 tSirTxPowerLimit hddtxlimit;
7536 QDF_STATUS status;
7537 int ret;
7538
7539 ENTER();
7540
7541 ret = hdd_update_country_code(hdd_ctx, adapter);
7542 if (ret) {
7543 hdd_err("Failed to update country code: %d", ret);
7544 goto out;
7545 }
7546
7547 /* FW capabilities received, Set the Dot11 mode */
7548 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07007549 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
7550 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307551
Arun Khandavallid4349a92016-07-25 11:10:43 +05307552
7553 if (hdd_ctx->config->fIsImpsEnabled)
7554 hdd_set_idle_ps_config(hdd_ctx, true);
7555 else
7556 hdd_set_idle_ps_config(hdd_ctx, false);
7557
7558 if (hdd_lro_init(hdd_ctx))
7559 hdd_err("Unable to initialize LRO in fw");
7560
7561 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7562 hdd_err("Unable to send adaptive dwelltime setting to FW");
7563
7564 ret = hdd_init_thermal_info(hdd_ctx);
7565 if (ret) {
7566 hdd_err("Error while initializing thermal information");
7567 goto deregister_frames;
7568 }
7569
7570 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7571 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7572 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7573 if (!QDF_IS_STATUS_SUCCESS(status))
7574 hdd_err("Error setting txlimit in sme: %d", status);
7575
7576 hdd_tsf_init(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307577 hdd_encrypt_decrypt_init(hdd_ctx);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307578
Arun Khandavallid4349a92016-07-25 11:10:43 +05307579 ret = hdd_register_cb(hdd_ctx);
7580 if (ret) {
7581 hdd_err("Failed to register HDD callbacks!");
7582 goto deregister_frames;
7583 }
7584
7585 if (hdd_ctx->config->dual_mac_feature_disable) {
7586 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7587 if (status != QDF_STATUS_SUCCESS) {
7588 hdd_err("Failed to disable dual mac features");
7589 goto deregister_cb;
7590 }
7591 }
7592
7593 /* register P2P Listen Offload event callback */
7594 if (wma_is_p2p_lo_capable())
7595 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7596 wlan_hdd_p2p_lo_event_callback);
7597
7598 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7599
7600 if (ret)
7601 goto deregister_cb;
7602
7603 EXIT();
7604 return 0;
7605
7606deregister_cb:
7607 hdd_deregister_cb(hdd_ctx);
7608deregister_frames:
7609 wlan_hdd_cfg80211_deregister_frames(adapter);
7610out:
7611 return -EINVAL;
7612
7613}
7614
7615
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307616/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307617 * hdd_configure_cds() - Configure cds modules
7618 * @hdd_ctx: HDD context
7619 * @adapter: Primary adapter context
7620 *
7621 * Enable Cds modules after WLAN firmware is up.
7622 *
7623 * Return: 0 on success and errno on failure.
7624 */
7625int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7626{
7627 int ret;
7628 QDF_STATUS status;
7629 /* structure of function pointers to be used by CDS */
7630 struct cds_sme_cbacks sme_cbacks;
7631
7632 ret = hdd_pre_enable_configure(hdd_ctx);
7633 if (ret) {
7634 hdd_err("Failed to pre-configure cds");
7635 goto out;
7636 }
7637
7638 /*
7639 * Start CDS which starts up the SME/MAC/HAL modules and everything
7640 * else
7641 */
7642 status = cds_enable(hdd_ctx->pcds_context);
7643
7644 if (!QDF_IS_STATUS_SUCCESS(status)) {
7645 hdd_alert("cds_enable failed");
7646 goto out;
7647 }
7648
7649 status = hdd_post_cds_enable_config(hdd_ctx);
7650 if (!QDF_IS_STATUS_SUCCESS(status)) {
7651 hdd_alert("hdd_post_cds_enable_config failed");
7652 goto out;
7653 }
7654
7655 ret = hdd_features_init(hdd_ctx, adapter);
7656 if (ret)
7657 goto out;
7658
7659 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7660 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7661 status = cds_init_policy_mgr(&sme_cbacks);
7662 if (!QDF_IS_STATUS_SUCCESS(status)) {
7663 hdd_err("Policy manager initialization failed");
7664 goto out;
7665 }
7666
7667 return 0;
7668out:
7669 return -EINVAL;
7670}
7671
7672/**
7673 * hdd_deconfigure_cds() -De-Configure cds
7674 * @hdd_ctx: HDD context
7675 *
7676 * Deconfigure Cds modules before WLAN firmware is down.
7677 *
7678 * Return: 0 on success and errno on failure.
7679 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007680static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307681{
7682 QDF_STATUS qdf_status;
7683
7684 ENTER();
7685 /* De-register the SME callbacks */
7686 hdd_deregister_cb(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307687 hdd_encrypt_decrypt_deinit(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307688
7689 /* De-init Policy Manager */
7690 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7691 hdd_err("Failed to deinit policy manager");
7692 /* Proceed and complete the clean up */
7693 return -EINVAL;
7694 }
7695
7696 qdf_status = cds_disable(hdd_ctx->pcds_context);
7697 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7698 hdd_err("Failed to Disable the CDS Modules! :%d",
7699 qdf_status);
7700 return -EINVAL;
7701 }
7702
7703 EXIT();
7704 return 0;
7705}
7706
7707
7708/**
7709 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7710 * @hdd_ctx: HDD context
Arun Khandavallifae92942016-08-01 13:31:08 +05307711 *
7712 * This function maintains the driver state machine it will be invoked from
7713 * exit, shutdown and con_mode change handler. Depending on the driver state
7714 * shall perform the stopping/closing of the modules.
7715 *
7716 * Return: 0 for success; non-zero for failure
7717 */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007718int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307719{
7720 void *hif_ctx;
7721 qdf_device_t qdf_ctx;
7722 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307723 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307724 p_cds_sched_context cds_sched_context = NULL;
7725
7726 ENTER();
7727
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307728
Arun Khandavallifae92942016-08-01 13:31:08 +05307729 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7730 if (!qdf_ctx) {
7731 hdd_err("QDF device context NULL");
7732 return -EINVAL;
7733 }
7734
7735 cds_sched_context = get_cds_sched_ctxt();
7736 if (!cds_sched_context) {
7737 hdd_err("cds scheduler context NULL");
7738 return -EINVAL;
7739 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307740 mutex_lock(&hdd_ctx->iface_change_lock);
7741 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307742
7743 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7744
7745 switch (hdd_ctx->driver_status) {
7746 case DRIVER_MODULES_UNINITIALIZED:
7747 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307748 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307749 case DRIVER_MODULES_CLOSED:
7750 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307751 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307752 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05307753 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05307754 if (hdd_deconfigure_cds(hdd_ctx)) {
7755 hdd_alert("Failed to de-configure CDS");
7756 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307757 ret = -EINVAL;
7758 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307759 }
7760 hdd_info("successfully Disabled the CDS modules!");
7761 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7762 break;
7763 case DRIVER_MODULES_OPENED:
7764 hdd_info("Closing CDS modules!");
7765 break;
7766 default:
7767 hdd_err("Trying to stop wlan in a wrong state: %d",
7768 hdd_ctx->driver_status);
7769 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307770 ret = -EINVAL;
7771 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307772 }
7773
7774 qdf_status = cds_close(hdd_ctx->pcds_context);
7775 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7776 hdd_warn("Failed to stop CDS:%d", qdf_status);
7777 QDF_ASSERT(0);
7778 }
7779 /* Clean up message queues of TX, RX and MC thread */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007780 if (!cds_is_driver_recovering())
7781 cds_sched_flush_mc_mqs(cds_sched_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307782
7783 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
7784 if (!hif_ctx) {
7785 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307786 ret = -EINVAL;
7787 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307788 }
7789
7790 hdd_hif_close(hif_ctx);
7791
7792 ol_cds_free();
7793
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007794 if (!cds_is_driver_recovering()) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307795 ret = pld_power_off(qdf_ctx->dev);
7796 if (ret)
7797 hdd_err("CNSS power down failed put device into Low power mode:%d",
7798 ret);
7799 }
7800 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
7801
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307802done:
7803 hdd_ctx->stop_modules_in_progress = false;
7804 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05307805 EXIT();
7806
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307807 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307808
7809}
7810
7811/**
7812 * hdd_iface_change_callback() - Function invoked when stop modules expires
7813 * @priv: pointer to hdd context
7814 *
7815 * This function is invoked when the timer waiting for the interface change
7816 * expires, it shall cut-down the power to wlan and stop all the modules.
7817 *
7818 * Return: void
7819 */
7820static void hdd_iface_change_callback(void *priv)
7821{
7822 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
7823 int ret;
7824 int status = wlan_hdd_validate_context(hdd_ctx);
7825
7826 if (status)
7827 return;
7828
7829 ENTER();
7830 hdd_info("Interface change timer expired close the modules!");
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007831 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307832 if (ret)
7833 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05307834 EXIT();
7835}
7836
7837/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05307838 * hdd_state_info_dump() - prints state information of hdd layer
7839 * @buf: buffer pointer
7840 * @size: size of buffer to be filled
7841 *
7842 * This function is used to dump state information of hdd layer
7843 *
7844 * Return: None
7845 */
7846static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
7847{
7848 hdd_context_t *hdd_ctx;
7849 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7850 QDF_STATUS status;
7851 hdd_station_ctx_t *hdd_sta_ctx;
7852 hdd_adapter_t *adapter;
7853 uint16_t len = 0;
7854 char *buf = *buf_ptr;
7855
7856 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7857 if (!hdd_ctx) {
7858 hdd_err("Failed to get hdd context ");
7859 return;
7860 }
7861
7862 hdd_notice("size of buffer: %d", *size);
7863
7864 len += scnprintf(buf + len, *size - len,
7865 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
7866 len += scnprintf(buf + len, *size - len,
7867 "\n isMcThreadSuspended %d",
7868 hdd_ctx->isMcThreadSuspended);
7869
7870 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7871
7872 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7873 adapter = adapter_node->pAdapter;
7874 if (adapter->dev)
7875 len += scnprintf(buf + len, *size - len,
7876 "\n device name: %s", adapter->dev->name);
7877 len += scnprintf(buf + len, *size - len,
7878 "\n device_mode: %d", adapter->device_mode);
7879 switch (adapter->device_mode) {
7880 case QDF_STA_MODE:
7881 case QDF_P2P_CLIENT_MODE:
7882 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
7883 len += scnprintf(buf + len, *size - len,
7884 "\n connState: %d",
7885 hdd_sta_ctx->conn_info.connState);
7886 break;
7887
7888 default:
7889 break;
7890 }
7891 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
7892 adapter_node = next;
7893 }
7894
7895 *size -= len;
7896 *buf_ptr += len;
7897}
7898
7899/**
7900 * hdd_register_debug_callback() - registration function for hdd layer
7901 * to print hdd state information
7902 *
7903 * Return: None
7904 */
7905static void hdd_register_debug_callback(void)
7906{
7907 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
7908}
7909
7910/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007911 * hdd_wlan_startup() - HDD init function
7912 * @dev: Pointer to the underlying device
7913 *
7914 * This is the driver startup code executed once a WLAN device has been detected
7915 *
7916 * Return: 0 for success, < 0 for failure
7917 */
Arun Khandavallifae92942016-08-01 13:31:08 +05307918int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007919{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307920 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007921 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007922 hdd_context_t *hdd_ctx = NULL;
7923 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307924 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007925 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05307926 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007927
7928 ENTER();
7929
Arun Khandavallifae92942016-08-01 13:31:08 +05307930 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007931
7932 if (IS_ERR(hdd_ctx))
7933 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007934
Arun Khandavallifae92942016-08-01 13:31:08 +05307935 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
7936 hdd_iface_change_callback, (void *)hdd_ctx);
7937
7938 mutex_init(&hdd_ctx->iface_change_lock);
7939
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007940 ret = hdd_init_netlink_services(hdd_ctx);
7941 if (ret)
7942 goto err_hdd_free_context;
7943
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07007944 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307945
Arun Khandavallifae92942016-08-01 13:31:08 +05307946 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
7947 if (ret) {
7948 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007949 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007950 }
7951
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007952 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007953
Anurag Chouhan6d760662016-02-20 16:05:43 +05307954 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007955
7956 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007957 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05307958 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007959 }
7960
Prashanth Bhatta07998752016-04-28 12:35:33 -07007961 ret = hdd_wiphy_init(hdd_ctx);
7962 if (ret) {
7963 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05307964 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007965 }
7966
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05307967 if (hdd_ctx->config->enable_dp_trace)
7968 qdf_dp_trace_init();
7969
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307970 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007971 goto err_wiphy_unregister;
7972
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08007973
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007974 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007975
Arun Khandavallifae92942016-08-01 13:31:08 +05307976
7977 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007978
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007979 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007980 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007981 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05307982 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007983 }
7984
Arun Khandavallifae92942016-08-01 13:31:08 +05307985 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Anurag Chouhance6a4052016-09-14 18:20:42 +05307986 if (!hif_sc) {
7987 hdd_err("HIF context is NULL");
7988 goto err_close_adapter;
7989 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007990 /*
7991 * target hw version/revision would only be retrieved after firmware
7992 * donwload
7993 */
7994 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
7995 &hdd_ctx->target_hw_revision,
7996 &hdd_ctx->target_hw_name);
7997
7998 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05307999 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008000
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008001 hdd_release_rtnl_lock();
8002 rtnl_held = false;
8003
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05308004 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8005 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008006#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05308007 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308008 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008009 hdd_skip_acs_scan_timer_handler,
8010 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308011 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07008012 hdd_err("Failed to init ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008013#endif
8014
Prashanth Bhattaab004382016-10-11 16:08:11 -07008015 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008016
Jeff Johnson9afc5012016-09-23 13:56:27 -07008017 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008018
Nirav Shahbd36b062016-07-18 11:12:59 +05308019 if (hdd_ctx->rps)
8020 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07008021
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008022
8023 if (cds_is_packet_log_enabled())
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008024 hdd_pktlog_enable_disable(hdd_ctx, true, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008025
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008026 ret = hdd_register_notifiers(hdd_ctx);
8027 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05308028 goto err_debugfs_exit;
8029
8030 status = wlansap_global_init();
8031 if (QDF_IS_STATUS_ERROR(status))
8032 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008033
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008034 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308035 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008036
Arun Khandavallifae92942016-08-01 13:31:08 +05308037 if (hdd_ctx->config->fIsImpsEnabled)
8038 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308039
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308040 if (hdd_ctx->config->sifs_burst_duration) {
8041 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
8042 hdd_ctx->config->sifs_burst_duration;
8043
8044 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
8045 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
8046 set_value, PDEV_CMD);
8047 }
8048
Arun Khandavallifae92942016-08-01 13:31:08 +05308049 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
8050 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308051
8052 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8053 status = sme_enable_disable_chanavoidind_event(
8054 hdd_ctx->hHal, 0);
8055 if (!QDF_IS_STATUS_SUCCESS(status))
8056 hdd_err("Failed to disable Chan Avoidance Indication");
8057 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008058 goto success;
8059
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008060err_debugfs_exit:
8061 hdd_debugfs_exit(adapter);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308062
8063err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008064 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008065
Arun Khandavallid4349a92016-07-25 11:10:43 +05308066 if (rtnl_held)
8067 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008068
Anurag Chouhance6a4052016-09-14 18:20:42 +05308069err_ipa_cleanup:
8070 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08008071
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008072err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008073 wiphy_unregister(hdd_ctx->wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05308074 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008075
Arun Khandavallifae92942016-08-01 13:31:08 +05308076err_stop_modules:
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008077 hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308078
8079
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008080 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308081 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008082 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308083 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008084 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008085
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008086err_exit_nl_srv:
8087 hdd_exit_netlink_services(hdd_ctx);
8088
8089 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
8090 hdd_err("Failed to deinit policy manager");
8091 /* Proceed and complete the clean up */
8092 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308093 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008094err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05308095 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
8096 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07008097 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308098 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008099
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008100 return -EIO;
8101
8102success:
8103 EXIT();
8104 return 0;
8105}
8106
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008107/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308108 * hdd_wlan_update_target_info() - update target type info
8109 * @hdd_ctx: HDD context
8110 * @context: hif context
8111 *
8112 * Update target info received from firmware in hdd context
8113 * Return:None
8114 */
8115
8116void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
8117{
8118 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
8119
8120 if (!tgt_info) {
8121 hdd_err("Target info is Null");
8122 return;
8123 }
8124
8125 hdd_ctx->target_type = tgt_info->target_type;
8126}
8127
8128/**
8129 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308130 * @hdd_ctx: HDD context
8131 *
8132 * Register the HDD callbacks to CDS/SME.
8133 *
8134 * Return: 0 for success or Error code for failure
8135 */
8136int hdd_register_cb(hdd_context_t *hdd_ctx)
8137{
8138 QDF_STATUS status;
8139 int ret = 0;
8140
8141 ENTER();
8142
8143 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
8144
8145 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
8146 hdd_send_oem_data_rsp_msg);
8147
8148 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
8149 wlan_hdd_cfg80211_fw_mem_dump_cb);
8150 if (!QDF_IS_STATUS_SUCCESS(status)) {
8151 hdd_err("Failed to register memdump callback");
8152 ret = -EINVAL;
8153 return ret;
8154 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05308155 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
8156 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308157 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
8158 sme_nan_register_callback(hdd_ctx->hHal,
8159 wlan_hdd_cfg80211_nan_callback);
8160 sme_stats_ext_register_callback(hdd_ctx->hHal,
8161 wlan_hdd_cfg80211_stats_ext_callback);
8162
8163 sme_ext_scan_register_callback(hdd_ctx->hHal,
8164 wlan_hdd_cfg80211_extscan_callback);
8165
8166 status = cds_register_sap_restart_channel_switch_cb(
8167 (void *)hdd_sap_restart_with_channel_switch);
8168 if (!QDF_IS_STATUS_SUCCESS(status)) {
8169 hdd_err("restart cb registration failed");
8170 ret = -EINVAL;
8171 return ret;
8172 }
8173
8174 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
8175 hdd_rssi_threshold_breached);
8176
8177 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
8178 hdd_get_bpf_offload_cb);
8179 if (!QDF_IS_STATUS_SUCCESS(status)) {
8180 hdd_err("set bpf offload callback failed");
8181 ret = -EINVAL;
8182 return ret;
8183 }
8184
8185 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
8186 wlan_hdd_cfg80211_link_layer_stats_callback);
8187
8188 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
8189
8190 EXIT();
8191
8192 return ret;
8193}
8194
8195/**
8196 * hdd_deregister_cb() - De-Register HDD callbacks.
8197 * @hdd_ctx: HDD context
8198 *
8199 * De-Register the HDD callbacks to CDS/SME.
8200 *
8201 * Return: void
8202 */
8203void hdd_deregister_cb(hdd_context_t *hdd_ctx)
8204{
8205 QDF_STATUS status;
8206
8207 ENTER();
8208
8209 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
8210 if (!QDF_IS_STATUS_SUCCESS(status))
8211 hdd_err("De-register of dcc stats callback failed: %d",
8212 status);
8213
8214 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
8215 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
8216 if (!QDF_IS_STATUS_SUCCESS(status))
8217 hdd_err("De-register bpf offload callback failed: %d",
8218 status);
8219 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
8220
8221 status = cds_deregister_sap_restart_channel_switch_cb();
8222 if (!QDF_IS_STATUS_SUCCESS(status))
8223 hdd_err("De-register restart cb registration failed: %d",
8224 status);
8225
8226 sme_stats_ext_register_callback(hdd_ctx->hHal,
8227 wlan_hdd_cfg80211_stats_ext_callback);
8228
8229 sme_nan_deregister_callback(hdd_ctx->hHal);
8230 status = sme_reset_tsfcb(hdd_ctx->hHal);
8231 if (!QDF_IS_STATUS_SUCCESS(status))
8232 hdd_err("Failed to de-register tsfcb the callback:%d",
8233 status);
8234 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
8235 if (!QDF_IS_STATUS_SUCCESS(status))
8236 hdd_err("Failed to de-register the fw mem dump callback: %d",
8237 status);
8238
8239 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
8240 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
8241
8242 EXIT();
8243}
8244
8245/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008246 * hdd_softap_sta_deauth() - handle deauth req from HDD
8247 * @adapter: Pointer to the HDD
8248 * @enable: bool value
8249 *
8250 * This to take counter measure to handle deauth req from HDD
8251 *
8252 * Return: None
8253 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308254QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008255 struct tagCsrDelStaParams *pDelStaParams)
8256{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308257 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008258
8259 ENTER();
8260
Jeff Johnson34c88b72016-08-15 14:27:11 -07008261 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008262 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8263
8264 /* Ignore request to deauth bcmc station */
8265 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308266 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008267
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308268 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008269 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8270 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008271
8272 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308273 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008274}
8275
8276/**
8277 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
8278 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308279 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008280 *
8281 * This to take counter measure to handle deauth req from HDD
8282 *
8283 * Return: None
8284 */
8285void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308286 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008287{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008288 ENTER();
8289
Jeff Johnson34c88b72016-08-15 14:27:11 -07008290 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008291 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8292
8293 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308294 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008295 return;
8296
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008297 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308298 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008299}
8300
8301void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
8302 bool enable)
8303{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008304 ENTER();
8305
Jeff Johnson34c88b72016-08-15 14:27:11 -07008306 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008307 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008309 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8310 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008311}
8312
8313/**
8314 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
8315 * @hdd_ctx: HDD Context
8316 *
8317 * API to find if there is any STA or P2P-Client is connected
8318 *
8319 * Return: true if connected; false otherwise
8320 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308321QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008322{
8323 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
8324}
8325
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008326/**
8327 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
8328 * @adapter: HDD adapter pointer
8329 *
8330 * This function loop through each adapter and disable roaming on each STA
8331 * device mode except the input adapter.
8332 *
8333 * Note: On the input adapter roaming is not enabled yet hence no need to
8334 * disable.
8335 *
8336 * Return: None
8337 */
8338void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8339{
8340 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8341 hdd_adapter_t *adapterIdx = NULL;
8342 hdd_adapter_list_node_t *adapterNode = NULL;
8343 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308344 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008345
8346 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8347 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008348 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008349 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008350 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008351 adapter->sessionId);
8352 /*
8353 * Loop through adapter and disable roaming for each STA device
8354 * mode except the input adapter.
8355 */
8356 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8357
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308358 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008359 adapterIdx = adapterNode->pAdapter;
8360
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008361 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008362 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008363 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008364 adapterIdx->sessionId);
8365 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8366 (adapterIdx),
8367 adapterIdx->sessionId, 0);
8368 }
8369
8370 status = hdd_get_next_adapter(hdd_ctx,
8371 adapterNode,
8372 &pNext);
8373 adapterNode = pNext;
8374 }
8375 }
8376}
8377
8378/**
8379 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8380 * @adapter: HDD adapter pointer
8381 *
8382 * This function loop through each adapter and enable roaming on each STA
8383 * device mode except the input adapter.
8384 * Note: On the input adapter no need to enable roaming because link got
8385 * disconnected on this.
8386 *
8387 * Return: None
8388 */
8389void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8390{
8391 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8392 hdd_adapter_t *adapterIdx = NULL;
8393 hdd_adapter_list_node_t *adapterNode = NULL;
8394 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308395 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008396
8397 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8398 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008399 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008400 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008401 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008402 adapter->sessionId);
8403 /*
8404 * Loop through adapter and enable roaming for each STA device
8405 * mode except the input adapter.
8406 */
8407 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8408
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308409 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008410 adapterIdx = adapterNode->pAdapter;
8411
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008412 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008413 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008414 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008415 adapterIdx->sessionId);
8416 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8417 (adapterIdx),
8418 adapterIdx->sessionId,
8419 REASON_CONNECT);
8420 }
8421
8422 status = hdd_get_next_adapter(hdd_ctx,
8423 adapterNode,
8424 &pNext);
8425 adapterNode = pNext;
8426 }
8427 }
8428}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008429
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308430void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008431{
8432 struct sk_buff *skb;
8433 struct nlmsghdr *nlh;
8434 tAniMsgHdr *ani_hdr;
8435 void *nl_data = NULL;
8436 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308437 struct radio_index_tlv *radio_info;
8438 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008439
8440 if (in_interrupt() || irqs_disabled() || in_atomic())
8441 flags = GFP_ATOMIC;
8442
8443 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8444
8445 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008446 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008447 return;
8448 }
8449
8450 nlh = (struct nlmsghdr *)skb->data;
8451 nlh->nlmsg_pid = 0; /* from kernel */
8452 nlh->nlmsg_flags = 0;
8453 nlh->nlmsg_seq = 0;
8454 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8455
8456 ani_hdr = NLMSG_DATA(nlh);
8457 ani_hdr->type = type;
8458
8459 switch (type) {
8460 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05308461 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008462 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008463 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008464 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008465 ani_hdr->length = 0;
8466 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8467 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8468 break;
8469 case WLAN_SVC_WLAN_STATUS_IND:
8470 case WLAN_SVC_WLAN_VERSION_IND:
8471 case WLAN_SVC_DFS_CAC_START_IND:
8472 case WLAN_SVC_DFS_CAC_END_IND:
8473 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8474 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8475 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008476 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308477 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008478 ani_hdr->length = len;
8479 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8480 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8481 memcpy(nl_data, data, len);
8482 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
8483 break;
8484
8485 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008486 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008487 type);
8488 kfree_skb(skb);
8489 return;
8490 }
8491
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308492 /*
8493 * Add radio index at the end of the svc event in TLV format to maintain
8494 * the backward compatibility with userspace applications.
8495 */
8496
8497 tlv_len = 0;
8498
8499 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8500 < WLAN_NL_MAX_PAYLOAD) {
8501 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8502 sizeof(*ani_hdr) + len);
8503 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8504 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8505 radio_info->radio = radio;
8506 tlv_len = sizeof(*radio_info);
8507 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8508 "Added radio index tlv - radio index %d",
8509 radio_info->radio);
8510 }
8511
8512 nlh->nlmsg_len += tlv_len;
8513 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8514
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008515 nl_srv_bcast(skb);
8516
8517 return;
8518}
8519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008520#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8521void wlan_hdd_auto_shutdown_cb(void)
8522{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008523 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308524
8525 if (!hdd_ctx)
8526 return;
8527
Jeff Johnson28f8a772016-08-15 15:30:36 -07008528 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308529 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8530 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008531}
8532
8533void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8534{
8535 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308536 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008537 hdd_adapter_t *adapter;
8538 bool ap_connected = false, sta_connected = false;
8539 tHalHandle hal_handle;
8540
8541 hal_handle = hdd_ctx->hHal;
8542 if (hal_handle == NULL)
8543 return;
8544
8545 if (hdd_ctx->config->WlanAutoShutdown == 0)
8546 return;
8547
8548 if (enable == false) {
8549 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308550 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008551 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008552 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308553 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008554 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008555 return;
8556 }
8557
8558 /* To enable shutdown timer check conncurrency */
8559 if (cds_concurrent_open_sessions_running()) {
8560 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8561
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308562 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563 adapter = adapterNode->pAdapter;
8564 if (adapter
8565 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008566 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008567 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8568 conn_info.connState ==
8569 eConnectionState_Associated) {
8570 sta_connected = true;
8571 break;
8572 }
8573 }
8574 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008575 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008576 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8577 bApActive == true) {
8578 ap_connected = true;
8579 break;
8580 }
8581 }
8582 status = hdd_get_next_adapter(hdd_ctx,
8583 adapterNode,
8584 &pNext);
8585 adapterNode = pNext;
8586 }
8587 }
8588
8589 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008590 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008591 return;
8592 } else {
8593 if (sme_set_auto_shutdown_timer(hal_handle,
8594 hdd_ctx->config->
8595 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308596 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008597 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008598 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008599 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008600 hdd_ctx->config->WlanAutoShutdown);
8601
8602 }
8603}
8604#endif
8605
8606hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8607 bool check_start_bss)
8608{
8609 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8610 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308611 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008612 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8613
8614 con_sap_adapter = NULL;
8615
8616 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308617 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008618 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008619 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8620 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008621 adapter != this_sap_adapter) {
8622 if (check_start_bss) {
8623 if (test_bit(SOFTAP_BSS_STARTED,
8624 &adapter->event_flags)) {
8625 con_sap_adapter = adapter;
8626 break;
8627 }
8628 } else {
8629 con_sap_adapter = adapter;
8630 break;
8631 }
8632 }
8633 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8634 adapterNode = pNext;
8635 }
8636
8637 return con_sap_adapter;
8638}
8639
8640#ifdef MSM_PLATFORM
8641void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8642{
8643 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8644
Anurag Chouhan210db072016-02-22 18:42:15 +05308645 if (QDF_TIMER_STATE_RUNNING ==
8646 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008647 return;
8648
Anurag Chouhan210db072016-02-22 18:42:15 +05308649 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008650 hdd_ctx->config->busBandwidthComputeInterval);
8651}
8652
8653void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8654{
8655 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308656 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008657 bool can_stop = true;
8658 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8659
Anurag Chouhan210db072016-02-22 18:42:15 +05308660 if (QDF_TIMER_STATE_RUNNING !=
8661 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008662 /* trying to stop timer, when not running is not good */
Srinivas Girigowda0ee96442016-08-17 19:10:56 -07008663 hdd_info("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008664 return;
8665 }
8666
8667 if (cds_concurrent_open_sessions_running()) {
8668 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8669
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308670 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008671 adapter = adapterNode->pAdapter;
8672 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008673 && (adapter->device_mode == QDF_STA_MODE
8674 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008675 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8676 conn_info.connState ==
8677 eConnectionState_Associated) {
8678 can_stop = false;
8679 break;
8680 }
8681 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008682 && (adapter->device_mode == QDF_SAP_MODE
8683 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008684 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8685 true) {
8686 can_stop = false;
8687 break;
8688 }
8689 status = hdd_get_next_adapter(hdd_ctx,
8690 adapterNode,
8691 &pNext);
8692 adapterNode = pNext;
8693 }
8694 }
8695
Ravi Joshib89e7f72016-09-07 13:43:15 -07008696 if (can_stop == true) {
Anurag Chouhan210db072016-02-22 18:42:15 +05308697 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Ravi Joshib89e7f72016-09-07 13:43:15 -07008698 hdd_reset_tcp_delack(hdd_ctx);
8699 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008700}
8701#endif
8702
8703/**
8704 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8705 * and sta's operating channel.
8706 * @sta_adapter: Describe the first argument to foobar.
8707 * @ap_adapter: Describe the second argument to foobar.
8708 * @roam_profile: Roam profile of AP to which STA wants to connect.
8709 * @concurrent_chnl_same: If both SAP and STA channels are same then
8710 * set this flag to true else false.
8711 *
8712 * This function checks the sap's operating channel and sta's operating channel.
8713 * if both are same then it will return false else it will restart the sap in
8714 * sta's channel and return true.
8715 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308716 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008717 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308718QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008719 hdd_adapter_t *ap_adapter,
8720 tCsrRoamProfile *roam_profile,
8721 tScanResultHandle *scan_cache,
8722 bool *concurrent_chnl_same)
8723{
8724 hdd_ap_ctx_t *hdd_ap_ctx;
8725 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308726 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008727 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008728 *concurrent_chnl_same = true;
8729
8730 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8731 status =
8732 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8733 roam_profile,
8734 scan_cache,
8735 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308736 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008737 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008738 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8739 if (hdd_ap_ctx->operatingChannel != channel_id) {
8740 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008741 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008742 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008743 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008744 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8745 if (hdd_ap_ctx->operatingChannel != channel_id) {
8746 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008747 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008748 }
8749 }
8750 } else {
8751 /*
8752 * Lets handle worst case scenario here, Scan cache lookup is
8753 * failed so we have to stop the SAP to avoid any channel
8754 * discrepancy between SAP's channel and STA's channel.
8755 * Return the status as failure so caller function could know
8756 * that scan look up is failed.
8757 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008758 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308759 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008760 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308761 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008762}
8763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008764/**
8765 * wlan_hdd_stop_sap() - This function stops bss of SAP.
8766 * @ap_adapter: SAP adapter
8767 *
8768 * This function will process the stopping of sap adapter.
8769 *
8770 * Return: None
8771 */
8772void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
8773{
8774 hdd_ap_ctx_t *hdd_ap_ctx;
8775 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308776 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008777 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008778
8779 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008780 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008781 return;
8782 }
8783
8784 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8785 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308786 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008787 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308788
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008789 mutex_lock(&hdd_ctx->sap_lock);
8790 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08008791 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008792 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
8793 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008794 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308795 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308796 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008797 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05308798 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308799 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008800 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308801 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008802 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008803 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008804 return;
8805 }
8806 }
8807 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008808 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008809 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008810 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008811 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008812 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008813 }
8814 mutex_unlock(&hdd_ctx->sap_lock);
8815 return;
8816}
8817
8818/**
8819 * wlan_hdd_start_sap() - this function starts bss of SAP.
8820 * @ap_adapter: SAP adapter
8821 *
8822 * This function will process the starting of sap adapter.
8823 *
8824 * Return: None
8825 */
8826void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
8827{
8828 hdd_ap_ctx_t *hdd_ap_ctx;
8829 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308830 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008831 hdd_context_t *hdd_ctx;
8832 tsap_Config_t *sap_config;
8833
8834 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008835 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008836 return;
8837 }
8838
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008839 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07008840 hdd_err("SoftAp role has not been enabled");
8841 return;
8842 }
8843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008844 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
8845 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8846 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8847 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
8848
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308849 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008850 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308851
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008852 mutex_lock(&hdd_ctx->sap_lock);
8853 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
8854 goto end;
8855
8856 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008857 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008858 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
8859 goto end;
8860 }
8861
8862 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
8863 &hdd_ap_ctx->sapConfig,
8864 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308865 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008866 goto end;
8867
Jeff Johnson28f8a772016-08-15 15:30:36 -07008868 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308869 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008870 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308871 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008872 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008873 goto end;
8874 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07008875 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008876 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008877 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008878 ap_adapter->sessionId);
8879 hostapd_state->bCommit = true;
8880
8881end:
8882 mutex_unlock(&hdd_ctx->sap_lock);
8883 return;
8884}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008885
8886/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08008887 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
8888 * mac scan config
8889 * @status: Status of set antenna mode
8890 *
8891 * Callback on setting the dual mac configuration
8892 *
8893 * Return: None
8894 */
8895void wlan_hdd_soc_set_antenna_mode_cb(
8896 enum set_antenna_mode_status status)
8897{
8898 hdd_context_t *hdd_ctx;
8899
8900 hdd_info("Status: %d", status);
8901
8902 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8903 if (0 != wlan_hdd_validate_context(hdd_ctx))
8904 return;
8905
8906 /* Signal the completion of set dual mac config */
8907 complete(&hdd_ctx->set_antenna_mode_cmpl);
8908}
8909
8910/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008911 * hdd_get_fw_version() - Get FW version
8912 * @hdd_ctx: pointer to HDD context.
8913 * @major_spid: FW version - major spid.
8914 * @minor_spid: FW version - minor spid
8915 * @ssid: FW version - ssid
8916 * @crmid: FW version - crmid
8917 *
8918 * This function is called to get the firmware build version stored
8919 * as part of the HDD context
8920 *
8921 * Return: None
8922 */
8923void hdd_get_fw_version(hdd_context_t *hdd_ctx,
8924 uint32_t *major_spid, uint32_t *minor_spid,
8925 uint32_t *siid, uint32_t *crmid)
8926{
8927 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
8928 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
8929 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
8930 *crmid = hdd_ctx->target_fw_version & 0x7fff;
8931}
8932
8933#ifdef QCA_CONFIG_SMP
8934/**
8935 * wlan_hdd_get_cpu() - get cpu_index
8936 *
8937 * Return: cpu_index
8938 */
8939int wlan_hdd_get_cpu(void)
8940{
8941 int cpu_index = get_cpu();
8942 put_cpu();
8943 return cpu_index;
8944}
8945#endif
8946
8947/**
8948 * hdd_get_fwpath() - get framework path
8949 *
8950 * This function is used to get the string written by
8951 * userspace to start the wlan driver
8952 *
8953 * Return: string
8954 */
8955const char *hdd_get_fwpath(void)
8956{
8957 return fwpath.string;
8958}
8959
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008960/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008961 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008962 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008963 * This function initilizes CDS global context with the help of cds_init. This
8964 * has to be the first function called after probe to get a valid global
8965 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008966 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008967 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008968 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008969int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008970{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008971 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008972 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008973
8974#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8975 wlan_logging_sock_init_svc();
8976#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008977 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008978
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008979 if (p_cds_context == NULL) {
8980 hdd_alert("Failed to allocate CDS context");
8981 ret = -ENOMEM;
8982 goto err_out;
8983 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008984
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008985 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308986 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008987
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008988err_out:
8989 return ret;
8990}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008991
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008992/**
8993 * hdd_deinit() - Deinitialize Driver
8994 *
8995 * This function frees CDS global context with the help of cds_deinit. This
8996 * has to be the last function call in remove callback to free the global
8997 * context.
8998 */
8999void hdd_deinit(void)
9000{
9001 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009002
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009003#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9004 wlan_logging_sock_deinit_svc();
9005#endif
9006}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009007
9008#ifdef QCA_WIFI_3_0_ADRASTEA
9009#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
9010#else
9011#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
9012#endif
9013
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009014/**
9015 * __hdd_module_init - Module init helper
9016 *
9017 * Module init helper function used by both module and static driver.
9018 *
9019 * Return: 0 for success, errno on failure
9020 */
9021static int __hdd_module_init(void)
9022{
9023 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009024
Arun Khandavallifae92942016-08-01 13:31:08 +05309025 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009026 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009027
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009028 pld_init();
9029
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309030 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009031
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009032 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009033
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009034 ret = wlan_hdd_register_driver();
9035 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07009036 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
9037 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009038 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009039 }
9040
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309041 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009042
9043 return 0;
9044out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309045 qdf_wake_lock_destroy(&wlan_wake_lock);
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009046 pld_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009047 return ret;
9048}
9049
9050/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309051 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
9052 *
9053 * Block the unloading of the driver until the cds recovery is completed
9054 *
9055 * Return: None
9056 */
9057static void hdd_wait_for_recovery_completion(void)
9058{
9059 int retry = 0;
9060
9061 /* Wait for recovery to complete */
9062 while (cds_is_driver_recovering()) {
9063 hdd_alert("Recovery in progress; wait here!!!");
9064 msleep(1000);
9065 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
9066 hdd_alert("SSR never completed, fatal error");
9067 QDF_BUG(0);
9068 }
9069 }
9070}
9071
9072/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009073 * __hdd_module_exit - Module exit helper
9074 *
9075 * Module exit helper function used by both module and static driver.
9076 */
9077static void __hdd_module_exit(void)
9078{
9079 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
9080 QWLAN_VERSIONSTR);
9081
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309082 hdd_wait_for_recovery_completion();
9083
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009084 wlan_hdd_unregister_driver();
9085
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309086 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009087
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009088 pld_deinit();
9089
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009090 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009091}
9092
Arun Khandavallifae92942016-08-01 13:31:08 +05309093#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009094/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309095 * wlan_boot_cb() - Wlan boot callback
9096 * @kobj: object whose directory we're creating the link in.
9097 * @attr: attribute the user is interacting with
9098 * @buff: the buffer containing the user data
9099 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009100 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309101 * This callback is invoked when the fs is ready to start the
9102 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009103 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309104 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009105 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309106static ssize_t wlan_boot_cb(struct kobject *kobj,
9107 struct kobj_attribute *attr,
9108 const char *buf,
9109 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009110{
Arun Khandavallifae92942016-08-01 13:31:08 +05309111
9112 int ret = 0;
9113
9114 if (wlan_loader->loaded_state) {
9115 pr_info("Wlan driver already initialized");
9116 return 0;
9117 }
9118
9119
9120 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9121 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9122
9123 if (__hdd_module_init()) {
9124 pr_err("%s: Failed to register handler\n", __func__);
9125 ret = -EINVAL;
9126 } else
9127 wlan_loader->loaded_state = MODULE_INITIALIZED;
9128
9129 return count;
9130
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009131}
Arun Khandavallifae92942016-08-01 13:31:08 +05309132
9133/**
9134 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
9135 * ready
9136 *
9137 * This is creates the syfs entry boot_wlan. Which shall be invoked
9138 * when the filesystem is ready.
9139 *
9140 * Return: None
9141 */
9142static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009143{
Arun Khandavallifae92942016-08-01 13:31:08 +05309144 int ret = -EINVAL;
9145
9146 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
9147 if (!wlan_loader) {
9148 pr_err("%s: memory alloc failed\n", __func__);
9149 ret = -ENOMEM;
9150 return ret;
9151 }
9152
9153 wlan_loader->boot_wlan_obj = NULL;
9154 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
9155 GFP_KERNEL);
9156 if (!wlan_loader->attr_group) {
9157 pr_err("%s: malloc attr_group failed\n", __func__);
9158 ret = -ENOMEM;
9159 goto error_return;
9160 }
9161
9162 wlan_loader->loaded_state = 0;
9163 wlan_loader->attr_group->attrs = attrs;
9164
9165 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
9166 kernel_kobj);
9167 if (!wlan_loader->boot_wlan_obj) {
9168 pr_err("%s: sysfs create and add failed\n", __func__);
9169 ret = -ENOMEM;
9170 goto error_return;
9171 }
9172
9173 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
9174 wlan_loader->attr_group);
9175 if (ret) {
9176 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
9177 goto error_return;
9178 }
9179
9180 return 0;
9181
9182error_return:
9183
9184 if (wlan_loader->boot_wlan_obj) {
9185 kobject_del(wlan_loader->boot_wlan_obj);
9186 wlan_loader->boot_wlan_obj = NULL;
9187 }
9188
9189 return ret;
9190}
9191
9192/**
9193 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
9194 *
9195 * Return: 0 on success or errno on failure
9196 */
9197static int wlan_deinit_sysfs(void)
9198{
9199
9200 if (!wlan_loader) {
9201 hdd_alert("wlan loader context is Null!");
9202 return -EINVAL;
9203 }
9204
9205 if (wlan_loader->boot_wlan_obj) {
9206 sysfs_remove_group(wlan_loader->boot_wlan_obj,
9207 wlan_loader->attr_group);
9208 kobject_del(wlan_loader->boot_wlan_obj);
9209 wlan_loader->boot_wlan_obj = NULL;
9210 }
9211
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009212 return 0;
9213}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009214
Arun Khandavallifae92942016-08-01 13:31:08 +05309215#endif
9216
9217#ifdef MODULE
9218/**
9219 * __hdd_module_init - Module init helper
9220 *
9221 * Module init helper function used by both module and static driver.
9222 *
9223 * Return: 0 for success, errno on failure
9224 */
9225static int hdd_module_init(void)
9226{
9227 int ret = 0;
9228
9229 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9230 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9231
9232 if (__hdd_module_init()) {
9233 pr_err("%s: Failed to register handler\n", __func__);
9234 ret = -EINVAL;
9235 }
9236
9237 return ret;
9238}
9239#else
9240static int __init hdd_module_init(void)
9241{
9242 int ret = -EINVAL;
9243
9244 ret = wlan_init_sysfs();
9245 if (!ret)
9246 pr_err("Failed to create sysfs entry for loading wlan");
9247
9248 return ret;
9249}
9250#endif
9251
9252
9253#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009254/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009255 * hdd_module_exit() - Exit function
9256 *
9257 * This is the driver exit point (invoked when module is unloaded using rmmod)
9258 *
9259 * Return: None
9260 */
9261static void __exit hdd_module_exit(void)
9262{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009263 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009264}
Arun Khandavallifae92942016-08-01 13:31:08 +05309265#else
9266static void __exit hdd_module_exit(void)
9267{
9268 __hdd_module_exit();
9269 wlan_deinit_sysfs();
9270}
9271#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009272
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009273static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
9274{
9275 return param_set_copystring(kmessage, kp);
9276}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009277
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309278/**
9279 * is_con_mode_valid() check con mode is valid or not
9280 * @mode: global con mode
9281 *
9282 * Return: TRUE on success FALSE on failure
9283 */
9284static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
9285{
9286 switch (mode) {
9287 case QDF_GLOBAL_MONITOR_MODE:
9288 case QDF_GLOBAL_FTM_MODE:
9289 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309290 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309291 return true;
9292 default:
9293 return false;
9294 }
9295}
9296
9297/**
9298 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
9299 * @mode: global con mode
9300 *
9301 * Return: adapter mode
9302 */
9303static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
9304 enum tQDF_GLOBAL_CON_MODE mode)
9305{
9306
9307 switch (mode) {
9308 case QDF_GLOBAL_MISSION_MODE:
9309 return QDF_STA_MODE;
9310 case QDF_GLOBAL_MONITOR_MODE:
9311 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309312 case QDF_GLOBAL_EPPING_MODE:
9313 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309314 case QDF_GLOBAL_FTM_MODE:
9315 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309316 case QDF_GLOBAL_QVIT_MODE:
9317 return QDF_QVIT_MODE;
9318 default:
9319 return QDF_MAX_NO_OF_MODE;
9320 }
9321}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009322
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309323static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
9324 enum tQDF_GLOBAL_CON_MODE curr_mode)
9325{
9326 switch (curr_mode) {
9327 case QDF_GLOBAL_MISSION_MODE:
9328 case QDF_GLOBAL_MONITOR_MODE:
9329 case QDF_GLOBAL_FTM_MODE:
9330 hdd_abort_mac_scan_all_adapters(hdd_ctx);
9331 hdd_stop_all_adapters(hdd_ctx);
9332 hdd_deinit_all_adapters(hdd_ctx, false);
9333 hdd_close_all_adapters(hdd_ctx, false);
9334 break;
9335 case QDF_GLOBAL_EPPING_MODE:
9336 epping_disable();
9337 epping_close();
9338 break;
9339 default:
9340 return;
9341 }
9342}
9343
9344static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
9345 enum tQDF_GLOBAL_CON_MODE mode)
9346{
9347 hdd_adapter_t *adapter;
9348 int ret = 0;
9349 bool rtnl_held;
9350 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
9351 QDF_STATUS status;
9352
9353 if (!qdf_dev) {
9354 hdd_err("qdf device context is Null return!");
9355 return -EINVAL;
9356 }
9357
9358 rtnl_held = hdd_hold_rtnl_lock();
9359 switch (mode) {
9360 case QDF_GLOBAL_MISSION_MODE:
9361 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
9362 if (IS_ERR(adapter)) {
9363 hdd_alert("Failed to open interface, adapter is NULL");
9364 ret = -EINVAL;
9365 }
9366 break;
9367 case QDF_GLOBAL_FTM_MODE:
9368 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
9369 wlan_hdd_get_intf_addr(hdd_ctx),
9370 NET_NAME_UNKNOWN, rtnl_held);
9371 if (adapter == NULL)
9372 ret = -EINVAL;
9373 break;
9374 case QDF_GLOBAL_MONITOR_MODE:
9375 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
9376 wlan_hdd_get_intf_addr(hdd_ctx),
9377 NET_NAME_UNKNOWN, rtnl_held);
9378 if (adapter == NULL)
9379 ret = -EINVAL;
9380 break;
9381 case QDF_GLOBAL_EPPING_MODE:
9382 status = epping_open();
9383 if (status != QDF_STATUS_SUCCESS) {
9384 hdd_err("Failed to open in eeping mode: %d", status);
9385 ret = -EINVAL;
9386 break;
9387 }
9388 ret = epping_enable(qdf_dev->dev);
9389 if (ret) {
9390 hdd_err("Failed to enable in epping mode : %d", ret);
9391 epping_close();
9392 }
9393 break;
9394 default:
9395 hdd_info("Mode not supported");
9396 ret = -ENOTSUPP;
9397 break;
9398 }
9399 hdd_release_rtnl_lock();
9400 rtnl_held = false;
9401 return ret;
9402}
9403
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009404/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009405 * con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309406 * @kmessage: con mode name on which driver to be bring up
9407 * @kp: The associated kernel parameter
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009408 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309409 * This function is invoked when user updates con mode using sys entry,
9410 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009411 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309412 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009413 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309414static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
9415 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009416{
9417 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309418 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309419 enum tQDF_GLOBAL_CON_MODE curr_mode;
9420 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309421
9422 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009423
Arun Khandavallifae92942016-08-01 13:31:08 +05309424 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009425 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05309426
Arun Khandavallifae92942016-08-01 13:31:08 +05309427
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309428
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309429 if (!(is_con_mode_valid(con_mode))) {
9430 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309431 ret = -EINVAL;
9432 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309433 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309434
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309435 curr_mode = hdd_get_conparam();
9436 if (curr_mode == con_mode) {
9437 hdd_err("curr mode: %d is same as user triggered mode %d",
9438 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309439 ret = 0;
9440 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309441 }
9442
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309443 /* Cleanup present mode before switching to new mode */
9444 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05309445
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07009446 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309447 if (ret) {
9448 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309449 goto reset_flags;
9450 }
9451
9452 hdd_set_conparam(con_mode);
9453
9454 /* Register for new con_mode & then kick_start modules again */
9455 ret = hdd_register_req_mode(hdd_ctx, con_mode);
9456 if (ret) {
9457 hdd_err("Failed to register for new mode");
9458 goto reset_flags;
9459 }
9460
9461 adapter_mode = hdd_get_adpter_mode(con_mode);
9462 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
9463 hdd_err("invalid adapter");
9464 ret = -EINVAL;
9465 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309466 }
9467
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309468 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309469 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309470 hdd_err("Failed to get adapter:%d", adapter_mode);
9471 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309472 }
9473
9474 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
9475 if (ret) {
9476 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309477 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309478 }
9479
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309480 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
9481 con_mode == QDF_GLOBAL_FTM_MODE) {
9482 if (hdd_start_adapter(adapter)) {
9483 hdd_err("Failed to start %s adapter", kmessage);
9484 ret = -EINVAL;
9485 goto reset_flags;
9486 }
Arun Khandavallifae92942016-08-01 13:31:08 +05309487 }
9488
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309489 hdd_info("Mode successfully changed to %s", kmessage);
9490 ret = 0;
9491
9492reset_flags:
9493 cds_set_load_in_progress(false);
9494 return ret;
9495}
9496
9497
9498static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
9499{
9500 int ret;
9501 hdd_context_t *hdd_ctx;
9502
9503 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9504 ret = wlan_hdd_validate_context(hdd_ctx);
9505 if (ret)
9506 return ret;
9507
9508 cds_ssr_protect(__func__);
9509 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
9510 cds_ssr_unprotect(__func__);
9511
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009512 return ret;
9513}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009514
9515/**
9516 * hdd_get_conparam() - driver exit point
9517 *
9518 * This is the driver exit point (invoked when module is unloaded using rmmod)
9519 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309520 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009521 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309522enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009523{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309524 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009525}
9526
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009527void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009528{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009529 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009530}
9531
Komal Seelamc11bb222016-01-27 18:57:10 +05309532/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309533 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9534 * @hdd_ctx: HDD context
9535 *
9536 * Cleans up the pre cac interface, if it exists
9537 *
9538 * Return: None
9539 */
9540void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9541{
9542 uint8_t session_id;
9543 QDF_STATUS status;
9544 struct hdd_adapter_s *precac_adapter;
9545
9546 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9547 if (QDF_IS_STATUS_ERROR(status)) {
9548 hdd_err("failed to get pre cac vdev id");
9549 return;
9550 }
9551
9552 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9553 if (!precac_adapter) {
9554 hdd_err("invalid pre cac adapater");
9555 return;
9556 }
9557
9558 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9559 wlan_hdd_sap_pre_cac_failure,
9560 (void *)precac_adapter);
9561 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9562
9563}
9564
9565/**
Komal Seelamec702b02016-02-24 18:42:16 +05309566 * hdd_update_ol_config - API to update ol configuration parameters
9567 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309568 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309569 * Return: void
9570 */
Komal Seelamec702b02016-02-24 18:42:16 +05309571static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309572{
Komal Seelamec702b02016-02-24 18:42:16 +05309573 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309574 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309575
Komal Seelamec702b02016-02-24 18:42:16 +05309576 if (!ol_ctx)
9577 return;
9578
9579 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9580 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9581 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9582 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -07009583 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +05309584
9585 ol_init_ini_config(ol_ctx, &cfg);
9586}
9587
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009588#ifdef FEATURE_RUNTIME_PM
9589/**
9590 * hdd_populate_runtime_cfg() - populate runtime configuration
9591 * @hdd_ctx: hdd context
9592 * @cfg: pointer to the configuration memory being populated
9593 *
9594 * Return: void
9595 */
9596static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9597 struct hif_config_info *cfg)
9598{
9599 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9600 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9601}
9602#else
9603static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9604 struct hif_config_info *cfg)
9605{
9606}
9607#endif
9608
Komal Seelamec702b02016-02-24 18:42:16 +05309609/**
9610 * hdd_update_hif_config - API to update HIF configuration parameters
9611 * @hdd_ctx: HDD Context
9612 *
9613 * Return: void
9614 */
9615static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9616{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309617 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309618 struct hif_config_info cfg;
9619
9620 if (!scn)
9621 return;
9622
9623 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009624 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05309625 hif_init_ini_config(scn, &cfg);
9626}
9627
9628/**
9629 * hdd_update_config() - Initialize driver per module ini parameters
9630 * @hdd_ctx: HDD Context
9631 *
9632 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309633 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05309634 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309635int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05309636{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309637 int ret;
9638
Komal Seelamec702b02016-02-24 18:42:16 +05309639 hdd_update_ol_config(hdd_ctx);
9640 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309641 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
9642 ret = hdd_update_cds_config_ftm(hdd_ctx);
9643 else
9644 ret = hdd_update_cds_config(hdd_ctx);
9645
9646 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05309647}
9648
Agrawal Ashish65634612016-08-18 13:24:32 +05309649/**
9650 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
9651 * @mode : cfg80211 DFS mode
9652 *
9653 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
9654 */
9655enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
9656{
9657 switch (mode) {
9658 case DFS_MODE_ENABLE:
9659 return ACS_DFS_MODE_ENABLE;
9660 break;
9661 case DFS_MODE_DISABLE:
9662 return ACS_DFS_MODE_DISABLE;
9663 break;
9664 case DFS_MODE_DEPRIORITIZE:
9665 return ACS_DFS_MODE_DEPRIORITIZE;
9666 break;
9667 default:
9668 hdd_err("ACS dfs mode is NONE");
9669 return ACS_DFS_MODE_NONE;
9670 }
9671}
9672
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309673/**
9674 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
9675 * @hddctx: pointer to hdd context
9676 * @set_value: enable/disable
9677 *
9678 * When Host sends vendor command enable, FW will send *ONE* CA ind to
9679 * Host(even though it is duplicate). When Host send vendor command
9680 * disable,FW doesn't perform any action. Whenever any change in
9681 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
9682 *
9683 * return - 0 on success, appropriate error values on failure.
9684 */
9685int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
9686{
9687 QDF_STATUS status;
9688
9689 if (0 != wlan_hdd_validate_context(hddctx)) {
9690 return -EAGAIN;
9691 }
9692
9693 if (!hddctx->config->goptimize_chan_avoid_event) {
9694 hdd_warn("goptimize_chan_avoid_event ini param disabled");
9695 return -EINVAL;
9696 }
9697
9698 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
9699 if (!QDF_IS_STATUS_SUCCESS(status)) {
9700 hdd_err("Failed to send chan avoid command to SME");
9701 return -EINVAL;
9702 }
9703 return 0;
9704}
Agrawal Ashish65634612016-08-18 13:24:32 +05309705
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009706/* Register the module init/exit functions */
9707module_init(hdd_module_init);
9708module_exit(hdd_module_exit);
9709
9710MODULE_LICENSE("Dual BSD/GPL");
9711MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9712MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009714module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9715 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009716
9717module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
9718 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
9719
9720module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
9721
9722module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
9723
9724module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);