blob: 8a9c02de79b8783069108b873861392cf0d9083d [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnsond9f08602016-12-02 11:31:30 -08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053039#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#include <linux/etherdevice.h>
41#include <linux/firmware.h>
42#include <wlan_hdd_tx_rx.h>
43#include <wni_api.h>
44#include <wlan_hdd_cfg.h>
45#include <wlan_ptt_sock_svc.h>
46#include <dbglog_host.h>
47#include <wlan_logging_sock_svc.h>
48#include <wlan_hdd_wowl.h>
49#include <wlan_hdd_misc.h>
50#include <wlan_hdd_wext.h>
51#include "wlan_hdd_trace.h"
52#include "wlan_hdd_ioctl.h"
53#include "wlan_hdd_ftm.h"
54#include "wlan_hdd_power.h"
55#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070056#include "wlan_hdd_scan.h"
Jeff Johnsonce0032c2017-01-20 07:18:27 -080057#include "wlan_hdd_request_manager.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053058#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053059#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070060#include <cdp_txrx_peer_ops.h>
Dhanashri Atrea8f82f22017-01-23 12:58:24 -080061#include <cdp_txrx_misc.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062
63#include <net/addrconf.h>
64#include <linux/wireless.h>
65#include <net/cfg80211.h>
66#include <linux/inetdevice.h>
67#include <net/addrconf.h>
68#include "wlan_hdd_cfg80211.h"
69#include "wlan_hdd_ext_scan.h"
70#include "wlan_hdd_p2p.h"
71#include <linux/rtnetlink.h>
72#include "sap_api.h"
73#include <linux/semaphore.h>
74#include <linux/ctype.h>
75#include <linux/compat.h>
76#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include <soc/qcom/subsystem_restart.h>
78#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079#include <wlan_hdd_hostapd.h>
80#include <wlan_hdd_softap_tx_rx.h>
81#include "cfg_api.h"
82#include "qwlan_version.h"
83#include "wma_types.h"
84#include "wlan_hdd_tdls.h"
85#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053086#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080087#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070089#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080090#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091#include "wlan_hdd_nan.h"
92#include "wlan_hdd_debugfs.h"
93#include "wlan_hdd_driver_ops.h"
94#include "epping_main.h"
95#include "wlan_hdd_memdump.h"
96
97#include <wlan_hdd_ipa.h>
98#include "hif.h"
99#include "wma.h"
100#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700101#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800102#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530103#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700104#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700105#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530106#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700107#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530108#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800109#include <dispatcher_init_deinit.h>
Rajeev Kumar699debf2017-01-06 14:17:00 -0800110#include "wlan_hdd_object_manager.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530111#include "cds_utils.h"
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -0800112#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800113#include <qca_vendor.h>
Mukul Sharma9d797a02017-01-05 20:26:03 +0530114#include "wlan_pmo_ucfg_api.h"
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +0530115#include "sir_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116
117#ifdef MODULE
118#define WLAN_MODULE_NAME module_name(THIS_MODULE)
119#else
120#define WLAN_MODULE_NAME "wlan"
121#endif
122
123#ifdef TIMER_MANAGER
124#define TIMER_MANAGER_STR " +TIMER_MANAGER"
125#else
126#define TIMER_MANAGER_STR ""
127#endif
128
129#ifdef MEMORY_DEBUG
130#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
131#else
132#define MEMORY_DEBUG_STR ""
133#endif
134
Arun Khandavallifae92942016-08-01 13:31:08 +0530135#ifndef MODULE
136static struct gwlan_loader *wlan_loader;
137static ssize_t wlan_boot_cb(struct kobject *kobj,
138 struct kobj_attribute *attr,
139 const char *buf, size_t count);
140struct gwlan_loader {
141 bool loaded_state;
142 struct kobject *boot_wlan_obj;
143 struct attribute_group *attr_group;
144};
145
146static struct kobj_attribute wlan_boot_attribute =
147 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
148
149static struct attribute *attrs[] = {
150 &wlan_boot_attribute.attr,
151 NULL,
152};
153
154#define MODULE_INITIALIZED 1
155#endif
156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157/* the Android framework expects this param even though we don't use it */
158#define BUF_LEN 20
159static char fwpath_buffer[BUF_LEN];
160static struct kparam_string fwpath = {
161 .string = fwpath_buffer,
162 .maxlen = BUF_LEN,
163};
164
165static char *country_code;
166static int enable_11d = -1;
167static int enable_dfs_chan_scan = -1;
168
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800169/*
170 * spinlock for synchronizing asynchronous request/response
171 * (full description of use in wlan_hdd_main.h)
172 */
173DEFINE_SPINLOCK(hdd_context_lock);
174
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800175#define WLAN_NLINK_CESIUM 30
176
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530177static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178
179#define WOW_MAX_FILTER_LISTS 1
180#define WOW_MAX_FILTERS_PER_LIST 4
181#define WOW_MIN_PATTERN_SIZE 6
182#define WOW_MAX_PATTERN_SIZE 64
183
184#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
185static const struct wiphy_wowlan_support wowlan_support_reg_init = {
186 .flags = WIPHY_WOWLAN_ANY |
187 WIPHY_WOWLAN_MAGIC_PKT |
188 WIPHY_WOWLAN_DISCONNECT |
189 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
190 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
191 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
192 WIPHY_WOWLAN_4WAY_HANDSHAKE |
193 WIPHY_WOWLAN_RFKILL_RELEASE,
194 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
195 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
196 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
197};
198#endif
199
200/* internal function declaration */
201
202struct sock *cesium_nl_srv_sock;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +0530203struct completion wlan_start_comp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
205void wlan_hdd_auto_shutdown_cb(void);
206#endif
207
208/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530209 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
210 * @hdd_ctx: pointer to hdd_context_t
211 *
212 * Return: none
213 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700214static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530215{
216 hdd_adapter_t *adapter;
217 hdd_adapter_list_node_t *adapter_node, *next;
218 QDF_STATUS status = QDF_STATUS_SUCCESS;
219
220 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
221 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
222 adapter = adapter_node->pAdapter;
223 if (NULL != adapter)
224 hdd_send_rps_ind(adapter);
225 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
226 adapter_node = next;
227 }
228}
229
230/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
232 * @vdev_id: vdev_id
233 * @action: action type
234 * @reason: reason type
235 *
236 * Return: none
237 */
238void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
239 enum netif_action_type action, enum netif_reason_type reason)
240{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530241 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800242 hdd_adapter_t *adapter;
243
244 if (!hdd_ctx) {
245 hdd_err("hdd ctx is NULL");
246 return;
247 }
248 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
249
250 wlan_hdd_netif_queue_control(adapter, action, reason);
251 return;
252}
253
254/*
255 * Store WLAN driver version info in a global variable such that crash debugger
256 * can extract it from driver debug symbol and crashdump for post processing
257 */
258uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
259
260/**
261 * hdd_device_mode_to_string() - return string conversion of device mode
262 * @device_mode: device mode
263 *
264 * This utility function helps log string conversion of device mode.
265 *
266 * Return: string conversion of device mode, if match found;
267 * "Unknown" otherwise.
268 */
269const char *hdd_device_mode_to_string(uint8_t device_mode)
270{
271 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800272 CASE_RETURN_STRING(QDF_STA_MODE);
273 CASE_RETURN_STRING(QDF_SAP_MODE);
274 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
275 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
276 CASE_RETURN_STRING(QDF_FTM_MODE);
277 CASE_RETURN_STRING(QDF_IBSS_MODE);
278 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
279 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700280 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 default:
282 return "Unknown";
283 }
284}
285
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530286/**
287 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
288 * @adapter: HDD adapter
289 * @chan_number: Channel number
290 * @chan_bw: Bandwidth
291 *
292 * Checks if the given bandwidth is valid for the given channel number.
293 *
294 * Return: 0 for success, non-zero for failure
295 */
296int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
297 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800298 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530299{
300 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
301 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
302 bool found = false;
303 tHalHandle hal;
304
305 hal = WLAN_HDD_GET_HAL_CTX(adapter);
306 if (!hal) {
307 hdd_err("Invalid HAL context");
308 return -EINVAL;
309 }
310
311 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
312 hdd_err("No valid channel list");
313 return -EOPNOTSUPP;
314 }
315
316 for (i = 0; i < len; i++) {
317 if (chan[i] == chan_number) {
318 found = true;
319 break;
320 }
321 }
322
323 if (found == false) {
324 hdd_err("Channel not in driver's valid channel list");
325 return -EOPNOTSUPP;
326 }
327
328 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
329 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
330 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
331 return -EINVAL;
332 }
333
334 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
335 if (chan_bw == CH_WIDTH_80MHZ) {
336 hdd_err("BW80 not possible in 2.4GHz band");
337 return -EINVAL;
338 }
339 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
340 (chan_bw != CH_WIDTH_MAX)) {
341 hdd_err("Only BW20 possible on channel 14");
342 return -EINVAL;
343 }
344 }
345
346 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
347 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
348 (chan_bw != CH_WIDTH_MAX)) {
349 hdd_err("Only BW20 possible on channel 165");
350 return -EINVAL;
351 }
352 }
353
354 return 0;
355}
356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357static int __hdd_netdev_notifier_call(struct notifier_block *nb,
358 unsigned long state, void *data)
359{
360#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
361 struct netdev_notifier_info *dev_notif_info = data;
362 struct net_device *dev = dev_notif_info->dev;
363#else
364 struct net_device *dev = data;
365#endif
366 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
367 hdd_context_t *hdd_ctx;
368
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800369 ENTER_DEV(dev);
370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 /* Make sure that this callback corresponds to our device. */
372 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
373 return NOTIFY_DONE;
374
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530375 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700377 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 return NOTIFY_DONE;
379 }
380
381 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700382 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 return NOTIFY_DONE;
384 }
385
386 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
387 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700388 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530389 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 return NOTIFY_DONE;
391 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800392 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 return NOTIFY_DONE;
394
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700395 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800396 dev->name, state);
397
398 switch (state) {
399 case NETDEV_REGISTER:
400 break;
401
402 case NETDEV_UNREGISTER:
403 break;
404
405 case NETDEV_UP:
406 sme_ch_avoid_update_req(hdd_ctx->hHal);
407 break;
408
409 case NETDEV_DOWN:
410 break;
411
412 case NETDEV_CHANGE:
413 if (true == adapter->isLinkUpSvcNeeded)
414 complete(&adapter->linkup_event_var);
415 break;
416
417 case NETDEV_GOING_DOWN:
418 if (adapter->scan_info.mScanPending != false) {
419 unsigned long rc;
420 INIT_COMPLETION(adapter->scan_info.
421 abortscan_event_var);
422 hdd_abort_mac_scan(adapter->pHddCtx,
423 adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530424 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425 eCSR_SCAN_ABORT_DEFAULT);
426 rc = wait_for_completion_timeout(
427 &adapter->scan_info.abortscan_event_var,
428 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
429 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700430 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431 }
432 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700433 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800434 }
435 break;
436
437 default:
438 break;
439 }
440
441 return NOTIFY_DONE;
442}
443
444/**
445 * hdd_netdev_notifier_call() - netdev notifier callback function
446 * @nb: pointer to notifier block
447 * @state: state
448 * @ndev: ndev pointer
449 *
450 * Return: 0 on success, error number otherwise.
451 */
452static int hdd_netdev_notifier_call(struct notifier_block *nb,
453 unsigned long state,
454 void *ndev)
455{
456 int ret;
457
458 cds_ssr_protect(__func__);
459 ret = __hdd_netdev_notifier_call(nb, state, ndev);
460 cds_ssr_unprotect(__func__);
461
462 return ret;
463}
464
465struct notifier_block hdd_netdev_notifier = {
466 .notifier_call = hdd_netdev_notifier_call,
467};
468
469/* variable to hold the insmod parameters */
470static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800471
472/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530475/**
476 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
477 * @ch_width: NL channel width
478 *
479 * Converts the NL channel width to the driver's internal representation
480 *
481 * Return: Converted channel width. In case of non matching NL channel width,
482 * CH_WIDTH_MAX will be returned.
483 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800484enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530485{
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800486 uint8_t fw_ch_bw;
487 fw_ch_bw = wma_get_vht_ch_width();
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530488 switch (ch_width) {
489 case NL80211_CHAN_WIDTH_20_NOHT:
490 case NL80211_CHAN_WIDTH_20:
491 return CH_WIDTH_20MHZ;
492 case NL80211_CHAN_WIDTH_40:
493 return CH_WIDTH_40MHZ;
494 break;
495 case NL80211_CHAN_WIDTH_80:
496 return CH_WIDTH_80MHZ;
497 case NL80211_CHAN_WIDTH_80P80:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800498 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
499 return CH_WIDTH_80P80MHZ;
500 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
501 return CH_WIDTH_160MHZ;
502 else
503 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530504 case NL80211_CHAN_WIDTH_160:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800505 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
506 return CH_WIDTH_160MHZ;
507 else
508 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530509 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800510 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530511 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800512 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530513 default:
514 hdd_err("Invalid channel width %d, setting to default",
515 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800516 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530517 }
518}
519
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530520/* wlan_hdd_find_opclass() - Find operating class for a channel
521 * @hal: handler to HAL
522 * @channel: channel id
523 * @bw_offset: bandwidth offset
524 *
525 * Function invokes sme api to find the operating class
526 *
527 * Return: operating class
528 */
529uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
530 uint8_t bw_offset)
531{
532 uint8_t opclass = 0;
533
534 sme_get_opclass(hal, channel, bw_offset, &opclass);
535 return opclass;
536}
537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530539 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530540 * @module_id: Module whose trace level is being configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 * @bitmask: Bitmask of log levels to be enabled
542 *
543 * Called immediately after the cfg.ini is read in order to configure
544 * the desired trace levels.
545 *
546 * Return: None
547 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530548int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530550 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530551 int qdf_print_idx = -1;
552 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 /*
554 * if the bitmask is the default value, then a bitmask was not
555 * specified in cfg.ini, so leave the logging level alone (it
556 * will remain at the "compiled in" default value)
557 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530558 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530559 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800560 }
561
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530562 qdf_print_idx = qdf_get_pidx();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530564 /* a mask was specified. start by disabling all logging */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530565 status = qdf_print_set_category_verbose(qdf_print_idx, module_id,
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530566 QDF_TRACE_LEVEL_NONE, 0);
567
568 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530569 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800570 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530571 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 while (0 != bitmask) {
573 if (bitmask & 1) {
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530574 status = qdf_print_set_category_verbose(qdf_print_idx,
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530575 module_id, level, 1);
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530576 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530577 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 }
579 level++;
580 bitmask >>= 1;
581 }
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530582 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583}
584
585/**
586 * wlan_hdd_validate_context() - check the HDD context
587 * @hdd_ctx: HDD context pointer
588 *
589 * Return: 0 if the context is valid. Error code otherwise
590 */
591int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
592{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530594 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 return -ENODEV;
596 }
597
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800598 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530599 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
600 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 return -EAGAIN;
602 }
603
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800604 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530605 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
606 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607 return -EAGAIN;
608 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530609
610 if (hdd_ctx->start_modules_in_progress ||
611 hdd_ctx->stop_modules_in_progress) {
612 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
613 (void *)_RET_IP_);
614 return -EAGAIN;
615 }
616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 return 0;
618}
619
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620/**
621 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
622 * @hdd_adapter_t Hdd adapter.
623 *
624 * This function sets the IBSS power save config parameters to WMA
625 * which will send it to firmware if FW supports IBSS power save
626 * before vdev start.
627 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530628 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629 * on failure.
630 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530631QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632{
633 int ret;
634 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
635
636 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700637 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530638 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 }
640
641 ret = wma_cli_set_command(adapter->sessionId,
642 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
643 hdd_ctx->config->ibssATIMWinSize,
644 VDEV_CMD);
645 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700646 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530647 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 }
649
650 ret = wma_cli_set_command(adapter->sessionId,
651 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
652 hdd_ctx->config->isIbssPowerSaveAllowed,
653 VDEV_CMD);
654 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700655 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
656 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530657 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 }
659
660 ret = wma_cli_set_command(adapter->sessionId,
661 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
662 hdd_ctx->config->
663 isIbssPowerCollapseAllowed, VDEV_CMD);
664 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700665 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
666 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530667 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668 }
669
670 ret = wma_cli_set_command(adapter->sessionId,
671 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
672 hdd_ctx->config->isIbssAwakeOnTxRx,
673 VDEV_CMD);
674 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700675 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 }
678
679 ret = wma_cli_set_command(adapter->sessionId,
680 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
681 hdd_ctx->config->ibssInactivityCount,
682 VDEV_CMD);
683 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700684 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530685 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 }
687
688 ret = wma_cli_set_command(adapter->sessionId,
689 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
690 hdd_ctx->config->ibssTxSpEndInactivityTime,
691 VDEV_CMD);
692 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700693 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
694 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530695 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 }
697
698 ret = wma_cli_set_command(adapter->sessionId,
699 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
700 hdd_ctx->config->ibssPsWarmupTime,
701 VDEV_CMD);
702 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700703 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
704 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530705 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 }
707
708 ret = wma_cli_set_command(adapter->sessionId,
709 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
710 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
711 VDEV_CMD);
712 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700713 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
714 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530715 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 }
717
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530718 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719}
720
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800721#define INTF_MACADDR_MASK 0x7
722
723/**
724 * hdd_update_macaddr() - update mac address
725 * @config: hdd configuration
726 * @hw_macaddr: mac address
727 *
728 * Mac address for multiple virtual interface is found as following
729 * i) The mac address of the first interface is just the actual hw mac address.
730 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
731 * define the mac address for the remaining interfaces and locally
732 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
733 * supported virtual interfaces, right now this is 0x07 (meaning 8
734 * interface).
735 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
736 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
737 *
738 * Return: None
739 */
740void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530741 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742{
743 int8_t i;
744 uint8_t macaddr_b3, tmp_br3;
745
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530746 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530747 QDF_MAC_ADDR_SIZE);
748 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530749 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530750 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751 macaddr_b3 = config->intfMacAddr[i].bytes[3];
752 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
753 INTF_MACADDR_MASK;
754 macaddr_b3 += tmp_br3;
755
756 /* XOR-ing bit-24 of the mac address. This will give enough
757 * mac address range before collision
758 */
759 macaddr_b3 ^= (1 << 7);
760
761 /* Set locally administered bit */
762 config->intfMacAddr[i].bytes[0] |= 0x02;
763 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700764 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800765 MAC_ADDRESS_STR, i,
766 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
767 }
768}
769
770static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
771 struct wma_tgt_services *cfg)
772{
773 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774
775 /* Set up UAPSD */
776 config->apUapsdEnabled &= cfg->uapsd;
777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 /* 11AC mode support */
779 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
780 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
781 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782
783 /* ARP offload: override user setting if invalid */
784 config->fhostArpOffload &= cfg->arp_offload;
785
786#ifdef FEATURE_WLAN_SCAN_PNO
787 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700788 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789 if (cfg->pno_offload)
790 config->PnoOffload = true;
791#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792#ifdef FEATURE_WLAN_TDLS
793 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530794 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
795 cfg->en_tdls_offchan;
796 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
797 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800798 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
799 config->fEnableTDLSSleepSta = true;
800 } else {
801 config->fEnableTDLSSleepSta = false;
802 }
803#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804#ifdef WLAN_FEATURE_ROAM_OFFLOAD
805 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
806#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700807 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808
809}
810
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700811/**
812 * hdd_update_vdev_nss() - sets the vdev nss
813 * @hdd_ctx: HDD context
814 *
815 * Sets the Nss per vdev type based on INI
816 *
817 * Return: None
818 */
819static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
820{
821 struct hdd_config *cfg_ini = hdd_ctx->config;
822 uint8_t max_supp_nss = 1;
823
Naveen Rawat10b1c152017-01-18 11:16:06 -0800824 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700825 max_supp_nss = 2;
826
827 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
828 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
829
830 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
831 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
832}
833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
835 struct wma_tgt_ht_cap *cfg)
836{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530837 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 uint32_t value, val32;
839 uint16_t val16;
840 struct hdd_config *pconfig = hdd_ctx->config;
841 tSirMacHTCapabilityInfo *phtCapInfo;
842 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
843 uint8_t enable_tx_stbc;
844
845 /* check and update RX STBC */
846 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
847 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
848
849 /* get the MPDU density */
850 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
851
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530852 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700853 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854 value = 0;
855 }
856
857 /*
858 * MPDU density:
859 * override user's setting if value is larger
860 * than the one supported by target
861 */
862 if (value > cfg->mpdu_density) {
863 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
864 cfg->mpdu_density);
865
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530866 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700867 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868 }
869
870 /* get the HT capability info */
871 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530872 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700873 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874 return;
875 }
876 val16 = (uint16_t) val32;
877 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
878
879 /* Set the LDPC capability */
880 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
881
882 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
883 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
884
885 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
886 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
887
888 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
889 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
890
891 enable_tx_stbc = pconfig->enableTxSTBC;
892
893 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
894 pconfig->enable2x2 = 1;
895 } else {
896 pconfig->enable2x2 = 0;
897 enable_tx_stbc = 0;
898
899 /* 1x1 */
900 /* Update Rx Highest Long GI data Rate */
901 if (sme_cfg_set_int(hdd_ctx->hHal,
902 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700903 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530904 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700905 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 }
907
908 /* Update Tx Highest Long GI data Rate */
909 if (sme_cfg_set_int
910 (hdd_ctx->hHal,
911 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700912 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530913 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700914 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800915 }
916 }
917 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
918 enable_tx_stbc = 0;
919 phtCapInfo->txSTBC = enable_tx_stbc;
920
921 val32 = val16;
922 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530923 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700924 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
926 value = SIZE_OF_SUPPORTED_MCS_SET;
927 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530928 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700929 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800930
931 if (pconfig->enable2x2) {
932 for (value = 0; value < cfg->num_rf_chains; value++)
933 mcs_set[value] =
934 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
935
936 status =
937 sme_cfg_set_str(hdd_ctx->hHal,
938 WNI_CFG_SUPPORTED_MCS_SET,
939 mcs_set,
940 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530941 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700942 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943 }
944 }
945#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
946}
947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
949 struct wma_tgt_vht_cap *cfg)
950{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530951 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 uint32_t value = 0;
953 struct hdd_config *pconfig = hdd_ctx->config;
954 struct wiphy *wiphy = hdd_ctx->wiphy;
955 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700956 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700957 uint32_t temp = 0;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800958 uint32_t ch_width = eHT_CHANNEL_WIDTH_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959
Dustin Brown5e06bd32016-10-04 12:49:10 -0700960 if (!band_5g) {
961 hdd_info("5GHz band disabled, skipping capability population");
962 return;
963 }
964
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800965 /* Get the current MPDU length */
966 status =
967 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
968 &value);
969
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530970 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700971 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800972 value = 0;
973 }
974
975 /*
976 * VHT max MPDU length:
977 * override if user configured value is too high
978 * that the target cannot support
979 */
980 if (value > cfg->vht_max_mpdu) {
981 status = sme_cfg_set_int(hdd_ctx->hHal,
982 WNI_CFG_VHT_MAX_MPDU_LENGTH,
983 cfg->vht_max_mpdu);
984
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530985 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700986 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987 }
988 }
989
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700990 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
991 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
992
993 if (pconfig->enable2x2)
994 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
995
996 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
997 QDF_STATUS_E_FAILURE) {
998 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
999 }
1000
1001 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1002 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1003 if (pconfig->enable2x2)
1004 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1005
1006 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1007 QDF_STATUS_E_FAILURE) {
1008 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1009 }
1010
1011 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1012 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1013 if (pconfig->enable2x2)
1014 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1015
1016 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1017 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1018
1019 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1020 QDF_STATUS_E_FAILURE) {
1021 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1022 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001023 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001024 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025 &value);
1026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301027 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001028 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001029 value = 0;
1030 }
1031
1032 /* Set the LDPC capability */
1033 if (value && !cfg->vht_rx_ldpc) {
1034 status = sme_cfg_set_int(hdd_ctx->hHal,
1035 WNI_CFG_VHT_LDPC_CODING_CAP,
1036 cfg->vht_rx_ldpc);
1037
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301038 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001039 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001040 }
1041 }
1042
1043 /* Get current GI 80 value */
1044 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1045 &value);
1046
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301047 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001048 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001049 value = 0;
1050 }
1051
1052 /* set the Guard interval 80MHz */
1053 if (value && !cfg->vht_short_gi_80) {
1054 status = sme_cfg_set_int(hdd_ctx->hHal,
1055 WNI_CFG_VHT_SHORT_GI_80MHZ,
1056 cfg->vht_short_gi_80);
1057
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301058 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001059 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 }
1061 }
1062
1063 /* Get current GI 160 value */
1064 status = sme_cfg_get_int(hdd_ctx->hHal,
1065 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1066 &value);
1067
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301068 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001069 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001070 value = 0;
1071 }
1072
1073 /* Get VHT TX STBC cap */
1074 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1075
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301076 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001077 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 value = 0;
1079 }
1080
1081 /* VHT TX STBC cap */
1082 if (value && !cfg->vht_tx_stbc) {
1083 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1084 cfg->vht_tx_stbc);
1085
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301086 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001087 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001088 }
1089 }
1090
1091 /* Get VHT RX STBC cap */
1092 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1093
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301094 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001095 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001096 value = 0;
1097 }
1098
1099 /* VHT RX STBC cap */
1100 if (value && !cfg->vht_rx_stbc) {
1101 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1102 cfg->vht_rx_stbc);
1103
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301104 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001105 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106 }
1107 }
1108
1109 /* Get VHT SU Beamformer cap */
1110 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1111 &value);
1112
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301113 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001114 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115 value = 0;
1116 }
1117
1118 /* set VHT SU Beamformer cap */
1119 if (value && !cfg->vht_su_bformer) {
1120 status = sme_cfg_set_int(hdd_ctx->hHal,
1121 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1122 cfg->vht_su_bformer);
1123
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301124 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001125 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126 }
1127 }
1128
1129 /* check and update SU BEAMFORMEE capabality */
1130 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1131 pconfig->enableTxBF = cfg->vht_su_bformee;
1132
1133 status = sme_cfg_set_int(hdd_ctx->hHal,
1134 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1135 pconfig->enableTxBF);
1136
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301137 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001138 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139 }
1140
1141 /* Get VHT MU Beamformer cap */
1142 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1143 &value);
1144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301145 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001146 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147 value = 0;
1148 }
1149
1150 /* set VHT MU Beamformer cap */
1151 if (value && !cfg->vht_mu_bformer) {
1152 status = sme_cfg_set_int(hdd_ctx->hHal,
1153 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1154 cfg->vht_mu_bformer);
1155
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301156 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001157 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158 }
1159 }
1160
1161 /* Get VHT MU Beamformee cap */
1162 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1163 &value);
1164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301165 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001166 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001167 value = 0;
1168 }
1169
1170 /* set VHT MU Beamformee cap */
1171 if (value && !cfg->vht_mu_bformee) {
1172 status = sme_cfg_set_int(hdd_ctx->hHal,
1173 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1174 cfg->vht_mu_bformee);
1175
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301176 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001177 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001178 }
1179 }
1180
1181 /* Get VHT MAX AMPDU Len exp */
1182 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1183 &value);
1184
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301185 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001186 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001187 value = 0;
1188 }
1189
1190 /*
1191 * VHT max AMPDU len exp:
1192 * override if user configured value is too high
1193 * that the target cannot support.
1194 * Even though Rome publish ampdu_len=7, it can
1195 * only support 4 because of some h/w bug.
1196 */
1197
1198 if (value > cfg->vht_max_ampdu_len_exp) {
1199 status = sme_cfg_set_int(hdd_ctx->hHal,
1200 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1201 cfg->vht_max_ampdu_len_exp);
1202
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301203 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001204 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205 }
1206 }
1207
1208 /* Get VHT TXOP PS CAP */
1209 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1210
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301211 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001212 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 value = 0;
1214 }
1215
1216 /* set VHT TXOP PS cap */
1217 if (value && !cfg->vht_txop_ps) {
1218 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1219 cfg->vht_txop_ps);
1220
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301221 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001222 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 }
1224 }
1225
1226 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1227 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1228 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1229 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1230 else
1231 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1232
1233
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001234 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1235 status = sme_cfg_set_int(hdd_ctx->hHal,
1236 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1237 VHT_CAP_160_AND_80P80_SUPP);
1238 if (status == QDF_STATUS_E_FAILURE)
1239 hdd_alert("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 band_5g->vht_cap.cap |=
1241 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001242 ch_width = eHT_CHANNEL_WIDTH_80P80MHZ;
1243 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1244 status = sme_cfg_set_int(hdd_ctx->hHal,
1245 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1246 VHT_CAP_160_SUPP);
1247 if (status == QDF_STATUS_E_FAILURE)
1248 hdd_alert("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 band_5g->vht_cap.cap |=
1250 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001251 ch_width = eHT_CHANNEL_WIDTH_160MHZ;
1252 }
1253 pconfig->vhtChannelWidth = QDF_MIN(pconfig->vhtChannelWidth,
1254 ch_width);
1255 /* Get the current supported chan width */
1256 status = sme_cfg_get_int(hdd_ctx->hHal,
1257 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1258 &value);
1259 if (status != QDF_STATUS_SUCCESS) {
1260 hdd_err("could not get CH BW");
1261 value = 0;
1262 }
1263 /* set the Guard interval 80MHz */
1264 if (value) {
1265 status = sme_cfg_set_int(hdd_ctx->hHal,
1266 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1267 cfg->vht_short_gi_160);
1268
1269 if (status == QDF_STATUS_E_FAILURE)
1270 hdd_alert("failed to set SHORT GI 80MHZ");
1271 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272
1273 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1274 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1275
1276 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1277 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1278 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1279 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1280
1281 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1282 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1283
1284 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1285 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1286 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1287 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1288 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1289 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1290
1291 band_5g->vht_cap.cap |=
1292 (cfg->vht_max_ampdu_len_exp <<
1293 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1294
1295 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1296 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1297 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1298 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1299 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1300 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1301 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1302 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1303
1304 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1305 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1306
1307}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001309/**
1310 * hdd_generate_macaddr_auto() - Auto-generate mac address
1311 * @hdd_ctx: Pointer to the HDD context
1312 *
1313 * Auto-generate mac address using device serial number.
1314 * Keep the first 3 bytes of OUI as before and replace
1315 * the last 3 bytes with the lower 3 bytes of serial number.
1316 *
1317 * Return: 0 for success
1318 * Non zero failure code for errors
1319 */
1320static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1321{
1322 unsigned int serialno = 0;
1323 struct qdf_mac_addr mac_addr = {
1324 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1325 };
1326
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001327 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001328 if (serialno == 0)
1329 return -EINVAL;
1330
1331 serialno &= 0x00ffffff;
1332
1333 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1334 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1335 mac_addr.bytes[5] = serialno & 0xff;
1336
1337 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1338 return 0;
1339}
1340
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301341/**
1342 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1343 * configuration to cfg_ini in HDD
1344 * @hdd_ctx: Pointer to hdd_ctx
1345 * @cfg: target configuration
1346 *
1347 * Return: None
1348 */
1349#ifdef FEATURE_WLAN_RA_FILTERING
1350static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1351 struct wma_tgt_cfg *cfg)
1352{
1353 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1354}
1355#else
1356static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1357 struct wma_tgt_cfg *cfg)
1358{
1359}
1360#endif
1361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362void hdd_update_tgt_cfg(void *context, void *param)
1363{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001364 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1366 struct wma_tgt_cfg *cfg = param;
1367 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001368 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301369
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001370 ret = hdd_create_and_store_pdev(hdd_ctx);
1371 if (ret) {
1372 hdd_err("pdev creation fails!");
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301373 QDF_BUG(0);
1374 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001375
1376 if (cds_cfg) {
1377 if (hdd_ctx->config->enable_sub_20_channel_width !=
1378 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1379 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1380 cds_cfg->sub_20_channel_width =
1381 WLAN_SUB_20_CH_WIDTH_NONE;
1382 } else {
1383 cds_cfg->sub_20_channel_width =
1384 hdd_ctx->config->enable_sub_20_channel_width;
1385 }
1386 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387
1388 /* first store the INI band capability */
1389 temp_band_cap = hdd_ctx->config->nBandCapability;
1390
1391 hdd_ctx->config->nBandCapability = cfg->band_cap;
1392
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001393 /*
1394 * now overwrite the target band capability with INI
1395 * setting if INI setting is a subset
1396 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397
1398 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1399 (temp_band_cap != eCSR_BAND_ALL))
1400 hdd_ctx->config->nBandCapability = temp_band_cap;
1401 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1402 (temp_band_cap != eCSR_BAND_ALL) &&
1403 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001404 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405 }
1406
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001407 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1409 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1410 }
1411
1412 /* This can be extended to other configurations like ht, vht cap... */
1413
Anurag Chouhanc5548422016-02-24 18:33:27 +05301414 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001415 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001416 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001418 static struct qdf_mac_addr default_mac_addr = {
1419 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1420 };
1421 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1422 &default_mac_addr)) {
1423 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1424 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1425 MAC_ADDRESS_STR,
1426 MAC_ADDR_ARRAY(hdd_ctx->config->
1427 intfMacAddr[0].bytes));
1428 } else {
1429 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1430 MAC_ADDRESS_STR,
1431 MAC_ADDR_ARRAY(hdd_ctx->config->
1432 intfMacAddr[0].bytes));
1433 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001434 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 }
1436
1437 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001438 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001439
1440 hdd_ctx->max_intf_count = cfg->max_intf_count;
1441
Jeff Johnsonc875e242016-09-23 18:12:34 -07001442 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001443 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001444
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001445 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1446 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1447
1448 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1449
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001451
1452 hdd_update_vdev_nss(hdd_ctx);
1453
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001454 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001455 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001456 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001457 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001458
1459 hdd_ctx->current_antenna_mode =
1460 (hdd_ctx->config->enable2x2 == 0x01) ?
1461 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1462 hdd_info("Init current antenna mode: %d",
1463 hdd_ctx->current_antenna_mode);
1464
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001465 hdd_info("Target BPF %d Host BPF %d",
1466 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1467 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1468 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301469 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301470
Arun Khandavallid454d422016-08-17 12:47:05 +05301471 /*
1472 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1473 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1474 * configure the STA mode wow pattern.
1475 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301476 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301477 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301478
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301479 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1480
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001481 /* Configure NAN datapath features */
1482 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483}
1484
1485/**
1486 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1487 * @context: HDD context pointer
1488 * @param: HDD radar indication pointer
1489 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001490 * This function is invoked in atomic context when a radar
1491 * is found on the SAP current operating channel and Data Tx
1492 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001493 * Actions: Stop the netif Tx queues,Indicate Radar present
1494 * in HDD context for future usage.
1495 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301496 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001497 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301498bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499{
1500 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1501 struct wma_dfs_radar_ind *hdd_radar_event =
1502 (struct wma_dfs_radar_ind *)param;
1503 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1504 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301505 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301506 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001507
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301508 if (!hdd_ctx || !hdd_radar_event ||
1509 hdd_ctx->config->disableDFSChSwitch)
1510 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511
1512 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001513 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301514 /*
1515 * Application already triggered channel switch
1516 * on current channel, so return here.
1517 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301518 return false;
1519 }
1520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301522 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301524 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1525 if ((QDF_SAP_MODE == adapter->device_mode ||
1526 QDF_P2P_GO_MODE == adapter->device_mode) &&
1527 (CHANNEL_STATE_DFS ==
1528 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1530 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301531 hdd_info("tx blocked for session:%d",
1532 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 }
1534
1535 status = hdd_get_next_adapter(hdd_ctx,
1536 adapterNode,
1537 &pNext);
1538 adapterNode = pNext;
1539 }
1540 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301541
1542 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544
1545/**
1546 * hdd_is_valid_mac_address() - validate MAC address
1547 * @pMacAddr: Pointer to the input MAC address
1548 *
1549 * This function validates whether the given MAC address is valid or not
1550 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1551 * where X is the hexa decimal digit character and separated by ':'
1552 * This algorithm works even if MAC address is not separated by ':'
1553 *
1554 * This code checks given input string mac contains exactly 12 hexadecimal
1555 * digits and a separator colon : appears in the input string only after
1556 * an even number of hex digits.
1557 *
1558 * Return: 1 for valid and 0 for invalid
1559 */
1560bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1561{
1562 int xdigit = 0;
1563 int separator = 0;
1564 while (*pMacAddr) {
1565 if (isxdigit(*pMacAddr)) {
1566 xdigit++;
1567 } else if (':' == *pMacAddr) {
1568 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1569 break;
1570
1571 ++separator;
1572 } else {
1573 /* Invalid MAC found */
1574 return 0;
1575 }
1576 ++pMacAddr;
1577 }
1578 return xdigit == 12 && (separator == 5 || separator == 0);
1579}
1580
1581/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301582 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1583 * @dev: Handle to struct net_device to be updated.
1584 *
1585 * Return: None
1586 */
1587static void hdd_mon_mode_ether_setup(struct net_device *dev)
1588{
1589 dev->header_ops = NULL;
1590 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1591 dev->hard_header_len = ETH_HLEN;
1592 dev->mtu = ETH_DATA_LEN;
1593 dev->addr_len = ETH_ALEN;
1594 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1595 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1596 dev->priv_flags |= IFF_TX_SKB_SHARING;
1597
1598 memset(dev->broadcast, 0xFF, ETH_ALEN);
1599}
1600
1601/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001602 * __hdd__mon_open() - HDD Open function
1603 * @dev: Pointer to net_device structure
1604 *
1605 * This is called in response to ifconfig up
1606 *
1607 * Return: 0 for success; non-zero for failure
1608 */
1609static int __hdd_mon_open(struct net_device *dev)
1610{
1611 int ret;
1612
1613 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301614 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001615 ret = hdd_set_mon_rx_cb(dev);
1616 return ret;
1617}
1618
1619/**
1620 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1621 * @dev: Pointer to net_device structure
1622 *
1623 * This is called in response to ifconfig up
1624 *
1625 * Return: 0 for success; non-zero for failure
1626 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001627static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001628{
1629 int ret;
1630
1631 cds_ssr_protect(__func__);
1632 ret = __hdd_mon_open(dev);
1633 cds_ssr_unprotect(__func__);
1634
1635 return ret;
1636}
1637
1638/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301639 * hdd_start_adapter() - Wrapper function for device specific adapter
1640 * @adapter: pointer to HDD adapter
1641 *
1642 * This function is called to start the device specific adapter for
1643 * the mode passed in the adapter's device_mode.
1644 *
1645 * Return: 0 for success; non-zero for failure
1646 */
1647int hdd_start_adapter(hdd_adapter_t *adapter)
1648{
1649
1650 int ret;
1651 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1652
1653 ENTER_DEV(adapter->dev);
1654 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1655
1656 switch (device_mode) {
1657 case QDF_P2P_CLIENT_MODE:
1658 case QDF_P2P_DEVICE_MODE:
1659 case QDF_OCB_MODE:
1660 case QDF_STA_MODE:
1661 case QDF_MONITOR_MODE:
1662 ret = hdd_start_station_adapter(adapter);
1663 if (ret)
1664 goto err_start_adapter;
1665 break;
1666 case QDF_P2P_GO_MODE:
1667 case QDF_SAP_MODE:
1668 ret = hdd_start_ap_adapter(adapter);
1669 if (ret)
1670 goto err_start_adapter;
1671 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301672 case QDF_IBSS_MODE:
1673 /*
1674 * For IBSS interface is initialized as part of
1675 * hdd_init_station_mode()
1676 */
1677 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301678 case QDF_FTM_MODE:
1679 ret = hdd_start_ftm_adapter(adapter);
1680 if (ret)
1681 goto err_start_adapter;
1682 break;
1683 default:
1684 hdd_err("Invalid session type %d", device_mode);
1685 QDF_ASSERT(0);
1686 goto err_start_adapter;
1687 }
1688 if (hdd_set_fw_params(adapter))
1689 hdd_err("Failed to set the FW params for the adapter!");
1690
1691 /*
1692 * Action frame registered in one adapter which will
1693 * applicable to all interfaces
1694 */
1695 wlan_hdd_cfg80211_register_frames(adapter);
1696 EXIT();
1697 return 0;
1698err_start_adapter:
1699 return -EINVAL;
1700}
1701
1702/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301703 * hdd_enable_power_management() - API to Enable Power Management
1704 *
1705 * API invokes Bus Interface Layer power management functionality
1706 *
1707 * Return: None
1708 */
1709static void hdd_enable_power_management(void)
1710{
1711 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1712
1713 if (!hif_ctx) {
1714 hdd_err("Bus Interface Context is Invalid");
1715 return;
1716 }
1717
1718 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1719}
1720
1721/**
1722 * hdd_disable_power_management() - API to disable Power Management
1723 *
1724 * API disable Bus Interface Layer Power management functionality
1725 *
1726 * Return: None
1727 */
1728static void hdd_disable_power_management(void)
1729{
1730 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1731
1732 if (!hif_ctx) {
1733 hdd_err("Bus Interface Context is Invalid");
1734 return;
1735 }
1736
1737 hif_disable_power_management(hif_ctx);
1738}
1739
1740/**
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301741 * hdd_update_hw_sw_info() - API to update the HW/SW information
1742 *
1743 * API to update the HW and SW information in the driver
1744 *
1745 * Return: None
1746 */
1747static void hdd_update_hw_sw_info(hdd_context_t *hdd_ctx)
1748{
1749 void *hif_sc;
1750
1751 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
1752 if (!hif_sc) {
1753 hdd_err("HIF context is NULL");
1754 return;
1755 }
1756
1757 /*
1758 * target hw version/revision would only be retrieved after firmware
1759 * download
1760 */
1761 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
1762 &hdd_ctx->target_hw_revision,
1763 &hdd_ctx->target_hw_name);
1764
1765 /* Get the wlan hw/fw version */
1766 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
1767
1768 return;
1769}
1770
1771/**
gbian62edd7e2017-03-07 13:12:13 +08001772 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
1773 * @hdd_ctx: Pointer to hdd context
1774 *
1775 * Return: none
1776 */
1777static void
1778hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
1779{
1780 uint8_t num_entries = 0;
1781 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
1782 uint8_t *tx_sched_wrr_ac;
1783 int i;
1784 cds_context_type *cds_ctx;
1785
1786 if (NULL == hdd_ctx)
1787 return;
1788
1789 if (NULL == hdd_ctx->config) {
1790 /* Do nothing if hdd_ctx is invalid */
1791 hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
1792 return;
1793 }
1794
1795 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1796
1797 if (!cds_ctx) {
1798 hdd_err("Invalid CDS Context");
1799 return;
1800 }
1801
1802 for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
1803 switch (i) {
1804 case OL_TX_WMM_AC_BE:
1805 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
1806 break;
1807 case OL_TX_WMM_AC_BK:
1808 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
1809 break;
1810 case OL_TX_WMM_AC_VI:
1811 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
1812 break;
1813 case OL_TX_WMM_AC_VO:
1814 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
1815 break;
1816 default:
1817 tx_sched_wrr_ac = NULL;
1818 break;
1819 }
1820
1821 hdd_string_to_u8_array(tx_sched_wrr_ac,
1822 tx_sched_wrr_param,
1823 &num_entries,
1824 sizeof(tx_sched_wrr_param));
1825
1826 if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
1827 cds_ctx->ac_specs[i].wrr_skip_weight =
1828 tx_sched_wrr_param[0];
1829 cds_ctx->ac_specs[i].credit_threshold =
1830 tx_sched_wrr_param[1];
1831 cds_ctx->ac_specs[i].send_limit =
1832 tx_sched_wrr_param[2];
1833 cds_ctx->ac_specs[i].credit_reserve =
1834 tx_sched_wrr_param[3];
1835 cds_ctx->ac_specs[i].discard_weight =
1836 tx_sched_wrr_param[4];
1837 }
1838
1839 num_entries = 0;
1840 }
1841}
1842
1843/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301844 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1845 * @hdd_ctx: HDD context
1846 * @adapter: HDD adapter
1847 * @reinit: flag to indicate from SSR or normal path
1848 *
1849 * This function maintains the driver state machine it will be invoked from
1850 * startup, reinit and change interface. Depending on the driver state shall
1851 * perform the opening of the modules.
1852 *
1853 * Return: 0 for success; non-zero for failure
1854 */
1855int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1856 bool reinit)
1857{
1858 int ret;
1859 qdf_device_t qdf_dev;
1860 QDF_STATUS status;
1861 p_cds_contextType p_cds_context;
1862 bool unint = false;
1863 void *hif_ctx;
1864
1865 ENTER();
1866
1867 p_cds_context = cds_get_global_context();
1868 if (!p_cds_context) {
1869 hdd_err("Global Context is NULL");
1870 QDF_ASSERT(0);
1871 return -EINVAL;
1872 }
1873
1874 hdd_info("start modules called in state! :%d reinit: %d",
1875 hdd_ctx->driver_status, reinit);
1876
1877 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1878 if (!qdf_dev) {
1879 hdd_err("QDF Device Context is Invalid return");
1880 return -EINVAL;
1881 }
1882
1883 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301884 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301885
1886 if (QDF_TIMER_STATE_RUNNING ==
1887 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1888
1889 hdd_set_idle_ps_config(hdd_ctx, false);
1890 hdd_info("Interface change Timer running Stop timer");
1891 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1892 }
1893
1894 switch (hdd_ctx->driver_status) {
1895 case DRIVER_MODULES_UNINITIALIZED:
1896 unint = true;
1897 /* Fall through dont add break here */
1898 case DRIVER_MODULES_CLOSED:
1899 if (!reinit && !unint) {
1900 ret = pld_power_on(qdf_dev->dev);
1901 if (ret) {
1902 hdd_err("Failed to Powerup the device: %d", ret);
1903 goto release_lock;
1904 }
1905 }
1906 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1907 qdf_dev->bus_type,
1908 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1909 HIF_ENABLE_TYPE_PROBE);
1910 if (ret) {
1911 hdd_err("Failed to open hif: %d", ret);
1912 goto power_down;
1913 }
1914
1915 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301916 if (!hif_ctx) {
1917 hdd_err("hif context is null!!");
1918 goto power_down;
1919 }
1920
Arun Khandavallifae92942016-08-01 13:31:08 +05301921 status = ol_cds_init(qdf_dev, hif_ctx);
1922 if (status != QDF_STATUS_SUCCESS) {
1923 hdd_err("No Memory to Create BMI Context :%d", status);
1924 goto hif_close;
1925 }
1926
Rajeev Kumar138ef912017-01-13 15:19:48 -08001927 ret = hdd_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID);
1928 if (ret) {
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301929 hdd_err("Psoc creation fails!");
1930 goto ol_cds_free;
1931 }
1932
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08001933 ret = hdd_update_config(hdd_ctx);
1934 if (ret) {
1935 hdd_err("Failed to update configuration :%d", ret);
1936 goto destroy_psoc_object;
1937 }
1938
gbian62edd7e2017-03-07 13:12:13 +08001939 hdd_update_cds_ac_specs_params(hdd_ctx);
1940
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301941 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05301942 if (!QDF_IS_STATUS_SUCCESS(status)) {
1943 hdd_err("Failed to Open CDS: %d", status);
Selvaraj, Sridhara7dc2382017-01-27 18:29:39 +05301944 goto destroy_psoc_object;
Arun Khandavallifae92942016-08-01 13:31:08 +05301945 }
1946
Mukul Sharma9d797a02017-01-05 20:26:03 +05301947 /* initalize components configurations after psoc open */
1948 ret = hdd_update_components_config(hdd_ctx);
1949 if (ret) {
1950 hdd_err("Failed to update components configs :%d",
1951 ret);
1952 goto close;
1953 }
1954
Arun Khandavallifae92942016-08-01 13:31:08 +05301955 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1956
1957 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1958
1959 status = cds_pre_enable(hdd_ctx->pcds_context);
1960 if (!QDF_IS_STATUS_SUCCESS(status)) {
1961 hdd_err("Failed to pre-enable CDS: %d", status);
1962 goto close;
1963 }
1964
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301965 hdd_update_hw_sw_info(hdd_ctx);
1966
Arun Khandavallifae92942016-08-01 13:31:08 +05301967 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1968 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1969 hdd_ftm_mc_process_msg);
1970 break;
1971 }
1972 if (unint) {
1973 hdd_info("In phase-1 initialization don't enable modules");
1974 break;
1975 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301976
1977 if (reinit) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08001978 if (hdd_ipa_uc_ssr_reinit(hdd_ctx)) {
1979 hdd_err("HDD IPA UC reinit failed");
1980 goto close;
1981 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301982 }
1983
Arun Khandavallifae92942016-08-01 13:31:08 +05301984 /* Fall through dont add break here */
1985 case DRIVER_MODULES_OPENED:
1986 if (!adapter) {
1987 hdd_alert("adapter is Null");
1988 goto close;
1989 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05301990 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1991 hdd_err("in ftm mode, no need to configure cds modules");
1992 break;
1993 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301994 if (hdd_configure_cds(hdd_ctx, adapter)) {
1995 hdd_err("Failed to Enable cds modules");
1996 goto close;
1997 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05301998 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05301999 hdd_info("Driver Modules Successfully Enabled");
2000 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
2001 break;
2002 case DRIVER_MODULES_ENABLED:
2003 hdd_info("Driver modules already Enabled");
2004 break;
2005 default:
2006 hdd_err("WLAN start invoked in wrong state! :%d\n",
2007 hdd_ctx->driver_status);
2008 goto release_lock;
2009 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302010 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302011 mutex_unlock(&hdd_ctx->iface_change_lock);
2012 EXIT();
2013 return 0;
2014
2015close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302016 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05302017
Selvaraj, Sridhara7dc2382017-01-27 18:29:39 +05302018destroy_psoc_object:
2019 hdd_release_and_destroy_psoc(hdd_ctx);
2020
Arun Khandavallifae92942016-08-01 13:31:08 +05302021ol_cds_free:
2022 ol_cds_free();
2023
2024hif_close:
2025 hdd_hif_close(p_cds_context->pHIFContext);
2026power_down:
2027 if (!reinit && !unint)
2028 pld_power_off(qdf_dev->dev);
2029release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302030 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302031 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302032 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05302033 return -EINVAL;
2034}
2035
2036/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 * __hdd_open() - HDD Open function
2038 * @dev: Pointer to net_device structure
2039 *
2040 * This is called in response to ifconfig up
2041 *
2042 * Return: 0 for success; non-zero for failure
2043 */
2044static int __hdd_open(struct net_device *dev)
2045{
2046 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2047 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2048 int ret;
2049
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002050 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302051 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05302052 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053
2054 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302055 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002056 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302057
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058
Arun Khandavallifae92942016-08-01 13:31:08 +05302059 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
2060 if (ret) {
2061 hdd_err("Failed to start WLAN modules return");
2062 return -ret;
2063 }
2064
2065
2066 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2067 ret = hdd_start_adapter(adapter);
2068 if (ret) {
2069 hdd_err("Failed to start adapter :%d",
2070 adapter->device_mode);
2071 return ret;
2072 }
2073 }
2074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2076 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302077 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 /* Enable TX queues only when we are connected */
2079 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05302080 WLAN_START_ALL_NETIF_QUEUE,
2081 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 }
2083
Naveen Rawat286def52016-09-23 15:38:02 -07002084 /* Enable carrier and transmit queues for NDI */
2085 if (WLAN_HDD_IS_NDI(adapter)) {
2086 hdd_notice("Enabling Tx Queues");
2087 wlan_hdd_netif_queue_control(adapter,
2088 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
2089 WLAN_CONTROL_PATH);
2090 }
2091
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 return ret;
2093}
2094
Arun Khandavallifae92942016-08-01 13:31:08 +05302095
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002096/**
2097 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
2098 * @dev: Pointer to net_device structure
2099 *
2100 * This is called in response to ifconfig up
2101 *
2102 * Return: 0 for success; non-zero for failure
2103 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002104static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002105{
2106 int ret;
2107
2108 cds_ssr_protect(__func__);
2109 ret = __hdd_open(dev);
2110 cds_ssr_unprotect(__func__);
2111
2112 return ret;
2113}
2114
2115/**
2116 * __hdd_stop() - HDD stop function
2117 * @dev: Pointer to net_device structure
2118 *
2119 * This is called in response to ifconfig down
2120 *
2121 * Return: 0 for success; non-zero for failure
2122 */
2123static int __hdd_stop(struct net_device *dev)
2124{
2125 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2126 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2127 int ret;
2128
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002129 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302131 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002132 adapter->sessionId, adapter->device_mode));
2133
2134 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302135 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002136 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002137
2138 /* Nothing to be done if the interface is not opened */
2139 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002140 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141 return -ENODEV;
2142 }
2143
2144 /* Make sure the interface is marked as closed */
2145 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002146 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002147
2148 /*
2149 * Disable TX on the interface, after this hard_start_xmit() will not
2150 * be called on that interface
2151 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002152 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002153 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2154 WLAN_CONTROL_PATH);
2155
2156 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002157 * NAN data interface is different in some sense. The traffic on NDI is
2158 * bursty in nature and depends on the need to transfer. The service
2159 * layer may down the interface after the usage and up again when
2160 * required. In some sense, the NDI is expected to be available
2161 * (like SAP) iface until NDI delete request is issued by the service
2162 * layer. Skip BSS termination and adapter deletion for NAN Data
2163 * interface (NDI).
2164 */
2165 if (WLAN_HDD_IS_NDI(adapter))
2166 return 0;
2167
2168 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002169 * The interface is marked as down for outside world (aka kernel)
2170 * But the driver is pretty much alive inside. The driver needs to
2171 * tear down the existing connection on the netdev (session)
2172 * cleanup the data pipes and wait until the control plane is stabilized
2173 * for this interface. The call also needs to wait until the above
2174 * mentioned actions are completed before returning to the caller.
2175 * Notice that the hdd_stop_adapter is requested not to close the session
2176 * That is intentional to be able to scan if it is a STA/P2P interface
2177 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302178 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179
2180 /* DeInit the adapter. This ensures datapath cleanup as well */
2181 hdd_deinit_adapter(hdd_ctx, adapter, true);
2182
Arun Khandavallifae92942016-08-01 13:31:08 +05302183
2184 /*
2185 * Find if any iface is up. If any iface is up then can't put device to
2186 * sleep/power save mode
2187 */
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05302188 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302189 hdd_info("Closing all modules from the hdd_stop");
2190 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2191 hdd_ctx->config->iface_change_wait_time
2192 * 50000);
2193 }
2194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 EXIT();
2196 return 0;
2197}
2198
2199/**
2200 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2201 * @dev: pointer to net_device structure
2202 *
2203 * This is called in response to ifconfig down
2204 *
2205 * Return: 0 for success and error number for failure
2206 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002207static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208{
2209 int ret;
2210
2211 cds_ssr_protect(__func__);
2212 ret = __hdd_stop(dev);
2213 cds_ssr_unprotect(__func__);
2214
2215 return ret;
2216}
2217
2218/**
2219 * __hdd_uninit() - HDD uninit function
2220 * @dev: Pointer to net_device structure
2221 *
2222 * This is called during the netdev unregister to uninitialize all data
2223 * associated with the device
2224 *
2225 * Return: None
2226 */
2227static void __hdd_uninit(struct net_device *dev)
2228{
2229 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2230
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002231 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232
2233 do {
2234 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002235 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236 break;
2237 }
2238
2239 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002240 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 break;
2242 }
2243
2244 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002245 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246 /*
2247 * we haven't validated all cases so let this go for
2248 * now
2249 */
2250 }
2251
2252 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2253
2254 /* after uninit our adapter structure will no longer be valid */
2255 adapter->dev = NULL;
2256 adapter->magic = 0;
2257 } while (0);
2258
2259 EXIT();
2260}
2261
2262/**
2263 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2264 * @dev: pointer to net_device structure
2265 *
2266 * This is called during the netdev unregister to uninitialize all data
2267 * associated with the device
2268 *
2269 * Return: none
2270 */
2271static void hdd_uninit(struct net_device *dev)
2272{
2273 cds_ssr_protect(__func__);
2274 __hdd_uninit(dev);
2275 cds_ssr_unprotect(__func__);
2276}
2277
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002278static int hdd_open_cesium_nl_sock(void)
2279{
2280#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2281 struct netlink_kernel_cfg cfg = {
2282 .groups = WLAN_NLINK_MCAST_GRP_ID,
2283 .input = NULL
2284 };
2285#endif
2286 int ret = 0;
2287
2288#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2289 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2290#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2291 THIS_MODULE,
2292#endif
2293 &cfg);
2294#else
2295 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2296 WLAN_NLINK_MCAST_GRP_ID,
2297 NULL, NULL, THIS_MODULE);
2298#endif
2299
2300 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002301 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002302 ret = -ECONNREFUSED;
2303 }
2304
2305 return ret;
2306}
2307
2308static void hdd_close_cesium_nl_sock(void)
2309{
2310 if (NULL != cesium_nl_srv_sock) {
2311 netlink_kernel_release(cesium_nl_srv_sock);
2312 cesium_nl_srv_sock = NULL;
2313 }
2314}
2315
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316/**
2317 * __hdd_set_mac_address() - set the user specified mac address
2318 * @dev: Pointer to the net device.
2319 * @addr: Pointer to the sockaddr.
2320 *
2321 * This function sets the user specified mac address using
2322 * the command ifconfig wlanX hw ether <mac adress>.
2323 *
2324 * Return: 0 for success, non zero for failure
2325 */
2326static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2327{
2328 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2329 hdd_context_t *hdd_ctx;
2330 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302331 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 int ret;
2333
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002334 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335
2336 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2337 ret = wlan_hdd_validate_context(hdd_ctx);
2338 if (0 != ret)
2339 return ret;
2340
2341 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2342 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2343
2344 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302345 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002346}
2347
2348/**
2349 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2350 * function from SSR
2351 * @dev: pointer to net_device structure
2352 * @addr: Pointer to the sockaddr
2353 *
2354 * This function sets the user specified mac address using
2355 * the command ifconfig wlanX hw ether <mac adress>.
2356 *
2357 * Return: 0 for success.
2358 */
2359static int hdd_set_mac_address(struct net_device *dev, void *addr)
2360{
2361 int ret;
2362
2363 cds_ssr_protect(__func__);
2364 ret = __hdd_set_mac_address(dev, addr);
2365 cds_ssr_unprotect(__func__);
2366
2367 return ret;
2368}
2369
2370uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2371{
2372 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302373 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2375 break;
2376 }
2377
Anurag Chouhan6d760662016-02-20 16:05:43 +05302378 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 return NULL;
2380
2381 hdd_ctx->config->intfAddrMask |= (1 << i);
2382 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2383}
2384
2385void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2386{
2387 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302388 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389 if (!memcmp(releaseAddr,
2390 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2391 6)) {
2392 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2393 break;
2394 }
2395 }
2396 return;
2397}
2398
2399#ifdef WLAN_FEATURE_PACKET_FILTERING
2400/**
2401 * __hdd_set_multicast_list() - set the multicast address list
2402 * @dev: Pointer to the WLAN device.
2403 * @skb: Pointer to OS packet (sk_buff).
2404 *
2405 * This funciton sets the multicast address list.
2406 *
2407 * Return: None
2408 */
2409static void __hdd_set_multicast_list(struct net_device *dev)
2410{
2411 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002412 int i = 0, status;
2413 struct netdev_hw_addr *ha;
2414 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302415 struct pmo_mc_addr_list_params *mc_list_request = NULL;
2416 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2417 int mc_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002419 ENTER_DEV(dev);
Anurag Chouhan6d760662016-02-20 16:05:43 +05302420 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302421 goto out;
Mukul Sharma51c44942015-10-30 19:30:19 +05302422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302424 if (0 != status)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302425 goto out;
2426
2427 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
2428 if (!mc_list_request) {
2429 hdd_notice("Cannot allocate mc_list_request");
2430 goto out;
2431 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002432
2433 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002434 hdd_notice("allow all multicast frames");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302435 hdd_disable_and_flush_mc_addr_list(adapter,
2436 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 } else {
2438 mc_count = netdev_mc_count(dev);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302439 if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
Dustin Brown61269462016-09-19 13:25:45 -07002440 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302441 pmo_ucfg_max_mc_addr_supported(psoc));
2442 hdd_disable_and_flush_mc_addr_list(adapter,
2443 pmo_mc_list_change_notify);
2444 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302447 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2448 i, MAC_ADDR_ARRAY(ha->addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 if (i == mc_count)
2450 break;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302451 memset(&(mc_list_request->mc_addr[i].bytes),
2452 0, ETH_ALEN);
2453 memcpy(&(mc_list_request->mc_addr[i].bytes),
2454 ha->addr, ETH_ALEN);
2455 hdd_info("mlist[%d] = %pM", i,
2456 mc_list_request->mc_addr[i].bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 i++;
2458 }
2459 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302460
2461 mc_list_request->psoc = psoc;
2462 mc_list_request->vdev_id = adapter->sessionId;
2463 mc_list_request->count = mc_count;
2464 status = hdd_cache_mc_addr_list(mc_list_request);
2465 if (status == 0) {
2466 hdd_enable_mc_addr_filtering(adapter,
2467 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 } else {
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302469 hdd_err("error while caching mc list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302471out:
2472 if (mc_list_request)
2473 qdf_mem_free(mc_list_request);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302474 EXIT();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302475
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476}
2477
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302478
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479/**
2480 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2481 * @dev: pointer to net_device
2482 *
2483 * Return: none
2484 */
2485static void hdd_set_multicast_list(struct net_device *dev)
2486{
2487 cds_ssr_protect(__func__);
2488 __hdd_set_multicast_list(dev);
2489 cds_ssr_unprotect(__func__);
2490}
2491#endif
2492
2493/**
2494 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2495 * @dev: Pointer to the WLAN device.
2496 * @skb: Pointer to OS packet (sk_buff).
2497 *
2498 * This function is registered with the Linux OS for network
2499 * core to decide which queue to use first.
2500 *
2501 * Return: ac, Queue Index/access category corresponding to UP in IP header
2502 */
2503static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2504#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2505 , void *accel_priv
2506#endif
2507#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2508 , select_queue_fallback_t fallback
2509#endif
2510)
2511{
2512 return hdd_wmm_select_queue(dev, skb);
2513}
2514
2515static struct net_device_ops wlan_drv_ops = {
2516 .ndo_open = hdd_open,
2517 .ndo_stop = hdd_stop,
2518 .ndo_uninit = hdd_uninit,
2519 .ndo_start_xmit = hdd_hard_start_xmit,
2520 .ndo_tx_timeout = hdd_tx_timeout,
2521 .ndo_get_stats = hdd_get_stats,
2522 .ndo_do_ioctl = hdd_ioctl,
2523 .ndo_set_mac_address = hdd_set_mac_address,
2524 .ndo_select_queue = hdd_select_queue,
2525#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527#endif
2528};
2529
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002530/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2531static struct net_device_ops wlan_mon_drv_ops = {
2532 .ndo_open = hdd_mon_open,
2533 .ndo_stop = hdd_stop,
2534 .ndo_get_stats = hdd_get_stats,
2535};
2536
2537/**
2538 * hdd_set_station_ops() - update net_device ops for monitor mode
2539 * @pWlanDev: Handle to struct net_device to be updated.
2540 * Return: None
2541 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542void hdd_set_station_ops(struct net_device *pWlanDev)
2543{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002544 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2545 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2546 else
2547 pWlanDev->netdev_ops = &wlan_drv_ops;
2548}
2549
Komal Seelama89be8d2016-09-29 11:09:26 +05302550#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302551/**
2552 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2553 * @hdd_ctx: HDD context
2554 *
2555 * Return: None
2556 */
2557static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2558{
2559 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2560
2561 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302562 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302563 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302564}
2565
2566/**
2567 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2568 * @hdd_ctx: HDD Context
2569 *
2570 * Return: None
2571 */
2572static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2573{
2574 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2575
2576 qdf_runtime_lock_deinit(ctx->scan);
2577 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302578 qdf_runtime_lock_deinit(ctx->roc);
2579 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302580 qdf_runtime_lock_deinit(ctx->dfs);
2581 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302582}
2583
Komal Seelama89be8d2016-09-29 11:09:26 +05302584static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2585{
2586 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2587
2588 ctx->connect = qdf_runtime_lock_init("connect");
2589}
2590
2591static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2592{
2593 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2594
2595 qdf_runtime_lock_deinit(ctx->connect);
2596 ctx->connect = NULL;
2597}
2598#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302599static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2600static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302601static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2602static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2603#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002604/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002605 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2606 * @hdd_ctx: global hdd context
2607 * @macAddr: mac address to assign to the interface
2608 * @name: User-visible name of the interface
2609 *
2610 * hdd adapter pointer would point to the netdev->priv space, this function
2611 * would retrive the pointer, and setup the hdd adapter configuration.
2612 *
2613 * Return: the pointer to hdd adapter, otherwise NULL
2614 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2616 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002617 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618 const char *name)
2619{
2620 struct net_device *pWlanDev = NULL;
2621 hdd_adapter_t *adapter = NULL;
2622 /*
2623 * cfg80211 initialization and registration....
2624 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002625 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2627 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002629 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2630 hdd_mon_mode_ether_setup : ether_setup),
2631 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002632
2633 if (pWlanDev != NULL) {
2634
2635 /* Save the pointer to the net_device in the HDD adapter */
2636 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2637
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302638 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639
2640 adapter->dev = pWlanDev;
2641 adapter->pHddCtx = hdd_ctx;
2642 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302643 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644
2645 init_completion(&adapter->session_open_comp_var);
2646 init_completion(&adapter->session_close_comp_var);
2647 init_completion(&adapter->disconnect_comp_var);
2648 init_completion(&adapter->linkup_event_var);
2649 init_completion(&adapter->cancel_rem_on_chan_var);
2650 init_completion(&adapter->rem_on_chan_ready_event);
2651 init_completion(&adapter->sta_authorized_event);
2652 init_completion(&adapter->offchannel_tx_event);
2653 init_completion(&adapter->tx_action_cnf_event);
2654#ifdef FEATURE_WLAN_TDLS
2655 init_completion(&adapter->tdls_add_station_comp);
2656 init_completion(&adapter->tdls_del_station_comp);
2657 init_completion(&adapter->tdls_mgmt_comp);
2658 init_completion(&adapter->tdls_link_establish_req_comp);
2659#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002660 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002661 init_completion(&adapter->change_country_code);
2662
2663
2664 init_completion(&adapter->scan_info.abortscan_event_var);
2665
2666 adapter->offloads_configured = false;
2667 adapter->isLinkUpSvcNeeded = false;
2668 adapter->higherDtimTransition = true;
2669 /* Init the net_device structure */
2670 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2671
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302672 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302674 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 sizeof(tSirMacAddr));
2676 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677
2678 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2679 pWlanDev->features |=
2680 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2681 pWlanDev->features |= NETIF_F_RXCSUM;
2682
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002683 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2684
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 hdd_set_station_ops(adapter->dev);
2686
2687 pWlanDev->destructor = free_netdev;
2688 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002689 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690 adapter->wdev.wiphy = hdd_ctx->wiphy;
2691 adapter->wdev.netdev = pWlanDev;
2692 /* set pWlanDev's parent to underlying device */
2693 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2694 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302695 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302697 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002698 }
2699
2700 return adapter;
2701}
2702
Jeff Johnson590e2012016-10-05 16:16:24 -07002703static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2704 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705{
2706 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002707
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002708 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2710 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002711 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302712 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 }
2714 }
2715 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002716 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302717 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718 }
2719 } else {
2720 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002721 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302722 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723 }
2724 }
2725 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2726
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302727 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728}
2729
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002730QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731{
2732 hdd_adapter_t *adapter = pContext;
2733
2734 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002735 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302736 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737 }
2738
2739 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002740 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302741 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002742 }
2743
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002744 /*
2745 * For NAN Data interface, the close session results in the final
2746 * indication to the userspace
2747 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002748 if (adapter->device_mode == QDF_NDI_MODE)
2749 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002751 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2752
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002753 /*
2754 * We can be blocked while waiting for scheduled work to be
2755 * flushed, and the adapter structure can potentially be freed, in
2756 * which case the magic will have been reset. So make sure the
2757 * magic is still good, and hence the adapter structure is still
2758 * valid, before signaling completion
2759 */
2760 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2761 complete(&adapter->session_close_comp_var);
2762
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302763 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764}
2765
Krunal Soni8c37e322016-02-03 16:08:37 -08002766/**
2767 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2768 * @adapter: pointer to device adapter
2769 * @type: type of interface
2770 *
2771 * This routine will check the mode of adapter and if it is required then it
2772 * will initialize the TDLS operations
2773 *
2774 * Return: QDF_STATUS
2775 */
2776#ifdef FEATURE_WLAN_TDLS
2777static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2778{
2779 if (QDF_IBSS_MODE != type) {
2780 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002781 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002782 return QDF_STATUS_E_FAILURE;
2783 }
2784 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2785 }
2786 return QDF_STATUS_SUCCESS;
2787}
2788#else
2789static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2790{
2791 return QDF_STATUS_SUCCESS;
2792}
2793#endif
2794
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302795QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796{
2797 struct net_device *pWlanDev = adapter->dev;
2798 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2799 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302800 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302801 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002802 uint32_t type, subType;
2803 unsigned long rc;
2804 int ret_val;
2805
2806 INIT_COMPLETION(adapter->session_open_comp_var);
2807 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002808 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302810 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002811 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812 goto error_sme_open;
2813 }
2814 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302815 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2817 (uint8_t *) &adapter->macAddressCurrent,
2818 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302819 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002820 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302821 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302822 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 goto error_sme_open;
2824 }
2825 /* Block on a completion variable. Can't wait forever though. */
2826 rc = wait_for_completion_timeout(
2827 &adapter->session_open_comp_var,
2828 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2829 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002830 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831 rc);
Sandeep Puligillae8065992016-11-14 00:23:43 -08002832 adapter->sessionId = HDD_SESSION_ID_INVALID;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302833 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 }
2835
Rajeev Kumardeabf3e2017-01-13 15:55:05 -08002836 ret_val = hdd_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
2837 if (ret_val)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302838 goto error_vdev_create;
2839
Naveen Rawata410c5a2016-09-19 14:22:33 -07002840 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302842 qdf_ret_status = hdd_register_wext(pWlanDev);
2843 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002844 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302845 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302846 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 goto error_register_wext;
2848 }
2849 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002850 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2852
Deepak Dhamdherea2785822016-11-17 01:17:45 -08002853 /* set fast roaming capability in sme session */
2854 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
2855 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856 /* Set the default operation channel */
2857 pHddStaCtx->conn_info.operationChannel =
2858 hdd_ctx->config->OperatingChannel;
2859
2860 /* Make the default Auth Type as OPEN */
2861 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2862
2863 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302864 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002865 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866 status, status);
2867 goto error_init_txrx;
2868 }
2869
2870 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2871
2872 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302873 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002874 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002875 status, status);
2876 goto error_wmm_init;
2877 }
2878
2879 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2880
2881 ret_val = wma_cli_set_command(adapter->sessionId,
2882 WMI_PDEV_PARAM_BURST_ENABLE,
2883 hdd_ctx->config->enableSifsBurst,
2884 PDEV_CMD);
2885
2886 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002887 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888 ret_val);
2889 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002890 status = hdd_check_and_init_tdls(adapter, type);
2891 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302894 status = hdd_lro_enable(hdd_ctx, adapter);
2895 if (status != QDF_STATUS_SUCCESS)
2896 goto error_lro_enable;
2897
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302898 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302900error_lro_enable:
2901 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902error_tdls_init:
2903 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2904 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905error_wmm_init:
2906 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2907 hdd_deinit_tx_rx(adapter);
2908error_init_txrx:
2909 hdd_unregister_wext(pWlanDev);
2910error_register_wext:
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08002911 ret_val = hdd_release_and_destroy_vdev(adapter);
2912 if (ret_val)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302913 hdd_err("vdev delete failed");
2914error_vdev_create:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2916 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302917 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918 adapter->sessionId,
2919 hdd_sme_close_session_callback,
2920 adapter)) {
2921 unsigned long rc;
2922
2923 /*
2924 * Block on a completion variable.
2925 * Can't wait forever though.
2926 */
2927 rc = wait_for_completion_timeout(
2928 &adapter->session_close_comp_var,
2929 msecs_to_jiffies
2930 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2931 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002932 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 rc);
2934 }
2935 }
2936error_sme_open:
2937 return status;
2938}
2939
2940void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2941{
2942 hdd_cfg80211_state_t *cfgState;
2943
2944 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2945
2946 if (NULL != cfgState->buf) {
2947 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 rc = wait_for_completion_timeout(
2949 &adapter->tx_action_cnf_event,
2950 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2951 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002952 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302953 /*
2954 * Inform tx status as FAILURE to upper layer and free
2955 * cfgState->buf
2956 */
2957 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 }
2959 }
2960 return;
2961}
2962
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302963/**
2964 * hdd_station_adapter_deinit() - De-initialize the station adapter
2965 * @hdd_ctx: global hdd context
2966 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07002967 * @rtnl_held: Used to indicate whether or not the caller is holding
2968 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302969 *
2970 * This function De-initializes the STA/P2P/OCB adapter.
2971 *
2972 * Return: None.
2973 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002974static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2975 hdd_adapter_t *adapter,
2976 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302977{
2978 ENTER_DEV(adapter->dev);
2979
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302980 if (adapter->dev) {
2981 if (rtnl_held)
2982 adapter->dev->wireless_handlers = NULL;
2983 else {
2984 rtnl_lock();
2985 adapter->dev->wireless_handlers = NULL;
2986 rtnl_unlock();
2987 }
2988 }
2989
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302990 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2991 hdd_deinit_tx_rx(adapter);
2992 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2993 }
2994
2995 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2996 hdd_wmm_adapter_close(adapter);
2997 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2998 }
2999
3000 hdd_cleanup_actionframe(hdd_ctx, adapter);
3001 wlan_hdd_tdls_exit(adapter);
3002
3003 EXIT();
3004}
3005
3006/**
3007 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
3008 * @hdd_ctx: global hdd context
3009 * @adapter: HDD adapter
3010 * @rtnl_held: the rtnl lock hold flag
3011 * This function De-initializes the AP/P2PGo adapter.
3012 *
3013 * Return: None.
3014 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003015static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
3016 hdd_adapter_t *adapter,
3017 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303018{
3019 ENTER_DEV(adapter->dev);
3020
3021 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3022 hdd_wmm_adapter_close(adapter);
3023 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3024 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003025 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303026
3027 hdd_cleanup_actionframe(hdd_ctx, adapter);
3028
3029 hdd_unregister_hostapd(adapter, rtnl_held);
3030
3031 EXIT();
3032}
3033
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3035 bool rtnl_held)
3036{
3037 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003040 case QDF_STA_MODE:
3041 case QDF_P2P_CLIENT_MODE:
3042 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303044 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045 break;
3046 }
3047
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003048 case QDF_SAP_MODE:
3049 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 {
3051
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303052 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053 break;
3054 }
3055
3056 default:
3057 break;
3058 }
3059
3060 EXIT();
3061}
3062
Jeff Johnson590e2012016-10-05 16:16:24 -07003063static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3064 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065{
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003066 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067 struct net_device *pWlanDev = NULL;
3068
3069 if (adapter)
3070 pWlanDev = adapter->dev;
3071 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003072 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003073 return;
3074 }
3075
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003076 ret = hdd_release_and_destroy_vdev(adapter);
3077 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303078 hdd_err("vdev delete failed");
3079
Rajeev Kumardca5f812016-02-04 17:28:06 -08003080 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303081
3082 if (adapter->scan_info.default_scan_ies) {
3083 qdf_mem_free(adapter->scan_info.default_scan_ies);
3084 adapter->scan_info.default_scan_ies = NULL;
3085 }
3086
Komal Seelama89be8d2016-09-29 11:09:26 +05303087 hdd_adapter_runtime_suspend_denit(adapter);
3088
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 /*
3090 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
3091 * the driver is almost closed and cannot handle either control
3092 * messages or data. However, unregister_netdevice() call above will
3093 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
3094 * to close the active connections (basically excites control path) which
3095 * is not right. Setting this flag helps hdd_stop() to recognize that
3096 * the interface is closed and restricts any operations on that
3097 */
3098 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3099
3100 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
3101 if (rtnl_held) {
3102 unregister_netdevice(pWlanDev);
3103 } else {
3104 unregister_netdev(pWlanDev);
3105 }
3106 /*
3107 * Note that the adapter is no longer valid at this point
3108 * since the memory has been reclaimed
3109 */
3110 }
3111}
3112
Jeff Johnson590e2012016-10-05 16:16:24 -07003113static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
3114 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115{
3116 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3117 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303118 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003119 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303120 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003121 adapter = adapterNode->pAdapter;
3122 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303123 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303125 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003126 }
3127 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3128 adapterNode = pNext;
3129 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303130 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131}
Ryan Hsu07495ea2016-01-21 15:25:39 -08003132
Arun Khandavalli2358d522016-05-16 18:05:37 +05303133#ifdef CONFIG_FW_LOGS_BASED_ON_INI
3134/**
3135 * hdd_set_fw_log_params() - Set log parameters to FW
3136 * @hdd_ctx: HDD Context
3137 * @adapter: HDD Adapter
3138 *
3139 * This function set the FW Debug log level based on the INI.
3140 *
3141 * Return: None
3142 */
3143static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3144 hdd_adapter_t *adapter)
3145{
3146 uint8_t count = 0, numentries = 0,
3147 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3148 uint32_t value = 0;
3149 int ret;
3150
Arun Khandavallifae92942016-08-01 13:31:08 +05303151 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3152 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303153 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
3154 return;
3155 }
3156
Arun Khandavallifae92942016-08-01 13:31:08 +05303157 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303158 hdd_ctx->fw_log_settings.dl_type =
3159 hdd_ctx->config->enableFwLogType;
3160 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303161 WMI_DBGLOG_TYPE,
3162 hdd_ctx->config->enableFwLogType,
3163 DBG_CMD);
3164 if (ret != 0)
3165 hdd_err("Failed to enable FW log type ret %d",
3166 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303167
3168 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303169 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303170 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303171 WMI_DBGLOG_LOG_LEVEL,
3172 hdd_ctx->config->enableFwLogLevel,
3173 DBG_CMD);
3174 if (ret != 0)
3175 hdd_err("Failed to enable FW log level ret %d",
3176 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303177
3178 hdd_string_to_u8_array(
3179 hdd_ctx->config->enableFwModuleLogLevel,
3180 moduleloglevel,
3181 &numentries,
3182 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3183
3184 while (count < numentries) {
3185 /*
3186 * FW module log level input string looks like
3187 * below:
3188 * gFwDebugModuleLoglevel=<FW Module ID>,
3189 * <Log Level>,...
3190 * For example:
3191 * gFwDebugModuleLoglevel=
3192 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3193 * Above input string means :
3194 * For FW module ID 1 enable log level 0
3195 * For FW module ID 2 enable log level 1
3196 * For FW module ID 3 enable log level 2
3197 * For FW module ID 4 enable log level 3
3198 * For FW module ID 5 enable log level 4
3199 * For FW module ID 6 enable log level 5
3200 * For FW module ID 7 enable log level 6
3201 */
3202
Nishank Aggarwale239d962017-03-03 12:26:02 +05303203 if ((moduleloglevel[count] > WLAN_MODULE_ID_MAX)
3204 || (moduleloglevel[count + 1] > DBGLOG_LVL_MAX)) {
3205 hdd_err("Module id %d and dbglog level %d input length is more than max",
3206 moduleloglevel[count],
3207 moduleloglevel[count + 1]);
3208 return;
3209 }
3210
3211 value = moduleloglevel[count] << 16;
3212 value |= moduleloglevel[count + 1];
Arun Khandavalli2358d522016-05-16 18:05:37 +05303213 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303214 WMI_DBGLOG_MOD_LOG_LEVEL,
3215 value, DBG_CMD);
3216 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303217 hdd_err("Failed to enable FW module log level %d ret %d",
3218 value, ret);
3219
3220 count += 2;
3221 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303222
Arun Khandavalli2358d522016-05-16 18:05:37 +05303223}
3224#else
3225static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3226 hdd_adapter_t *adapter)
3227{
3228}
3229
3230#endif
3231
3232/**
3233 * hdd_set_fw_params() - Set parameters to firmware
3234 * @adapter: HDD adapter
3235 *
3236 * This function Sets various parameters to fw once the
3237 * adapter is started.
3238 *
3239 * Return: 0 on success or errno on failure
3240 */
3241int hdd_set_fw_params(hdd_adapter_t *adapter)
3242{
3243 int ret;
3244 hdd_context_t *hdd_ctx;
3245
3246 ENTER_DEV(adapter->dev);
3247
3248 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3249 if (!hdd_ctx)
3250 return -EINVAL;
3251
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003252 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303253 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303254#define HDD_DTIM_1CHAIN_RX_ID 0x5
3255#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003256 /*
3257 * Disable DTIM 1 chain Rx when in 1x1,
3258 * we are passing two value
3259 * as param_id << 29 | param_value.
3260 * Below param_value = 0(disable)
3261 */
3262 ret = wma_cli_set_command(adapter->sessionId,
3263 WMI_STA_SMPS_PARAM_CMDID,
3264 HDD_DTIM_1CHAIN_RX_ID <<
3265 HDD_SMPS_PARAM_VALUE_S,
3266 VDEV_CMD);
3267 if (ret) {
3268 hdd_err("DTIM 1 chain set failed %d", ret);
3269 goto error;
3270 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303271
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003272 ret = wma_cli_set_command(adapter->sessionId,
3273 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3274 hdd_ctx->config->txchainmask1x1,
3275 PDEV_CMD);
3276 if (ret) {
3277 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3278 ret);
3279 goto error;
3280 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303281
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003282 ret = wma_cli_set_command(adapter->sessionId,
3283 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3284 hdd_ctx->config->rxchainmask1x1,
3285 PDEV_CMD);
3286 if (ret) {
3287 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3288 ret);
3289 goto error;
3290 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303291#undef HDD_DTIM_1CHAIN_RX_ID
3292#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003293 } else {
3294 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3295 }
3296
Arun Khandavallifae92942016-08-01 13:31:08 +05303297 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3298 ret = wma_cli_set_command(adapter->sessionId,
3299 WMI_PDEV_PARAM_HYST_EN,
3300 hdd_ctx->config->enableMemDeepSleep,
3301 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303302
Arun Khandavallifae92942016-08-01 13:31:08 +05303303 if (ret) {
3304 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3305 ret);
3306 goto error;
3307 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303308
3309 ret = wma_cli_set_command(adapter->sessionId,
3310 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3311 hdd_ctx->config->rts_profile,
3312 VDEV_CMD);
3313 if (ret) {
3314 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3315 goto error;
3316 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303317 }
3318
3319 hdd_set_fw_log_params(hdd_ctx, adapter);
3320
3321 EXIT();
3322 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303323
Arun Khandavalli2358d522016-05-16 18:05:37 +05303324error:
3325 return -EINVAL;
3326}
3327
Ryan Hsu07495ea2016-01-21 15:25:39 -08003328/**
3329 * hdd_open_adapter() - open and setup the hdd adatper
3330 * @hdd_ctx: global hdd context
3331 * @session_type: type of the interface to be created
3332 * @iface_name: User-visible name of the interface
3333 * @macAddr: MAC address to assign to the interface
3334 * @name_assign_type: the name of assign type of the netdev
3335 * @rtnl_held: the rtnl lock hold flag
3336 *
3337 * This function open and setup the hdd adpater according to the device
3338 * type request, assign the name, the mac address assigned, and then prepared
3339 * the hdd related parameters, queue, lock and ready to start.
3340 *
3341 * Return: the pointer of hdd adapter, otherwise NULL.
3342 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3344 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003345 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003346 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347{
3348 hdd_adapter_t *adapter = NULL;
3349 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303350 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352
Arun Khandavallifae92942016-08-01 13:31:08 +05303353 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354
3355 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3356 /*
3357 * Max limit reached on the number of vdevs configured by the
3358 * host. Return error
3359 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303360 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3361 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362 return NULL;
3363 }
3364
3365 if (macAddr == NULL) {
3366 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303367 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003368 return NULL;
3369 }
3370 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303372 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3373 " already exists",
3374 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375 return NULL;
3376 }
3377
3378 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003379 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003380 /* Reset locally administered bit if the device mode is STA */
3381 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3382 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003383 case QDF_P2P_CLIENT_MODE:
3384 case QDF_P2P_DEVICE_MODE:
3385 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003386 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303387 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003388 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3389 name_assign_type,
3390 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391
3392 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303393 hdd_err("failed to allocate adapter for session %d",
3394 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 return NULL;
3396 }
3397
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003398 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003399 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003400 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003401 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303402 else if (QDF_MONITOR_MODE == session_type)
3403 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404 else
3405 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3406
3407 adapter->device_mode = session_type;
3408
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303409 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003410 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303411 if (QDF_STATUS_SUCCESS != status)
3412 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303413 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 /*
3416 * Workqueue which gets scheduled in IPv4 notification
3417 * callback
3418 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3420 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421
3422#ifdef WLAN_NS_OFFLOAD
3423 /*
3424 * Workqueue which gets scheduled in IPv6
3425 * notification callback.
3426 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003427 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3428 hdd_ipv6_notifier_work_queue);
3429#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303431 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003432 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303433 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003434 }
3435
3436 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303437 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303439 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3440 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003441 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303442
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003443
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003444 case QDF_P2P_GO_MODE:
3445 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003446 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3447 name_assign_type,
3448 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003449 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303450 hdd_alert("failed to allocate adapter for session %d",
3451 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003452 return NULL;
3453 }
3454
3455 adapter->wdev.iftype =
3456 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003457 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 NL80211_IFTYPE_P2P_GO;
3459 adapter->device_mode = session_type;
3460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003461 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303462 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3464 goto err_free_netdev;
3465 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303466 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003467 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303468 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3469 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303471 case QDF_FTM_MODE:
3472 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3473 name_assign_type,
3474 "wlan0");
3475 if (NULL == adapter) {
3476 hdd_err("Failed to allocate adapter for FTM mode");
3477 return NULL;
3478 }
3479 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3480 adapter->device_mode = session_type;
3481 status = hdd_register_interface(adapter, rtnl_held);
3482 if (QDF_STATUS_SUCCESS != status) {
3483 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3484 goto err_free_netdev;
3485 }
3486 /* Stop the Interface TX queue. */
3487 hdd_info("Disabling queues");
3488 wlan_hdd_netif_queue_control(adapter,
3489 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3490 WLAN_CONTROL_PATH);
3491 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303493 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303494 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495 return NULL;
3496 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497
3498 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3499 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3500
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303501 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003502 /* Add it to the hdd's session list. */
3503 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303504 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303506 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 } else {
3508 pHddAdapterNode->pAdapter = adapter;
3509 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3510 }
3511 }
3512
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303513 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514 if (NULL != adapter) {
3515 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3516 adapter = NULL;
3517 }
3518 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303519 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 }
3521 return NULL;
3522 }
3523
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303524 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003525 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526
3527 /* Initialize the WoWL service */
3528 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003529 hdd_alert("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303530 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 }
3532
3533 /* Adapter successfully added. Increment the vdev count */
3534 hdd_ctx->current_intf_count++;
3535
Jeff Johnson5880d792016-08-15 13:32:30 -07003536 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 hdd_ctx->current_intf_count);
3538
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003539 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 }
3541
Rajeev Kumardca5f812016-02-04 17:28:06 -08003542 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3543 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003544
3545 return adapter;
3546
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303547err_close_adapter:
3548 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003550 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303551 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552
3553 return NULL;
3554}
3555
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303556QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003557 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558{
3559 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303560 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561
3562 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303563 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003564 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003565 status);
3566 return status;
3567 }
3568
3569 while (pCurrent->pAdapter != adapter) {
3570 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303571 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572 break;
3573
3574 pCurrent = pNext;
3575 }
3576 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303577 if (QDF_STATUS_SUCCESS == status) {
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303578 hdd_info("wait for bus bw work to flush");
3579 cancel_work_sync(&hdd_ctx->bus_bw_work);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003580 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3582
3583 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303584 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 adapterNode = NULL;
3586
3587 /* Adapter removed. Decrement vdev count */
3588 if (hdd_ctx->current_intf_count != 0)
3589 hdd_ctx->current_intf_count--;
3590
3591 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303592 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003593 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303595 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003596}
3597
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003598/**
3599 * hdd_close_all_adapters - Close all open adapters
3600 * @hdd_ctx: Hdd context
3601 * rtnl_held: True if RTNL lock held
3602 *
3603 * Close all open adapters.
3604 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303605 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003606 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303607QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608{
3609 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303610 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611
3612 ENTER();
3613
3614 do {
3615 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303616 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303617 wlan_hdd_release_intf_addr(hdd_ctx,
3618 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003619 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003620 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303621 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303622 /* Adapter removed. Decrement vdev count */
3623 if (hdd_ctx->current_intf_count != 0)
3624 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303626 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627
3628 EXIT();
3629
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303630 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003631}
3632
3633void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3634{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303635 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 tSirUpdateIE updateIE;
3637 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003638 case QDF_STA_MODE:
3639 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003640 {
3641 hdd_station_ctx_t *pHddStaCtx =
3642 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003643 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 break;
3645 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003646 case QDF_SAP_MODE:
3647 case QDF_P2P_GO_MODE:
3648 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003650 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003651 break;
3652 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003653 case QDF_FTM_MODE:
3654 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655 default:
3656 /*
3657 * wlan_hdd_reset_prob_rspies should not have been called
3658 * for these kind of devices
3659 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003660 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661 pHostapdAdapter->device_mode);
3662 return;
3663 }
3664
Anurag Chouhanc5548422016-02-24 18:33:27 +05303665 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3667 updateIE.ieBufferlength = 0;
3668 updateIE.pAdditionIEBuffer = NULL;
3669 updateIE.append = true;
3670 updateIE.notify = false;
3671 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3672 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303673 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003674 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003675 }
3676}
3677
Peng Xu66162de2016-02-11 17:01:20 -08003678/**
3679 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3680 * @hdd_ctx: HDD context which is already NULL validated
3681 * @adapter: HDD adapter which is already NULL validated
3682 *
3683 * Close the SME session and wait for its completion, if needed.
3684 *
3685 * Return: None
3686 */
3687static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3688 hdd_adapter_t *adapter)
3689{
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003690 int ret;
Peng Xu66162de2016-02-11 17:01:20 -08003691 unsigned long rc;
3692
3693 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3694 hdd_err("session is not opened:%d", adapter->sessionId);
3695 return;
3696 }
3697
3698 INIT_COMPLETION(adapter->session_close_comp_var);
3699 if (QDF_STATUS_SUCCESS ==
3700 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3701 hdd_sme_close_session_callback,
3702 adapter)) {
3703 /*
3704 * Block on a completion variable. Can't wait
3705 * forever though.
3706 */
3707 rc = wait_for_completion_timeout(
3708 &adapter->session_close_comp_var,
3709 msecs_to_jiffies
3710 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003711 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003712 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003713 if (adapter->device_mode == QDF_NDI_MODE)
3714 hdd_ndp_session_end_handler(adapter);
3715 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303716 return;
Sandeep Puligillaada72922016-09-29 19:31:21 -07003717 }
Rajeev Kumar9591d2b2017-01-13 16:05:06 -08003718 ret = hdd_release_and_destroy_vdev(adapter);
3719 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303720 hdd_err("vdev delete failed");
3721
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303722 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003723 }
3724}
3725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303726QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003727 const bool bCloseSession)
3728{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303729 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3731 union iwreq_data wrqu;
3732 tSirUpdateIE updateIE;
3733 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303734 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735
3736 ENTER();
3737
Sachin Ahuja988fd102016-09-15 17:16:25 +05303738 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003739 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003740 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3741 WLAN_CONTROL_PATH);
3742 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003743 case QDF_STA_MODE:
3744 case QDF_P2P_CLIENT_MODE:
3745 case QDF_IBSS_MODE:
3746 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003747 case QDF_NDI_MODE:
3748 if ((QDF_NDI_MODE == adapter->device_mode) ||
3749 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3751 hdd_is_connecting(
3752 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003753 INIT_COMPLETION(adapter->disconnect_comp_var);
3754 /*
3755 * For NDI do not use pWextState from sta_ctx, if needed
3756 * extract from ndi_ctx.
3757 */
3758 if (QDF_NDI_MODE == adapter->device_mode)
3759 qdf_ret_status = sme_roam_disconnect(
3760 hdd_ctx->hHal,
3761 adapter->sessionId,
3762 eCSR_DISCONNECT_REASON_NDI_DELETE);
3763 else if (pWextState->roamProfile.BSSType ==
3764 eCSR_BSS_TYPE_START_IBSS)
3765 qdf_ret_status = sme_roam_disconnect(
3766 hdd_ctx->hHal,
3767 adapter->sessionId,
3768 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003770 qdf_ret_status = sme_roam_disconnect(
3771 hdd_ctx->hHal,
3772 adapter->sessionId,
3773 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303775 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 rc = wait_for_completion_timeout(
3777 &adapter->disconnect_comp_var,
3778 msecs_to_jiffies
3779 (WLAN_WAIT_TIME_DISCONNECT));
3780 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003781 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 }
3783 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003784 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 }
3786 memset(&wrqu, '\0', sizeof(wrqu));
3787 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3788 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3789 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3790 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303791 }
3792 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303793 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003794 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303795 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303796 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797
3798#ifdef WLAN_OPEN_SOURCE
3799 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3800#endif
3801
3802 hdd_deregister_tx_flow_control(adapter);
3803
3804#ifdef WLAN_NS_OFFLOAD
3805#ifdef WLAN_OPEN_SOURCE
3806 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3807#endif
3808#endif
3809
3810 /*
3811 * It is possible that the caller of this function does not
3812 * wish to close the session
3813 */
Krunal Soni985b8132017-02-10 18:49:08 -08003814 if (true == bCloseSession) {
3815 if (0 != wlan_hdd_try_disconnect(adapter)) {
3816 hdd_err("Error: Can't disconnect adapter");
3817 return QDF_STATUS_E_FAILURE;
3818 }
Peng Xu66162de2016-02-11 17:01:20 -08003819 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Krunal Soni985b8132017-02-10 18:49:08 -08003820 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821 break;
3822
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003823 case QDF_SAP_MODE:
3824 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003826 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827 /*
3828 * Before stopping the sap adapter, lets make sure there
3829 * is no sap restart work pending.
3830 */
3831 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003832 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003833 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834 }
3835 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003836 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3838
3839 hdd_deregister_tx_flow_control(adapter);
3840
3841 mutex_lock(&hdd_ctx->sap_lock);
3842 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303843 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303844 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845
3846 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 status = wlansap_stop_bss(
3848 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303850 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003851 hdd_hostapd_state_t *hostapd_state =
3852 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303853 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303854 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303855 qdf_status =
3856 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08003857 qdf_stop_bss_event,
3858 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859
Anurag Chouhance0dc992016-02-16 18:18:03 +05303860 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003861 hdd_err("failure waiting for wlansap_stop_bss %d",
3862 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003863 }
3864 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003865 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 }
3867 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003868 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869 adapter->device_mode,
3870 adapter->sessionId);
3871
Anurag Chouhanc5548422016-02-24 18:33:27 +05303872 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003873 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 updateIE.smeSessionId = adapter->sessionId;
3875 updateIE.ieBufferlength = 0;
3876 updateIE.pAdditionIEBuffer = NULL;
3877 updateIE.append = false;
3878 updateIE.notify = false;
3879 /* Probe bcn reset */
3880 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3881 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303882 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003883 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 }
3885 /* Assoc resp reset */
3886 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3887 &updateIE,
3888 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303889 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003890 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003891 }
3892 /* Reset WNI_CFG_PROBE_RSP Flags */
3893 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303894 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 adapter->sessionCtx.ap.beacon = NULL;
3896 }
3897 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003898 if (true == bCloseSession)
3899 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003900 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003901 case QDF_OCB_MODE:
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -08003902 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003903 (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
Leo Changfdb45c32016-10-28 11:09:23 -07003904 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 break;
3906 default:
3907 break;
3908 }
3909
3910 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303911 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912}
3913
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05303914/**
3915 * hdd_deinit_all_adapters - deinit all adapters
3916 * @hdd_ctx: HDD context
3917 * @rtnl_held: True if RTNL lock held
3918 *
3919 */
3920void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
3921{
3922 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3923 QDF_STATUS status;
3924 hdd_adapter_t *adapter;
3925
3926 ENTER();
3927
3928 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
3929
3930 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
3931 adapter = adapter_node->pAdapter;
3932 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3933 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
3934 adapter_node = next;
3935 }
3936
3937 EXIT();
3938}
3939
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303940QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003941{
3942 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303943 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944 hdd_adapter_t *adapter;
3945
3946 ENTER();
3947
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303948 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3951
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303952 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003953 adapter = adapterNode->pAdapter;
3954 hdd_stop_adapter(hdd_ctx, adapter, true);
3955 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3956 adapterNode = pNext;
3957 }
3958
3959 EXIT();
3960
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303961 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962}
3963
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303964QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003965{
3966 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303967 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003968 hdd_adapter_t *adapter;
3969
3970 ENTER();
3971
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303972 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3973
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003974 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3975
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303976 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003977 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003978 hdd_notice("Disabling queues");
Arun Khandavallicc544b32017-01-30 19:52:16 +05303979 if (hdd_ctx->config->sap_internal_restart &&
3980 adapter->device_mode == QDF_SAP_MODE) {
3981 wlan_hdd_netif_queue_control(adapter,
3982 WLAN_NETIF_TX_DISABLE,
3983 WLAN_CONTROL_PATH);
3984 hdd_sap_indicate_disconnect_for_sta(adapter);
3985 hdd_cleanup_actionframe(hdd_ctx, adapter);
3986 hdd_sap_destroy_events(adapter);
3987 } else
3988 wlan_hdd_netif_queue_control(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3990 WLAN_CONTROL_PATH);
3991
3992 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3993
3994 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003995 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003996 adapter->sessionId);
3997 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3998 hdd_wmm_adapter_close(adapter);
3999 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
4000 }
4001
Wu Gao36717432016-11-21 15:09:48 +08004002 /*
4003 * If adapter is SAP, set session ID to invalid since SAP
4004 * session will be cleanup during SSR.
4005 */
4006 if (adapter->device_mode == QDF_SAP_MODE)
4007 wlansap_set_invalid_session(
4008 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
4009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4011 adapterNode = pNext;
4012 }
4013
4014 EXIT();
4015
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304016 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017}
4018
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304019bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
4020{
4021 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4022 QDF_STATUS status;
4023 bool close_modules = true;
4024
4025 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4026 while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
4027 if (test_bit(DEVICE_IFACE_OPENED,
4028 &adapter_node->pAdapter->event_flags)) {
4029 hdd_info("Still other ifaces are up cannot close modules");
4030 close_modules = false;
4031 break;
4032 }
4033 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4034 adapter_node = next;
4035 }
4036
4037 return close_modules;
4038}
4039
Arun Khandavallifae92942016-08-01 13:31:08 +05304040/**
4041 * hdd_is_interface_up()- Checkfor interface up before ssr
4042 * @hdd_ctx: HDD context
4043 *
4044 * check if there are any wlan interfaces before SSR accordingly start
4045 * the interface.
4046 *
4047 * Return: 0 if interface was opened else false
4048 */
4049static bool hdd_is_interface_up(hdd_adapter_t *adapter)
4050{
4051 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
4052 return true;
4053 else
4054 return false;
4055}
4056
Anurag Chouhanc4092922016-09-08 15:56:11 +05304057#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05304058 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304059struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4060 struct ieee80211_channel *channel,
4061 const u8 *bssid, const u8 *ssid,
4062 size_t ssid_len)
4063{
4064 return cfg80211_get_bss(wiphy, channel, bssid,
4065 ssid, ssid_len,
4066 WLAN_CAPABILITY_ESS,
4067 WLAN_CAPABILITY_ESS);
4068}
4069#else
4070struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4071 struct ieee80211_channel *channel,
4072 const u8 *bssid, const u8 *ssid,
4073 size_t ssid_len)
4074{
4075 return cfg80211_get_bss(wiphy, channel, bssid,
4076 ssid, ssid_len,
4077 IEEE80211_BSS_TYPE_ESS,
4078 IEEE80211_PRIVACY_ANY);
4079}
4080#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304081
Abhishek Singha84d3952016-09-13 13:45:05 +05304082#if defined CFG80211_CONNECT_BSS
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304083#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
4084 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
4085/**
4086 * hdd_convert_timeout_reason() - Convert to kernel specific enum
4087 * @timeout_reason: reason for connect timeout
4088 *
4089 * This function is used to convert host timeout
4090 * reason enum to kernel specific enum.
4091 *
4092 * Return: nl timeout enum
4093 */
4094static enum nl80211_timeout_reason hdd_convert_timeout_reason(
4095 tSirResultCodes timeout_reason)
4096{
4097 switch (timeout_reason) {
4098 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
4099 return NL80211_TIMEOUT_SCAN;
4100 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
4101 return NL80211_TIMEOUT_AUTH;
4102 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
4103 return NL80211_TIMEOUT_ASSOC;
4104 default:
4105 return NL80211_TIMEOUT_UNSPECIFIED;
4106 }
4107}
4108
4109/**
4110 * hdd_cfg80211_connect_timeout() - API to send connection timeout reason
4111 * @dev: network device
4112 * @bssid: bssid to which we want to associate
4113 * @timeout_reason: reason for connect timeout
4114 *
4115 * This API is used to send connection timeout reason to supplicant
4116 *
4117 * Return: void
4118 */
4119static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4120 const u8 *bssid,
4121 tSirResultCodes timeout_reason)
4122{
4123 enum nl80211_timeout_reason nl_timeout_reason;
4124 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4125
4126 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
4127 nl_timeout_reason);
4128}
4129
4130/**
4131 * __hdd_connect_bss() - API to send connection status to supplicant
4132 * @dev: network device
4133 * @bssid: bssid to which we want to associate
4134 * @req_ie: Request Information Element
4135 * @req_ie_len: len of the req IE
4136 * @resp_ie: Response IE
4137 * @resp_ie_len: len of ht response IE
4138 * @status: status
4139 * @gfp: Kernel Flag
4140 * @timeout_reason: reason for connect timeout
4141 *
4142 * Return: void
4143 */
4144static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4145 struct cfg80211_bss *bss, const u8 *req_ie,
4146 size_t req_ie_len, const u8 *resp_ie,
4147 size_t resp_ie_len, int status, gfp_t gfp,
4148 tSirResultCodes timeout_reason)
4149{
4150 enum nl80211_timeout_reason nl_timeout_reason;
4151 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4152
4153 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4154 resp_ie, resp_ie_len, status, gfp,
4155 nl_timeout_reason);
4156}
4157#else
4158#if defined CFG80211_CONNECT_TIMEOUT
4159static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4160 const u8 *bssid,
4161 tSirResultCodes timeout_reason)
4162{
4163 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
4164}
4165#endif
4166
4167static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4168 struct cfg80211_bss *bss, const u8 *req_ie,
4169 size_t req_ie_len, const u8 *resp_ie,
4170 size_t resp_ie_len, int status, gfp_t gfp,
4171 tSirResultCodes timeout_reason)
4172{
4173 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4174 resp_ie, resp_ie_len, status, gfp);
4175}
4176#endif
4177
Abhishek Singha84d3952016-09-13 13:45:05 +05304178/**
4179 * hdd_connect_bss() - API to send connection status to supplicant
4180 * @dev: network device
4181 * @bssid: bssid to which we want to associate
4182 * @req_ie: Request Information Element
4183 * @req_ie_len: len of the req IE
4184 * @resp_ie: Response IE
4185 * @resp_ie_len: len of ht response IE
4186 * @status: status
4187 * @gfp: Kernel Flag
4188 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304189 * @timeout_reason: reason for connect timeout
Abhishek Singha84d3952016-09-13 13:45:05 +05304190 *
4191 * The API is a wrapper to send connection status to supplicant
4192 *
4193 * Return: Void
4194 */
4195#if defined CFG80211_CONNECT_TIMEOUT
4196static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4197 struct cfg80211_bss *bss, const u8 *req_ie,
4198 size_t req_ie_len, const u8 *resp_ie,
4199 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304200 bool connect_timeout,
4201 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304202{
4203 if (connect_timeout)
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304204 hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304205 else
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304206 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4207 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304208}
4209#else
4210static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4211 struct cfg80211_bss *bss, const u8 *req_ie,
4212 size_t req_ie_len, const u8 *resp_ie,
4213 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304214 bool connect_timeout,
4215 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304216{
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304217 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4218 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304219}
4220#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304221
4222/**
4223 * hdd_connect_result() - API to send connection status to supplicant
4224 * @dev: network device
4225 * @bssid: bssid to which we want to associate
4226 * @roam_info: information about connected bss
4227 * @req_ie: Request Information Element
4228 * @req_ie_len: len of the req IE
4229 * @resp_ie: Response IE
4230 * @resp_ie_len: len of ht response IE
4231 * @status: status
4232 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05304233 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304234 * @timeout_reason: reason for connect timeout
Anurag Chouhanc4092922016-09-08 15:56:11 +05304235 *
4236 * The API is a wrapper to send connection status to supplicant
4237 * and allow runtime suspend
4238 *
4239 * Return: Void
4240 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304241void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4242 tCsrRoamInfo *roam_info, const u8 *req_ie,
4243 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304244 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304245 bool connect_timeout,
4246 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304247{
4248 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4249 struct cfg80211_bss *bss = NULL;
4250
4251 if (WLAN_STATUS_SUCCESS == status) {
4252 struct ieee80211_channel *chan;
4253 int freq;
4254 int chan_no = roam_info->pBssDesc->channelId;
4255
4256 if (chan_no <= 14)
4257 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004258 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304259 else
4260 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004261 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304262
4263 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
4264 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
4265 roam_info->u.pConnectedProfile->SSID.ssId,
4266 roam_info->u.pConnectedProfile->SSID.length);
4267 }
Komal Seelama89be8d2016-09-29 11:09:26 +05304268
Abhishek Singha84d3952016-09-13 13:45:05 +05304269 hdd_connect_bss(dev, bssid, bss, req_ie,
4270 req_ie_len, resp_ie, resp_ie_len,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304271 status, gfp, connect_timeout, timeout_reason);
Komal Seelama89be8d2016-09-29 11:09:26 +05304272
4273 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304274}
4275#else
4276void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4277 tCsrRoamInfo *roam_info, const u8 *req_ie,
4278 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304279 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304280 bool connect_timeout,
4281 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304282{
Komal Seelama89be8d2016-09-29 11:09:26 +05304283 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4284
Anurag Chouhanc4092922016-09-08 15:56:11 +05304285 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4286 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304287 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304288}
4289#endif
4290
4291
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304292QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293{
4294 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304295 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 hdd_adapter_t *adapter;
4297#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304298 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299#endif
4300 eConnectionState connState;
4301
4302 ENTER();
4303
4304 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
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
Arun Khandavallifae92942016-08-01 13:31:08 +05304308 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304309 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304310
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311 hdd_wmm_init(adapter);
4312
4313 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004314 case QDF_STA_MODE:
4315 case QDF_P2P_CLIENT_MODE:
4316 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004317
4318 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4319 ->conn_info.connState;
4320
4321 hdd_init_station_mode(adapter);
4322 /* Open the gates for HDD to receive Wext commands */
4323 adapter->isLinkUpSvcNeeded = false;
4324 adapter->scan_info.mScanPending = false;
4325
4326 /* Indicate disconnect event to supplicant if associated previously */
4327 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004328 eConnectionState_IbssConnected == connState ||
4329 eConnectionState_NotConnected == connState ||
4330 eConnectionState_IbssDisconnected == connState ||
4331 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004332 union iwreq_data wrqu;
4333 memset(&wrqu, '\0', sizeof(wrqu));
4334 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4335 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4336 wireless_send_event(adapter->dev, SIOCGIWAP,
4337 &wrqu, NULL);
4338 adapter->sessionCtx.station.
4339 hdd_ReassocScenario = false;
4340
4341 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304342 wlan_hdd_cfg80211_indicate_disconnect(
4343 adapter->dev, false,
4344 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 } else if (eConnectionState_Connecting == connState) {
4346 /*
4347 * Indicate connect failure to supplicant if we were in the
4348 * process of connecting
4349 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304350 hdd_connect_result(adapter->dev, NULL, NULL,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304351 NULL, 0, NULL, 0,
4352 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4353 GFP_KERNEL, false,
4354 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 }
4356
4357 hdd_register_tx_flow_control(adapter,
4358 hdd_tx_resume_timer_expired_handler,
4359 hdd_tx_resume_cb);
4360
4361 break;
4362
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004363 case QDF_SAP_MODE:
Arun Khandavallicc544b32017-01-30 19:52:16 +05304364 if (hdd_ctx->config->sap_internal_restart)
4365 hdd_init_ap_mode(adapter, true);
4366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 break;
4368
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004369 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07004371 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004372 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4373#else
Jeff Johnson5880d792016-08-15 13:32:30 -07004374 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 /* event supplicant to restart */
4376 cfg80211_del_sta(adapter->dev,
4377 (const u8 *)&bcastMac.bytes[0],
4378 GFP_KERNEL);
4379#endif
4380 break;
4381
4382 default:
4383 break;
4384 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304385get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4387 adapterNode = pNext;
4388 }
4389
4390 EXIT();
4391
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304392 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393}
4394
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304395QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396 hdd_adapter_list_node_t **padapterNode)
4397{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304398 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004399 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304400 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4401 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004402 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403 return status;
4404}
4405
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304406QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407 hdd_adapter_list_node_t *adapterNode,
4408 hdd_adapter_list_node_t **pNextAdapterNode)
4409{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304410 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004411 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304412 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4413 (qdf_list_node_t *) adapterNode,
4414 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004416 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 return status;
4418}
4419
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304420QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004421 hdd_adapter_list_node_t *adapterNode)
4422{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304423 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004424 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304425 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004427 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 return status;
4429}
4430
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304431QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004432 hdd_adapter_list_node_t **padapterNode)
4433{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304434 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004435 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304436 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4437 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004438 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 return status;
4440}
4441
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304442QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443 hdd_adapter_list_node_t *adapterNode)
4444{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304445 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004446 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304447 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4448 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004449 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004450 return status;
4451}
4452
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304453QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454 hdd_adapter_list_node_t *adapterNode)
4455{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304456 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004457 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304458 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4459 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004460 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004461 return status;
4462}
4463
4464hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4465 tSirMacAddr macAddr)
4466{
4467 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4468 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304469 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470
4471 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4472
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304473 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 adapter = adapterNode->pAdapter;
4475
4476 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304477 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004478 macAddr, sizeof(tSirMacAddr))) {
4479 return adapter;
4480 }
4481 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4482 adapterNode = pNext;
4483 }
4484
4485 return NULL;
4486
4487}
4488
4489hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4490 uint32_t vdev_id)
4491{
4492 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4493 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304494 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304496 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304498 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 adapter = adapterNode->pAdapter;
4500
4501 if (adapter->sessionId == vdev_id)
4502 return adapter;
4503
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304504 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4506 adapterNode = pNext;
4507 }
4508
Jeff Johnson5880d792016-08-15 13:32:30 -07004509 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510
4511 return NULL;
4512}
4513
Abhishek Singh7996eb72015-12-30 17:24:02 +05304514/**
4515 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4516 * the sessionid
4517 * @hdd_ctx: hdd context.
4518 * @sme_session_id: sme session is for the adapter to get.
4519 *
4520 * This function is used to get the adapter with provided session id
4521 *
4522 * Return: adapter pointer if found
4523 *
4524 */
4525hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4526 uint32_t sme_session_id)
4527{
4528 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4529 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304530 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304531
4532
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304533 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304534
4535 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304536 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304537 adapter = adapter_node->pAdapter;
4538
4539 if (adapter &&
4540 adapter->sessionId == sme_session_id)
4541 return adapter;
4542
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304543 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304544 hdd_get_next_adapter(hdd_ctx,
4545 adapter_node, &next);
4546 adapter_node = next;
4547 }
4548 return NULL;
4549}
4550
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004551/**
4552 * hdd_get_adapter() - to get adapter matching the mode
4553 * @hdd_ctx: hdd context
4554 * @mode: adapter mode
4555 *
4556 * This routine will return the pointer to adapter matching
4557 * with the passed mode.
4558 *
4559 * Return: pointer to adapter or null
4560 */
4561hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4562 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563{
4564 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4565 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304566 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004567
4568 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4569
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304570 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 adapter = adapterNode->pAdapter;
4572
4573 if (adapter && (mode == adapter->device_mode))
4574 return adapter;
4575
4576 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4577 adapterNode = pNext;
4578 }
4579
4580 return NULL;
4581
4582}
4583
4584/**
4585 * hdd_get_operating_channel() - return operating channel of the device mode
4586 * @hdd_ctx: Pointer to the HDD context.
4587 * @mode: Device mode for which operating channel is required.
4588 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004589 * QDF_STA_MODE,
4590 * QDF_P2P_CLIENT_MODE,
4591 * QDF_SAP_MODE,
4592 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593 *
4594 * This API returns the operating channel of the requested device mode
4595 *
4596 * Return: channel number. "0" id the requested device is not found OR it is
4597 * not connected.
4598 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004599uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4600 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601{
4602 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304603 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004604 hdd_adapter_t *adapter;
4605 uint8_t operatingChannel = 0;
4606
4607 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4608
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304609 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610 adapter = adapterNode->pAdapter;
4611
4612 if (mode == adapter->device_mode) {
4613 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004614 case QDF_STA_MODE:
4615 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616 if (hdd_conn_is_connected
4617 (WLAN_HDD_GET_STATION_CTX_PTR
4618 (adapter))) {
4619 operatingChannel =
4620 (WLAN_HDD_GET_STATION_CTX_PTR
4621 (adapter))->conn_info.
4622 operationChannel;
4623 }
4624 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004625 case QDF_SAP_MODE:
4626 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004627 /* softap connection info */
4628 if (test_bit
4629 (SOFTAP_BSS_STARTED,
4630 &adapter->event_flags))
4631 operatingChannel =
4632 (WLAN_HDD_GET_AP_CTX_PTR
4633 (adapter))->operatingChannel;
4634 break;
4635 default:
4636 break;
4637 }
4638
4639 break; /* Found the device of interest. break the loop */
4640 }
4641
4642 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4643 adapterNode = pNext;
4644 }
4645 return operatingChannel;
4646}
4647
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304648static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 hdd_ctx)
4650{
4651 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304652 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653 hdd_adapter_t *adapter;
4654
4655 ENTER();
4656
4657 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4658
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304659 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004661 if ((adapter->device_mode == QDF_STA_MODE) ||
4662 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4663 (adapter->device_mode == QDF_IBSS_MODE) ||
4664 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4665 (adapter->device_mode == QDF_SAP_MODE) ||
4666 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667 wlan_hdd_cfg80211_deregister_frames(adapter);
4668 hdd_unregister_wext(adapter->dev);
4669 }
4670 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4671 adapterNode = pNext;
4672 }
4673
4674 EXIT();
4675
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304676 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677}
4678
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304679QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680{
4681 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304682 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 hdd_adapter_t *adapter;
4684
4685 ENTER();
4686
4687 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4688
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304689 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004691 if ((adapter->device_mode == QDF_STA_MODE) ||
4692 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4693 (adapter->device_mode == QDF_IBSS_MODE) ||
4694 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4695 (adapter->device_mode == QDF_SAP_MODE) ||
4696 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05304698 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 eCSR_SCAN_ABORT_DEFAULT);
4700 }
4701 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4702 adapterNode = pNext;
4703 }
4704
4705 EXIT();
4706
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304707 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708}
4709
Dustin Brownf27bce82016-11-03 12:52:27 -07004710/**
4711 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4712 * adapters
4713 * @hdd_ctx: The HDD context containing the adapters to operate on
4714 *
4715 * return: QDF_STATUS_SUCCESS
4716 */
4717static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4718{
4719 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4720 QDF_STATUS status;
4721 hdd_adapter_t *adapter;
4722 int err;
4723
4724 ENTER();
4725
4726 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4727
4728 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4729 adapter = adapter_node->pAdapter;
4730 if ((adapter->device_mode == QDF_STA_MODE) ||
4731 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4732 (adapter->device_mode == QDF_IBSS_MODE) ||
4733 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4734 (adapter->device_mode == QDF_SAP_MODE) ||
4735 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4736 err = wlan_hdd_sched_scan_stop(adapter->dev);
4737 if (err)
4738 hdd_err("Unable to stop scheduled scan");
4739 }
4740 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node);
4741 adapter_node = next_node;
4742 }
4743
4744 EXIT();
4745
4746 return QDF_STATUS_SUCCESS;
4747}
4748
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749#ifdef WLAN_NS_OFFLOAD
4750/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004751 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004752 * @hdd_ctx: Pointer to hdd context
4753 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004754 * Unregister for IPv6 address change notifications.
4755 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004756 * Return: None
4757 */
4758static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4759{
4760 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4761
4762 return;
4763}
4764
4765/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004766 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767 * @hdd_ctx: Pointer to hdd context
4768 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004769 * Register for IPv6 address change notifications.
4770 *
4771 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004772 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004773static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004774{
4775 int ret;
4776
4777 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4778 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004779 if (ret) {
4780 hdd_err("Failed to register IPv6 notifier: %d", ret);
4781 goto out;
4782 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004783
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004784 hdd_info("Registered IPv6 notifier");
4785out:
4786 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004787}
4788#else
4789/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004790 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004791 * @hdd_ctx: Pointer to hdd context
4792 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004793 * Unregister for IPv6 address change notifications.
4794 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004795 * Return: None
4796 */
4797static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4798{
4799}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004800
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004801/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004802 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803 * @hdd_ctx: Pointer to hdd context
4804 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004805 * Register for IPv6 address change notifications.
4806 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 * Return: None
4808 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004809static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004810{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004811 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004812}
4813#endif
4814
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304815#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4816/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004817 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304818 * @hdd_ctx: HDD context
4819 *
4820 * Activates the logging service
4821 *
4822 * Return: Zero in case of success, negative value otherwise
4823 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004824static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304825{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004826 int ret;
4827 struct hdd_config *config = hdd_ctx->config;
4828
4829 if (!config->wlanLoggingEnable)
4830 return 0;
4831
4832 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4833 config->wlanLoggingNumBuf);
4834 if (ret)
4835 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4836 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304837}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004838
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304839/**
4840 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4841 * @hdd_ctx: HDD context
4842 *
4843 * Deactivates the logging service
4844 *
4845 * Return: 0 on deactivating the logging service
4846 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004847static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304848{
4849 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4850 return wlan_logging_sock_deactivate_svc();
4851
4852 return 0;
4853}
4854#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004855static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304856{
4857 return 0;
4858}
4859
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004860static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304861{
4862 return 0;
4863}
4864#endif
4865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004867 * hdd_register_notifiers - Register netdev notifiers.
4868 * @hdd_ctx: HDD context
4869 *
4870 * Register netdev notifiers like IPv4 and IPv6.
4871 *
4872 * Return: 0 on success and errno on failure
4873 */
4874static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4875{
4876 int ret;
4877
4878 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4879 if (ret) {
4880 hdd_err("register_netdevice_notifier failed: %d", ret);
4881 goto out;
4882 }
4883
4884 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4885 if (ret)
4886 goto unregister_notifier;
4887
4888 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4889 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4890 if (ret) {
4891 hdd_err("Failed to register IPv4 notifier: %d", ret);
4892 goto unregister_ip6_notifier;
4893 }
4894
4895 return 0;
4896
4897unregister_ip6_notifier:
4898 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4899unregister_notifier:
4900 unregister_netdevice_notifier(&hdd_netdev_notifier);
4901out:
4902 return ret;
4903
4904}
4905
4906/**
4907 * hdd_unregister_notifiers - Unregister netdev notifiers.
4908 * @hdd_ctx: HDD context
4909 *
4910 * Unregister netdev notifiers like IPv4 and IPv6.
4911 *
4912 * Return: None.
4913 */
4914static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4915{
4916 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4917
4918 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4919
4920 unregister_netdevice_notifier(&hdd_netdev_notifier);
4921}
4922
4923/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004924 * hdd_exit_netlink_services - Exit netlink services
4925 * @hdd_ctx: HDD context
4926 *
4927 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4928 * nl service.
4929 *
4930 * Return: None.
4931 */
4932static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4933{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004934 hdd_close_cesium_nl_sock();
4935
4936 ptt_sock_deactivate_svc();
4937
4938 nl_srv_exit();
4939}
4940
4941/**
4942 * hdd_init_netlink_services- Init netlink services
4943 * @hdd_ctx: HDD context
4944 *
4945 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4946 * nl service.
4947 *
4948 * Return: 0 on success and errno on failure.
4949 */
4950static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4951{
4952 int ret;
4953
Ryan Hsuceddceb2016-04-28 10:20:14 -07004954 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004955 if (ret) {
4956 hdd_alert("nl_srv_init failed: %d", ret);
4957 goto out;
4958 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004959 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004960
4961 ret = oem_activate_service(hdd_ctx);
4962 if (ret) {
4963 hdd_alert("oem_activate_service failed: %d", ret);
4964 goto err_nl_srv;
4965 }
4966
4967 ret = ptt_sock_activate_svc();
4968 if (ret) {
4969 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4970 goto err_nl_srv;
4971 }
4972
4973 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004974 if (ret)
4975 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004976
4977 ret = cnss_diag_activate_service();
4978 if (ret) {
4979 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4980 goto err_close_cesium;
4981 }
4982
4983 return 0;
4984
4985err_close_cesium:
4986 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004987 ptt_sock_deactivate_svc();
4988err_nl_srv:
4989 nl_srv_exit();
4990out:
4991 return ret;
4992}
4993
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004994/**
4995 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4996 * @hdd_ctx: HDD context.
4997 *
4998 * Destroy RX wakelock.
4999 *
5000 * Return: None.
5001 */
5002static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
5003{
5004 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
5005}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005006
5007/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005008 * hdd_rx_wake_lock_create() - Create RX wakelock
5009 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005010 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005011 * Create RX wakelock.
5012 *
5013 * Return: None.
5014 */
5015static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
5016{
5017 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5018}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005019
5020/**
5021 * hdd_roc_context_init() - Init ROC context
5022 * @hdd_ctx: HDD context.
5023 *
5024 * Initialize ROC context.
5025 *
5026 * Return: 0 on success and errno on failure.
5027 */
5028static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
5029{
5030 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
5031 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
5032
5033 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5034
5035 return 0;
5036}
5037
5038/**
5039 * hdd_roc_context_destroy() - Destroy ROC context
5040 * @hdd_ctx: HDD context.
5041 *
5042 * Destroy roc list and flush the pending roc work.
5043 *
5044 * Return: None.
5045 */
5046static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
5047{
5048 flush_delayed_work(&hdd_ctx->roc_req_work);
5049 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08005050 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005051}
5052
5053/**
Houston Hoffman160db392016-10-10 17:37:51 -07005054 * hdd_context_deinit() - Deinitialize HDD context
5055 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005056 *
Houston Hoffman160db392016-10-10 17:37:51 -07005057 * Deinitialize HDD context along with all the feature specific contexts but
5058 * do not free hdd context itself. Caller of this API is supposed to free
5059 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005060 *
Houston Hoffman160db392016-10-10 17:37:51 -07005061 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005062 */
Houston Hoffman160db392016-10-10 17:37:51 -07005063static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005064{
Houston Hoffman160db392016-10-10 17:37:51 -07005065 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005066
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005067 hdd_roc_context_destroy(hdd_ctx);
5068
5069 hdd_sap_context_destroy(hdd_ctx);
5070
5071 hdd_rx_wake_lock_destroy(hdd_ctx);
5072
5073 hdd_tdls_context_destroy(hdd_ctx);
5074
5075 hdd_scan_context_destroy(hdd_ctx);
5076
5077 qdf_list_destroy(&hdd_ctx->hddAdapters);
5078
Houston Hoffman160db392016-10-10 17:37:51 -07005079 return 0;
5080}
5081
5082/**
5083 * hdd_context_destroy() - Destroy HDD context
5084 * @hdd_ctx: HDD context to be destroyed.
5085 *
5086 * Free config and HDD context as well as destroy all the resources.
5087 *
5088 * Return: None
5089 */
5090static void hdd_context_destroy(hdd_context_t *hdd_ctx)
5091{
5092 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
5093 hdd_logging_sock_deactivate_svc(hdd_ctx);
5094
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05305095 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5096
Houston Hoffman160db392016-10-10 17:37:51 -07005097 hdd_context_deinit(hdd_ctx);
5098
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305099 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005100 hdd_ctx->config = NULL;
5101
5102 wiphy_free(hdd_ctx->wiphy);
5103}
5104
5105/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 * hdd_wlan_exit() - HDD WLAN exit function
5107 * @hdd_ctx: Pointer to the HDD Context
5108 *
5109 * This is the driver exit point (invoked during rmmod)
5110 *
5111 * Return: None
5112 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005113static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005114{
5115 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305116 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05305118 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005119
5120 ENTER();
5121
Arun Khandavallifae92942016-08-01 13:31:08 +05305122 if (QDF_TIMER_STATE_RUNNING ==
5123 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
5124 hdd_info("Stpp interface change timer");
5125 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005126 }
5127
Arun Khandavallifae92942016-08-01 13:31:08 +05305128 if (!QDF_IS_STATUS_SUCCESS
5129 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
5130 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005131
Arun Khandavallifae92942016-08-01 13:31:08 +05305132
5133 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005134
Nitesh Shah61c10d92016-10-19 19:29:15 +05305135 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
5136
Prashanth Bhattaab004382016-10-11 16:08:11 -07005137 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005138
5139#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305140 if (QDF_TIMER_STATE_RUNNING ==
5141 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
5142 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143 }
5144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305145 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05305146 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005147 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 }
Liangwei Dongaef84342016-10-21 05:28:00 -04005149 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5150 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5151 hdd_ctx->last_acs_channel_list = NULL;
5152 hdd_ctx->num_of_channels = 0;
5153 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005154#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005155
Arun Khandavallifae92942016-08-01 13:31:08 +05305156 mutex_lock(&hdd_ctx->iface_change_lock);
5157 driver_status = hdd_ctx->driver_status;
5158 mutex_unlock(&hdd_ctx->iface_change_lock);
5159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160 /*
5161 * Powersave Offload Case
5162 * Disable Idle Power Save Mode
5163 */
5164 hdd_set_idle_ps_config(hdd_ctx, false);
5165
Arun Khandavallifae92942016-08-01 13:31:08 +05305166 if (driver_status != DRIVER_MODULES_CLOSED) {
5167 hdd_unregister_wext_all_adapters(hdd_ctx);
5168 /*
5169 * Cancel any outstanding scan requests. We are about to close
5170 * all of our adapters, but an adapter structure is what SME
5171 * passes back to our callback function. Hence if there
5172 * are any outstanding scan requests then there is a
5173 * race condition between when the adapter is closed and
5174 * when the callback is invoked. We try to resolve that
5175 * race condition here by canceling any outstanding scans
5176 * before we close the adapters.
5177 * Note that the scans may be cancelled in an asynchronous
5178 * manner, so ideally there needs to be some kind of
5179 * synchronization. Rather than introduce a new
5180 * synchronization here, we will utilize the fact that we are
5181 * about to Request Full Power, and since that is synchronized,
5182 * the expectation is that by the time Request Full Power has
5183 * completed, all scans will be cancelled
5184 */
5185 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07005186 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305187 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005188 }
5189
5190 /*
5191 * Close the scheduler before calling cds_close to make sure no thread
5192 * is scheduled after the each module close is called i.e after all the
5193 * data structures are freed.
5194 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305195 qdf_status = cds_sched_close(p_cds_context);
5196 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005197 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305198 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05305201 hdd_wlan_stop_modules(hdd_ctx);
5202
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305203 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
5204 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
5205 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
5206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207 /*
5208 * Close CDS
5209 * This frees pMac(HAL) context. There should not be any call
5210 * that requires pMac access after this.
5211 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07005213 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08005214 hdd_request_manager_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005215
Komal Seelam8634b772016-09-29 12:12:24 +05305216 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005217 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218
5219 hdd_ipa_cleanup(hdd_ctx);
5220
5221 /* Free up RoC request queue and flush workqueue */
5222 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05305224 wlansap_global_deinit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05305225 wlan_hdd_deinit_chan_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05305227 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005228
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07005229 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07005230
Arun Khandavallifae92942016-08-01 13:31:08 +05305231 hdd_exit_netlink_services(hdd_ctx);
5232 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005233 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234}
5235
5236void __hdd_wlan_exit(void)
5237{
5238 hdd_context_t *hdd_ctx;
5239
5240 ENTER();
5241
Anurag Chouhan6d760662016-02-20 16:05:43 +05305242 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005244 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 EXIT();
5246 return;
5247 }
5248
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005249 /* Check IPA HW Pipe shutdown */
5250 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
5251
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005252 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05305253 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 /* Do all the cleanup before deregistering the driver */
5256 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07005257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005258 EXIT();
5259}
5260
5261#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04005262/**
5263 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
5264 * @data: pointer to hdd_context_t
5265 *
5266 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
5267 * Then new ACS request will do a fresh scan without reusing the cached
5268 * scan information.
5269 *
5270 * Return: void
5271 */
Tang Yingying523322d2017-01-17 23:28:43 +08005272static void hdd_skip_acs_scan_timer_handler(void *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005273{
5274 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
5275
Jeff Johnson760350b2016-08-15 14:01:52 -07005276 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005277 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04005278 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5279 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5280 hdd_ctx->last_acs_channel_list = NULL;
5281 hdd_ctx->num_of_channels = 0;
5282 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283
5284 if (!hdd_ctx->hHal)
5285 return;
5286 sme_scan_flush_result(hdd_ctx->hHal);
5287}
5288#endif
5289
5290#ifdef QCA_HT_2040_COEX
5291/**
5292 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5293 * @adapter: pointer to adapter
5294 * @staId: station id
5295 * @macAddrSTA: station MAC address
5296 * @channel_type: channel type
5297 *
5298 * This function notifies FW with HT20/HT40 mode
5299 *
5300 * Return: 0 if successful, error number otherwise
5301 */
5302int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305303 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304{
5305 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305306 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 hdd_context_t *hdd_ctx = NULL;
5308
5309 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5310
5311 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305312 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305314
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005315 if (!hdd_ctx->hHal)
5316 return -EINVAL;
5317
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305318 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305320 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005321 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 return -EINVAL;
5323 }
5324
5325 return 0;
5326}
5327#endif
5328
5329/**
5330 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5331 * @state: state
5332 *
5333 * This function notifies FW with modem power status
5334 *
5335 * Return: 0 if successful, error number otherwise
5336 */
5337int hdd_wlan_notify_modem_power_state(int state)
5338{
5339 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305340 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005341 hdd_context_t *hdd_ctx;
5342
Anurag Chouhan6d760662016-02-20 16:05:43 +05305343 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305345 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305347
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 if (!hdd_ctx->hHal)
5349 return -EINVAL;
5350
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305351 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5352 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005353 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 state);
5355 return -EINVAL;
5356 }
5357 return 0;
5358}
5359
5360/**
5361 *
5362 * hdd_post_cds_enable_config() - HDD post cds start config helper
5363 * @adapter - Pointer to the HDD
5364 *
5365 * Return: None
5366 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305367QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305369 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005370
5371 /*
5372 * Send ready indication to the HDD. This will kick off the MAC
5373 * into a 'running' state and should kick off an initial scan.
5374 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305375 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5376 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005377 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5378 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305379 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 }
5381
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305382 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383}
5384
5385/* wake lock APIs for HDD */
5386void hdd_prevent_suspend(uint32_t reason)
5387{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305388 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389}
5390
5391void hdd_allow_suspend(uint32_t reason)
5392{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305393 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005394}
5395
5396void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5397{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305398 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5399 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400}
5401
5402/**
5403 * hdd_exchange_version_and_caps() - exchange version and capability with target
5404 * @hdd_ctx: Pointer to HDD context
5405 *
5406 * This is the HDD function to exchange version and capability information
5407 * between Host and Target
5408 *
5409 * This function gets reported version of FW.
5410 * It also finds the version of target headers used to compile the host;
5411 * It compares the above two and prints a warning if they are different;
5412 * It gets the SW and HW version string;
5413 * Finally, it exchanges capabilities between host and target i.e. host
5414 * and target exchange a msg indicating the features they support through a
5415 * bitmap
5416 *
5417 * Return: None
5418 */
5419void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5420{
5421
5422 tSirVersionType versionCompiled;
5423 tSirVersionType versionReported;
5424 tSirVersionString versionString;
5425 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305426 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427
5428 memset(&versionCompiled, 0, sizeof(versionCompiled));
5429 memset(&versionReported, 0, sizeof(versionReported));
5430
5431 /* retrieve and display WCNSS version information */
5432 do {
5433
5434 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5435 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305436 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005437 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 break;
5439 }
5440
5441 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5442 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305443 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005444 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445 break;
5446 }
5447
5448 if ((versionCompiled.major != versionReported.major) ||
5449 (versionCompiled.minor != versionReported.minor) ||
5450 (versionCompiled.version != versionReported.version) ||
5451 (versionCompiled.revision != versionReported.revision)) {
5452 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5453 "Host expected %u.%u.%u.%u\n",
5454 WLAN_MODULE_NAME,
5455 (int)versionReported.major,
5456 (int)versionReported.minor,
5457 (int)versionReported.version,
5458 (int)versionReported.revision,
5459 (int)versionCompiled.major,
5460 (int)versionCompiled.minor,
5461 (int)versionCompiled.version,
5462 (int)versionCompiled.revision);
5463 } else {
5464 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5465 WLAN_MODULE_NAME,
5466 (int)versionReported.major,
5467 (int)versionReported.minor,
5468 (int)versionReported.version,
5469 (int)versionReported.revision);
5470 }
5471
5472 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5473 versionString,
5474 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305475 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005476 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 break;
5478 }
5479
5480 pr_info("%s: WCNSS software version %s\n",
5481 WLAN_MODULE_NAME, versionString);
5482
5483 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5484 versionString,
5485 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305486 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005487 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488 break;
5489 }
5490
5491 pr_info("%s: WCNSS hardware version %s\n",
5492 WLAN_MODULE_NAME, versionString);
5493
5494 /*
5495 * 1.Check if FW version is greater than 0.1.1.0. Only then
5496 * send host-FW capability exchange message
5497 * 2.Host-FW capability exchange message is only present on
5498 * target 1.1 so send the message only if it the target is 1.1
5499 * minor numbers for different target branches:
5500 * 0 -> (1.0)Mainline Build
5501 * 1 -> (1.1)Mainline Build
5502 * 2->(1.04) Stability Build
5503 */
5504 if (((versionReported.major > 0) || (versionReported.minor > 1)
5505 || ((versionReported.minor >= 1)
5506 && (versionReported.version >= 1)))
5507 && ((versionReported.major == 1)
5508 && (versionReported.minor >= 1)))
5509 fwFeatCapsMsgSupported = 1;
5510
5511 if (fwFeatCapsMsgSupported) {
5512 /*
5513 * Indicate if IBSS heartbeat monitoring needs to be
5514 * offloaded
5515 */
5516 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5517 sme_disable_feature_capablity
5518 (IBSS_HEARTBEAT_OFFLOAD);
5519 }
5520
5521 sme_feature_caps_exchange(hdd_ctx->hHal);
5522 }
5523
5524 } while (0);
5525
5526}
5527
5528/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305529QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530{
5531 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5532 hdd_ctx->reg.cc_src);
5533}
5534
5535/**
5536 * hdd_is_5g_supported() - check if hardware supports 5GHz
5537 * @hdd_ctx: Pointer to the hdd context
5538 *
5539 * HDD function to know if hardware supports 5GHz
5540 *
5541 * Return: true if hardware supports 5GHz
5542 */
5543bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5544{
zdingf54169a2016-10-12 17:08:45 +08005545 if (!hdd_ctx || !hdd_ctx->config)
5546 return true;
5547
5548 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5549 return true;
5550 else
5551 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005552}
5553
Amar Singhale4f28ee2015-10-21 14:36:56 -07005554static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555{
5556 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005557 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558
5559 wiphy = hdd_ctx->wiphy;
5560
5561 /*
5562 * The channel information in
5563 * wiphy needs to be initialized before wiphy registration
5564 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005565 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5566 if (ret_val) {
5567 hdd_alert("regulatory init failed");
5568 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 }
5570
5571#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5572 wiphy->wowlan = &wowlan_support_reg_init;
5573#else
5574 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5575 WIPHY_WOWLAN_MAGIC_PKT |
5576 WIPHY_WOWLAN_DISCONNECT |
5577 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5578 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5579 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5580 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5581 WIPHY_WOWLAN_RFKILL_RELEASE;
5582
5583 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5584 WOW_MAX_FILTERS_PER_LIST);
5585 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5586 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5587#endif
5588
5589 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005590 ret_val = wlan_hdd_cfg80211_register(wiphy);
5591 if (0 > ret_val)
5592 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593
Amar Singhale4f28ee2015-10-21 14:36:56 -07005594 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005595}
5596
Ravi Joshie2331e82015-07-01 18:18:54 -07005597/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005598 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005599 * @hdd_ctx - handle to hdd context
5600 * @tx_packets - transmit packet count
5601 * @rx_packets - receive packet count
5602 *
5603 * The function controls the bus bandwidth and dynamic control of
5604 * tcp delayed ack configuration
5605 *
5606 * Returns: None
5607 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005608#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005609static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5610 const uint64_t tx_packets,
5611 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005612{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005614 uint64_t temp_rx = 0;
5615 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005616 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005617 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5618 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005619 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005621 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005622 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005623 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005624 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005625 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005626 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005627 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005628 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005629
Mohit Khannae71e2262015-11-10 09:37:24 -08005630 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5631 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632
5633 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005634 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5635 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005636 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005637 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305638 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305639 if (hdd_ctx->hbw_requested) {
5640 pld_remove_pm_qos(hdd_ctx->parent_dev);
5641 hdd_ctx->hbw_requested = false;
5642 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305643 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005644 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305645 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305646 if (!hdd_ctx->hbw_requested) {
5647 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5648 hdd_ctx->hbw_requested = true;
5649 }
5650
Nirav Shah3bbfa512016-05-12 16:43:49 +05305651 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005652 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305653 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005654 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005655 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005656
5657 /* fine-tuning parameters for RX Flows */
5658 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 hdd_ctx->prev_rx = rx_packets;
Ravi Joshifed83572016-10-07 16:20:37 -07005661 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5662 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5663 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5664 next_rx_level = WLAN_SVC_TP_HIGH;
5665 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005666 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005667 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005668 hdd_ctx->rx_high_ind_cnt = 0;
5669 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005670
Mohit Khannae71e2262015-11-10 09:37:24 -08005671 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5672 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005673
5674 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005675 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005676 next_rx_level, temp_rx);
5677 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005678 /* Send throughput indication only if it is enabled.
5679 * Disabling tcp_del_ack will revert the tcp stack behavior
5680 * to default delayed ack. Note that this will disable the
5681 * dynamic delayed ack mechanism across the system
5682 */
5683 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305684 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5685 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 &next_rx_level,
5687 sizeof(next_rx_level));
5688 }
5689
Mohit Khannae71e2262015-11-10 09:37:24 -08005690 /* fine-tuning parameters for TX Flows */
5691 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5692 hdd_ctx->prev_tx = tx_packets;
5693 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5694 next_tx_level = WLAN_SVC_TP_HIGH;
5695 else
5696 next_tx_level = WLAN_SVC_TP_LOW;
5697
5698 if (hdd_ctx->cur_tx_level != next_tx_level) {
5699 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5700 next_tx_level, temp_tx);
5701 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305702 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5703 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005704 &next_tx_level,
5705 sizeof(next_tx_level));
5706 }
5707
5708 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5709 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005710 hdd_ctx->hdd_txrx_hist_idx++;
5711 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712}
5713
5714#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305715static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005716{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305717 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5718 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005719 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305720 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305721 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5722 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723 uint64_t total_tx = 0, total_rx = 0;
5724 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305725 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305726 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727 bool connected = false;
5728 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5729
Prashanth Bhattaab004382016-10-11 16:08:11 -07005730 if (wlan_hdd_validate_context(hdd_ctx))
5731 return;
5732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305734 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735 status =
5736 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5737
5738 if (adapterNode->pAdapter == NULL)
5739 continue;
5740 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305741 /*
5742 * Validate magic so we don't end up accessing
5743 * an invalid adapter.
5744 */
5745 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5746 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005747
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005748 if ((adapter->device_mode == QDF_STA_MODE ||
5749 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5751 != eConnectionState_Associated) {
5752
5753 continue;
5754 }
5755
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005756 if ((adapter->device_mode == QDF_SAP_MODE ||
5757 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005758 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5759
5760 continue;
5761 }
5762
5763 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5764 adapter->prev_tx_packets);
5765 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5766 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305767
5768 if (adapter->device_mode == QDF_SAP_MODE ||
5769 adapter->device_mode == QDF_P2P_GO_MODE ||
5770 adapter->device_mode == QDF_IBSS_MODE) {
5771
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08005772 ret = cdp_get_intra_bss_fwd_pkts_count(
5773 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305774 adapter->sessionId,
5775 &fwd_tx_packets, &fwd_rx_packets);
5776 if (ret == A_OK) {
5777 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5778 fwd_tx_packets,
5779 adapter->prev_fwd_tx_packets);
5780 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5781 fwd_tx_packets,
5782 adapter->prev_fwd_rx_packets);
5783 }
5784 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005785
5786 total_rx += adapter->stats.rx_packets;
5787 total_tx += adapter->stats.tx_packets;
5788
5789 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5790 adapter->prev_tx_packets = adapter->stats.tx_packets;
5791 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305792 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5793 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5795 connected = true;
5796 }
5797
5798 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5799 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5800 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5801 rx_packets;
5802 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5803 tx_packets;
5804
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305805 /* add intra bss forwarded tx and rx packets */
5806 tx_packets += fwd_tx_packets_diff;
5807 rx_packets += fwd_rx_packets_diff;
5808
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5810 tx_packets += (uint64_t)ipa_tx_packets;
5811 rx_packets += (uint64_t)ipa_rx_packets;
5812
5813 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005814 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005815 return;
5816 }
5817
Yuanyuan Liu13738502016-04-06 17:41:37 -07005818 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819
5820 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5821 hdd_ipa_uc_stat_request(adapter, 2);
5822
Dustin Brown2ed60362017-01-18 12:25:50 -08005823 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08005824 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08005825 if (hdd_ctx->bus_bw_timer_running)
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05305826 qdf_timer_mod(&hdd_ctx->bus_bw_timer,
Dustin Brownfce08d12017-01-17 16:29:38 -08005827 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08005828 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005829}
Prashanth Bhattaab004382016-10-11 16:08:11 -07005830
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305831/**
5832 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
5833 * @arg: Argument of timer function
5834 *
5835 * Schedule a workqueue in this function where all the processing is done.
5836 *
5837 * Return: None.
5838 */
5839static void __hdd_bus_bw_cbk(void *arg)
5840{
5841 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
5842
5843 if (wlan_hdd_validate_context(hdd_ctx))
5844 return;
5845
5846 schedule_work(&hdd_ctx->bus_bw_work);
5847}
5848
5849/**
5850 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
5851 * @arg: Argument of timer function
5852 *
5853 * Return: None.
5854 */
5855static void hdd_bus_bw_cbk(void *arg)
5856{
5857 cds_ssr_protect(__func__);
5858 __hdd_bus_bw_cbk(arg);
5859 cds_ssr_unprotect(__func__);
5860}
5861
Prashanth Bhattaab004382016-10-11 16:08:11 -07005862int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
5863{
5864 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305865 INIT_WORK(&hdd_ctx->bus_bw_work,
5866 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08005867 hdd_ctx->bus_bw_timer_running = false;
5868 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305869 qdf_timer_init(NULL,
5870 &hdd_ctx->bus_bw_timer,
5871 hdd_bus_bw_cbk, (void *)hdd_ctx,
5872 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005873
5874 return 0;
5875}
5876
5877void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
5878{
Dustin Brownfce08d12017-01-17 16:29:38 -08005879 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07005880 hdd_reset_tcp_delack(hdd_ctx);
5881
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305882 hdd_info("wait for bus bw work to flush");
5883 cancel_work_sync(&hdd_ctx->bus_bw_work);
5884 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08005885 hdd_ctx->bus_bw_timer_running = false;
5886 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005887}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005888#endif
5889
5890/**
Nirav Shahed34b212016-04-25 10:59:16 +05305891 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5892 * @hdd_ctx: hdd context
5893 *
5894 * Return: 0 for success or error code
5895 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005896static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305897{
5898 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5899 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5900 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005901 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305902 return -ENOMEM;
5903 }
5904 return 0;
5905}
5906
5907/**
5908 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5909 * @hdd_ctx: hdd context
5910 *
5911 * Return: none
5912 */
5913void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5914{
5915 if (hdd_ctx->hdd_txrx_hist) {
5916 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5917 hdd_ctx->hdd_txrx_hist = NULL;
5918 }
5919}
5920
Nirav Shahda008342016-05-17 18:50:40 +05305921static uint8_t *convert_level_to_string(uint32_t level)
5922{
5923 switch (level) {
5924 /* initialize the wlan sub system */
5925 case WLAN_SVC_TP_NONE:
5926 return "NONE";
5927 case WLAN_SVC_TP_LOW:
5928 return "LOW";
5929 case WLAN_SVC_TP_MEDIUM:
5930 return "MED";
5931 case WLAN_SVC_TP_HIGH:
5932 return "HIGH";
5933 default:
5934 return "INVAL";
5935 }
5936}
5937
Nirav Shahed34b212016-04-25 10:59:16 +05305938
5939/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5941 * @hdd_ctx: hdd context
5942 *
5943 * Return: none
5944 */
5945void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5946{
5947 int i;
5948
5949#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005950 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305951 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005952 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953 hdd_ctx->config->busBandwidthHighThreshold,
5954 hdd_ctx->config->busBandwidthMediumThreshold,
5955 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005956 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305957 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005958 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005959 hdd_ctx->config->tcpDelackThresholdHigh,
5960 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005961 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305962 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005963#endif
5964
Jeff Johnson760350b2016-08-15 14:01:52 -07005965 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305966 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5967
Jeff Johnson760350b2016-08-15 14:01:52 -07005968 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 -08005969
5970 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005971 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5973 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5974 hdd_ctx->hdd_txrx_hist[i].total_tx,
5975 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305976 convert_level_to_string(
5977 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5978 convert_level_to_string(
5979 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5980 convert_level_to_string(
5981 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005982 }
5983 return;
5984}
5985
5986/**
5987 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5988 * @hdd_ctx: hdd context
5989 *
5990 * Return: none
5991 */
5992void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5993{
5994 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305995 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5996 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005997}
5998
5999/**
6000 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
6001 * @pHddCtx: hdd context
6002 *
6003 * Return: none
6004 */
6005void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
6006{
6007
6008 hdd_adapter_t *adapter = NULL;
6009 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306010 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006011 int i;
Nirav Shahda008342016-05-17 18:50:40 +05306012 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006013
6014 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306015 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006016 adapter = adapter_node->pAdapter;
6017
Jeff Johnson760350b2016-08-15 14:01:52 -07006018 hdd_err("\nNetif queue operation statistics:");
6019 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05306020 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07006021 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05306022 curr_time = qdf_system_ticks();
6023 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05306024 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05306025 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05306026 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306027 unpause = adapter->total_unpause_time;
6028 } else {
Nirav Shahda008342016-05-17 18:50:40 +05306029 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306030 pause = adapter->total_pause_time;
6031 }
Jeff Johnson760350b2016-08-15 14:01:52 -07006032 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05306033 qdf_system_ticks_to_msecs(total),
6034 qdf_system_ticks_to_msecs(pause),
6035 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07006036 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006037
Nirav Shahda008342016-05-17 18:50:40 +05306038 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
6039 qdf_time_t pause_delta = 0;
6040
6041 if (adapter->pause_map & (1 << i))
6042 pause_delta = delta;
6043
Jeff Johnson760350b2016-08-15 14:01:52 -07006044 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006045 hdd_reason_type_to_string(i),
6046 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05306047 adapter->queue_oper_stats[i].unpause_count,
6048 qdf_system_ticks_to_msecs(
6049 adapter->queue_oper_stats[i].total_pause_time +
6050 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 }
6052
Jeff Johnson760350b2016-08-15 14:01:52 -07006053 hdd_err("\nNetif queue operation history:");
6054 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05306055 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
6056
Jeff Johnson760350b2016-08-15 14:01:52 -07006057 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058
6059 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006060 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05306061 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006062 adapter->queue_oper_history[i].time),
6063 hdd_action_type_to_string(
6064 adapter->queue_oper_history[i].netif_action),
6065 hdd_reason_type_to_string(
6066 adapter->queue_oper_history[i].netif_reason),
6067 adapter->queue_oper_history[i].pause_map);
6068 }
6069
6070 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6071 adapter_node = next;
6072 }
6073
6074
6075}
6076
6077/**
6078 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
6079 * @hdd_ctx: hdd context
6080 *
6081 * Return: none
6082 */
6083void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
6084{
6085 hdd_adapter_t *adapter = NULL;
6086 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306087 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006088
6089 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306090 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006091 adapter = adapter_node->pAdapter;
6092
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306093 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006094 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306095 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006096 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05306097 adapter->history_index = 0;
6098 adapter->start_time = adapter->last_time = qdf_system_ticks();
6099 adapter->total_pause_time = 0;
6100 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006101 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6102 adapter_node = next;
6103 }
6104}
6105
6106/**
6107 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
6108 * @halHandle: Hal handle
6109 * @pContext: Pointer to the context
6110 * @sessionId: Session ID
6111 * @scanId: Scan ID
6112 * @status: Status
6113 *
6114 * This is the callback to be executed when 11d scan is completed to flush out
6115 * the scan results
6116 *
6117 * 11d scan is done during driver load and is a passive scan on all
6118 * channels supported by the device, 11d scans may find some APs on
6119 * frequencies which are forbidden to be used in the regulatory domain
6120 * the device is operating in. If these APs are notified to the supplicant
6121 * it may try to connect to these APs, thus flush out all the scan results
6122 * which are present in SME after 11d scan is done.
6123 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306124 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006125 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306126static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006127 uint8_t sessionId, uint32_t scanId,
6128 eCsrScanStatus status)
6129{
6130 ENTER();
6131
6132 sme_scan_flush_result(halHandle);
6133
6134 EXIT();
6135
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306136 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006137}
6138
6139#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6140/**
6141 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
6142 * @hdd_ctx: hdd global context
6143 *
6144 * Return: none
6145 */
6146static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6147{
6148 uint8_t i;
6149
6150 mutex_init(&hdd_ctx->op_ctx.op_lock);
6151 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6152 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6153 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
6154 }
6155}
6156#else
6157static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6158{
6159}
6160#endif
6161
Yingying Tang95409972016-10-20 15:16:15 +08006162#ifdef WLAN_FEATURE_WOW_PULSE
6163/**
6164 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
6165 * @phddctx: hdd_context_t structure pointer
6166 * @enable: enable or disable this behaviour
6167 *
6168 * Return: int
6169 */
6170static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6171{
6172 struct hdd_config *pcfg_ini = phddctx->config;
6173 struct wow_pulse_mode wow_pulse_set_info;
6174 QDF_STATUS status;
6175
6176 hdd_notice("wow pulse enable flag is %d", enable);
6177
6178 if (false == phddctx->config->wow_pulse_support)
6179 return 0;
6180
6181 /* prepare the request to send to SME */
6182 if (enable == true) {
6183 wow_pulse_set_info.wow_pulse_enable = true;
6184 wow_pulse_set_info.wow_pulse_pin =
6185 pcfg_ini->wow_pulse_pin;
6186 wow_pulse_set_info.wow_pulse_interval_low =
6187 pcfg_ini->wow_pulse_interval_low;
6188 wow_pulse_set_info.wow_pulse_interval_high =
6189 pcfg_ini->wow_pulse_interval_high;
6190 } else {
6191 wow_pulse_set_info.wow_pulse_enable = false;
6192 wow_pulse_set_info.wow_pulse_pin = 0;
6193 wow_pulse_set_info.wow_pulse_interval_low = 0;
6194 wow_pulse_set_info.wow_pulse_interval_high = 0;
6195 }
6196 hdd_notice("enable %d pin %d low %d high %d",
6197 wow_pulse_set_info.wow_pulse_enable,
6198 wow_pulse_set_info.wow_pulse_pin,
6199 wow_pulse_set_info.wow_pulse_interval_low,
6200 wow_pulse_set_info.wow_pulse_interval_high);
6201
6202 status = sme_set_wow_pulse(&wow_pulse_set_info);
6203 if (QDF_STATUS_E_FAILURE == status) {
6204 hdd_notice("sme_set_wow_pulse failure!");
6205 return -EIO;
6206 }
6207 hdd_notice("sme_set_wow_pulse success!");
6208 return 0;
6209}
6210#else
6211static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6212{
6213 return 0;
6214}
6215#endif
6216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006217#ifdef WLAN_FEATURE_FASTPATH
6218/**
6219 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
6220 * @hdd_cfg: hdd config
6221 * @context: lower layer context
6222 *
6223 * Return: none
6224 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306225void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006226 void *context)
6227{
6228 if (hdd_cfg->fastpath_enable)
6229 hif_enable_fastpath(context);
6230}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006231#endif
6232
Yuanyuan Liu13738502016-04-06 17:41:37 -07006233#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006234/**
6235 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006236 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006237 * @level: thermal level
6238 *
6239 * Change IPA data path to SW path when the thermal throttle level greater
6240 * than 0, and restore the original data path when throttle level is 0
6241 *
6242 * Return: none
6243 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006244static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006245{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006246 hdd_context_t *hdd_ctx = context;
6247
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006248 /* Change IPA to SW path when throttle level greater than 0 */
6249 if (level > THROTTLE_LEVEL_0)
6250 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
6251 else
6252 /* restore original concurrency mode */
6253 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
6254}
6255
6256/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306257 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
6258 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05306259 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006260 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306261 * Get a safe channel to restart SAP. PCL already takes into account the
6262 * unsafe channels. So, the PCL is validated with the ACS range to provide
6263 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006264 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306265 * Return: Channel number to restart SAP in case of success. In case of any
6266 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306268static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
6269 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306271 struct sir_pcl_list pcl;
6272 QDF_STATUS status;
6273 uint32_t i, j;
6274 tHalHandle *hal_handle;
6275 hdd_context_t *hdd_ctx;
6276 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006277
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306278 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6279 if (!hdd_ctx) {
6280 hdd_err("invalid HDD context");
6281 return INVALID_CHANNEL_ID;
6282 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006283
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306284 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6285 if (!hal_handle) {
6286 hdd_err("invalid HAL handle");
6287 return INVALID_CHANNEL_ID;
6288 }
6289
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306290 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
6291 pcl.pcl_list, &pcl.pcl_len,
6292 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6293 if (QDF_IS_STATUS_ERROR(status)) {
6294 hdd_err("Get PCL failed");
6295 return INVALID_CHANNEL_ID;
6296 }
6297
6298 if (!pcl.pcl_len) {
6299 hdd_alert("pcl length is zero. this is not expected");
6300 return INVALID_CHANNEL_ID;
6301 }
6302
6303 hdd_info("start:%d end:%d",
6304 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6305 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6306
6307 /* PCL already takes unsafe channel into account */
6308 for (i = 0; i < pcl.pcl_len; i++) {
6309 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6310 if ((pcl.pcl_list[i] >=
6311 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6312 (pcl.pcl_list[i] <=
6313 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6314 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
6315 return pcl.pcl_list[i];
6316 }
6317 }
6318
6319 hdd_info("no safe channel from PCL found in ACS range");
6320
6321 /* Try for safe channel from all valid channel */
6322 pcl.pcl_len = MAX_NUM_CHAN;
6323 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
6324 &pcl.pcl_len);
6325 if (QDF_IS_STATUS_ERROR(status)) {
6326 hdd_err("error in getting valid channel list");
6327 return INVALID_CHANNEL_ID;
6328 }
6329
6330 for (i = 0; i < pcl.pcl_len; i++) {
6331 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6332 found = false;
6333 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006334 if (pcl.pcl_list[i] ==
6335 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306336 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
6337 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006338 break;
6339 }
6340 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306341
6342 if (found)
6343 continue;
6344
6345 if ((pcl.pcl_list[i] >=
6346 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6347 (pcl.pcl_list[i] <=
6348 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6349 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
6350 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006351 }
6352 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306353
6354 return INVALID_CHANNEL_ID;
6355}
6356
6357/**
6358 * hdd_restart_sap() - Restarts SAP on the given channel
6359 * @adapter: AP adapter
6360 * @channel: Channel
6361 *
6362 * Restarts the SAP interface by invoking the function which executes the
6363 * callback to perform channel switch using (E)CSA.
6364 *
6365 * Return: None
6366 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05306367void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306368{
6369 hdd_ap_ctx_t *hdd_ap_ctx;
6370 tHalHandle *hal_handle;
6371
6372 if (!adapter) {
6373 hdd_err("invalid adapter");
6374 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006375 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306376
6377 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6378
6379 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6380 if (!hal_handle) {
6381 hdd_err("invalid HAL handle");
6382 return;
6383 }
6384
6385 hdd_ap_ctx->sapConfig.channel = channel;
6386 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6387 hdd_ap_ctx->sapConfig.ch_width_orig;
6388
6389 hdd_info("chan:%d width:%d",
6390 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6391
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006392 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306393 hdd_ap_ctx->sapConfig.sec_ch,
6394 &hdd_ap_ctx->sapConfig.ch_params);
6395
6396 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006397}
Kapil Gupta8878ad92017-02-13 11:56:04 +05306398
6399int hdd_update_acs_timer_reason(hdd_adapter_t *adapter, uint8_t reason)
6400{
6401 struct hdd_external_acs_timer_context *timer_context;
6402
6403 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6404
6405 if (QDF_TIMER_STATE_RUNNING ==
6406 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
6407 ap.vendor_acs_timer)) {
6408 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
6409 }
6410 timer_context = (struct hdd_external_acs_timer_context *)
6411 adapter->sessionCtx.ap.vendor_acs_timer.user_data;
6412 timer_context->reason = reason;
6413 qdf_mc_timer_start(&adapter->sessionCtx.ap.vendor_acs_timer,
6414 WLAN_VENDOR_ACS_WAIT_TIME);
6415 /* Update config to application */
6416 hdd_cfg80211_update_acs_config(adapter, reason);
6417 hdd_notice("Updated ACS config to nl with reason %d", reason);
6418
6419 return 0;
6420}
6421
Agrawal Ashish467dde42016-09-08 18:44:22 +05306422/**
6423 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6424 * @hdd_ctx: hdd context pointer
6425 *
6426 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6427 * and if ACS is enabled, driver will ask userspace to restart the
6428 * sap. User space on LTE coex indication restart driver.
6429 *
6430 * Return - none
6431 */
6432void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6433{
6434 QDF_STATUS status;
6435 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6436 hdd_adapter_t *adapter_temp;
6437 uint32_t i;
6438 bool found = false;
6439 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006440
Agrawal Ashish467dde42016-09-08 18:44:22 +05306441 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6442 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6443 adapter_temp = adapter_node->pAdapter;
6444
6445 if (!adapter_temp) {
6446 hdd_err("adapter is NULL, moving to next one");
6447 goto next_adapater;
6448 }
6449
6450 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6451 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
6452 hdd_info("skip device mode:%d acs:%d",
6453 adapter_temp->device_mode,
6454 adapter_temp->sessionCtx.ap.sapConfig.
6455 acs_cfg.acs_mode);
6456 goto next_adapater;
6457 }
6458
6459 found = false;
6460 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006461 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306462 hdd_ctxt->unsafe_channel_list[i]) {
6463 found = true;
6464 hdd_info("operating ch:%d is unsafe",
6465 adapter_temp->sessionCtx.ap.operatingChannel);
6466 break;
6467 }
6468 }
6469
6470 if (!found) {
6471 hdd_info("ch:%d is safe. no need to change channel",
6472 adapter_temp->sessionCtx.ap.operatingChannel);
6473 goto next_adapater;
6474 }
6475
Kapil Gupta8878ad92017-02-13 11:56:04 +05306476 if (hdd_ctxt->config->vendor_acs_support &&
6477 hdd_ctxt->config->acs_support_for_dfs_ltecoex) {
6478 hdd_update_acs_timer_reason(adapter_temp,
6479 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
6480 goto next_adapater;
6481 } else
6482 restart_chan =
6483 hdd_get_safe_channel_from_pcl_and_acs_range(
Agrawal Ashish467dde42016-09-08 18:44:22 +05306484 adapter_temp);
6485 if (!restart_chan) {
6486 hdd_alert("fail to restart SAP");
6487 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006488 /*
6489 * SAP restart due to unsafe channel. While
6490 * restarting the SAP, make sure to clear
6491 * acs_channel, channel to reset to
6492 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306493 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006494 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306495 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6496 adapter_temp->sessionCtx.ap.sapConfig.channel =
6497 AUTO_CHANNEL_SELECT;
Agrawal Ashish467dde42016-09-08 18:44:22 +05306498 hdd_info("sending coex indication");
6499 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6500 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6501 hdd_restart_sap(adapter_temp, restart_chan);
6502 }
6503
6504next_adapater:
6505 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6506 adapter_node = next;
6507 }
6508}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006509/**
6510 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6511 * @adapter: HDD adapter pointer
6512 * @indParam: Channel avoid notification parameter
6513 *
6514 * Avoid channel notification from FW handler.
6515 * FW will send un-safe channel list to avoid over wrapping.
6516 * hostapd should not use notified channel
6517 *
6518 * Return: None
6519 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306520void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006521{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006522 hdd_context_t *hdd_ctxt;
6523 tSirChAvoidIndType *ch_avoid_indi;
6524 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006525 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6526 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006527 uint16_t start_channel;
6528 uint16_t end_channel;
6529 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006530 tHddAvoidFreqList hdd_avoid_freq_list;
6531 uint32_t i;
6532
6533 /* Basic sanity */
6534 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006535 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006536 return;
6537 }
6538
6539 hdd_ctxt = (hdd_context_t *) hdd_context;
6540 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6541 cds_context = hdd_ctxt->pcds_context;
6542
6543 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006544 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006545 ch_avoid_indi->avoid_range_count);
6546
6547 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306548 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006549 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6550 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6551 ch_avoid_indi->avoid_freq_range[i].start_freq;
6552 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6553 ch_avoid_indi->avoid_freq_range[i].end_freq;
6554 }
6555 hdd_avoid_freq_list.avoidFreqRangeCount =
6556 ch_avoid_indi->avoid_range_count;
6557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006558 /* clear existing unsafe channel cache */
6559 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306560 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006561 sizeof(hdd_ctxt->unsafe_channel_list));
6562
6563 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6564 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006565 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006566 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006567 break;
6568 }
6569
6570 start_channel = ieee80211_frequency_to_channel(
6571 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6572 end_channel = ieee80211_frequency_to_channel(
6573 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006574 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006575 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6576 start_channel,
6577 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6578 end_channel);
6579
6580 /* do not process frequency bands that are not mapped to
6581 * predefined channels
6582 */
6583 if (start_channel == 0 || end_channel == 0)
6584 continue;
6585
Amar Singhalb8d4f152016-02-10 10:21:43 -08006586 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6587 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006588 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006589 ch_avoid_indi->avoid_freq_range[
6590 range_loop].start_freq) {
6591 start_channel_idx = channel_loop;
6592 break;
6593 }
6594 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006595 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6596 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006597 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006598 ch_avoid_indi->avoid_freq_range[
6599 range_loop].end_freq) {
6600 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006601 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602 ch_avoid_indi->avoid_freq_range[
6603 range_loop].end_freq)
6604 end_channel_idx--;
6605 break;
6606 }
6607 }
6608
Amar Singhalb8d4f152016-02-10 10:21:43 -08006609 if (start_channel_idx == INVALID_CHANNEL ||
6610 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006611 continue;
6612
6613 for (channel_loop = start_channel_idx; channel_loop <=
6614 end_channel_idx; channel_loop++) {
6615 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006616 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006617 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006619 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006620 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006621 break;
6622 }
6623 }
6624 }
6625
Jeff Johnson34c88b72016-08-15 14:27:11 -07006626 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006627 hdd_ctxt->unsafe_channel_count);
6628
Yuanyuan Liu13738502016-04-06 17:41:37 -07006629 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6630 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006631 hdd_ctxt->unsafe_channel_count)) {
6632 hdd_err("Failed to set unsafe channel");
6633
6634 /* clear existing unsafe channel cache */
6635 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306636 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006637 sizeof(hdd_ctxt->unsafe_channel_list));
6638
6639 return;
6640 }
6641
6642 for (channel_loop = 0;
6643 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006644 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006645 hdd_ctxt->unsafe_channel_list[channel_loop]);
6646 }
6647
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306648 /*
6649 * first update the unsafe channel list to the platform driver and
6650 * send the avoid freq event to the application
6651 */
6652 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6653
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306654 if (!hdd_ctxt->unsafe_channel_count) {
6655 hdd_info("no unsafe channels - not restarting SAP");
6656 return;
6657 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306658 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006659 return;
6660}
6661
6662/**
6663 * hdd_init_channel_avoidance() - Initialize channel avoidance
6664 * @hdd_ctx: HDD global context
6665 *
6666 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006667 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006668 * down to the lower layers. Then subscribe to subsequent channel
6669 * avoidance events.
6670 *
6671 * Return: None
6672 */
6673static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6674{
6675 uint16_t unsafe_channel_count;
6676 int index;
6677
Yuanyuan Liu13738502016-04-06 17:41:37 -07006678 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6679 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006680 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006681 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006682
Jeff Johnson34c88b72016-08-15 14:27:11 -07006683 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006684 hdd_ctx->unsafe_channel_count);
6685
Anurag Chouhan6d760662016-02-20 16:05:43 +05306686 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006687 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006688
6689 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006690 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691 hdd_ctx->unsafe_channel_list[index]);
6692
6693 }
6694
6695 /* Plug in avoid channel notification callback */
6696 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6697}
6698#else
6699static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6700{
6701}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006702static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703{
6704}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006705#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006706
6707/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006708 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6709 * user space
6710 * @frame_ind: Management frame data to be informed.
6711 *
6712 * This function is used to indicate management frame to
6713 * user space
6714 *
6715 * Return: None
6716 *
6717 */
6718void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6719{
6720 hdd_context_t *hdd_ctx = NULL;
6721 hdd_adapter_t *adapter = NULL;
6722 void *cds_context = NULL;
6723 int i;
6724
6725 /* Get the global VOSS context.*/
6726 cds_context = cds_get_global_context();
6727 if (!cds_context) {
6728 hdd_err("Global CDS context is Null");
6729 return;
6730 }
6731 /* Get the HDD context.*/
6732 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6733
6734 if (0 != wlan_hdd_validate_context(hdd_ctx))
6735 return;
6736
6737 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6738 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6739 adapter =
6740 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6741 if (adapter)
6742 break;
6743 }
6744 } else {
6745 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6746 frame_ind->sessionId);
6747 }
6748
6749 if ((NULL != adapter) &&
6750 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6751 __hdd_indicate_mgmt_frame(adapter,
6752 frame_ind->frame_len,
6753 frame_ind->frameBuf,
6754 frame_ind->frameType,
6755 frame_ind->rxChan,
6756 frame_ind->rxRssi);
6757 return;
6758}
6759
Kapil Gupta8878ad92017-02-13 11:56:04 +05306760static void hdd_lte_coex_restart_sap(hdd_adapter_t *adapter,
6761 hdd_context_t *hdd_ctx)
6762{
6763 uint8_t restart_chan = 0;
6764
6765 restart_chan =
6766 hdd_get_safe_channel_from_pcl_and_acs_range(adapter);
6767 if (!restart_chan) {
6768 hdd_alert("fail to restart SAP");
6769 } else {
6770 /* SAP restart due to unsafe channel. While restarting
6771 * the SAP, make sure to clear acs_channel, channel to
6772 * reset to 0. Otherwise these settings will override
6773 * the ACS while restart.
6774 */
6775 hdd_ctx->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6776 adapter->sessionCtx.ap.sapConfig.channel =
6777 AUTO_CHANNEL_SELECT;
6778 hdd_info("sending coex indication");
6779 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
6780 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6781 hdd_restart_sap(adapter, restart_chan);
6782 }
6783}
6784
6785void hdd_acs_response_timeout_handler(void *context)
6786{
6787 struct hdd_external_acs_timer_context *timer_context =
6788 (struct hdd_external_acs_timer_context *)context;
6789 hdd_adapter_t *adapter;
6790 hdd_context_t *hdd_ctx;
6791 uint8_t reason;
6792
6793 ENTER();
6794 if (!timer_context) {
6795 hdd_err("invlaid timer context");
6796 return;
6797 }
6798 adapter = timer_context->adapter;
6799 reason = timer_context->reason;
6800
6801
6802 if ((!adapter) ||
6803 (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
6804 hdd_err("invalid adapter or adapter has invalid magic");
6805 return;
6806 }
6807 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6808 if (wlan_hdd_validate_context(hdd_ctx))
6809 return;
6810
6811 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
6812 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6813 else
6814 return;
6815
6816 hdd_err("ACS timeout happened for %s reason %d",
6817 adapter->dev->name, reason);
6818 switch (reason) {
6819 /* SAP init case */
6820 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
6821 wlan_sap_set_vendor_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6822 false);
6823 wlan_hdd_cfg80211_start_acs(adapter);
6824 break;
6825 /* DFS detected on current channel */
6826 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
6827 wlan_sap_update_next_channel(
6828 WLAN_HDD_GET_SAP_CTX_PTR(adapter), 0, 0);
6829 sme_update_new_channel_event(WLAN_HDD_GET_HAL_CTX(adapter),
6830 adapter->sessionId);
6831 break;
6832 /* LTE coex event on current channel */
6833 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
6834 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
6835 break;
6836 default:
6837 hdd_info("invalid reason for timer invoke");
6838
6839 }
6840}
6841
Rajeev Kumard004abc2016-02-17 12:09:56 -08006842/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006843 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6844 * @hdd_ctx: HDD context
6845 *
6846 * Disables all the dual mac features like DBS, Agile DFS etc.
6847 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306848 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006849 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306850static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006851{
6852 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306853 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006854
6855 if (!hdd_ctx) {
6856 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306857 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006858 }
6859
6860 cfg.scan_config = 0;
6861 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306862 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006863
6864 hdd_debug("Disabling all dual mac features...");
6865
6866 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306867 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006868 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6869 return status;
6870 }
6871
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306872 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873}
6874
6875/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006876 * hdd_override_ini_config - Override INI config
6877 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006878 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006879 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006880 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006881 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006882 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006883static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006884{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006885
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006886 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6887 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6888 hdd_notice("Module enable_dfs_chan_scan set to %d",
6889 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006890 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006891 if (0 == enable_11d || 1 == enable_11d) {
6892 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6893 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006894 }
Leo Chang11545d62016-10-17 14:53:50 -07006895
6896 if (!hdd_ipa_is_present(hdd_ctx))
6897 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006898}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006899
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006900/**
6901 * hdd_set_trace_level_for_each - Set trace level for each INI config
6902 * @hdd_ctx - HDD context
6903 *
6904 * Set trace level for each module based on INI config.
6905 *
6906 * Return: None
6907 */
6908static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6909{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306910 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6911 hdd_ctx->config->qdf_trace_enable_wdi);
6912 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6913 hdd_ctx->config->qdf_trace_enable_hdd);
6914 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6915 hdd_ctx->config->qdf_trace_enable_sme);
6916 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6917 hdd_ctx->config->qdf_trace_enable_pe);
6918 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6919 hdd_ctx->config->qdf_trace_enable_wma);
6920 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6921 hdd_ctx->config->qdf_trace_enable_sys);
6922 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6923 hdd_ctx->config->qdf_trace_enable_qdf);
6924 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6925 hdd_ctx->config->qdf_trace_enable_sap);
6926 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6927 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6928 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6929 hdd_ctx->config->qdf_trace_enable_bmi);
6930 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6931 hdd_ctx->config->qdf_trace_enable_cfg);
6932 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6933 hdd_ctx->config->qdf_trace_enable_epping);
6934 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6935 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6936 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306937 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306938 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6939 hdd_ctx->config->qdf_trace_enable_htc);
6940 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6941 hdd_ctx->config->qdf_trace_enable_hif);
6942 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6943 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6944 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6945 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306946
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006947 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006948}
6949
6950/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006951 * hdd_context_init() - Initialize HDD context
6952 * @hdd_ctx: HDD context.
6953 *
6954 * Initialize HDD context along with all the feature specific contexts.
6955 *
6956 * return: 0 on success and errno on failure.
6957 */
6958static int hdd_context_init(hdd_context_t *hdd_ctx)
6959{
6960 int ret;
6961
6962 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6963 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6964
6965 hdd_init_ll_stats_ctx();
6966
6967 init_completion(&hdd_ctx->mc_sus_event_var);
6968 init_completion(&hdd_ctx->ready_to_suspend);
6969
6970 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306971 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006972 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306973
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006974 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6975
6976 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6977
6978 ret = hdd_scan_context_init(hdd_ctx);
6979 if (ret)
6980 goto list_destroy;
6981
Nitesh Shahd1266d72017-01-25 22:07:07 +05306982 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006983
6984 hdd_rx_wake_lock_create(hdd_ctx);
6985
6986 ret = hdd_sap_context_init(hdd_ctx);
6987 if (ret)
6988 goto scan_destroy;
6989
6990 ret = hdd_roc_context_init(hdd_ctx);
6991 if (ret)
6992 goto sap_destroy;
6993
6994 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6995
6996 hdd_init_offloaded_packets_ctx(hdd_ctx);
6997
6998 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6999 hdd_ctx->config);
7000 if (ret)
7001 goto roc_destroy;
7002
7003 return 0;
7004
7005roc_destroy:
7006 hdd_roc_context_destroy(hdd_ctx);
7007
7008sap_destroy:
7009 hdd_sap_context_destroy(hdd_ctx);
7010
7011scan_destroy:
7012 hdd_scan_context_destroy(hdd_ctx);
7013 hdd_rx_wake_lock_destroy(hdd_ctx);
7014 hdd_tdls_context_destroy(hdd_ctx);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007015list_destroy:
7016 qdf_list_destroy(&hdd_ctx->hddAdapters);
Sandeep Puligillad0004212017-02-26 18:34:56 -08007017
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007018 return ret;
7019}
7020
7021/**
7022 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05307023 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007024 *
7025 * Allocate and initialize HDD context. HDD context is allocated as part of
7026 * wiphy allocation and then context is initialized.
7027 *
7028 * Return: HDD context on success and ERR_PTR on failure
7029 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007030static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007031{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307032 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007033 int ret = 0;
7034 hdd_context_t *hdd_ctx;
7035 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307036 int qdf_print_idx = -1;
7037
7038 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
7039 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
7040 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
7041 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
7042 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
7043 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
7044 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
7045 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
7046 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
7047 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
7048 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
7049 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
7050 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7051 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7052 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
7053 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
7054 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
7055 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
7056 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
7057 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
7058 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiyaf928edf2017-02-06 14:43:24 +05307059 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
7060 [QDF_MODULE_ID_DP] = {QDF_TRACE_LEVEL_ALL},
7061 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
7062 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
7063 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
7064 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
Mukul Sharma4d7d6b02017-02-13 20:45:22 +05307065 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
Abhishek Singh9679dbf2017-02-15 11:35:41 +05307066 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
7067 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL}
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307068 };
7069
7070 status = qdf_print_setup();
7071 if (status != QDF_STATUS_SUCCESS) {
7072 pr_err("QDF print control object setup failed\n");
7073 ret = -EINVAL;
7074 goto err_out;
7075 }
7076 /* Register the module here with QDF */
7077 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
7078 "MCL_WLAN");
7079
7080 /* if qdf_print_idx is negative */
7081 if (qdf_print_idx < 0) {
7082 pr_err("QDF print control can not be registered %d\n",
7083 qdf_print_idx);
7084 ret = -EINVAL;
7085 goto err_out;
7086 }
7087
7088 /* Store the qdf_pidx information into qdf module */
7089 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007090
7091 ENTER();
7092
7093 p_cds_context = cds_get_global_context();
7094 if (p_cds_context == NULL) {
7095 hdd_alert("Failed to get CDS global context");
7096 ret = -EINVAL;
7097 goto err_out;
7098 }
7099
7100 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
7101
7102 if (hdd_ctx == NULL) {
7103 ret = -ENOMEM;
7104 goto err_out;
7105 }
7106
7107 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007108 hdd_ctx->parent_dev = dev;
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05307109 hdd_ctx->last_scan_reject_session_id = 0xFF;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007110
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307111 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007112 if (hdd_ctx->config == NULL) {
7113 hdd_alert("Failed to alloc memory for HDD config!");
7114 ret = -ENOMEM;
7115 goto err_free_hdd_context;
7116 }
7117
7118 /* Read and parse the qcom_cfg.ini file */
7119 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307120 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307121 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007122 WLAN_INI_FILE);
7123 ret = -EINVAL;
7124 goto err_free_config;
7125 }
7126
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007127 hdd_notice("Setting configuredMcastBcastFilter: %d",
7128 hdd_ctx->config->mcastBcastFilterSetting);
7129
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307130 if (hdd_ctx->config->fhostNSOffload)
7131 hdd_ctx->ns_offload_enable = true;
7132
Abhishek Singh5ea86532016-04-27 14:10:53 +05307133 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
7134
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007135 hdd_override_ini_config(hdd_ctx);
7136
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007137 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007138
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007139 ret = hdd_context_init(hdd_ctx);
7140
7141 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007142 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007143
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007144
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -08007145 pld_set_fw_log_mode(hdd_ctx->parent_dev,
7146 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007147
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007148
7149 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05307150 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007151
Anurag Chouhan6d760662016-02-20 16:05:43 +05307152 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007153 goto skip_multicast_logging;
7154
7155 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
7156
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007157 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
7158 if (ret)
7159 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05307160
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007161 ret = hdd_logging_sock_activate_svc(hdd_ctx);
7162 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05307163 goto err_free_histogram;
7164
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007165skip_multicast_logging:
7166 hdd_set_trace_level_for_each(hdd_ctx);
7167
7168 return hdd_ctx;
7169
Nirav Shahed34b212016-04-25 10:59:16 +05307170err_free_histogram:
7171 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
7172
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007173err_deinit_hdd_context:
7174 hdd_context_deinit(hdd_ctx);
7175
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007176err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307177 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007178
7179err_free_hdd_context:
7180 wiphy_free(hdd_ctx->wiphy);
7181
7182err_out:
7183 return ERR_PTR(ret);
7184}
7185
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007186#ifdef WLAN_OPEN_P2P_INTERFACE
7187/**
7188 * hdd_open_p2p_interface - Open P2P interface
7189 * @hdd_ctx: HDD context
7190 * @rtnl_held: True if RTNL lock held
7191 *
7192 * Open P2P interface during probe. This function called to open the P2P
7193 * interface at probe along with STA interface.
7194 *
7195 * Return: 0 on success and errno on failure
7196 */
7197static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7198{
7199 hdd_adapter_t *adapter;
7200 uint8_t *p2p_dev_addr;
7201
7202 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
7203 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307204 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007205 hdd_ctx->config->intfMacAddr[0].bytes,
7206 sizeof(tSirMacAddr));
7207
7208 /*
7209 * Generate the P2P Device Address. This consists of
7210 * the device's primary MAC address with the locally
7211 * administered bit set.
7212 */
7213 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
7214 } else {
7215 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7216 if (p2p_dev_addr == NULL) {
7217 hdd_alert("Failed to allocate mac_address for p2p_device");
7218 return -ENOSPC;
7219 }
7220
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307221 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307222 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007223 }
7224
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007225 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007226 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08007227 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007228
7229 if (NULL == adapter) {
7230 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
7231 return -ENOSPC;
7232 }
7233
7234 return 0;
7235}
7236#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05307237static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007238 bool rtnl_held)
7239{
7240 return 0;
7241}
7242#endif
7243
Jeff Johnson957bc272017-02-02 08:54:48 -08007244static int hdd_open_ocb_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7245{
7246 hdd_adapter_t *adapter;
7247 int ret = 0;
7248
7249 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
7250 wlan_hdd_get_intf_addr(hdd_ctx),
7251 NET_NAME_UNKNOWN, rtnl_held);
7252 if (adapter == NULL) {
7253 hdd_err("Failed to open 802.11p interface");
7254 ret = -ENOSPC;
7255 }
7256
7257 return ret;
7258}
7259
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007260/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307261 * hdd_start_station_adapter()- Start the Station Adapter
7262 * @adapter: HDD adapter
7263 *
7264 * This function initializes the adapter for the station mode.
7265 *
7266 * Return: 0 on success or errno on failure.
7267 */
7268int hdd_start_station_adapter(hdd_adapter_t *adapter)
7269{
7270 QDF_STATUS status;
7271
7272 ENTER_DEV(adapter->dev);
7273
7274 status = hdd_init_station_mode(adapter);
7275
7276 if (QDF_STATUS_SUCCESS != status) {
7277 hdd_err("Error Initializing station mode: %d", status);
7278 return qdf_status_to_os_return(status);
7279 }
7280
Arun Khandavallifae92942016-08-01 13:31:08 +05307281 hdd_register_tx_flow_control(adapter,
7282 hdd_tx_resume_timer_expired_handler,
7283 hdd_tx_resume_cb);
7284
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307285 EXIT();
7286 return 0;
7287}
7288
7289/**
7290 * hdd_start_ap_adapter()- Start AP Adapter
7291 * @adapter: HDD adapter
7292 *
7293 * This function initializes the adapter for the AP mode.
7294 *
7295 * Return: 0 on success errno on failure.
7296 */
7297int hdd_start_ap_adapter(hdd_adapter_t *adapter)
7298{
7299 QDF_STATUS status;
7300
7301 ENTER();
7302
Arun Khandavallicc544b32017-01-30 19:52:16 +05307303 status = hdd_init_ap_mode(adapter, false);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307304
7305 if (QDF_STATUS_SUCCESS != status) {
7306 hdd_err("Error Initializing the AP mode: %d", status);
7307 return qdf_status_to_os_return(status);
7308 }
7309
Arun Khandavallifae92942016-08-01 13:31:08 +05307310 hdd_register_tx_flow_control(adapter,
7311 hdd_softap_tx_resume_timer_expired_handler,
7312 hdd_softap_tx_resume_cb);
7313
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307314 EXIT();
7315 return 0;
7316}
7317
7318/**
7319 * hdd_start_ftm_adapter()- Start FTM adapter
7320 * @adapter: HDD adapter
7321 *
7322 * This function initializes the adapter for the FTM mode.
7323 *
7324 * Return: 0 on success or errno on failure.
7325 */
7326int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
7327{
7328 QDF_STATUS qdf_status;
7329
7330 ENTER_DEV(adapter->dev);
7331
7332 qdf_status = hdd_init_tx_rx(adapter);
7333
7334 if (QDF_STATUS_SUCCESS != qdf_status) {
7335 hdd_err("Failed to start FTM adapter: %d", qdf_status);
7336 return qdf_status_to_os_return(qdf_status);
7337 }
7338
7339 return 0;
7340 EXIT();
7341}
7342
7343/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007344 * hdd_open_interfaces - Open all required interfaces
7345 * hdd_ctx: HDD context
7346 * rtnl_held: True if RTNL lock is held
7347 *
7348 * Open all the interfaces like STA, P2P and OCB based on the configuration.
7349 *
Jeff Johnson957bc272017-02-02 08:54:48 -08007350 * Return: 0 if all interfaces were created, otherwise negative errno
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007351 */
Jeff Johnson957bc272017-02-02 08:54:48 -08007352static int hdd_open_interfaces(hdd_context_t *hdd_ctx, bool rtnl_held)
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007353{
Jeff Johnson957bc272017-02-02 08:54:48 -08007354 hdd_adapter_t *adapter;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007355 int ret;
7356
Jeff Johnson957bc272017-02-02 08:54:48 -08007357 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
Arun Khandavallifae92942016-08-01 13:31:08 +05307358 /* Create only 802.11p interface */
Jeff Johnson957bc272017-02-02 08:54:48 -08007359 return hdd_open_ocb_interface(hdd_ctx, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007360
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007361 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007362 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08007363 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007364
7365 if (adapter == NULL)
Jeff Johnson957bc272017-02-02 08:54:48 -08007366 return -ENOSPC;
7367
Deepak Dhamdherea2785822016-11-17 01:17:45 -08007368 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
7369 adapter->fast_roaming_allowed = true;
7370
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007371 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
7372 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08007373 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007374
7375 /* Open 802.11p Interface */
7376 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Jeff Johnson957bc272017-02-02 08:54:48 -08007377 ret = hdd_open_ocb_interface(hdd_ctx, rtnl_held);
7378 if (ret)
7379 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007380 }
7381
Jeff Johnson957bc272017-02-02 08:54:48 -08007382 return 0;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007383
Jeff Johnson957bc272017-02-02 08:54:48 -08007384err_close_adapters:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007385 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Jeff Johnson957bc272017-02-02 08:54:48 -08007386 return ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007387}
7388
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007389/**
7390 * hdd_update_country_code - Update country code
7391 * @hdd_ctx: HDD context
7392 * @adapter: Primary adapter context
7393 *
7394 * Update country code based on module parameter country_code at SME and wait
7395 * for the settings to take effect.
7396 *
7397 * Return: 0 on success and errno on failure
7398 */
7399static int hdd_update_country_code(hdd_context_t *hdd_ctx,
7400 hdd_adapter_t *adapter)
7401{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307402 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007403 int ret = 0;
7404 unsigned long rc;
7405
7406 if (country_code == NULL)
7407 return 0;
7408
7409 INIT_COMPLETION(adapter->change_country_code);
7410
7411 status = sme_change_country_code(hdd_ctx->hHal,
7412 wlan_hdd_change_country_code_callback,
7413 country_code, adapter,
7414 hdd_ctx->pcds_context, eSIR_TRUE,
7415 eSIR_TRUE);
7416
7417
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307418 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007419 hdd_err("SME Change Country code from module param fail ret=%d",
7420 ret);
7421 return -EINVAL;
7422 }
7423
7424 rc = wait_for_completion_timeout(&adapter->change_country_code,
7425 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
7426 if (!rc) {
7427 hdd_err("SME while setting country code timed out");
7428 ret = -ETIMEDOUT;
7429 }
7430
7431 return ret;
7432}
7433
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307434#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7435/**
7436 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7437 * @cds_cfg: CDS Configuration
7438 * @hdd_ctx: Pointer to hdd context
7439 *
7440 * Return: none
7441 */
7442static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7443 *cds_cfg,
7444 hdd_context_t *hdd_ctx)
7445{
7446 cds_cfg->tx_flow_stop_queue_th =
7447 hdd_ctx->config->TxFlowStopQueueThreshold;
7448 cds_cfg->tx_flow_start_queue_offset =
7449 hdd_ctx->config->TxFlowStartQueueOffset;
7450}
7451#else
7452static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7453 *cds_cfg,
7454 hdd_context_t *hdd_ctx)
7455{
7456}
7457#endif
7458
7459#ifdef FEATURE_WLAN_RA_FILTERING
7460/**
7461 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7462 * @cds_cfg: CDS Configuration
7463 * @hdd_ctx: Pointer to hdd context
7464 *
7465 * Return: none
7466 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307467static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307468 hdd_context_t *hdd_ctx)
7469{
7470 cds_cfg->ra_ratelimit_interval =
7471 hdd_ctx->config->RArateLimitInterval;
7472 cds_cfg->is_ra_ratelimit_enabled =
7473 hdd_ctx->config->IsRArateLimitEnabled;
7474}
7475#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307476static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307477 hdd_context_t *hdd_ctx)
7478{
7479}
7480#endif
7481
7482/**
7483 * hdd_update_cds_config() - API to update cds configuration parameters
7484 * @hdd_ctx: HDD Context
7485 *
7486 * Return: 0 for Success, errno on failure
7487 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007488static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307489{
7490 struct cds_config_info *cds_cfg;
7491
7492 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7493 if (!cds_cfg) {
7494 hdd_err("failed to allocate cds config");
7495 return -ENOMEM;
7496 }
7497
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307498 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
7499 cds_cfg->powersave_offload_enabled =
7500 hdd_ctx->config->enablePowersaveOffload;
7501 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7502 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7503 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7504 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7505 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7506
7507 /* Here ol_ini_info is used to store ini status of arp offload
7508 * ns offload and others. Currently 1st bit is used for arp
7509 * off load and 2nd bit for ns offload currently, rest bits are unused
7510 */
7511 if (hdd_ctx->config->fhostArpOffload)
7512 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7513 if (hdd_ctx->config->fhostNSOffload)
7514 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7515
7516 /*
7517 * Copy the DFS Phyerr Filtering Offload status.
7518 * This parameter reflects the value of the
7519 * dfs_phyerr_filter_offload flag as set in the ini.
7520 */
7521 cds_cfg->dfs_phyerr_filter_offload =
7522 hdd_ctx->config->fDfsPhyerrFilterOffload;
7523 if (hdd_ctx->config->ssdp)
7524 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7525
7526 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7527 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7528
7529 cds_cfg->ap_maxoffload_reorderbuffs =
7530 hdd_ctx->config->apMaxOffloadReorderBuffs;
7531
7532 cds_cfg->ap_disable_intrabss_fwd =
7533 hdd_ctx->config->apDisableIntraBssFwd;
7534
7535 cds_cfg->dfs_pri_multiplier =
7536 hdd_ctx->config->dfsRadarPriMultiplier;
7537 cds_cfg->reorder_offload =
7538 hdd_ctx->config->reorderOffloadSupport;
7539
7540 /* IPA micro controller data path offload resource config item */
7541 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007542 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7543 /* IpaUcTxBufCount should be power of 2 */
7544 hdd_err("Round down IpaUcTxBufCount %d to nearest power of 2",
7545 hdd_ctx->config->IpaUcTxBufCount);
7546 hdd_ctx->config->IpaUcTxBufCount =
7547 rounddown_pow_of_two(
7548 hdd_ctx->config->IpaUcTxBufCount);
7549 if (!hdd_ctx->config->IpaUcTxBufCount) {
7550 hdd_err("Failed to round down IpaUcTxBufCount");
7551 return -EINVAL;
7552 }
7553 hdd_err("IpaUcTxBufCount rounded down to %d",
7554 hdd_ctx->config->IpaUcTxBufCount);
7555 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307556 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7557 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007558 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7559 /* IpaUcRxIndRingCount should be power of 2 */
7560 hdd_err("Round down IpaUcRxIndRingCount %d to nearest power of 2",
7561 hdd_ctx->config->IpaUcRxIndRingCount);
7562 hdd_ctx->config->IpaUcRxIndRingCount =
7563 rounddown_pow_of_two(
7564 hdd_ctx->config->IpaUcRxIndRingCount);
7565 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7566 hdd_err("Failed to round down IpaUcRxIndRingCount");
7567 return -EINVAL;
7568 }
7569 hdd_err("IpaUcRxIndRingCount rounded down to %d",
7570 hdd_ctx->config->IpaUcRxIndRingCount);
7571 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307572 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007573 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307574 cds_cfg->uc_tx_partition_base =
7575 hdd_ctx->config->IpaUcTxPartitionBase;
7576 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7577
7578 cds_cfg->ip_tcp_udp_checksum_offload =
7579 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307580 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307581 cds_cfg->ce_classify_enabled =
7582 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007583 cds_cfg->bpf_packet_filter_enable =
7584 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307585 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7586 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7587 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007588 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007589 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007590 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007591 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307592
7593 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7594 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7595 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007596 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307597 cds_init_ini_config(cds_cfg);
7598 return 0;
7599}
7600
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007601/**
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007602 * hdd_update_user_config() - API to update user configuration
7603 * parameters to obj mgr which are used by multiple components
7604 * @hdd_ctx: HDD Context
7605 *
7606 * Return: 0 for Success, errno on failure
7607 */
7608static int hdd_update_user_config(hdd_context_t *hdd_ctx)
7609{
7610 struct wlan_objmgr_psoc_user_config *user_config;
7611
7612 user_config = qdf_mem_malloc(sizeof(*user_config));
7613 if (user_config == NULL) {
7614 hdd_alert("Failed to alloc memory for user_config!");
7615 return -ENOMEM;
7616 }
7617
7618 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
7619 user_config->dual_mac_feature_disable =
7620 hdd_ctx->config->dual_mac_feature_disable;
7621 user_config->indoor_channel_support =
7622 hdd_ctx->config->indoor_channel_support;
7623 user_config->is_11d_support_enabled =
7624 hdd_ctx->config->Is11dSupportEnabled;
7625 user_config->is_11h_support_enabled =
7626 hdd_ctx->config->Is11hSupportEnabled;
7627 user_config->optimize_chan_avoid_event =
7628 hdd_ctx->config->goptimize_chan_avoid_event;
7629 user_config->skip_dfs_chnl_in_p2p_search =
7630 hdd_ctx->config->skipDfsChnlInP2pSearch;
7631
7632 wlan_objmgr_psoc_set_user_config(hdd_ctx->hdd_psoc, user_config);
7633
7634 qdf_mem_free(user_config);
7635 return 0;
7636}
7637
7638/**
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007639 * hdd_init_thermal_info - Initialize thermal level
7640 * @hdd_ctx: HDD context
7641 *
7642 * Initialize thermal level at SME layer and set the thermal level callback
7643 * which would be called when a configured thermal threshold is hit.
7644 *
7645 * Return: 0 on success and errno on failure
7646 */
7647static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7648{
7649 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307650 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007651
7652 thermal_param.smeThermalMgmtEnabled =
7653 hdd_ctx->config->thermalMitigationEnable;
7654 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7655
Poddar, Siddarth83905022016-04-16 17:56:08 -07007656 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7657 hdd_ctx->config->throttle_dutycycle_level0;
7658 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7659 hdd_ctx->config->throttle_dutycycle_level1;
7660 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7661 hdd_ctx->config->throttle_dutycycle_level2;
7662 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7663 hdd_ctx->config->throttle_dutycycle_level3;
7664
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007665 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7666 hdd_ctx->config->thermalTempMinLevel0;
7667 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7668 hdd_ctx->config->thermalTempMaxLevel0;
7669 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7670 hdd_ctx->config->thermalTempMinLevel1;
7671 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7672 hdd_ctx->config->thermalTempMaxLevel1;
7673 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7674 hdd_ctx->config->thermalTempMinLevel2;
7675 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7676 hdd_ctx->config->thermalTempMaxLevel2;
7677 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7678 hdd_ctx->config->thermalTempMinLevel3;
7679 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7680 hdd_ctx->config->thermalTempMaxLevel3;
7681
7682 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7683
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307684 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307685 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007686
7687 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7688 hdd_set_thermal_level_cb);
7689
7690 return 0;
7691
7692}
7693
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007694#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7695/**
7696 * hdd_hold_rtnl_lock - Hold RTNL lock
7697 *
7698 * Hold RTNL lock
7699 *
7700 * Return: True if held and false otherwise
7701 */
7702static inline bool hdd_hold_rtnl_lock(void)
7703{
7704 rtnl_lock();
7705 return true;
7706}
7707
7708/**
7709 * hdd_release_rtnl_lock - Release RTNL lock
7710 *
7711 * Release RTNL lock
7712 *
7713 * Return: None
7714 */
7715static inline void hdd_release_rtnl_lock(void)
7716{
7717 rtnl_unlock();
7718}
7719#else
7720static inline bool hdd_hold_rtnl_lock(void) { return false; }
7721static inline void hdd_release_rtnl_lock(void) { }
7722#endif
7723
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007724#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007725
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307726/* MAX iwpriv command support */
7727#define PKTLOG_SET_BUFF_SIZE 3
7728#define MAX_PKTLOG_SIZE 16
7729
7730/**
7731 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7732 * @hdd_ctx: hdd context
7733 * @set_value2: pktlog buffer size value
7734 *
7735 *
7736 * Return: 0 for success or error.
7737 */
7738static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7739{
7740 struct sir_wifi_start_log start_log = { 0 };
7741 QDF_STATUS status;
7742
7743 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7744 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7745 start_log.ini_triggered = cds_is_packet_log_enabled();
7746 start_log.user_triggered = 1;
7747 start_log.size = set_value2;
7748
7749 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7750 if (!QDF_IS_STATUS_SUCCESS(status)) {
7751 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7752 EXIT();
7753 return -EINVAL;
7754 }
7755
7756 return 0;
7757}
7758
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007759/**
7760 * hdd_process_pktlog_command() - process pktlog command
7761 * @hdd_ctx: hdd context
7762 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307763 * @set_value2: pktlog buffer size value
7764 *
7765 * This function process pktlog command.
7766 * set_value2 only matters when set_value is 3 (set buff size)
7767 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007768 *
7769 * Return: 0 for success or error.
7770 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307771int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
7772 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007773{
7774 int ret;
7775 bool enable;
7776 uint8_t user_triggered = 0;
7777
7778 ret = wlan_hdd_validate_context(hdd_ctx);
7779 if (0 != ret)
7780 return ret;
7781
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307782 hdd_info("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007783
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307784 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007785 hdd_err("invalid pktlog value %d", set_value);
7786 return -EINVAL;
7787 }
7788
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307789 if (set_value == PKTLOG_SET_BUFF_SIZE) {
7790 if (set_value2 <= 0) {
7791 hdd_err("invalid pktlog size %d", set_value2);
7792 return -EINVAL;
7793 } else if (set_value2 > MAX_PKTLOG_SIZE) {
7794 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
7795 return -EINVAL;
7796 }
7797 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
7798 }
7799
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007800 /*
7801 * set_value = 0 then disable packetlog
7802 * set_value = 1 enable packetlog forcefully
7803 * set_vlaue = 2 then disable packetlog if disabled through ini or
7804 * enable packetlog with AUTO type.
7805 */
7806 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
7807 true : false;
7808
7809 if (1 == set_value) {
7810 enable = true;
7811 user_triggered = 1;
7812 }
7813
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307814 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007815}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007816/**
7817 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
7818 * @hdd_ctx: HDD context
7819 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307820 * @user_triggered: triggered through iwpriv
7821 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007822 *
7823 * Return: 0 on success; error number otherwise
7824 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007825int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307826 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007827{
7828 struct sir_wifi_start_log start_log;
7829 QDF_STATUS status;
7830
7831 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7832 start_log.verbose_level =
7833 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007834 start_log.ini_triggered = cds_is_packet_log_enabled();
7835 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307836 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307837 /*
7838 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7839 * commands. Host uses this flag to decide whether to send pktlog
7840 * disable command to fw without sending pktlog enable command
7841 * previously. For eg, If vendor sends pktlog disable command without
7842 * sending pktlog enable command, then host discards the packet
7843 * but for iwpriv command, host will send it to fw.
7844 */
7845 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007846 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7847 if (!QDF_IS_STATUS_SUCCESS(status)) {
7848 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7849 EXIT();
7850 return -EINVAL;
7851 }
7852
7853 return 0;
7854}
7855#endif /* REMOVE_PKT_LOG */
7856
7857
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307858#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7859/**
7860 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7861 * switch without restart
7862 *
7863 * Registers callback function to change the operating channel of SAP by using
7864 * channel switch announcements instead of restarting SAP.
7865 *
7866 * Return: QDF_STATUS
7867 */
7868QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7869{
7870 QDF_STATUS status;
7871
7872 status = cds_register_sap_restart_channel_switch_cb(
7873 (void *)hdd_sap_restart_with_channel_switch);
7874 if (!QDF_IS_STATUS_SUCCESS(status))
7875 hdd_err("restart cb registration failed");
7876
7877 return status;
7878}
7879#endif
7880
Komal Seelam92fff912016-03-24 11:51:41 +05307881/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007882 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
7883 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05307884 * @dev: Device Pointer
7885 * @num: Number of Valid Mac address
7886 *
7887 * Return: Pointer to MAC address buffer
7888 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007889static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
7890 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05307891{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007892 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05307893}
Komal Seelam92fff912016-03-24 11:51:41 +05307894
7895/**
7896 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7897 * @hdd_ctx: HDD Context
7898 * @num: Number of random mac addresses needed
7899 *
7900 * Generate random addresses using bit manipulation on the base mac address
7901 *
7902 * Return: None
7903 */
7904static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7905{
7906 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7907 uint32_t iter;
7908 struct hdd_config *ini = hdd_ctx->config;
7909 uint8_t *buf = NULL;
7910 uint8_t macaddr_b3, tmp_br3;
7911 uint8_t *src = ini->intfMacAddr[0].bytes;
7912
7913 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
7914 buf = ini->intfMacAddr[iter].bytes;
7915 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7916 macaddr_b3 = buf[3];
7917 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7918 INTF_MACADDR_MASK;
7919 macaddr_b3 += tmp_br3;
7920 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7921 buf[0] |= 0x02;
7922 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007923 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307924 }
7925}
7926
7927/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007928 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05307929 * @hdd_ctx: HDD Context
7930 *
7931 * API to get mac addresses from platform driver and update the driver
7932 * structures and configure FW with the base mac address.
7933 * Return: int
7934 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007935static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05307936{
7937 uint32_t no_of_mac_addr, iter;
7938 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7939 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7940 uint8_t *addr, *buf;
7941 struct device *dev = hdd_ctx->parent_dev;
7942 struct hdd_config *ini = hdd_ctx->config;
7943 tSirMacAddr mac_addr;
7944 QDF_STATUS status;
7945
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007946 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05307947
7948 if (no_of_mac_addr == 0 || !addr) {
7949 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7950 return -EINVAL;
7951 }
7952
7953 if (no_of_mac_addr > max_mac_addr)
7954 no_of_mac_addr = max_mac_addr;
7955
7956 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7957
7958 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7959 buf = ini->intfMacAddr[iter].bytes;
7960 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007961 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307962 }
7963
7964 status = sme_set_custom_mac_addr(mac_addr);
7965
7966 if (!QDF_IS_STATUS_SUCCESS(status))
7967 return -EAGAIN;
7968 if (no_of_mac_addr < max_mac_addr)
7969 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7970 no_of_mac_addr);
7971 return 0;
7972}
7973
7974/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007975 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7976 * @hdd_ctx: HDD Context
7977 *
7978 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7979 * will generate its own MAC and update it to FW.
7980 *
7981 * Return: 0 for success
7982 * Non-zero error code for failure
7983 */
7984static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7985{
7986 tSirMacAddr customMacAddr;
7987 QDF_STATUS status;
7988
7989 qdf_mem_copy(&customMacAddr,
7990 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7991 sizeof(tSirMacAddr));
7992 status = sme_set_custom_mac_addr(customMacAddr);
7993 if (!QDF_IS_STATUS_SUCCESS(status))
7994 return -EAGAIN;
7995 return 0;
7996}
7997
7998/**
Komal Seelam92fff912016-03-24 11:51:41 +05307999 * hdd_initialize_mac_address() - API to get wlan mac addresses
8000 * @hdd_ctx: HDD Context
8001 *
8002 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
8003 * is provisioned with mac addresses, driver uses it, else it will use
8004 * wlan_mac.bin to update HW MAC addresses.
8005 *
8006 * Return: None
8007 */
8008static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
8009{
8010 QDF_STATUS status;
8011 int ret;
8012
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008013 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05308014 if (ret == 0)
8015 return;
8016
8017 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
8018
8019 status = hdd_update_mac_config(hdd_ctx);
8020
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008021 if (QDF_IS_STATUS_SUCCESS(status))
8022 return;
8023
8024 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
8025
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008026 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008027 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008028 if (ret != 0) {
8029 hdd_err("MAC address out-of-sync, ret:%d", ret);
8030 QDF_ASSERT(ret);
8031 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008032 }
Komal Seelam92fff912016-03-24 11:51:41 +05308033}
8034
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008035/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008036 * hdd_tsf_init() - Initialize the TSF synchronization interface
8037 * @hdd_ctx: HDD global context
8038 *
8039 * When TSF synchronization via GPIO is supported by the driver and
8040 * has been enabled in the configuration file, this function plumbs
8041 * the GPIO value down to firmware via SME.
8042 *
8043 * Return: None
8044 */
8045#ifdef WLAN_FEATURE_TSF
8046static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8047{
8048 QDF_STATUS status;
8049
8050 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
8051 return;
8052
8053 status = sme_set_tsf_gpio(hdd_ctx->hHal,
8054 hdd_ctx->config->tsf_gpio_pin);
8055 if (!QDF_IS_STATUS_SUCCESS(status))
8056 hdd_err("Set tsf GPIO failed, status: %d", status);
8057}
8058#else
8059static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8060{
8061}
8062#endif
8063
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008064static int hdd_set_smart_chainmask_enabled(hdd_context_t *hdd_ctx)
8065{
8066 int vdev_id = 0;
8067 int param_id = WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME;
8068 int value = hdd_ctx->config->smart_chainmask_enabled;
8069 int vpdev = PDEV_CMD;
8070 int ret;
8071
8072 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8073 if (ret)
8074 hdd_err("WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME failed %d", ret);
8075
8076 return ret;
8077}
8078
8079static int hdd_set_alternative_chainmask_enabled(hdd_context_t *hdd_ctx)
8080{
8081 int vdev_id = 0;
8082 int param_id = WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME;
8083 int value = hdd_ctx->config->alternative_chainmask_enabled;
8084 int vpdev = PDEV_CMD;
8085 int ret;
8086
8087 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8088 if (ret)
8089 hdd_err("WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME failed %d",
8090 ret);
8091
8092 return ret;
8093}
8094
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008095/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07008096 * hdd_pre_enable_configure() - Configurations prior to cds_enable
8097 * @hdd_ctx: HDD context
8098 *
8099 * Pre configurations to be done at lower layer before calling cds enable.
8100 *
8101 * Return: 0 on success and errno on failure.
8102 */
8103static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
8104{
8105 int ret;
8106 QDF_STATUS status;
8107 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07008108 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008109
Leo Changfdb45c32016-10-28 11:09:23 -07008110 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008111 /*
8112 * Set 802.11p config
8113 * TODO-OCB: This has been temporarily added here to ensure this
8114 * parameter is set in CSR when we init the channel list. This should
8115 * be removed once the 5.9 GHz channels are added to the regulatory
8116 * domain.
8117 */
8118 hdd_set_dot11p_config(hdd_ctx);
8119
8120 /*
8121 * Note that the cds_pre_enable() sequence triggers the cfg download.
8122 * The cfg download must occur before we update the SME config
8123 * since the SME config operation must access the cfg database
8124 */
8125 status = hdd_set_sme_config(hdd_ctx);
8126
8127 if (QDF_STATUS_SUCCESS != status) {
8128 hdd_alert("Failed hdd_set_sme_config: %d", status);
8129 ret = qdf_status_to_os_return(status);
8130 goto out;
8131 }
8132
8133 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
8134 hdd_ctx->config->tx_chain_mask_1ss,
8135 PDEV_CMD);
8136 if (0 != ret) {
8137 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
8138 goto out;
8139 }
8140
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008141 ret = hdd_set_smart_chainmask_enabled(hdd_ctx);
8142 if (ret)
8143 goto out;
8144
8145 ret = hdd_set_alternative_chainmask_enabled(hdd_ctx);
8146 if (ret)
8147 goto out;
8148
Prashanth Bhatta07998752016-04-28 12:35:33 -07008149 hdd_program_country_code(hdd_ctx);
8150
8151 status = hdd_set_sme_chan_list(hdd_ctx);
8152 if (status != QDF_STATUS_SUCCESS) {
8153 hdd_alert("Failed to init channel list: %d", status);
8154 ret = qdf_status_to_os_return(status);
8155 goto out;
8156 }
8157
8158 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07008159 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07008160 hdd_alert("config update failed");
8161 ret = -EINVAL;
8162 goto out;
8163 }
8164
Prashanth Bhatta07998752016-04-28 12:35:33 -07008165 /*
8166 * Set the MAC Address Currently this is used by HAL to add self sta.
8167 * Remove this once self sta is added as part of session open.
8168 */
8169 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
8170 hdd_ctx->config->intfMacAddr[0].bytes,
8171 sizeof(hdd_ctx->config->intfMacAddr[0]));
8172
8173 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
8174 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
8175 hal_status, hal_status);
8176 ret = -EINVAL;
8177 goto out;
8178 }
8179
8180 hdd_init_channel_avoidance(hdd_ctx);
8181
8182out:
8183 return ret;
8184}
8185
8186/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008187 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
8188 * @context_ptr - hdd context pointer
8189 * @event_ptr - event structure pointer
8190 *
8191 * This is the p2p listen offload stop event handler, it sends vendor
8192 * event back to supplicant to notify the stop reason.
8193 *
8194 * Return: None
8195 */
8196static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
8197 void *event_ptr)
8198{
8199 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
8200 struct sir_p2p_lo_event *evt = event_ptr;
8201 struct sk_buff *vendor_event;
8202
8203 ENTER();
8204
8205 if (hdd_ctx == NULL) {
8206 hdd_err("Invalid HDD context pointer");
8207 return;
8208 }
8209
8210 vendor_event =
8211 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8212 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
8213 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
8214 GFP_KERNEL);
8215
8216 if (!vendor_event) {
8217 hdd_err("cfg80211_vendor_event_alloc failed");
8218 return;
8219 }
8220
8221 if (nla_put_u32(vendor_event,
8222 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
8223 evt->reason_code)) {
8224 hdd_err("nla put failed");
8225 kfree_skb(vendor_event);
8226 return;
8227 }
8228
8229 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8230}
8231
8232/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308233 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
8234 * @hdd_ctx: HDD context
8235 *
8236 * This function sends the adaptive dwell time config configuration to the
8237 * firmware via WMA
8238 *
8239 * Return: 0 - success, < 0 - failure
8240 */
8241static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
8242{
8243 QDF_STATUS status;
8244 struct adaptive_dwelltime_params dwelltime_params;
8245
8246 dwelltime_params.is_enabled =
8247 hdd_ctx->config->adaptive_dwell_mode_enabled;
8248 dwelltime_params.dwelltime_mode =
8249 hdd_ctx->config->global_adapt_dwelltime_mode;
8250 dwelltime_params.lpf_weight =
8251 hdd_ctx->config->adapt_dwell_lpf_weight;
8252 dwelltime_params.passive_mon_intval =
8253 hdd_ctx->config->adapt_dwell_passive_mon_intval;
8254 dwelltime_params.wifi_act_threshold =
8255 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
8256
8257 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
8258 &dwelltime_params);
8259
8260 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
8261 if (!QDF_IS_STATUS_SUCCESS(status)) {
8262 hdd_err("Failed to send Adaptive Dwelltime configuration!");
8263 return -EAGAIN;
8264 }
8265 return 0;
8266}
8267
Arun Khandavallid4349a92016-07-25 11:10:43 +05308268#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8269/**
8270 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
8271 * @hdd_ctx: HDD context
8272 *
8273 * Set auto shutdown callback to get indications from firmware to indicate
8274 * userspace to shutdown WLAN after a configured amount of inactivity.
8275 *
8276 * Return: 0 on success and errno on failure.
8277 */
8278static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8279{
8280 QDF_STATUS status;
8281
8282 if (!hdd_ctx->config->WlanAutoShutdown)
8283 return 0;
8284
8285 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
8286 wlan_hdd_auto_shutdown_cb);
8287 if (status != QDF_STATUS_SUCCESS)
8288 hdd_err("Auto shutdown feature could not be enabled: %d",
8289 status);
8290
8291 return qdf_status_to_os_return(status);
8292}
8293#else
8294static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8295{
8296 return 0;
8297}
8298#endif
8299
8300/**
8301 * hdd_features_init() - Init features
8302 * @hdd_ctx: HDD context
8303 * @adapter: Primary adapter context
8304 *
8305 * Initialize features and their feature context after WLAN firmware is up.
8306 *
8307 * Return: 0 on success and errno on failure.
8308 */
8309static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8310{
8311 tSirTxPowerLimit hddtxlimit;
8312 QDF_STATUS status;
8313 int ret;
8314
8315 ENTER();
8316
8317 ret = hdd_update_country_code(hdd_ctx, adapter);
8318 if (ret) {
8319 hdd_err("Failed to update country code: %d", ret);
8320 goto out;
8321 }
8322
8323 /* FW capabilities received, Set the Dot11 mode */
8324 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07008325 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
8326 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308327
Arun Khandavallid4349a92016-07-25 11:10:43 +05308328
8329 if (hdd_ctx->config->fIsImpsEnabled)
8330 hdd_set_idle_ps_config(hdd_ctx, true);
8331 else
8332 hdd_set_idle_ps_config(hdd_ctx, false);
8333
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308334 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8335 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
8336
Arun Khandavallid4349a92016-07-25 11:10:43 +05308337 if (hdd_lro_init(hdd_ctx))
8338 hdd_err("Unable to initialize LRO in fw");
8339
8340 if (hdd_adaptive_dwelltime_init(hdd_ctx))
8341 hdd_err("Unable to send adaptive dwelltime setting to FW");
8342
8343 ret = hdd_init_thermal_info(hdd_ctx);
8344 if (ret) {
8345 hdd_err("Error while initializing thermal information");
8346 goto deregister_frames;
8347 }
8348
Poddar, Siddarth66a46592017-02-22 11:44:44 +05308349 if (cds_is_packet_log_enabled())
8350 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
8351
Arun Khandavallid4349a92016-07-25 11:10:43 +05308352 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
8353 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
8354 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
8355 if (!QDF_IS_STATUS_SUCCESS(status))
8356 hdd_err("Error setting txlimit in sme: %d", status);
8357
8358 hdd_tsf_init(hdd_ctx);
8359
Arun Khandavallid4349a92016-07-25 11:10:43 +05308360 ret = hdd_register_cb(hdd_ctx);
8361 if (ret) {
8362 hdd_err("Failed to register HDD callbacks!");
8363 goto deregister_frames;
8364 }
8365
8366 if (hdd_ctx->config->dual_mac_feature_disable) {
8367 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
8368 if (status != QDF_STATUS_SUCCESS) {
8369 hdd_err("Failed to disable dual mac features");
8370 goto deregister_cb;
8371 }
8372 }
Selvaraj, Sridhar371f55e2017-02-21 10:36:15 +05308373 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8374 status = sme_enable_disable_chanavoidind_event(
8375 hdd_ctx->hHal, 0);
8376 if (!QDF_IS_STATUS_SUCCESS(status)) {
8377 hdd_err("Failed to disable Chan Avoidance Indication");
8378 goto deregister_cb;
8379 }
8380 }
Arun Khandavallid4349a92016-07-25 11:10:43 +05308381
8382 /* register P2P Listen Offload event callback */
8383 if (wma_is_p2p_lo_capable())
8384 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
8385 wlan_hdd_p2p_lo_event_callback);
8386
8387 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
8388
8389 if (ret)
8390 goto deregister_cb;
8391
8392 EXIT();
8393 return 0;
8394
8395deregister_cb:
8396 hdd_deregister_cb(hdd_ctx);
8397deregister_frames:
8398 wlan_hdd_cfg80211_deregister_frames(adapter);
8399out:
8400 return -EINVAL;
8401
8402}
8403
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308404#ifdef NAPIER_SCAN
8405/**
8406 *
8407 * hdd_post_cds_enable_config() - HDD post cds start config helper
8408 * @adapter - Pointer to the HDD
8409 *
8410 * Return: None
8411 */
8412static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8413{
8414 QDF_STATUS status;
8415
8416 status = ucfg_scan_register_bcn_cb(hdd_ctx->hdd_psoc,
8417 wlan_cfg80211_inform_bss_frame,
8418 SCAN_CB_TYPE_INFORM_BCN);
8419 if (!QDF_IS_STATUS_SUCCESS(status)) {
8420 hdd_err("failed with status code %08d [x%08x]",
8421 status, status);
8422 return status;
8423 }
8424
8425 return QDF_STATUS_SUCCESS;
8426}
8427#else
8428static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8429{
8430 return QDF_STATUS_SUCCESS;
8431}
8432
8433#endif
Arun Khandavallid4349a92016-07-25 11:10:43 +05308434
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308435/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308436 * hdd_configure_cds() - Configure cds modules
8437 * @hdd_ctx: HDD context
8438 * @adapter: Primary adapter context
8439 *
8440 * Enable Cds modules after WLAN firmware is up.
8441 *
8442 * Return: 0 on success and errno on failure.
8443 */
8444int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8445{
8446 int ret;
8447 QDF_STATUS status;
8448 /* structure of function pointers to be used by CDS */
8449 struct cds_sme_cbacks sme_cbacks;
8450
8451 ret = hdd_pre_enable_configure(hdd_ctx);
8452 if (ret) {
8453 hdd_err("Failed to pre-configure cds");
8454 goto out;
8455 }
8456
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008457 /* Always get latest IPA resources allocated from cds_open and configure
8458 * IPA module before configuring them to FW. Sequence required as crash
8459 * observed otherwise.
8460 */
8461 if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
8462 if (hdd_ipa_uc_ol_init(hdd_ctx)) {
8463 hdd_err("Failed to setup pipes");
8464 goto out;
8465 }
8466 }
8467
Arun Khandavallifae92942016-08-01 13:31:08 +05308468 /*
8469 * Start CDS which starts up the SME/MAC/HAL modules and everything
8470 * else
8471 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308472 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308473
8474 if (!QDF_IS_STATUS_SUCCESS(status)) {
8475 hdd_alert("cds_enable failed");
8476 goto out;
8477 }
8478
8479 status = hdd_post_cds_enable_config(hdd_ctx);
8480 if (!QDF_IS_STATUS_SUCCESS(status)) {
8481 hdd_alert("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008482 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308483 }
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308484 status = hdd_register_bcn_cb(hdd_ctx);
8485 if (!QDF_IS_STATUS_SUCCESS(status)) {
8486 hdd_alert("hdd_post_cds_enable_config failed");
8487 goto cds_disable;
8488 }
Arun Khandavallifae92942016-08-01 13:31:08 +05308489
8490 ret = hdd_features_init(hdd_ctx, adapter);
8491 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008492 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308493
8494 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
8495 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
8496 status = cds_init_policy_mgr(&sme_cbacks);
8497 if (!QDF_IS_STATUS_SUCCESS(status)) {
8498 hdd_err("Policy manager initialization failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008499 goto hdd_features_deinit;
Arun Khandavallifae92942016-08-01 13:31:08 +05308500 }
8501
8502 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008503
8504hdd_features_deinit:
8505 hdd_deregister_cb(hdd_ctx);
8506 wlan_hdd_cfg80211_deregister_frames(adapter);
8507cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308508 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008509
Arun Khandavallifae92942016-08-01 13:31:08 +05308510out:
8511 return -EINVAL;
8512}
8513
8514/**
8515 * hdd_deconfigure_cds() -De-Configure cds
8516 * @hdd_ctx: HDD context
8517 *
8518 * Deconfigure Cds modules before WLAN firmware is down.
8519 *
8520 * Return: 0 on success and errno on failure.
8521 */
Jeff Johnson590e2012016-10-05 16:16:24 -07008522static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308523{
8524 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07008525 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308526
8527 ENTER();
8528 /* De-register the SME callbacks */
8529 hdd_deregister_cb(hdd_ctx);
8530
8531 /* De-init Policy Manager */
8532 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
8533 hdd_err("Failed to deinit policy manager");
8534 /* Proceed and complete the clean up */
Houston Hoffman6640cf32016-10-10 16:44:29 -07008535 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308536 }
8537
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308538 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308539 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8540 hdd_err("Failed to Disable the CDS Modules! :%d",
8541 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07008542 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308543 }
8544
8545 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07008546 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308547}
8548
8549
8550/**
8551 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
8552 * @hdd_ctx: HDD context
Arun Khandavallifae92942016-08-01 13:31:08 +05308553 *
8554 * This function maintains the driver state machine it will be invoked from
8555 * exit, shutdown and con_mode change handler. Depending on the driver state
8556 * shall perform the stopping/closing of the modules.
8557 *
8558 * Return: 0 for success; non-zero for failure
8559 */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008560int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308561{
8562 void *hif_ctx;
8563 qdf_device_t qdf_ctx;
8564 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308565 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308566 p_cds_sched_context cds_sched_context = NULL;
8567
8568 ENTER();
8569
8570 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8571 if (!qdf_ctx) {
8572 hdd_err("QDF device context NULL");
8573 return -EINVAL;
8574 }
8575
8576 cds_sched_context = get_cds_sched_ctxt();
8577 if (!cds_sched_context) {
8578 hdd_err("cds scheduler context NULL");
8579 return -EINVAL;
8580 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308581 mutex_lock(&hdd_ctx->iface_change_lock);
8582 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05308583
8584 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
8585
8586 switch (hdd_ctx->driver_status) {
8587 case DRIVER_MODULES_UNINITIALIZED:
8588 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308589 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308590 case DRIVER_MODULES_CLOSED:
8591 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308592 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308593 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05308594 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308595 if (hdd_deconfigure_cds(hdd_ctx)) {
8596 hdd_alert("Failed to de-configure CDS");
8597 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308598 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308599 }
8600 hdd_info("successfully Disabled the CDS modules!");
8601 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8602 break;
8603 case DRIVER_MODULES_OPENED:
8604 hdd_info("Closing CDS modules!");
8605 break;
8606 default:
8607 hdd_err("Trying to stop wlan in a wrong state: %d",
8608 hdd_ctx->driver_status);
8609 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308610 ret = -EINVAL;
8611 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308612 }
8613
Govind Singhb048e872016-09-27 22:07:43 +05308614 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8615 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8616 hdd_err("Failed to process post CDS disable Modules! :%d",
8617 qdf_status);
8618 ret = -EINVAL;
8619 QDF_ASSERT(0);
8620 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308621 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308622 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8623 hdd_warn("Failed to stop CDS:%d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308624 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308625 QDF_ASSERT(0);
8626 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008627
Rajeev Kumarecf87ff2017-01-13 15:46:07 -08008628 ret = hdd_release_and_destroy_pdev(hdd_ctx);
8629 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308630 hdd_err("Pdev delete failed");
8631
Rajeev Kumar99e4cf62017-01-13 15:31:19 -08008632 ret = hdd_release_and_destroy_psoc(hdd_ctx);
8633 if (ret)
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308634 hdd_err("Psoc delete failed");
8635
Arun Khandavallifae92942016-08-01 13:31:08 +05308636 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8637 if (!hif_ctx) {
8638 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308639 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308640 }
8641
8642 hdd_hif_close(hif_ctx);
8643
8644 ol_cds_free();
8645
Arunk Khandavalli649c0092016-11-22 21:20:43 +05308646 if (!cds_is_driver_recovering() && !cds_is_driver_unloading()) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308647 ret = pld_power_off(qdf_ctx->dev);
8648 if (ret)
8649 hdd_err("CNSS power down failed put device into Low power mode:%d",
8650 ret);
8651 }
8652 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
8653
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308654done:
8655 hdd_ctx->stop_modules_in_progress = false;
8656 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308657 EXIT();
8658
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308659 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308660
8661}
8662
8663/**
8664 * hdd_iface_change_callback() - Function invoked when stop modules expires
8665 * @priv: pointer to hdd context
8666 *
8667 * This function is invoked when the timer waiting for the interface change
8668 * expires, it shall cut-down the power to wlan and stop all the modules.
8669 *
8670 * Return: void
8671 */
8672static void hdd_iface_change_callback(void *priv)
8673{
8674 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
8675 int ret;
8676 int status = wlan_hdd_validate_context(hdd_ctx);
8677
8678 if (status)
8679 return;
8680
8681 ENTER();
8682 hdd_info("Interface change timer expired close the modules!");
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008683 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308684 if (ret)
8685 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05308686 EXIT();
8687}
8688
8689/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308690 * hdd_state_info_dump() - prints state information of hdd layer
8691 * @buf: buffer pointer
8692 * @size: size of buffer to be filled
8693 *
8694 * This function is used to dump state information of hdd layer
8695 *
8696 * Return: None
8697 */
8698static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
8699{
8700 hdd_context_t *hdd_ctx;
8701 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8702 QDF_STATUS status;
8703 hdd_station_ctx_t *hdd_sta_ctx;
8704 hdd_adapter_t *adapter;
8705 uint16_t len = 0;
8706 char *buf = *buf_ptr;
8707
8708 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8709 if (!hdd_ctx) {
8710 hdd_err("Failed to get hdd context ");
8711 return;
8712 }
8713
8714 hdd_notice("size of buffer: %d", *size);
8715
8716 len += scnprintf(buf + len, *size - len,
8717 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8718 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008719 "\n is_scheduler_suspended %d",
8720 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308721
8722 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8723
8724 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8725 adapter = adapter_node->pAdapter;
8726 if (adapter->dev)
8727 len += scnprintf(buf + len, *size - len,
8728 "\n device name: %s", adapter->dev->name);
8729 len += scnprintf(buf + len, *size - len,
8730 "\n device_mode: %d", adapter->device_mode);
8731 switch (adapter->device_mode) {
8732 case QDF_STA_MODE:
8733 case QDF_P2P_CLIENT_MODE:
8734 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8735 len += scnprintf(buf + len, *size - len,
8736 "\n connState: %d",
8737 hdd_sta_ctx->conn_info.connState);
8738 break;
8739
8740 default:
8741 break;
8742 }
8743 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
8744 adapter_node = next;
8745 }
8746
8747 *size -= len;
8748 *buf_ptr += len;
8749}
8750
8751/**
8752 * hdd_register_debug_callback() - registration function for hdd layer
8753 * to print hdd state information
8754 *
8755 * Return: None
8756 */
8757static void hdd_register_debug_callback(void)
8758{
8759 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
8760}
8761
8762/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008763 * hdd_wlan_startup() - HDD init function
8764 * @dev: Pointer to the underlying device
8765 *
8766 * This is the driver startup code executed once a WLAN device has been detected
8767 *
8768 * Return: 0 for success, < 0 for failure
8769 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308770int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008771{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308772 QDF_STATUS status;
Jeff Johnson957bc272017-02-02 08:54:48 -08008773 hdd_context_t *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008774 int ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008775 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308776 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008777
8778 ENTER();
8779
Arun Khandavallifae92942016-08-01 13:31:08 +05308780 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008781
8782 if (IS_ERR(hdd_ctx))
8783 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008784
Arun Khandavallifae92942016-08-01 13:31:08 +05308785 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
8786 hdd_iface_change_callback, (void *)hdd_ctx);
8787
8788 mutex_init(&hdd_ctx->iface_change_lock);
8789
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008790 ret = hdd_init_netlink_services(hdd_ctx);
8791 if (ret)
8792 goto err_hdd_free_context;
8793
Jeff Johnsonce0032c2017-01-20 07:18:27 -08008794 hdd_request_manager_init();
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07008795 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308796
Jeff Johnson957bc272017-02-02 08:54:48 -08008797 ret = hdd_wlan_start_modules(hdd_ctx, NULL, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05308798 if (ret) {
8799 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008800 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008801 }
8802
Yingying Tang80e15f32016-09-27 18:23:01 +08008803 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008804
Yingying Tang95409972016-10-20 15:16:15 +08008805 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
8806 hdd_notice("Failed to set wow pulse");
8807
Anurag Chouhan6d760662016-02-20 16:05:43 +05308808 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008809
8810 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008811 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05308812 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008813 }
8814
Prashanth Bhatta07998752016-04-28 12:35:33 -07008815 ret = hdd_wiphy_init(hdd_ctx);
8816 if (ret) {
8817 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05308818 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008819 }
8820
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05308821 if (hdd_ctx->config->enable_dp_trace)
8822 qdf_dp_trace_init();
8823
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308824 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008825 goto err_wiphy_unregister;
8826
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05308827 wlan_hdd_init_chan_info(hdd_ctx);
8828
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07008829 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08008830
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008831 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008832
Jeff Johnson957bc272017-02-02 08:54:48 -08008833 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
8834 if (ret) {
8835 hdd_alert("Failed to open interfaces: %d", ret);
Jeff Johnson46bde382017-02-01 15:31:16 -08008836 goto err_release_rtnl_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008837 }
8838
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008839 hdd_release_rtnl_lock();
8840 rtnl_held = false;
8841
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08008842 wlan_hdd_update_11n_mode(hdd_ctx->config);
8843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008844#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05308845 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308846 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008847 hdd_skip_acs_scan_timer_handler,
8848 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308849 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07008850 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04008851 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008852#endif
8853
Nitesh Shah61c10d92016-10-19 19:29:15 +05308854 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
8855 QDF_TIMER_TYPE_SW,
8856 wlan_hdd_change_tdls_mode,
8857 hdd_ctx);
8858
Prashanth Bhattaab004382016-10-11 16:08:11 -07008859 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008860
Jeff Johnson9afc5012016-09-23 13:56:27 -07008861 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008862
Nirav Shahbd36b062016-07-18 11:12:59 +05308863 if (hdd_ctx->rps)
8864 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07008865
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008866 ret = hdd_register_notifiers(hdd_ctx);
8867 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08008868 goto err_close_adapters;
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05308869
8870 status = wlansap_global_init();
8871 if (QDF_IS_STATUS_ERROR(status))
Jeff Johnson957bc272017-02-02 08:54:48 -08008872 goto err_close_adapters;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008873
Komal Seelam8634b772016-09-29 12:12:24 +05308874 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008875 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308876 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008877
bings612b9c42016-11-07 10:52:03 +08008878 if (hdd_enable_egap(hdd_ctx))
8879 hdd_err("enhance green ap is not enabled");
8880
Arun Khandavallifae92942016-08-01 13:31:08 +05308881 if (hdd_ctx->config->fIsImpsEnabled)
8882 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308883
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308884 if (hdd_ctx->config->sifs_burst_duration) {
8885 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
8886 hdd_ctx->config->sifs_burst_duration;
8887
8888 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
8889 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
8890 set_value, PDEV_CMD);
8891 }
8892
Arun Khandavallifae92942016-08-01 13:31:08 +05308893 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
8894 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008896 goto success;
8897
Jeff Johnson957bc272017-02-02 08:54:48 -08008898err_close_adapters:
Jeff Johnson46bde382017-02-01 15:31:16 -08008899 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008900
Jeff Johnson46bde382017-02-01 15:31:16 -08008901err_release_rtnl_lock:
Arun Khandavallid4349a92016-07-25 11:10:43 +05308902 if (rtnl_held)
8903 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008904
Anurag Chouhance6a4052016-09-14 18:20:42 +05308905 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08008906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008907err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008908 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008909
Arun Khandavallifae92942016-08-01 13:31:08 +05308910err_stop_modules:
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008911 hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308912
8913
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008914 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308915 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008916 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308917 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008918 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008919
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008920err_exit_nl_srv:
Houston Hoffman47a4a052016-11-14 23:22:44 -08008921 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08008922 hdd_request_manager_deinit();
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008923 hdd_exit_netlink_services(hdd_ctx);
8924
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308925 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008926err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05308927 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
8928 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07008929 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308930 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008932 return -EIO;
8933
8934success:
8935 EXIT();
8936 return 0;
8937}
8938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008939/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308940 * hdd_wlan_update_target_info() - update target type info
8941 * @hdd_ctx: HDD context
8942 * @context: hif context
8943 *
8944 * Update target info received from firmware in hdd context
8945 * Return:None
8946 */
8947
8948void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
8949{
8950 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
8951
8952 if (!tgt_info) {
8953 hdd_err("Target info is Null");
8954 return;
8955 }
8956
8957 hdd_ctx->target_type = tgt_info->target_type;
8958}
8959
8960/**
8961 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308962 * @hdd_ctx: HDD context
8963 *
8964 * Register the HDD callbacks to CDS/SME.
8965 *
8966 * Return: 0 for success or Error code for failure
8967 */
8968int hdd_register_cb(hdd_context_t *hdd_ctx)
8969{
8970 QDF_STATUS status;
8971 int ret = 0;
8972
8973 ENTER();
8974
8975 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
8976
8977 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
8978 hdd_send_oem_data_rsp_msg);
8979
8980 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
8981 wlan_hdd_cfg80211_fw_mem_dump_cb);
8982 if (!QDF_IS_STATUS_SUCCESS(status)) {
8983 hdd_err("Failed to register memdump callback");
8984 ret = -EINVAL;
8985 return ret;
8986 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05308987 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
8988 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308989 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
8990 sme_nan_register_callback(hdd_ctx->hHal,
8991 wlan_hdd_cfg80211_nan_callback);
8992 sme_stats_ext_register_callback(hdd_ctx->hHal,
8993 wlan_hdd_cfg80211_stats_ext_callback);
8994
8995 sme_ext_scan_register_callback(hdd_ctx->hHal,
8996 wlan_hdd_cfg80211_extscan_callback);
8997
8998 status = cds_register_sap_restart_channel_switch_cb(
8999 (void *)hdd_sap_restart_with_channel_switch);
9000 if (!QDF_IS_STATUS_SUCCESS(status)) {
9001 hdd_err("restart cb registration failed");
9002 ret = -EINVAL;
9003 return ret;
9004 }
9005
9006 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
9007 hdd_rssi_threshold_breached);
9008
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309009 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
9010 wlan_hdd_cfg80211_link_layer_stats_callback);
9011
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05309012 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
9013 hdd_lost_link_info_cb);
9014 /* print error and not block the startup process */
9015 if (!QDF_IS_STATUS_SUCCESS(status))
9016 hdd_err("set lost link info callback failed");
9017
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309018 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
9019
9020 EXIT();
9021
9022 return ret;
9023}
9024
9025/**
9026 * hdd_deregister_cb() - De-Register HDD callbacks.
9027 * @hdd_ctx: HDD context
9028 *
9029 * De-Register the HDD callbacks to CDS/SME.
9030 *
9031 * Return: void
9032 */
9033void hdd_deregister_cb(hdd_context_t *hdd_ctx)
9034{
9035 QDF_STATUS status;
9036
9037 ENTER();
9038
9039 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
9040 if (!QDF_IS_STATUS_SUCCESS(status))
9041 hdd_err("De-register of dcc stats callback failed: %d",
9042 status);
9043
9044 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309045 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
9046
9047 status = cds_deregister_sap_restart_channel_switch_cb();
9048 if (!QDF_IS_STATUS_SUCCESS(status))
9049 hdd_err("De-register restart cb registration failed: %d",
9050 status);
9051
9052 sme_stats_ext_register_callback(hdd_ctx->hHal,
9053 wlan_hdd_cfg80211_stats_ext_callback);
9054
9055 sme_nan_deregister_callback(hdd_ctx->hHal);
9056 status = sme_reset_tsfcb(hdd_ctx->hHal);
9057 if (!QDF_IS_STATUS_SUCCESS(status))
9058 hdd_err("Failed to de-register tsfcb the callback:%d",
9059 status);
9060 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
9061 if (!QDF_IS_STATUS_SUCCESS(status))
9062 hdd_err("Failed to de-register the fw mem dump callback: %d",
9063 status);
9064
9065 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
9066 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
9067
9068 EXIT();
9069}
9070
9071/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009072 * hdd_softap_sta_deauth() - handle deauth req from HDD
9073 * @adapter: Pointer to the HDD
9074 * @enable: bool value
9075 *
9076 * This to take counter measure to handle deauth req from HDD
9077 *
9078 * Return: None
9079 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309080QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009081 struct tagCsrDelStaParams *pDelStaParams)
9082{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309083 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009084
9085 ENTER();
9086
Jeff Johnson34c88b72016-08-15 14:27:11 -07009087 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009088 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9089
9090 /* Ignore request to deauth bcmc station */
9091 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309092 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009093
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309094 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009095 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9096 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009097
9098 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309099 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009100}
9101
9102/**
9103 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
9104 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309105 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009106 *
9107 * This to take counter measure to handle deauth req from HDD
9108 *
9109 * Return: None
9110 */
9111void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309112 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009114 ENTER();
9115
Jeff Johnson34c88b72016-08-15 14:27:11 -07009116 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9118
9119 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309120 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009121 return;
9122
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009123 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309124 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009125}
9126
9127void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
9128 bool enable)
9129{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009130 ENTER();
9131
Jeff Johnson34c88b72016-08-15 14:27:11 -07009132 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009133 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009135 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9136 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009137}
9138
9139/**
9140 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
9141 * @hdd_ctx: HDD Context
9142 *
9143 * API to find if there is any STA or P2P-Client is connected
9144 *
9145 * Return: true if connected; false otherwise
9146 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309147QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009148{
9149 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
9150}
9151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152/**
9153 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
9154 * @adapter: HDD adapter pointer
9155 *
9156 * This function loop through each adapter and disable roaming on each STA
9157 * device mode except the input adapter.
9158 *
9159 * Note: On the input adapter roaming is not enabled yet hence no need to
9160 * disable.
9161 *
9162 * Return: None
9163 */
9164void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
9165{
9166 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9167 hdd_adapter_t *adapterIdx = NULL;
9168 hdd_adapter_list_node_t *adapterNode = NULL;
9169 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309170 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009171
9172 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
9173 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009174 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009175 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009176 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009177 adapter->sessionId);
9178 /*
9179 * Loop through adapter and disable roaming for each STA device
9180 * mode except the input adapter.
9181 */
9182 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9183
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309184 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009185 adapterIdx = adapterNode->pAdapter;
9186
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009187 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009188 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009189 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009190 adapterIdx->sessionId);
9191 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
9192 (adapterIdx),
9193 adapterIdx->sessionId, 0);
9194 }
9195
9196 status = hdd_get_next_adapter(hdd_ctx,
9197 adapterNode,
9198 &pNext);
9199 adapterNode = pNext;
9200 }
9201 }
9202}
9203
9204/**
9205 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
9206 * @adapter: HDD adapter pointer
9207 *
9208 * This function loop through each adapter and enable roaming on each STA
9209 * device mode except the input adapter.
9210 * Note: On the input adapter no need to enable roaming because link got
9211 * disconnected on this.
9212 *
9213 * Return: None
9214 */
9215void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
9216{
9217 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9218 hdd_adapter_t *adapterIdx = NULL;
9219 hdd_adapter_list_node_t *adapterNode = NULL;
9220 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309221 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009222
9223 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
9224 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009225 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009226 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009227 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009228 adapter->sessionId);
9229 /*
9230 * Loop through adapter and enable roaming for each STA device
9231 * mode except the input adapter.
9232 */
9233 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9234
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309235 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009236 adapterIdx = adapterNode->pAdapter;
9237
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009238 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009239 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009240 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009241 adapterIdx->sessionId);
9242 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
9243 (adapterIdx),
9244 adapterIdx->sessionId,
9245 REASON_CONNECT);
9246 }
9247
9248 status = hdd_get_next_adapter(hdd_ctx,
9249 adapterNode,
9250 &pNext);
9251 adapterNode = pNext;
9252 }
9253 }
9254}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009255
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309256void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009257{
9258 struct sk_buff *skb;
9259 struct nlmsghdr *nlh;
9260 tAniMsgHdr *ani_hdr;
9261 void *nl_data = NULL;
9262 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309263 struct radio_index_tlv *radio_info;
9264 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009265
9266 if (in_interrupt() || irqs_disabled() || in_atomic())
9267 flags = GFP_ATOMIC;
9268
9269 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
9270
9271 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009272 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009273 return;
9274 }
9275
9276 nlh = (struct nlmsghdr *)skb->data;
9277 nlh->nlmsg_pid = 0; /* from kernel */
9278 nlh->nlmsg_flags = 0;
9279 nlh->nlmsg_seq = 0;
9280 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
9281
9282 ani_hdr = NLMSG_DATA(nlh);
9283 ani_hdr->type = type;
9284
9285 switch (type) {
9286 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05309287 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009288 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009289 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009290 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009291 ani_hdr->length = 0;
9292 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009293 break;
9294 case WLAN_SVC_WLAN_STATUS_IND:
9295 case WLAN_SVC_WLAN_VERSION_IND:
9296 case WLAN_SVC_DFS_CAC_START_IND:
9297 case WLAN_SVC_DFS_CAC_END_IND:
9298 case WLAN_SVC_DFS_RADAR_DETECT_IND:
9299 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
9300 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08009301 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05309302 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009303 ani_hdr->length = len;
9304 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
9305 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
9306 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009307 break;
9308
9309 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07009310 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009311 type);
9312 kfree_skb(skb);
9313 return;
9314 }
9315
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309316 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08009317 * Add radio index at the end of the svc event in TLV format
9318 * to maintain the backward compatibility with userspace
9319 * applications.
9320 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309321
9322 tlv_len = 0;
9323
9324 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
9325 < WLAN_NL_MAX_PAYLOAD) {
9326 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
9327 sizeof(*ani_hdr) + len);
9328 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
9329 radio_info->length = (unsigned short) sizeof(radio_info->radio);
9330 radio_info->radio = radio;
9331 tlv_len = sizeof(*radio_info);
9332 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
9333 "Added radio index tlv - radio index %d",
9334 radio_info->radio);
9335 }
9336
9337 nlh->nlmsg_len += tlv_len;
9338 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
9339
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340 nl_srv_bcast(skb);
9341
9342 return;
9343}
9344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009345#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
9346void wlan_hdd_auto_shutdown_cb(void)
9347{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07009348 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309349
9350 if (!hdd_ctx)
9351 return;
9352
Jeff Johnson28f8a772016-08-15 15:30:36 -07009353 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309354 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
9355 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009356}
9357
9358void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
9359{
9360 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309361 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009362 hdd_adapter_t *adapter;
9363 bool ap_connected = false, sta_connected = false;
9364 tHalHandle hal_handle;
9365
9366 hal_handle = hdd_ctx->hHal;
9367 if (hal_handle == NULL)
9368 return;
9369
9370 if (hdd_ctx->config->WlanAutoShutdown == 0)
9371 return;
9372
9373 if (enable == false) {
9374 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309375 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009376 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309378 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009379 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009380 return;
9381 }
9382
9383 /* To enable shutdown timer check conncurrency */
9384 if (cds_concurrent_open_sessions_running()) {
9385 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9386
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309387 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009388 adapter = adapterNode->pAdapter;
9389 if (adapter
9390 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009391 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009392 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9393 conn_info.connState ==
9394 eConnectionState_Associated) {
9395 sta_connected = true;
9396 break;
9397 }
9398 }
9399 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009400 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009401 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
9402 bApActive == true) {
9403 ap_connected = true;
9404 break;
9405 }
9406 }
9407 status = hdd_get_next_adapter(hdd_ctx,
9408 adapterNode,
9409 &pNext);
9410 adapterNode = pNext;
9411 }
9412 }
9413
9414 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009415 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009416 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 }
Jeff Johnson68755312017-02-10 11:46:55 -08009418
9419 if (sme_set_auto_shutdown_timer(hal_handle,
9420 hdd_ctx->config->WlanAutoShutdown)
9421 != QDF_STATUS_SUCCESS)
9422 hdd_err("Failed to start wlan auto shutdown timer");
9423 else
9424 hdd_notice("Auto Shutdown timer for %d seconds enabled",
9425 hdd_ctx->config->WlanAutoShutdown);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426}
9427#endif
9428
9429hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
9430 bool check_start_bss)
9431{
9432 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
9433 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309434 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
9436
9437 con_sap_adapter = NULL;
9438
9439 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309440 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009441 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009442 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
9443 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009444 adapter != this_sap_adapter) {
9445 if (check_start_bss) {
9446 if (test_bit(SOFTAP_BSS_STARTED,
9447 &adapter->event_flags)) {
9448 con_sap_adapter = adapter;
9449 break;
9450 }
9451 } else {
9452 con_sap_adapter = adapter;
9453 break;
9454 }
9455 }
9456 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
9457 adapterNode = pNext;
9458 }
9459
9460 return con_sap_adapter;
9461}
9462
9463#ifdef MSM_PLATFORM
9464void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
9465{
9466 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9467
Dustin Brownfce08d12017-01-17 16:29:38 -08009468 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9469 if (!hdd_ctx->bus_bw_timer_running) {
9470 hdd_ctx->bus_bw_timer_running = true;
9471 qdf_timer_start(&hdd_ctx->bus_bw_timer,
9472 hdd_ctx->config->busBandwidthComputeInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009473
Dustin Brownfce08d12017-01-17 16:29:38 -08009474 }
9475 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009477}
9478
9479void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
9480{
9481 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309482 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009483 bool can_stop = true;
9484 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9485
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309486 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brownfce08d12017-01-17 16:29:38 -08009487 if (!hdd_ctx->bus_bw_timer_running) {
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309488 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009489 /* trying to stop timer, when not running is not good */
Srinivas Girigowda0ee96442016-08-17 19:10:56 -07009490 hdd_info("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009491 return;
9492 }
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309493 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009494
9495 if (cds_concurrent_open_sessions_running()) {
9496 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9497
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309498 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009499 adapter = adapterNode->pAdapter;
9500 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009501 && (adapter->device_mode == QDF_STA_MODE
9502 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009503 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9504 conn_info.connState ==
9505 eConnectionState_Associated) {
9506 can_stop = false;
9507 break;
9508 }
9509 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009510 && (adapter->device_mode == QDF_SAP_MODE
9511 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009512 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
9513 true) {
9514 can_stop = false;
9515 break;
9516 }
9517 status = hdd_get_next_adapter(hdd_ctx,
9518 adapterNode,
9519 &pNext);
9520 adapterNode = pNext;
9521 }
9522 }
9523
Ravi Joshib89e7f72016-09-07 13:43:15 -07009524 if (can_stop == true) {
Chris Guoc0c95bf2016-11-10 14:28:25 +08009525 /* reset the ipa perf level */
9526 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
Dustin Brownfce08d12017-01-17 16:29:38 -08009527 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05309528 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08009529 hdd_ctx->bus_bw_timer_running = false;
9530 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Ravi Joshib89e7f72016-09-07 13:43:15 -07009531 hdd_reset_tcp_delack(hdd_ctx);
9532 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009533}
9534#endif
9535
9536/**
9537 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
9538 * and sta's operating channel.
9539 * @sta_adapter: Describe the first argument to foobar.
9540 * @ap_adapter: Describe the second argument to foobar.
9541 * @roam_profile: Roam profile of AP to which STA wants to connect.
9542 * @concurrent_chnl_same: If both SAP and STA channels are same then
9543 * set this flag to true else false.
9544 *
9545 * This function checks the sap's operating channel and sta's operating channel.
9546 * if both are same then it will return false else it will restart the sap in
9547 * sta's channel and return true.
9548 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309549 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009550 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309551QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009552 hdd_adapter_t *ap_adapter,
9553 tCsrRoamProfile *roam_profile,
9554 tScanResultHandle *scan_cache,
9555 bool *concurrent_chnl_same)
9556{
9557 hdd_ap_ctx_t *hdd_ap_ctx;
9558 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309559 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009560 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009561 *concurrent_chnl_same = true;
9562
9563 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9564 status =
9565 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
9566 roam_profile,
9567 scan_cache,
9568 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309569 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009570 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009571 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9572 if (hdd_ap_ctx->operatingChannel != channel_id) {
9573 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009574 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009575 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009576 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009577 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
9578 if (hdd_ap_ctx->operatingChannel != channel_id) {
9579 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009580 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581 }
9582 }
9583 } else {
9584 /*
9585 * Lets handle worst case scenario here, Scan cache lookup is
9586 * failed so we have to stop the SAP to avoid any channel
9587 * discrepancy between SAP's channel and STA's channel.
9588 * Return the status as failure so caller function could know
9589 * that scan look up is failed.
9590 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07009591 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309592 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009593 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309594 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595}
9596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009597/**
9598 * wlan_hdd_stop_sap() - This function stops bss of SAP.
9599 * @ap_adapter: SAP adapter
9600 *
9601 * This function will process the stopping of sap adapter.
9602 *
9603 * Return: None
9604 */
9605void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
9606{
9607 hdd_ap_ctx_t *hdd_ap_ctx;
9608 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309609 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009611
9612 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009613 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009614 return;
9615 }
9616
9617 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9618 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309619 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009620 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309621
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009622 mutex_lock(&hdd_ctx->sap_lock);
9623 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08009624 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009625 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
9626 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009627 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309628 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309629 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009630 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309631 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08009632 qdf_stop_bss_event,
9633 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309634 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009635 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009636 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009637 return;
9638 }
9639 }
9640 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08009641 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009643 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009644 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009645 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009646 }
9647 mutex_unlock(&hdd_ctx->sap_lock);
9648 return;
9649}
9650
9651/**
9652 * wlan_hdd_start_sap() - this function starts bss of SAP.
9653 * @ap_adapter: SAP adapter
9654 *
9655 * This function will process the starting of sap adapter.
9656 *
9657 * Return: None
9658 */
Arun Khandavallicc544b32017-01-30 19:52:16 +05309659void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009660{
9661 hdd_ap_ctx_t *hdd_ap_ctx;
9662 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309663 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009664 hdd_context_t *hdd_ctx;
9665 tsap_Config_t *sap_config;
9666
9667 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009668 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009669 return;
9670 }
9671
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009672 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07009673 hdd_err("SoftAp role has not been enabled");
9674 return;
9675 }
9676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009677 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
9678 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9679 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9680 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
9681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009682 mutex_lock(&hdd_ctx->sap_lock);
9683 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
9684 goto end;
9685
9686 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009687 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009688 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9689 goto end;
9690 }
9691
Wei Song2f76f642016-11-18 16:32:53 +08009692 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009693 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
9694 &hdd_ap_ctx->sapConfig,
9695 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309696 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009697 goto end;
9698
Jeff Johnson28f8a772016-08-15 15:30:36 -07009699 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309700 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -08009701 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309702 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009703 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009704 goto end;
9705 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07009706 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009707 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -08009708 if (hostapd_state->bssState == BSS_START)
9709 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009710 ap_adapter->sessionId);
9711 hostapd_state->bCommit = true;
9712
9713end:
9714 mutex_unlock(&hdd_ctx->sap_lock);
9715 return;
9716}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717
9718/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08009719 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
9720 * mac scan config
9721 * @status: Status of set antenna mode
9722 *
9723 * Callback on setting the dual mac configuration
9724 *
9725 * Return: None
9726 */
9727void wlan_hdd_soc_set_antenna_mode_cb(
9728 enum set_antenna_mode_status status)
9729{
9730 hdd_context_t *hdd_ctx;
9731
9732 hdd_info("Status: %d", status);
9733
9734 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9735 if (0 != wlan_hdd_validate_context(hdd_ctx))
9736 return;
9737
9738 /* Signal the completion of set dual mac config */
9739 complete(&hdd_ctx->set_antenna_mode_cmpl);
9740}
9741
9742/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743 * hdd_get_fw_version() - Get FW version
9744 * @hdd_ctx: pointer to HDD context.
9745 * @major_spid: FW version - major spid.
9746 * @minor_spid: FW version - minor spid
9747 * @ssid: FW version - ssid
9748 * @crmid: FW version - crmid
9749 *
9750 * This function is called to get the firmware build version stored
9751 * as part of the HDD context
9752 *
9753 * Return: None
9754 */
9755void hdd_get_fw_version(hdd_context_t *hdd_ctx,
9756 uint32_t *major_spid, uint32_t *minor_spid,
9757 uint32_t *siid, uint32_t *crmid)
9758{
9759 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
9760 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
9761 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
9762 *crmid = hdd_ctx->target_fw_version & 0x7fff;
9763}
9764
9765#ifdef QCA_CONFIG_SMP
9766/**
9767 * wlan_hdd_get_cpu() - get cpu_index
9768 *
9769 * Return: cpu_index
9770 */
9771int wlan_hdd_get_cpu(void)
9772{
9773 int cpu_index = get_cpu();
9774 put_cpu();
9775 return cpu_index;
9776}
9777#endif
9778
9779/**
9780 * hdd_get_fwpath() - get framework path
9781 *
9782 * This function is used to get the string written by
9783 * userspace to start the wlan driver
9784 *
9785 * Return: string
9786 */
9787const char *hdd_get_fwpath(void)
9788{
9789 return fwpath.string;
9790}
9791
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009792/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009793 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009794 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009795 * This function initilizes CDS global context with the help of cds_init. This
9796 * has to be the first function called after probe to get a valid global
9797 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009798 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009799 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009800 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009801int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009802{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009803 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009804 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009805
Houston Hoffman9e06e542016-12-12 12:06:26 -08009806 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009807#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9808 wlan_logging_sock_init_svc();
9809#endif
9810
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009811 if (p_cds_context == NULL) {
9812 hdd_alert("Failed to allocate CDS context");
9813 ret = -ENOMEM;
9814 goto err_out;
9815 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009816
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009817 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309818 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009819
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009820err_out:
9821 return ret;
9822}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009823
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009824/**
9825 * hdd_deinit() - Deinitialize Driver
9826 *
9827 * This function frees CDS global context with the help of cds_deinit. This
9828 * has to be the last function call in remove callback to free the global
9829 * context.
9830 */
9831void hdd_deinit(void)
9832{
9833 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009834
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009835#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9836 wlan_logging_sock_deinit_svc();
9837#endif
9838}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009839
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009840#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009841
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009842/**
9843 * __hdd_module_init - Module init helper
9844 *
9845 * Module init helper function used by both module and static driver.
9846 *
9847 * Return: 0 for success, errno on failure
9848 */
9849static int __hdd_module_init(void)
9850{
9851 int ret = 0;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +05309852 unsigned long rc;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009853
Arun Khandavallifae92942016-08-01 13:31:08 +05309854 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009855 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009856
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009857 pld_init();
9858
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309859 ret = hdd_init();
9860 if (ret) {
9861 pr_err("hdd_init failed %x\n", ret);
9862 goto err_hdd_init;
9863 }
9864
Rajeev Kumar97767a02016-11-30 11:20:40 -08009865 dispatcher_init();
9866
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309867 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009868
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009869 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009870
Arun Khandavalli13cb5da2017-01-19 15:43:52 +05309871 init_completion(&wlan_start_comp);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009872 ret = wlan_hdd_register_driver();
9873 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07009874 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
9875 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009876 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009877 }
9878
Arun Khandavalli13cb5da2017-01-19 15:43:52 +05309879 rc = wait_for_completion_timeout(&wlan_start_comp,
9880 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
9881
9882 if (!rc) {
9883 hdd_alert("Timed-out waiting for wlan_hdd_register_driver");
9884 QDF_BUG(0);
9885 goto out;
9886 }
9887
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309888 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009889
9890 return 0;
9891out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309892 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -08009893 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309894 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009895
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309896err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009897 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009898
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009899 return ret;
9900}
9901
9902/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309903 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
9904 *
9905 * Block the unloading of the driver until the cds recovery is completed
9906 *
9907 * Return: None
9908 */
9909static void hdd_wait_for_recovery_completion(void)
9910{
9911 int retry = 0;
9912
9913 /* Wait for recovery to complete */
9914 while (cds_is_driver_recovering()) {
9915 hdd_alert("Recovery in progress; wait here!!!");
9916 msleep(1000);
9917 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
9918 hdd_alert("SSR never completed, fatal error");
9919 QDF_BUG(0);
9920 }
9921 }
9922}
9923
9924/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009925 * __hdd_module_exit - Module exit helper
9926 *
9927 * Module exit helper function used by both module and static driver.
9928 */
9929static void __hdd_module_exit(void)
9930{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05309931 int qdf_print_idx = -1;
9932
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009933 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
9934 QWLAN_VERSIONSTR);
9935
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309936 hdd_wait_for_recovery_completion();
9937
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009938 wlan_hdd_unregister_driver();
9939
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309940 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009941
Rajeev Kumar97767a02016-11-30 11:20:40 -08009942 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309943 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009944 pld_deinit();
9945
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05309946 qdf_print_idx = qdf_get_pidx();
9947 qdf_print_ctrl_cleanup(qdf_print_idx);
9948
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009949 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009950}
9951
Arun Khandavallifae92942016-08-01 13:31:08 +05309952#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009953/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309954 * wlan_boot_cb() - Wlan boot callback
9955 * @kobj: object whose directory we're creating the link in.
9956 * @attr: attribute the user is interacting with
9957 * @buff: the buffer containing the user data
9958 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009959 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309960 * This callback is invoked when the fs is ready to start the
9961 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009962 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309963 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009964 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309965static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009966 struct kobj_attribute *attr,
9967 const char *buf,
9968 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009969{
Arun Khandavallifae92942016-08-01 13:31:08 +05309970
Arun Khandavallifae92942016-08-01 13:31:08 +05309971 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009972 pr_err("%s: wlan driver already initialized\n", __func__);
9973 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +05309974 }
9975
Arun Khandavallifae92942016-08-01 13:31:08 +05309976 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009977 pr_err("%s: wlan driver initialization failed\n", __func__);
9978 return -EIO;
9979 }
9980
9981 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +05309982
9983 return count;
9984
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009985}
Arun Khandavallifae92942016-08-01 13:31:08 +05309986
9987/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -07009988 * hdd_sysfs_cleanup() - cleanup sysfs
9989 *
9990 * Return: None
9991 *
9992 */
9993static void hdd_sysfs_cleanup(void)
9994{
9995
9996 /* remove from group */
9997 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
9998 sysfs_remove_group(wlan_loader->boot_wlan_obj,
9999 wlan_loader->attr_group);
10000
10001 /* unlink the object from parent */
10002 kobject_del(wlan_loader->boot_wlan_obj);
10003
10004 /* free the object */
10005 kobject_put(wlan_loader->boot_wlan_obj);
10006
10007 kfree(wlan_loader->attr_group);
10008 kfree(wlan_loader);
10009
10010 wlan_loader = NULL;
10011}
10012
10013/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010014 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
10015 * ready
10016 *
10017 * This is creates the syfs entry boot_wlan. Which shall be invoked
10018 * when the filesystem is ready.
10019 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010020 * QDF API cannot be used here since this function is called even before
10021 * initializing WLAN driver.
10022 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010023 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +053010024 */
10025static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010026{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010027 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010028
10029 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
10030 if (!wlan_loader) {
10031 pr_err("%s: memory alloc failed\n", __func__);
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010032 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010033 }
10034
10035 wlan_loader->boot_wlan_obj = NULL;
10036 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
10037 GFP_KERNEL);
10038 if (!wlan_loader->attr_group) {
10039 pr_err("%s: malloc attr_group failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010040 goto error_return;
10041 }
10042
10043 wlan_loader->loaded_state = 0;
10044 wlan_loader->attr_group->attrs = attrs;
10045
10046 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
10047 kernel_kobj);
10048 if (!wlan_loader->boot_wlan_obj) {
10049 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010050 goto error_return;
10051 }
10052
10053 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
10054 wlan_loader->attr_group);
10055 if (ret) {
10056 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
10057 goto error_return;
10058 }
10059
10060 return 0;
10061
10062error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010063 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +053010064
10065 return ret;
10066}
10067
10068/**
10069 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
10070 *
10071 * Return: 0 on success or errno on failure
10072 */
10073static int wlan_deinit_sysfs(void)
10074{
Arun Khandavallifae92942016-08-01 13:31:08 +053010075 if (!wlan_loader) {
10076 hdd_alert("wlan loader context is Null!");
10077 return -EINVAL;
10078 }
10079
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010080 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010081 return 0;
10082}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010083
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010084#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +053010085
10086#ifdef MODULE
10087/**
10088 * __hdd_module_init - Module init helper
10089 *
10090 * Module init helper function used by both module and static driver.
10091 *
10092 * Return: 0 for success, errno on failure
10093 */
10094static int hdd_module_init(void)
10095{
10096 int ret = 0;
10097
10098 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
10099 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
10100
10101 if (__hdd_module_init()) {
10102 pr_err("%s: Failed to register handler\n", __func__);
10103 ret = -EINVAL;
10104 }
10105
10106 return ret;
10107}
10108#else
10109static int __init hdd_module_init(void)
10110{
10111 int ret = -EINVAL;
10112
10113 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010114 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +053010115 pr_err("Failed to create sysfs entry for loading wlan");
10116
10117 return ret;
10118}
10119#endif
10120
10121
10122#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010123/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010124 * hdd_module_exit() - Exit function
10125 *
10126 * This is the driver exit point (invoked when module is unloaded using rmmod)
10127 *
10128 * Return: None
10129 */
10130static void __exit hdd_module_exit(void)
10131{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010132 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010133}
Arun Khandavallifae92942016-08-01 13:31:08 +053010134#else
10135static void __exit hdd_module_exit(void)
10136{
10137 __hdd_module_exit();
10138 wlan_deinit_sysfs();
10139}
10140#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010141
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010142static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
10143{
10144 return param_set_copystring(kmessage, kp);
10145}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010146
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010147/**
10148 * is_con_mode_valid() check con mode is valid or not
10149 * @mode: global con mode
10150 *
10151 * Return: TRUE on success FALSE on failure
10152 */
10153static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
10154{
10155 switch (mode) {
10156 case QDF_GLOBAL_MONITOR_MODE:
10157 case QDF_GLOBAL_FTM_MODE:
10158 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010159 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010160 return true;
10161 default:
10162 return false;
10163 }
10164}
10165
10166/**
10167 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
10168 * @mode: global con mode
10169 *
10170 * Return: adapter mode
10171 */
10172static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
10173 enum tQDF_GLOBAL_CON_MODE mode)
10174{
10175
10176 switch (mode) {
10177 case QDF_GLOBAL_MISSION_MODE:
10178 return QDF_STA_MODE;
10179 case QDF_GLOBAL_MONITOR_MODE:
10180 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010181 case QDF_GLOBAL_EPPING_MODE:
10182 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010183 case QDF_GLOBAL_FTM_MODE:
10184 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010185 case QDF_GLOBAL_QVIT_MODE:
10186 return QDF_QVIT_MODE;
10187 default:
10188 return QDF_MAX_NO_OF_MODE;
10189 }
10190}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010191
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010192static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
10193 enum tQDF_GLOBAL_CON_MODE curr_mode)
10194{
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010195 int driver_status;
10196
10197 driver_status = hdd_ctx->driver_status;
10198
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010199 switch (curr_mode) {
10200 case QDF_GLOBAL_MISSION_MODE:
10201 case QDF_GLOBAL_MONITOR_MODE:
10202 case QDF_GLOBAL_FTM_MODE:
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010203 if (driver_status != DRIVER_MODULES_CLOSED) {
10204 hdd_abort_mac_scan_all_adapters(hdd_ctx);
10205 hdd_stop_all_adapters(hdd_ctx);
10206 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010207 hdd_deinit_all_adapters(hdd_ctx, false);
10208 hdd_close_all_adapters(hdd_ctx, false);
10209 break;
10210 case QDF_GLOBAL_EPPING_MODE:
10211 epping_disable();
10212 epping_close();
10213 break;
10214 default:
10215 return;
10216 }
10217}
10218
10219static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
10220 enum tQDF_GLOBAL_CON_MODE mode)
10221{
10222 hdd_adapter_t *adapter;
10223 int ret = 0;
10224 bool rtnl_held;
10225 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
10226 QDF_STATUS status;
10227
10228 if (!qdf_dev) {
10229 hdd_err("qdf device context is Null return!");
10230 return -EINVAL;
10231 }
10232
10233 rtnl_held = hdd_hold_rtnl_lock();
10234 switch (mode) {
10235 case QDF_GLOBAL_MISSION_MODE:
Jeff Johnson957bc272017-02-02 08:54:48 -080010236 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
10237 if (ret)
10238 hdd_alert("Failed to open interfaces: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010239 break;
10240 case QDF_GLOBAL_FTM_MODE:
10241 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
10242 wlan_hdd_get_intf_addr(hdd_ctx),
10243 NET_NAME_UNKNOWN, rtnl_held);
10244 if (adapter == NULL)
10245 ret = -EINVAL;
10246 break;
10247 case QDF_GLOBAL_MONITOR_MODE:
10248 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
10249 wlan_hdd_get_intf_addr(hdd_ctx),
10250 NET_NAME_UNKNOWN, rtnl_held);
10251 if (adapter == NULL)
10252 ret = -EINVAL;
10253 break;
10254 case QDF_GLOBAL_EPPING_MODE:
10255 status = epping_open();
10256 if (status != QDF_STATUS_SUCCESS) {
10257 hdd_err("Failed to open in eeping mode: %d", status);
10258 ret = -EINVAL;
10259 break;
10260 }
10261 ret = epping_enable(qdf_dev->dev);
10262 if (ret) {
10263 hdd_err("Failed to enable in epping mode : %d", ret);
10264 epping_close();
10265 }
10266 break;
10267 default:
10268 hdd_info("Mode not supported");
10269 ret = -ENOTSUPP;
10270 break;
10271 }
10272 hdd_release_rtnl_lock();
10273 rtnl_held = false;
10274 return ret;
10275}
10276
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010277/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010278 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010279 * @kmessage: con mode name on which driver to be bring up
10280 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010281 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010282 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010283 * This function is invoked when user updates con mode using sys entry,
10284 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010285 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010286 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010287 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010288static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
10289 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010290{
10291 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +053010292 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010293 enum tQDF_GLOBAL_CON_MODE curr_mode;
10294 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010295
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010296 ret = wlan_hdd_validate_context(hdd_ctx);
10297 if (ret)
10298 return ret;
10299
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010300 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010301
Arun Khandavallifae92942016-08-01 13:31:08 +053010302 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010303 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +053010304
Arun Khandavallifae92942016-08-01 13:31:08 +053010305
Arun Khandavallia172c3e2016-08-26 17:33:13 +053010306
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010307 if (!(is_con_mode_valid(con_mode))) {
10308 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010309 ret = -EINVAL;
10310 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010311 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010312
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010313 curr_mode = hdd_get_conparam();
10314 if (curr_mode == con_mode) {
10315 hdd_err("curr mode: %d is same as user triggered mode %d",
10316 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010317 ret = 0;
10318 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010319 }
10320
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010321 /* Cleanup present mode before switching to new mode */
10322 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +053010323
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -070010324 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +053010325 if (ret) {
10326 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010327 goto reset_flags;
10328 }
10329
10330 hdd_set_conparam(con_mode);
10331
10332 /* Register for new con_mode & then kick_start modules again */
10333 ret = hdd_register_req_mode(hdd_ctx, con_mode);
10334 if (ret) {
10335 hdd_err("Failed to register for new mode");
10336 goto reset_flags;
10337 }
10338
10339 adapter_mode = hdd_get_adpter_mode(con_mode);
10340 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
10341 hdd_err("invalid adapter");
10342 ret = -EINVAL;
10343 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010344 }
10345
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010346 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +053010347 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010348 hdd_err("Failed to get adapter:%d", adapter_mode);
10349 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010350 }
10351
10352 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
10353 if (ret) {
10354 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010355 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010356 }
10357
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010358 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
10359 con_mode == QDF_GLOBAL_FTM_MODE) {
10360 if (hdd_start_adapter(adapter)) {
10361 hdd_err("Failed to start %s adapter", kmessage);
10362 ret = -EINVAL;
10363 goto reset_flags;
10364 }
Arun Khandavallifae92942016-08-01 13:31:08 +053010365 }
10366
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010367 hdd_info("Mode successfully changed to %s", kmessage);
10368 ret = 0;
10369
10370reset_flags:
10371 cds_set_load_in_progress(false);
10372 return ret;
10373}
10374
10375
10376static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
10377{
10378 int ret;
10379 hdd_context_t *hdd_ctx;
10380
10381 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10382 ret = wlan_hdd_validate_context(hdd_ctx);
10383 if (ret)
10384 return ret;
10385
10386 cds_ssr_protect(__func__);
10387 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
10388 cds_ssr_unprotect(__func__);
10389
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010390 return ret;
10391}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010392
10393/**
10394 * hdd_get_conparam() - driver exit point
10395 *
10396 * This is the driver exit point (invoked when module is unloaded using rmmod)
10397 *
Anurag Chouhan6d760662016-02-20 16:05:43 +053010398 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010399 */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010400enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010401{
Anurag Chouhan6d760662016-02-20 16:05:43 +053010402 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010403}
10404
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010405void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010406{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010407 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010408}
10409
Komal Seelamc11bb222016-01-27 18:57:10 +053010410/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010411 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
10412 * @hdd_ctx: HDD context
10413 *
10414 * Cleans up the pre cac interface, if it exists
10415 *
10416 * Return: None
10417 */
10418void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
10419{
10420 uint8_t session_id;
10421 QDF_STATUS status;
10422 struct hdd_adapter_s *precac_adapter;
10423
10424 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
10425 if (QDF_IS_STATUS_ERROR(status)) {
10426 hdd_err("failed to get pre cac vdev id");
10427 return;
10428 }
10429
10430 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
10431 if (!precac_adapter) {
10432 hdd_err("invalid pre cac adapater");
10433 return;
10434 }
10435
10436 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
10437 wlan_hdd_sap_pre_cac_failure,
10438 (void *)precac_adapter);
10439 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
10440
10441}
10442
10443/**
Komal Seelamec702b02016-02-24 18:42:16 +053010444 * hdd_update_ol_config - API to update ol configuration parameters
10445 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +053010446 *
Komal Seelamc11bb222016-01-27 18:57:10 +053010447 * Return: void
10448 */
Komal Seelamec702b02016-02-24 18:42:16 +053010449static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +053010450{
Komal Seelamec702b02016-02-24 18:42:16 +053010451 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010452 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +053010453
Komal Seelamec702b02016-02-24 18:42:16 +053010454 if (!ol_ctx)
10455 return;
10456
10457 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
10458 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
10459 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
10460 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -070010461 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +053010462
10463 ol_init_ini_config(ol_ctx, &cfg);
10464}
10465
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010466#ifdef FEATURE_RUNTIME_PM
10467/**
10468 * hdd_populate_runtime_cfg() - populate runtime configuration
10469 * @hdd_ctx: hdd context
10470 * @cfg: pointer to the configuration memory being populated
10471 *
10472 * Return: void
10473 */
10474static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10475 struct hif_config_info *cfg)
10476{
10477 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
10478 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
10479}
10480#else
10481static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10482 struct hif_config_info *cfg)
10483{
10484}
10485#endif
10486
Komal Seelamec702b02016-02-24 18:42:16 +053010487/**
10488 * hdd_update_hif_config - API to update HIF configuration parameters
10489 * @hdd_ctx: HDD Context
10490 *
10491 * Return: void
10492 */
10493static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
10494{
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010495 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +053010496 struct hif_config_info cfg;
10497
10498 if (!scn)
10499 return;
10500
10501 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010502 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053010503 hif_init_ini_config(scn, &cfg);
10504}
10505
10506/**
10507 * hdd_update_config() - Initialize driver per module ini parameters
10508 * @hdd_ctx: HDD Context
10509 *
10510 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010511 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053010512 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010513int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053010514{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010515 int ret;
10516
Komal Seelamec702b02016-02-24 18:42:16 +053010517 hdd_update_ol_config(hdd_ctx);
10518 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010519 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
10520 ret = hdd_update_cds_config_ftm(hdd_ctx);
10521 else
10522 ret = hdd_update_cds_config(hdd_ctx);
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -080010523 ret = hdd_update_user_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010524
10525 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053010526}
10527
Mukul Sharma9d797a02017-01-05 20:26:03 +053010528#ifdef FEATURE_WLAN_RA_FILTERING
10529/**
10530 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
10531 * @psoc_cfg: pmo psoc Configuration
10532 * @hdd_ctx: Pointer to hdd context
10533 *
10534 * Return: none
10535 */
10536static inline void hdd_ra_populate_pmo_config(
10537 struct pmo_psoc_cfg *psoc_cfg,
10538 hdd_context_t *hdd_ctx)
10539{
10540 psoc_cfg->ra_ratelimit_interval =
10541 hdd_ctx->config->RArateLimitInterval;
10542 psoc_cfg->ra_ratelimit_enable =
10543 hdd_ctx->config->IsRArateLimitEnabled;
10544}
10545#else
10546static inline void hdd_ra_populate_pmo_config(
10547 struct cds_config_info *cds_cfg,
10548 hdd_context_t *hdd_ctx)
10549{
10550}
10551#endif
10552/**
10553 * hdd_update_pmo_config - API to update pmo configuration parameters
10554 * @hdd_ctx: HDD context
10555 *
10556 * Return: void
10557 */
10558static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
10559{
10560 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10561 struct pmo_psoc_cfg psoc_cfg;
10562 QDF_STATUS status;
10563
10564 /*
10565 * Value of hdd_ctx->wowEnable can be,
10566 * 0 - Disable both magic pattern match and pattern byte match.
10567 * 1 - Enable magic pattern match on all interfaces.
10568 * 2 - Enable pattern byte match on all interfaces.
10569 * 3 - Enable both magic patter and pattern byte match on
10570 * all interfaces.
10571 */
10572 psoc_cfg.magic_ptrn_enable =
10573 (hdd_ctx->config->wowEnable & 0x01) ? true : false;
10574 psoc_cfg.ptrn_match_enable_all_vdev =
10575 (hdd_ctx->config->wowEnable & 0x02) ? true : false;
10576 psoc_cfg.bpf_enable =
10577 hdd_ctx->config->bpf_packet_filter_enable;
10578 psoc_cfg.arp_offload_enable = hdd_ctx->config->fhostArpOffload;
10579 psoc_cfg.ns_offload_enable_static = hdd_ctx->config->fhostNSOffload;
10580 if (hdd_ctx->config->fhostNSOffload)
10581 psoc_cfg.ns_offload_enable_dynamic = true;
10582 psoc_cfg.ssdp = hdd_ctx->config->ssdp;
10583 psoc_cfg.enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
10584 psoc_cfg.active_mode_offload =
10585 hdd_ctx->config->active_mode_offload;
10586 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
10587 psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters;
10588
10589 hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
10590 status = pmo_ucfg_update_psoc_config(psoc, &psoc_cfg);
10591 if (status != QDF_STATUS_SUCCESS) {
10592 hdd_err("failed pmo psoc configuration");
10593 return -EINVAL;
10594 }
10595
10596 return 0;
10597}
10598
10599int hdd_update_components_config(hdd_context_t *hdd_ctx)
10600{
10601 int ret;
10602
10603 ret = hdd_update_pmo_config(hdd_ctx);
10604
10605 return ret;
10606}
10607
Agrawal Ashish65634612016-08-18 13:24:32 +053010608/**
10609 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
10610 * @mode : cfg80211 DFS mode
10611 *
10612 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
10613 */
10614enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
10615{
10616 switch (mode) {
10617 case DFS_MODE_ENABLE:
10618 return ACS_DFS_MODE_ENABLE;
10619 break;
10620 case DFS_MODE_DISABLE:
10621 return ACS_DFS_MODE_DISABLE;
10622 break;
10623 case DFS_MODE_DEPRIORITIZE:
10624 return ACS_DFS_MODE_DEPRIORITIZE;
10625 break;
10626 default:
10627 hdd_err("ACS dfs mode is NONE");
10628 return ACS_DFS_MODE_NONE;
10629 }
10630}
10631
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053010632/**
10633 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
10634 * @hddctx: pointer to hdd context
10635 * @set_value: enable/disable
10636 *
10637 * When Host sends vendor command enable, FW will send *ONE* CA ind to
10638 * Host(even though it is duplicate). When Host send vendor command
10639 * disable,FW doesn't perform any action. Whenever any change in
10640 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
10641 *
10642 * return - 0 on success, appropriate error values on failure.
10643 */
10644int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
10645{
10646 QDF_STATUS status;
10647
10648 if (0 != wlan_hdd_validate_context(hddctx)) {
10649 return -EAGAIN;
10650 }
10651
10652 if (!hddctx->config->goptimize_chan_avoid_event) {
10653 hdd_warn("goptimize_chan_avoid_event ini param disabled");
10654 return -EINVAL;
10655 }
10656
10657 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
10658 if (!QDF_IS_STATUS_SUCCESS(status)) {
10659 hdd_err("Failed to send chan avoid command to SME");
10660 return -EINVAL;
10661 }
10662 return 0;
10663}
Agrawal Ashish65634612016-08-18 13:24:32 +053010664
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010665/**
10666 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
10667 * @value: value to set
10668 *
10669 * This function will set the passed value to roaming in progress flag.
10670 *
10671 * Return: None
10672 */
10673void hdd_set_roaming_in_progress(bool value)
10674{
10675 hdd_context_t *hdd_ctx;
10676
10677 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10678 if (!hdd_ctx) {
10679 hdd_err("HDD context is NULL");
10680 return;
10681 }
10682
10683 hdd_ctx->roaming_in_progress = value;
10684 hdd_info("Roaming in Progress set to %d", value);
10685}
10686
10687/**
10688 * hdd_is_roaming_in_progress() - check if roaming is in progress
10689 * @hdd_ctx - HDD context
10690 *
10691 * Return: true if roaming is in progress else false
10692 */
10693bool hdd_is_roaming_in_progress(void)
10694{
10695 hdd_context_t *hdd_ctx;
10696
10697 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10698 if (!hdd_ctx) {
10699 hdd_err("HDD context is NULL");
10700 return false;
10701 }
10702 return hdd_ctx->roaming_in_progress;
10703}
10704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010705/* Register the module init/exit functions */
10706module_init(hdd_module_init);
10707module_exit(hdd_module_exit);
10708
10709MODULE_LICENSE("Dual BSD/GPL");
10710MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10711MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10712
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010713module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10714 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010715
10716module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
10717 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
10718
10719module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
10720
10721module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
10722
10723module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);