blob: 5b121dea260ff15c94c2439b517af8bb6d59edc1 [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"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -0800100#include "wlan_policy_mgr_api.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"
Naveen Rawat910726a2017-03-06 11:42:51 -0800116#include "os_if_wifi_pos.h"
117#include "wifi_pos_api.h"
118#include "wlan_hdd_oemdata.h"
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800119#include "wlan_hdd_he.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +0530121#ifdef CNSS_GENL
122#include <net/cnss_nl.h>
123#endif
124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800125#ifdef MODULE
126#define WLAN_MODULE_NAME module_name(THIS_MODULE)
127#else
128#define WLAN_MODULE_NAME "wlan"
129#endif
130
131#ifdef TIMER_MANAGER
132#define TIMER_MANAGER_STR " +TIMER_MANAGER"
133#else
134#define TIMER_MANAGER_STR ""
135#endif
136
137#ifdef MEMORY_DEBUG
138#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
139#else
140#define MEMORY_DEBUG_STR ""
141#endif
142
Arun Khandavallifae92942016-08-01 13:31:08 +0530143#ifndef MODULE
144static struct gwlan_loader *wlan_loader;
145static ssize_t wlan_boot_cb(struct kobject *kobj,
146 struct kobj_attribute *attr,
147 const char *buf, size_t count);
148struct gwlan_loader {
149 bool loaded_state;
150 struct kobject *boot_wlan_obj;
151 struct attribute_group *attr_group;
152};
153
154static struct kobj_attribute wlan_boot_attribute =
155 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
156
157static struct attribute *attrs[] = {
158 &wlan_boot_attribute.attr,
159 NULL,
160};
161
162#define MODULE_INITIALIZED 1
163#endif
164
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165/* the Android framework expects this param even though we don't use it */
166#define BUF_LEN 20
167static char fwpath_buffer[BUF_LEN];
168static struct kparam_string fwpath = {
169 .string = fwpath_buffer,
170 .maxlen = BUF_LEN,
171};
172
173static char *country_code;
174static int enable_11d = -1;
175static int enable_dfs_chan_scan = -1;
176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177/*
178 * spinlock for synchronizing asynchronous request/response
179 * (full description of use in wlan_hdd_main.h)
180 */
181DEFINE_SPINLOCK(hdd_context_lock);
182
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800183#define WLAN_NLINK_CESIUM 30
184
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530185static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186
187#define WOW_MAX_FILTER_LISTS 1
188#define WOW_MAX_FILTERS_PER_LIST 4
189#define WOW_MIN_PATTERN_SIZE 6
190#define WOW_MAX_PATTERN_SIZE 64
191
192#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
193static const struct wiphy_wowlan_support wowlan_support_reg_init = {
194 .flags = WIPHY_WOWLAN_ANY |
195 WIPHY_WOWLAN_MAGIC_PKT |
196 WIPHY_WOWLAN_DISCONNECT |
197 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
198 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
199 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
200 WIPHY_WOWLAN_4WAY_HANDSHAKE |
201 WIPHY_WOWLAN_RFKILL_RELEASE,
202 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
203 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
204 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
205};
206#endif
207
208/* internal function declaration */
209
210struct sock *cesium_nl_srv_sock;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +0530211struct completion wlan_start_comp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
213void wlan_hdd_auto_shutdown_cb(void);
214#endif
215
216/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530217 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
218 * @hdd_ctx: pointer to hdd_context_t
219 *
220 * Return: none
221 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700222static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530223{
224 hdd_adapter_t *adapter;
225 hdd_adapter_list_node_t *adapter_node, *next;
226 QDF_STATUS status = QDF_STATUS_SUCCESS;
227
228 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
229 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
230 adapter = adapter_node->pAdapter;
231 if (NULL != adapter)
232 hdd_send_rps_ind(adapter);
233 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
234 adapter_node = next;
235 }
236}
237
238/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
240 * @vdev_id: vdev_id
241 * @action: action type
242 * @reason: reason type
243 *
244 * Return: none
245 */
246void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
247 enum netif_action_type action, enum netif_reason_type reason)
248{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530249 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250 hdd_adapter_t *adapter;
251
252 if (!hdd_ctx) {
253 hdd_err("hdd ctx is NULL");
254 return;
255 }
256 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
257
258 wlan_hdd_netif_queue_control(adapter, action, reason);
259 return;
260}
261
262/*
263 * Store WLAN driver version info in a global variable such that crash debugger
264 * can extract it from driver debug symbol and crashdump for post processing
265 */
266uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
267
268/**
269 * hdd_device_mode_to_string() - return string conversion of device mode
270 * @device_mode: device mode
271 *
272 * This utility function helps log string conversion of device mode.
273 *
274 * Return: string conversion of device mode, if match found;
275 * "Unknown" otherwise.
276 */
277const char *hdd_device_mode_to_string(uint8_t device_mode)
278{
279 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800280 CASE_RETURN_STRING(QDF_STA_MODE);
281 CASE_RETURN_STRING(QDF_SAP_MODE);
282 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
283 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
284 CASE_RETURN_STRING(QDF_FTM_MODE);
285 CASE_RETURN_STRING(QDF_IBSS_MODE);
286 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
287 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700288 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 default:
290 return "Unknown";
291 }
292}
293
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530294/**
295 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
296 * @adapter: HDD adapter
297 * @chan_number: Channel number
298 * @chan_bw: Bandwidth
299 *
300 * Checks if the given bandwidth is valid for the given channel number.
301 *
302 * Return: 0 for success, non-zero for failure
303 */
304int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
305 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800306 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530307{
308 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
309 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
310 bool found = false;
311 tHalHandle hal;
312
313 hal = WLAN_HDD_GET_HAL_CTX(adapter);
314 if (!hal) {
315 hdd_err("Invalid HAL context");
316 return -EINVAL;
317 }
318
319 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
320 hdd_err("No valid channel list");
321 return -EOPNOTSUPP;
322 }
323
324 for (i = 0; i < len; i++) {
325 if (chan[i] == chan_number) {
326 found = true;
327 break;
328 }
329 }
330
331 if (found == false) {
332 hdd_err("Channel not in driver's valid channel list");
333 return -EOPNOTSUPP;
334 }
335
336 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
337 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
338 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
339 return -EINVAL;
340 }
341
342 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
343 if (chan_bw == CH_WIDTH_80MHZ) {
344 hdd_err("BW80 not possible in 2.4GHz band");
345 return -EINVAL;
346 }
347 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
348 (chan_bw != CH_WIDTH_MAX)) {
349 hdd_err("Only BW20 possible on channel 14");
350 return -EINVAL;
351 }
352 }
353
354 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
355 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
356 (chan_bw != CH_WIDTH_MAX)) {
357 hdd_err("Only BW20 possible on channel 165");
358 return -EINVAL;
359 }
360 }
361
362 return 0;
363}
364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365static int __hdd_netdev_notifier_call(struct notifier_block *nb,
366 unsigned long state, void *data)
367{
368#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
369 struct netdev_notifier_info *dev_notif_info = data;
370 struct net_device *dev = dev_notif_info->dev;
371#else
372 struct net_device *dev = data;
373#endif
374 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
375 hdd_context_t *hdd_ctx;
376
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800377 ENTER_DEV(dev);
378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379 /* Make sure that this callback corresponds to our device. */
380 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
381 return NOTIFY_DONE;
382
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530383 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700385 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 return NOTIFY_DONE;
387 }
388
389 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700390 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 return NOTIFY_DONE;
392 }
393
394 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
395 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700396 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530397 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 return NOTIFY_DONE;
399 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800400 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 return NOTIFY_DONE;
402
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700403 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800404 dev->name, state);
405
406 switch (state) {
407 case NETDEV_REGISTER:
408 break;
409
410 case NETDEV_UNREGISTER:
411 break;
412
413 case NETDEV_UP:
414 sme_ch_avoid_update_req(hdd_ctx->hHal);
415 break;
416
417 case NETDEV_DOWN:
418 break;
419
420 case NETDEV_CHANGE:
421 if (true == adapter->isLinkUpSvcNeeded)
422 complete(&adapter->linkup_event_var);
423 break;
424
425 case NETDEV_GOING_DOWN:
426 if (adapter->scan_info.mScanPending != false) {
427 unsigned long rc;
428 INIT_COMPLETION(adapter->scan_info.
429 abortscan_event_var);
430 hdd_abort_mac_scan(adapter->pHddCtx,
431 adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +0530432 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 eCSR_SCAN_ABORT_DEFAULT);
434 rc = wait_for_completion_timeout(
435 &adapter->scan_info.abortscan_event_var,
436 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
437 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700438 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800439 }
440 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700441 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 }
443 break;
444
445 default:
446 break;
447 }
448
449 return NOTIFY_DONE;
450}
451
452/**
453 * hdd_netdev_notifier_call() - netdev notifier callback function
454 * @nb: pointer to notifier block
455 * @state: state
456 * @ndev: ndev pointer
457 *
458 * Return: 0 on success, error number otherwise.
459 */
460static int hdd_netdev_notifier_call(struct notifier_block *nb,
461 unsigned long state,
462 void *ndev)
463{
464 int ret;
465
466 cds_ssr_protect(__func__);
467 ret = __hdd_netdev_notifier_call(nb, state, ndev);
468 cds_ssr_unprotect(__func__);
469
470 return ret;
471}
472
473struct notifier_block hdd_netdev_notifier = {
474 .notifier_call = hdd_netdev_notifier_call,
475};
476
477/* variable to hold the insmod parameters */
478static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800479
480/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530483/**
484 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
485 * @ch_width: NL channel width
486 *
487 * Converts the NL channel width to the driver's internal representation
488 *
489 * Return: Converted channel width. In case of non matching NL channel width,
490 * CH_WIDTH_MAX will be returned.
491 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800492enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530493{
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800494 uint8_t fw_ch_bw;
495 fw_ch_bw = wma_get_vht_ch_width();
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530496 switch (ch_width) {
497 case NL80211_CHAN_WIDTH_20_NOHT:
498 case NL80211_CHAN_WIDTH_20:
499 return CH_WIDTH_20MHZ;
500 case NL80211_CHAN_WIDTH_40:
501 return CH_WIDTH_40MHZ;
502 break;
503 case NL80211_CHAN_WIDTH_80:
504 return CH_WIDTH_80MHZ;
505 case NL80211_CHAN_WIDTH_80P80:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800506 if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
507 return CH_WIDTH_80P80MHZ;
508 else if (fw_ch_bw == WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
509 return CH_WIDTH_160MHZ;
510 else
511 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530512 case NL80211_CHAN_WIDTH_160:
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800513 if (fw_ch_bw >= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
514 return CH_WIDTH_160MHZ;
515 else
516 return CH_WIDTH_80MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530517 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800518 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530519 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800520 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530521 default:
522 hdd_err("Invalid channel width %d, setting to default",
523 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800524 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530525 }
526}
527
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530528/* wlan_hdd_find_opclass() - Find operating class for a channel
529 * @hal: handler to HAL
530 * @channel: channel id
531 * @bw_offset: bandwidth offset
532 *
533 * Function invokes sme api to find the operating class
534 *
535 * Return: operating class
536 */
537uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
538 uint8_t bw_offset)
539{
540 uint8_t opclass = 0;
541
542 sme_get_opclass(hal, channel, bw_offset, &opclass);
543 return opclass;
544}
545
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530547 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530548 * @module_id: Module whose trace level is being configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 * @bitmask: Bitmask of log levels to be enabled
550 *
551 * Called immediately after the cfg.ini is read in order to configure
552 * the desired trace levels.
553 *
554 * Return: None
555 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530556int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530558 QDF_TRACE_LEVEL level;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530559 int qdf_print_idx = -1;
560 int status = -1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 /*
562 * if the bitmask is the default value, then a bitmask was not
563 * specified in cfg.ini, so leave the logging level alone (it
564 * will remain at the "compiled in" default value)
565 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530566 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530567 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 }
569
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530570 qdf_print_idx = qdf_get_pidx();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800571
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530572 /* a mask was specified. start by disabling all logging */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530573 status = qdf_print_set_category_verbose(qdf_print_idx, module_id,
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530574 QDF_TRACE_LEVEL_NONE, 0);
575
576 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530577 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530579 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 while (0 != bitmask) {
581 if (bitmask & 1) {
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530582 status = qdf_print_set_category_verbose(qdf_print_idx,
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530583 module_id, level, 1);
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +0530584 if (QDF_STATUS_SUCCESS != status)
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530585 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586 }
587 level++;
588 bitmask >>= 1;
589 }
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +0530590 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591}
592
593/**
594 * wlan_hdd_validate_context() - check the HDD context
595 * @hdd_ctx: HDD context pointer
596 *
597 * Return: 0 if the context is valid. Error code otherwise
598 */
599int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
600{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530602 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 return -ENODEV;
604 }
605
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800606 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530607 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
608 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609 return -EAGAIN;
610 }
611
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800612 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530613 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
614 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 return -EAGAIN;
616 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530617
618 if (hdd_ctx->start_modules_in_progress ||
619 hdd_ctx->stop_modules_in_progress) {
620 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
621 (void *)_RET_IP_);
622 return -EAGAIN;
623 }
624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625 return 0;
626}
627
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628/**
629 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
630 * @hdd_adapter_t Hdd adapter.
631 *
632 * This function sets the IBSS power save config parameters to WMA
633 * which will send it to firmware if FW supports IBSS power save
634 * before vdev start.
635 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530636 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637 * on failure.
638 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530639QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640{
641 int ret;
642 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
643
644 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700645 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530646 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647 }
648
649 ret = wma_cli_set_command(adapter->sessionId,
650 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
651 hdd_ctx->config->ibssATIMWinSize,
652 VDEV_CMD);
653 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700654 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530655 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 }
657
658 ret = wma_cli_set_command(adapter->sessionId,
659 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
660 hdd_ctx->config->isIbssPowerSaveAllowed,
661 VDEV_CMD);
662 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700663 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
664 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530665 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800666 }
667
668 ret = wma_cli_set_command(adapter->sessionId,
669 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
670 hdd_ctx->config->
671 isIbssPowerCollapseAllowed, VDEV_CMD);
672 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700673 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
674 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530675 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 }
677
678 ret = wma_cli_set_command(adapter->sessionId,
679 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
680 hdd_ctx->config->isIbssAwakeOnTxRx,
681 VDEV_CMD);
682 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700683 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530684 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 }
686
687 ret = wma_cli_set_command(adapter->sessionId,
688 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
689 hdd_ctx->config->ibssInactivityCount,
690 VDEV_CMD);
691 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700692 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530693 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 }
695
696 ret = wma_cli_set_command(adapter->sessionId,
697 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
698 hdd_ctx->config->ibssTxSpEndInactivityTime,
699 VDEV_CMD);
700 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700701 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
702 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530703 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 }
705
706 ret = wma_cli_set_command(adapter->sessionId,
707 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
708 hdd_ctx->config->ibssPsWarmupTime,
709 VDEV_CMD);
710 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700711 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
712 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530713 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 }
715
716 ret = wma_cli_set_command(adapter->sessionId,
717 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
718 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
719 VDEV_CMD);
720 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700721 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
722 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530723 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 }
725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530726 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727}
728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729#define INTF_MACADDR_MASK 0x7
730
731/**
732 * hdd_update_macaddr() - update mac address
733 * @config: hdd configuration
734 * @hw_macaddr: mac address
735 *
736 * Mac address for multiple virtual interface is found as following
737 * i) The mac address of the first interface is just the actual hw mac address.
738 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
739 * define the mac address for the remaining interfaces and locally
740 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
741 * supported virtual interfaces, right now this is 0x07 (meaning 8
742 * interface).
743 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
744 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
745 *
746 * Return: None
747 */
748void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530749 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800750{
751 int8_t i;
752 uint8_t macaddr_b3, tmp_br3;
753
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530754 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530755 QDF_MAC_ADDR_SIZE);
756 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530757 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530758 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 macaddr_b3 = config->intfMacAddr[i].bytes[3];
760 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
761 INTF_MACADDR_MASK;
762 macaddr_b3 += tmp_br3;
763
764 /* XOR-ing bit-24 of the mac address. This will give enough
765 * mac address range before collision
766 */
767 macaddr_b3 ^= (1 << 7);
768
769 /* Set locally administered bit */
770 config->intfMacAddr[i].bytes[0] |= 0x02;
771 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700772 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 MAC_ADDRESS_STR, i,
774 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
775 }
776}
777
778static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
779 struct wma_tgt_services *cfg)
780{
781 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782
783 /* Set up UAPSD */
784 config->apUapsdEnabled &= cfg->uapsd;
785
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -0800786 /* 11AX mode support */
787 if ((config->dot11Mode == eHDD_DOT11_MODE_11ax ||
788 config->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY) && !cfg->en_11ax)
789 config->dot11Mode = eHDD_DOT11_MODE_11ac;
790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 /* 11AC mode support */
792 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
793 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
794 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795
796 /* ARP offload: override user setting if invalid */
797 config->fhostArpOffload &= cfg->arp_offload;
798
799#ifdef FEATURE_WLAN_SCAN_PNO
800 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700801 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800802 if (cfg->pno_offload)
803 config->PnoOffload = true;
804#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805#ifdef FEATURE_WLAN_TDLS
806 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530807 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
808 cfg->en_tdls_offchan;
809 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
810 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
812 config->fEnableTDLSSleepSta = true;
813 } else {
814 config->fEnableTDLSSleepSta = false;
815 }
816#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817#ifdef WLAN_FEATURE_ROAM_OFFLOAD
818 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
819#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700820 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821
822}
823
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700824/**
825 * hdd_update_vdev_nss() - sets the vdev nss
826 * @hdd_ctx: HDD context
827 *
828 * Sets the Nss per vdev type based on INI
829 *
830 * Return: None
831 */
832static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
833{
834 struct hdd_config *cfg_ini = hdd_ctx->config;
835 uint8_t max_supp_nss = 1;
836
Naveen Rawat10b1c152017-01-18 11:16:06 -0800837 if (cfg_ini->enable2x2 && !cds_is_sub_20_mhz_enabled())
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700838 max_supp_nss = 2;
839
840 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
841 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
842
843 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
844 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
845}
846
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530847/**
848 * hdd_update_hw_dbs_capable() - sets the dbs capability of the device
849 * @hdd_ctx: HDD context
850 *
851 * Sets the DBS capability as per INI and firmware capability
852 *
853 * Return: None
854 */
855static void hdd_update_hw_dbs_capable(hdd_context_t *hdd_ctx)
856{
857 struct hdd_config *cfg_ini = hdd_ctx->config;
858 uint8_t hw_dbs_capable = 0;
859
860 if ((!cfg_ini->dual_mac_feature_disable)
Archana Ramachandran62886ce2017-03-24 14:46:32 -0700861 && policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc))
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +0530862 hw_dbs_capable = 1;
863
864 sme_update_hw_dbs_capable(hdd_ctx->hHal, hw_dbs_capable);
865}
866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
868 struct wma_tgt_ht_cap *cfg)
869{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530870 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871 uint32_t value, val32;
872 uint16_t val16;
873 struct hdd_config *pconfig = hdd_ctx->config;
874 tSirMacHTCapabilityInfo *phtCapInfo;
875 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
876 uint8_t enable_tx_stbc;
877
878 /* check and update RX STBC */
879 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
880 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
881
882 /* get the MPDU density */
883 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
884
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530885 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700886 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800887 value = 0;
888 }
889
890 /*
891 * MPDU density:
892 * override user's setting if value is larger
893 * than the one supported by target
894 */
895 if (value > cfg->mpdu_density) {
896 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
897 cfg->mpdu_density);
898
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530899 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700900 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901 }
902
903 /* get the HT capability info */
904 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530905 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700906 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800907 return;
908 }
909 val16 = (uint16_t) val32;
910 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
911
912 /* Set the LDPC capability */
913 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
914
915 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
916 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
917
918 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
919 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
920
921 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
922 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
923
924 enable_tx_stbc = pconfig->enableTxSTBC;
925
926 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
927 pconfig->enable2x2 = 1;
928 } else {
929 pconfig->enable2x2 = 0;
930 enable_tx_stbc = 0;
931
932 /* 1x1 */
933 /* Update Rx Highest Long GI data Rate */
934 if (sme_cfg_set_int(hdd_ctx->hHal,
935 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700936 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530937 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700938 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 }
940
941 /* Update Tx Highest Long GI data Rate */
942 if (sme_cfg_set_int
943 (hdd_ctx->hHal,
944 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700945 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530946 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700947 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948 }
949 }
950 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
951 enable_tx_stbc = 0;
952 phtCapInfo->txSTBC = enable_tx_stbc;
953
954 val32 = val16;
955 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530956 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700957 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800958#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
959 value = SIZE_OF_SUPPORTED_MCS_SET;
960 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700962 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963
964 if (pconfig->enable2x2) {
965 for (value = 0; value < cfg->num_rf_chains; value++)
966 mcs_set[value] =
967 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
968
969 status =
970 sme_cfg_set_str(hdd_ctx->hHal,
971 WNI_CFG_SUPPORTED_MCS_SET,
972 mcs_set,
973 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530974 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700975 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 }
977 }
978#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
979}
980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800981static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
982 struct wma_tgt_vht_cap *cfg)
983{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530984 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985 uint32_t value = 0;
986 struct hdd_config *pconfig = hdd_ctx->config;
987 struct wiphy *wiphy = hdd_ctx->wiphy;
988 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700989 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700990 uint32_t temp = 0;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -0800991 uint32_t ch_width = eHT_CHANNEL_WIDTH_80MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992
Dustin Brown5e06bd32016-10-04 12:49:10 -0700993 if (!band_5g) {
994 hdd_info("5GHz band disabled, skipping capability population");
995 return;
996 }
997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998 /* Get the current MPDU length */
999 status =
1000 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1001 &value);
1002
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301003 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001004 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001005 value = 0;
1006 }
1007
1008 /*
1009 * VHT max MPDU length:
1010 * override if user configured value is too high
1011 * that the target cannot support
1012 */
1013 if (value > cfg->vht_max_mpdu) {
1014 status = sme_cfg_set_int(hdd_ctx->hHal,
1015 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1016 cfg->vht_max_mpdu);
1017
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301018 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001019 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001020 }
1021 }
1022
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001023 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1024 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1025
1026 if (pconfig->enable2x2)
1027 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1028
1029 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1030 QDF_STATUS_E_FAILURE) {
1031 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1032 }
1033
1034 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1035 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1036 if (pconfig->enable2x2)
1037 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1038
1039 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1040 QDF_STATUS_E_FAILURE) {
1041 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1042 }
1043
1044 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1045 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1046 if (pconfig->enable2x2)
1047 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1048
1049 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1050 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1051
1052 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1053 QDF_STATUS_E_FAILURE) {
1054 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1055 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001056 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001057 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001058 &value);
1059
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301060 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001061 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001062 value = 0;
1063 }
1064
1065 /* Set the LDPC capability */
1066 if (value && !cfg->vht_rx_ldpc) {
1067 status = sme_cfg_set_int(hdd_ctx->hHal,
1068 WNI_CFG_VHT_LDPC_CODING_CAP,
1069 cfg->vht_rx_ldpc);
1070
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301071 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001072 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001073 }
1074 }
1075
1076 /* Get current GI 80 value */
1077 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1078 &value);
1079
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301080 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001081 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 value = 0;
1083 }
1084
1085 /* set the Guard interval 80MHz */
1086 if (value && !cfg->vht_short_gi_80) {
1087 status = sme_cfg_set_int(hdd_ctx->hHal,
1088 WNI_CFG_VHT_SHORT_GI_80MHZ,
1089 cfg->vht_short_gi_80);
1090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301091 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001092 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001093 }
1094 }
1095
1096 /* Get current GI 160 value */
1097 status = sme_cfg_get_int(hdd_ctx->hHal,
1098 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1099 &value);
1100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301101 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001102 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 value = 0;
1104 }
1105
1106 /* Get VHT TX STBC cap */
1107 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1108
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301109 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001110 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 value = 0;
1112 }
1113
1114 /* VHT TX STBC cap */
1115 if (value && !cfg->vht_tx_stbc) {
1116 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1117 cfg->vht_tx_stbc);
1118
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301119 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001120 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 }
1122 }
1123
1124 /* Get VHT RX STBC cap */
1125 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1126
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301127 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001128 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001129 value = 0;
1130 }
1131
1132 /* VHT RX STBC cap */
1133 if (value && !cfg->vht_rx_stbc) {
1134 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1135 cfg->vht_rx_stbc);
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 the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139 }
1140 }
1141
1142 /* Get VHT SU Beamformer cap */
1143 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1144 &value);
1145
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301146 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001147 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 value = 0;
1149 }
1150
1151 /* set VHT SU Beamformer cap */
1152 if (value && !cfg->vht_su_bformer) {
1153 status = sme_cfg_set_int(hdd_ctx->hHal,
1154 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1155 cfg->vht_su_bformer);
1156
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301157 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001158 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001159 }
1160 }
1161
1162 /* check and update SU BEAMFORMEE capabality */
1163 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1164 pconfig->enableTxBF = cfg->vht_su_bformee;
1165
1166 status = sme_cfg_set_int(hdd_ctx->hHal,
1167 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1168 pconfig->enableTxBF);
1169
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301170 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001171 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001172 }
1173
1174 /* Get VHT MU Beamformer cap */
1175 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1176 &value);
1177
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301178 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001179 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001180 value = 0;
1181 }
1182
1183 /* set VHT MU Beamformer cap */
1184 if (value && !cfg->vht_mu_bformer) {
1185 status = sme_cfg_set_int(hdd_ctx->hHal,
1186 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1187 cfg->vht_mu_bformer);
1188
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301189 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001190 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001191 }
1192 }
1193
1194 /* Get VHT MU Beamformee cap */
1195 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1196 &value);
1197
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301198 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001199 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001200 value = 0;
1201 }
1202
1203 /* set VHT MU Beamformee cap */
1204 if (value && !cfg->vht_mu_bformee) {
1205 status = sme_cfg_set_int(hdd_ctx->hHal,
1206 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1207 cfg->vht_mu_bformee);
1208
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301209 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001210 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211 }
1212 }
1213
1214 /* Get VHT MAX AMPDU Len exp */
1215 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1216 &value);
1217
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301218 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001219 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001220 value = 0;
1221 }
1222
1223 /*
1224 * VHT max AMPDU len exp:
1225 * override if user configured value is too high
1226 * that the target cannot support.
1227 * Even though Rome publish ampdu_len=7, it can
1228 * only support 4 because of some h/w bug.
1229 */
1230
1231 if (value > cfg->vht_max_ampdu_len_exp) {
1232 status = sme_cfg_set_int(hdd_ctx->hHal,
1233 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1234 cfg->vht_max_ampdu_len_exp);
1235
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301236 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001237 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 }
1239 }
1240
1241 /* Get VHT TXOP PS CAP */
1242 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1243
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301244 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001245 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 value = 0;
1247 }
1248
1249 /* set VHT TXOP PS cap */
1250 if (value && !cfg->vht_txop_ps) {
1251 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1252 cfg->vht_txop_ps);
1253
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301254 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001255 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256 }
1257 }
1258
1259 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1260 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1261 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1262 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1263 else
1264 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1265
1266
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001267 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1268 status = sme_cfg_set_int(hdd_ctx->hHal,
1269 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1270 VHT_CAP_160_AND_80P80_SUPP);
1271 if (status == QDF_STATUS_E_FAILURE)
1272 hdd_alert("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001273 band_5g->vht_cap.cap |=
1274 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001275 ch_width = eHT_CHANNEL_WIDTH_80P80MHZ;
1276 } else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1277 status = sme_cfg_set_int(hdd_ctx->hHal,
1278 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1279 VHT_CAP_160_SUPP);
1280 if (status == QDF_STATUS_E_FAILURE)
1281 hdd_alert("could not set the VHT CAP 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 band_5g->vht_cap.cap |=
1283 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Kiran Kumar Lokere4bbbd0d2017-02-07 00:06:43 -08001284 ch_width = eHT_CHANNEL_WIDTH_160MHZ;
1285 }
1286 pconfig->vhtChannelWidth = QDF_MIN(pconfig->vhtChannelWidth,
1287 ch_width);
1288 /* Get the current supported chan width */
1289 status = sme_cfg_get_int(hdd_ctx->hHal,
1290 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1291 &value);
1292 if (status != QDF_STATUS_SUCCESS) {
1293 hdd_err("could not get CH BW");
1294 value = 0;
1295 }
1296 /* set the Guard interval 80MHz */
1297 if (value) {
1298 status = sme_cfg_set_int(hdd_ctx->hHal,
1299 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1300 cfg->vht_short_gi_160);
1301
1302 if (status == QDF_STATUS_E_FAILURE)
1303 hdd_alert("failed to set SHORT GI 80MHZ");
1304 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305
1306 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1307 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1308
1309 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1310 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1311 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1312 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1313
1314 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1315 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1316
1317 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1318 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1319 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1320 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1321 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1322 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1323
1324 band_5g->vht_cap.cap |=
1325 (cfg->vht_max_ampdu_len_exp <<
1326 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1327
1328 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1329 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1330 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1331 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1332 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1333 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1334 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1335 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1336
1337 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1338 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1339
1340}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001342/**
1343 * hdd_generate_macaddr_auto() - Auto-generate mac address
1344 * @hdd_ctx: Pointer to the HDD context
1345 *
1346 * Auto-generate mac address using device serial number.
1347 * Keep the first 3 bytes of OUI as before and replace
1348 * the last 3 bytes with the lower 3 bytes of serial number.
1349 *
1350 * Return: 0 for success
1351 * Non zero failure code for errors
1352 */
1353static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1354{
1355 unsigned int serialno = 0;
1356 struct qdf_mac_addr mac_addr = {
1357 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1358 };
1359
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001360 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001361 if (serialno == 0)
1362 return -EINVAL;
1363
1364 serialno &= 0x00ffffff;
1365
1366 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1367 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1368 mac_addr.bytes[5] = serialno & 0xff;
1369
1370 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1371 return 0;
1372}
1373
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301374/**
1375 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1376 * configuration to cfg_ini in HDD
1377 * @hdd_ctx: Pointer to hdd_ctx
1378 * @cfg: target configuration
1379 *
1380 * Return: None
1381 */
1382#ifdef FEATURE_WLAN_RA_FILTERING
1383static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1384 struct wma_tgt_cfg *cfg)
1385{
1386 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1387}
1388#else
1389static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1390 struct wma_tgt_cfg *cfg)
1391{
1392}
1393#endif
1394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395void hdd_update_tgt_cfg(void *context, void *param)
1396{
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001397 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1399 struct wma_tgt_cfg *cfg = param;
1400 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001401 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301402
Dustin Brown7d043f62017-03-27 12:07:36 -07001403 ret = hdd_objmgr_create_and_store_pdev(hdd_ctx);
Rajeev Kumarf49dfdb2017-01-13 15:40:35 -08001404 if (ret) {
1405 hdd_err("pdev creation fails!");
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301406 QDF_BUG(0);
1407 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001408
1409 if (cds_cfg) {
1410 if (hdd_ctx->config->enable_sub_20_channel_width !=
1411 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1412 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1413 cds_cfg->sub_20_channel_width =
1414 WLAN_SUB_20_CH_WIDTH_NONE;
1415 } else {
1416 cds_cfg->sub_20_channel_width =
1417 hdd_ctx->config->enable_sub_20_channel_width;
1418 }
1419 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001420
1421 /* first store the INI band capability */
1422 temp_band_cap = hdd_ctx->config->nBandCapability;
1423
1424 hdd_ctx->config->nBandCapability = cfg->band_cap;
1425
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001426 /*
1427 * now overwrite the target band capability with INI
1428 * setting if INI setting is a subset
1429 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430
1431 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1432 (temp_band_cap != eCSR_BAND_ALL))
1433 hdd_ctx->config->nBandCapability = temp_band_cap;
1434 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1435 (temp_band_cap != eCSR_BAND_ALL) &&
1436 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001437 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438 }
1439
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001440 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1442 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1443 }
1444
1445 /* This can be extended to other configurations like ht, vht cap... */
1446
Anurag Chouhanc5548422016-02-24 18:33:27 +05301447 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001449 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001451 static struct qdf_mac_addr default_mac_addr = {
1452 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1453 };
1454 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1455 &default_mac_addr)) {
1456 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1457 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1458 MAC_ADDRESS_STR,
1459 MAC_ADDR_ARRAY(hdd_ctx->config->
1460 intfMacAddr[0].bytes));
1461 } else {
1462 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1463 MAC_ADDRESS_STR,
1464 MAC_ADDR_ARRAY(hdd_ctx->config->
1465 intfMacAddr[0].bytes));
1466 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001467 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 }
1469
1470 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001471 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472
1473 hdd_ctx->max_intf_count = cfg->max_intf_count;
1474
Jeff Johnsonc875e242016-09-23 18:12:34 -07001475 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001476 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001477
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1479 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1480
1481 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1482
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajaned1efd92016-09-24 18:05:47 -07001484 if (cfg->services.en_11ax) {
1485 hdd_info("11AX: 11ax is enabled - update HDD config");
1486 hdd_update_tgt_he_cap(hdd_ctx, cfg);
1487 }
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001488
1489 hdd_update_vdev_nss(hdd_ctx);
1490
Nitesh Shahdb5ea0d2017-03-22 15:17:47 +05301491 hdd_update_hw_dbs_capable(hdd_ctx);
1492
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001493 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001494 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001495 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001496 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001497
1498 hdd_ctx->current_antenna_mode =
1499 (hdd_ctx->config->enable2x2 == 0x01) ?
1500 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1501 hdd_info("Init current antenna mode: %d",
1502 hdd_ctx->current_antenna_mode);
1503
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001504 hdd_info("Target BPF %d Host BPF %d",
1505 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1506 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1507 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301508 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301509
Arun Khandavallid454d422016-08-17 12:47:05 +05301510 /*
1511 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1512 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1513 * configure the STA mode wow pattern.
1514 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301515 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301516 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301517
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301518 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1519
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001520 /* Configure NAN datapath features */
1521 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Arif Hussain759a0232017-03-20 13:17:18 -07001522 hdd_ctx->dfs_cac_offload = cfg->dfs_cac_offload;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523}
1524
1525/**
1526 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1527 * @context: HDD context pointer
1528 * @param: HDD radar indication pointer
1529 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001530 * This function is invoked in atomic context when a radar
1531 * is found on the SAP current operating channel and Data Tx
1532 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 * Actions: Stop the netif Tx queues,Indicate Radar present
1534 * in HDD context for future usage.
1535 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301536 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301538bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539{
1540 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1541 struct wma_dfs_radar_ind *hdd_radar_event =
1542 (struct wma_dfs_radar_ind *)param;
1543 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1544 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301545 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301546 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301548 if (!hdd_ctx || !hdd_radar_event ||
1549 hdd_ctx->config->disableDFSChSwitch)
1550 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551
1552 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001553 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301554 /*
1555 * Application already triggered channel switch
1556 * on current channel, so return here.
1557 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301558 return false;
1559 }
1560
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301562 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301564 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1565 if ((QDF_SAP_MODE == adapter->device_mode ||
1566 QDF_P2P_GO_MODE == adapter->device_mode) &&
1567 (CHANNEL_STATE_DFS ==
1568 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001569 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1570 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301571 hdd_info("tx blocked for session:%d",
1572 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 }
1574
1575 status = hdd_get_next_adapter(hdd_ctx,
1576 adapterNode,
1577 &pNext);
1578 adapterNode = pNext;
1579 }
1580 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301581
1582 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584
1585/**
1586 * hdd_is_valid_mac_address() - validate MAC address
1587 * @pMacAddr: Pointer to the input MAC address
1588 *
1589 * This function validates whether the given MAC address is valid or not
1590 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1591 * where X is the hexa decimal digit character and separated by ':'
1592 * This algorithm works even if MAC address is not separated by ':'
1593 *
1594 * This code checks given input string mac contains exactly 12 hexadecimal
1595 * digits and a separator colon : appears in the input string only after
1596 * an even number of hex digits.
1597 *
1598 * Return: 1 for valid and 0 for invalid
1599 */
1600bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1601{
1602 int xdigit = 0;
1603 int separator = 0;
1604 while (*pMacAddr) {
1605 if (isxdigit(*pMacAddr)) {
1606 xdigit++;
1607 } else if (':' == *pMacAddr) {
1608 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1609 break;
1610
1611 ++separator;
1612 } else {
1613 /* Invalid MAC found */
1614 return 0;
1615 }
1616 ++pMacAddr;
1617 }
1618 return xdigit == 12 && (separator == 5 || separator == 0);
1619}
1620
1621/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301622 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1623 * @dev: Handle to struct net_device to be updated.
1624 *
1625 * Return: None
1626 */
1627static void hdd_mon_mode_ether_setup(struct net_device *dev)
1628{
1629 dev->header_ops = NULL;
1630 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1631 dev->hard_header_len = ETH_HLEN;
1632 dev->mtu = ETH_DATA_LEN;
1633 dev->addr_len = ETH_ALEN;
1634 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1635 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1636 dev->priv_flags |= IFF_TX_SKB_SHARING;
1637
1638 memset(dev->broadcast, 0xFF, ETH_ALEN);
1639}
1640
1641/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001642 * __hdd__mon_open() - HDD Open function
1643 * @dev: Pointer to net_device structure
1644 *
1645 * This is called in response to ifconfig up
1646 *
1647 * Return: 0 for success; non-zero for failure
1648 */
1649static int __hdd_mon_open(struct net_device *dev)
1650{
1651 int ret;
1652
1653 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301654 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001655 ret = hdd_set_mon_rx_cb(dev);
1656 return ret;
1657}
1658
1659/**
1660 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1661 * @dev: Pointer to net_device structure
1662 *
1663 * This is called in response to ifconfig up
1664 *
1665 * Return: 0 for success; non-zero for failure
1666 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001667static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001668{
1669 int ret;
1670
1671 cds_ssr_protect(__func__);
1672 ret = __hdd_mon_open(dev);
1673 cds_ssr_unprotect(__func__);
1674
1675 return ret;
1676}
1677
1678/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301679 * hdd_start_adapter() - Wrapper function for device specific adapter
1680 * @adapter: pointer to HDD adapter
1681 *
1682 * This function is called to start the device specific adapter for
1683 * the mode passed in the adapter's device_mode.
1684 *
1685 * Return: 0 for success; non-zero for failure
1686 */
1687int hdd_start_adapter(hdd_adapter_t *adapter)
1688{
1689
1690 int ret;
1691 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1692
1693 ENTER_DEV(adapter->dev);
1694 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1695
1696 switch (device_mode) {
1697 case QDF_P2P_CLIENT_MODE:
1698 case QDF_P2P_DEVICE_MODE:
1699 case QDF_OCB_MODE:
1700 case QDF_STA_MODE:
1701 case QDF_MONITOR_MODE:
1702 ret = hdd_start_station_adapter(adapter);
1703 if (ret)
1704 goto err_start_adapter;
1705 break;
1706 case QDF_P2P_GO_MODE:
1707 case QDF_SAP_MODE:
1708 ret = hdd_start_ap_adapter(adapter);
1709 if (ret)
1710 goto err_start_adapter;
1711 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301712 case QDF_IBSS_MODE:
1713 /*
1714 * For IBSS interface is initialized as part of
1715 * hdd_init_station_mode()
1716 */
1717 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301718 case QDF_FTM_MODE:
1719 ret = hdd_start_ftm_adapter(adapter);
1720 if (ret)
1721 goto err_start_adapter;
1722 break;
1723 default:
1724 hdd_err("Invalid session type %d", device_mode);
1725 QDF_ASSERT(0);
1726 goto err_start_adapter;
1727 }
1728 if (hdd_set_fw_params(adapter))
1729 hdd_err("Failed to set the FW params for the adapter!");
1730
1731 /*
1732 * Action frame registered in one adapter which will
1733 * applicable to all interfaces
1734 */
1735 wlan_hdd_cfg80211_register_frames(adapter);
1736 EXIT();
1737 return 0;
1738err_start_adapter:
1739 return -EINVAL;
1740}
1741
1742/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301743 * hdd_enable_power_management() - API to Enable Power Management
1744 *
1745 * API invokes Bus Interface Layer power management functionality
1746 *
1747 * Return: None
1748 */
1749static void hdd_enable_power_management(void)
1750{
1751 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1752
1753 if (!hif_ctx) {
1754 hdd_err("Bus Interface Context is Invalid");
1755 return;
1756 }
1757
1758 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1759}
1760
1761/**
1762 * hdd_disable_power_management() - API to disable Power Management
1763 *
1764 * API disable Bus Interface Layer Power management functionality
1765 *
1766 * Return: None
1767 */
1768static void hdd_disable_power_management(void)
1769{
1770 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1771
1772 if (!hif_ctx) {
1773 hdd_err("Bus Interface Context is Invalid");
1774 return;
1775 }
1776
1777 hif_disable_power_management(hif_ctx);
1778}
1779
1780/**
Arunk Khandavalli67193d52017-02-21 12:03:48 +05301781 * hdd_update_hw_sw_info() - API to update the HW/SW information
1782 *
1783 * API to update the HW and SW information in the driver
1784 *
1785 * Return: None
1786 */
1787static void hdd_update_hw_sw_info(hdd_context_t *hdd_ctx)
1788{
1789 void *hif_sc;
1790
1791 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
1792 if (!hif_sc) {
1793 hdd_err("HIF context is NULL");
1794 return;
1795 }
1796
1797 /*
1798 * target hw version/revision would only be retrieved after firmware
1799 * download
1800 */
1801 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
1802 &hdd_ctx->target_hw_revision,
1803 &hdd_ctx->target_hw_name);
1804
1805 /* Get the wlan hw/fw version */
1806 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
1807
1808 return;
1809}
1810
1811/**
gbian62edd7e2017-03-07 13:12:13 +08001812 * hdd_update_cds_ac_specs_params() - update cds ac_specs params
1813 * @hdd_ctx: Pointer to hdd context
1814 *
1815 * Return: none
1816 */
1817static void
1818hdd_update_cds_ac_specs_params(hdd_context_t *hdd_ctx)
1819{
1820 uint8_t num_entries = 0;
1821 uint8_t tx_sched_wrr_param[TX_SCHED_WRR_PARAMS_NUM];
1822 uint8_t *tx_sched_wrr_ac;
1823 int i;
1824 cds_context_type *cds_ctx;
1825
1826 if (NULL == hdd_ctx)
1827 return;
1828
1829 if (NULL == hdd_ctx->config) {
1830 /* Do nothing if hdd_ctx is invalid */
1831 hdd_err("%s: Warning: hdd_ctx->cfg_ini is NULL", __func__);
1832 return;
1833 }
1834
1835 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1836
1837 if (!cds_ctx) {
1838 hdd_err("Invalid CDS Context");
1839 return;
1840 }
1841
1842 for (i = 0; i < OL_TX_NUM_WMM_AC; i++) {
1843 switch (i) {
1844 case OL_TX_WMM_AC_BE:
1845 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_be;
1846 break;
1847 case OL_TX_WMM_AC_BK:
1848 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_bk;
1849 break;
1850 case OL_TX_WMM_AC_VI:
1851 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vi;
1852 break;
1853 case OL_TX_WMM_AC_VO:
1854 tx_sched_wrr_ac = hdd_ctx->config->tx_sched_wrr_vo;
1855 break;
1856 default:
1857 tx_sched_wrr_ac = NULL;
1858 break;
1859 }
1860
1861 hdd_string_to_u8_array(tx_sched_wrr_ac,
1862 tx_sched_wrr_param,
1863 &num_entries,
1864 sizeof(tx_sched_wrr_param));
1865
1866 if (num_entries == TX_SCHED_WRR_PARAMS_NUM) {
1867 cds_ctx->ac_specs[i].wrr_skip_weight =
1868 tx_sched_wrr_param[0];
1869 cds_ctx->ac_specs[i].credit_threshold =
1870 tx_sched_wrr_param[1];
1871 cds_ctx->ac_specs[i].send_limit =
1872 tx_sched_wrr_param[2];
1873 cds_ctx->ac_specs[i].credit_reserve =
1874 tx_sched_wrr_param[3];
1875 cds_ctx->ac_specs[i].discard_weight =
1876 tx_sched_wrr_param[4];
1877 }
1878
1879 num_entries = 0;
1880 }
1881}
1882
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001883#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001884static enum policy_mgr_con_mode wlan_hdd_get_mode_for_non_connected_vdev(
1885 struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
1886{
1887 hdd_adapter_t *adapter = NULL;
1888 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1889
1890 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
1891 if (!adapter) {
1892 hdd_err("Adapter is NULL");
1893 return PM_MAX_NUM_OF_MODE;
1894 }
1895
1896 return policy_mgr_convert_device_mode_to_qdf_type(
1897 adapter->device_mode);
1898}
1899
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001900static void hdd_register_policy_manager_callback(
1901 struct wlan_objmgr_psoc *psoc)
1902{
1903 struct policy_mgr_hdd_cbacks hdd_cbacks;
1904 hdd_cbacks.sap_restart_chan_switch_cb =
1905 sap_restart_chan_switch_cb;
1906 hdd_cbacks.wlan_hdd_get_channel_for_sap_restart =
1907 wlan_hdd_get_channel_for_sap_restart;
Tushnim Bhattacharyya9fb2e422017-03-23 09:49:10 -07001908 hdd_cbacks.get_mode_for_non_connected_vdev =
1909 wlan_hdd_get_mode_for_non_connected_vdev;
1910
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07001911 if (QDF_STATUS_SUCCESS !=
1912 policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {
1913 hdd_err("HDD callback registration with policy manager failed");
1914 }
1915}
1916#else
1917static void hdd_register_policy_manager_callback(
1918 struct wlan_objmgr_psoc *psoc)
1919{
1920}
1921#endif
1922
gbian62edd7e2017-03-07 13:12:13 +08001923/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301924 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1925 * @hdd_ctx: HDD context
1926 * @adapter: HDD adapter
1927 * @reinit: flag to indicate from SSR or normal path
1928 *
1929 * This function maintains the driver state machine it will be invoked from
1930 * startup, reinit and change interface. Depending on the driver state shall
1931 * perform the opening of the modules.
1932 *
1933 * Return: 0 for success; non-zero for failure
1934 */
1935int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1936 bool reinit)
1937{
1938 int ret;
1939 qdf_device_t qdf_dev;
1940 QDF_STATUS status;
1941 p_cds_contextType p_cds_context;
1942 bool unint = false;
1943 void *hif_ctx;
1944
1945 ENTER();
1946
1947 p_cds_context = cds_get_global_context();
1948 if (!p_cds_context) {
1949 hdd_err("Global Context is NULL");
1950 QDF_ASSERT(0);
1951 return -EINVAL;
1952 }
1953
1954 hdd_info("start modules called in state! :%d reinit: %d",
1955 hdd_ctx->driver_status, reinit);
1956
1957 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1958 if (!qdf_dev) {
1959 hdd_err("QDF Device Context is Invalid return");
1960 return -EINVAL;
1961 }
1962
1963 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301964 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301965
1966 if (QDF_TIMER_STATE_RUNNING ==
1967 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1968
1969 hdd_set_idle_ps_config(hdd_ctx, false);
1970 hdd_info("Interface change Timer running Stop timer");
1971 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1972 }
1973
1974 switch (hdd_ctx->driver_status) {
1975 case DRIVER_MODULES_UNINITIALIZED:
1976 unint = true;
1977 /* Fall through dont add break here */
1978 case DRIVER_MODULES_CLOSED:
1979 if (!reinit && !unint) {
1980 ret = pld_power_on(qdf_dev->dev);
1981 if (ret) {
1982 hdd_err("Failed to Powerup the device: %d", ret);
1983 goto release_lock;
1984 }
1985 }
1986 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1987 qdf_dev->bus_type,
1988 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1989 HIF_ENABLE_TYPE_PROBE);
1990 if (ret) {
1991 hdd_err("Failed to open hif: %d", ret);
1992 goto power_down;
1993 }
1994
1995 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301996 if (!hif_ctx) {
1997 hdd_err("hif context is null!!");
1998 goto power_down;
1999 }
2000
Arun Khandavallifae92942016-08-01 13:31:08 +05302001 status = ol_cds_init(qdf_dev, hif_ctx);
2002 if (status != QDF_STATUS_SUCCESS) {
2003 hdd_err("No Memory to Create BMI Context :%d", status);
2004 goto hif_close;
2005 }
2006
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002007 ret = hdd_update_config(hdd_ctx);
2008 if (ret) {
2009 hdd_err("Failed to update configuration :%d", ret);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302010 goto ol_cds_free;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08002011 }
2012
gbian62edd7e2017-03-07 13:12:13 +08002013 hdd_update_cds_ac_specs_params(hdd_ctx);
2014
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302015 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05302016 if (!QDF_IS_STATUS_SUCCESS(status)) {
2017 hdd_err("Failed to Open CDS: %d", status);
Abhishek Singhe9068f12017-03-31 14:14:52 +05302018 goto ol_cds_free;
Arun Khandavallifae92942016-08-01 13:31:08 +05302019 }
2020
Mukul Sharma9d797a02017-01-05 20:26:03 +05302021 /* initalize components configurations after psoc open */
2022 ret = hdd_update_components_config(hdd_ctx);
2023 if (ret) {
2024 hdd_err("Failed to update components configs :%d",
2025 ret);
2026 goto close;
2027 }
2028
Arun Khandavallifae92942016-08-01 13:31:08 +05302029 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
2030
2031 status = cds_pre_enable(hdd_ctx->pcds_context);
2032 if (!QDF_IS_STATUS_SUCCESS(status)) {
2033 hdd_err("Failed to pre-enable CDS: %d", status);
2034 goto close;
2035 }
2036
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07002037 hdd_register_policy_manager_callback(
2038 hdd_ctx->hdd_psoc);
2039
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302040 hdd_update_hw_sw_info(hdd_ctx);
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05302041 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
Arunk Khandavalli67193d52017-02-21 12:03:48 +05302042
Arun Khandavallifae92942016-08-01 13:31:08 +05302043 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2044 sme_register_ftm_msg_processor(hdd_ctx->hHal,
2045 hdd_ftm_mc_process_msg);
2046 break;
2047 }
2048 if (unint) {
2049 hdd_info("In phase-1 initialization don't enable modules");
2050 break;
2051 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302052
2053 if (reinit) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08002054 if (hdd_ipa_uc_ssr_reinit(hdd_ctx)) {
2055 hdd_err("HDD IPA UC reinit failed");
2056 goto close;
2057 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05302058 }
2059
Arun Khandavallifae92942016-08-01 13:31:08 +05302060 /* Fall through dont add break here */
2061 case DRIVER_MODULES_OPENED:
2062 if (!adapter) {
2063 hdd_alert("adapter is Null");
2064 goto close;
2065 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05302066 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2067 hdd_err("in ftm mode, no need to configure cds modules");
2068 break;
2069 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302070 if (hdd_configure_cds(hdd_ctx, adapter)) {
2071 hdd_err("Failed to Enable cds modules");
2072 goto close;
2073 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05302074 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05302075 hdd_info("Driver Modules Successfully Enabled");
2076 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
2077 break;
2078 case DRIVER_MODULES_ENABLED:
2079 hdd_info("Driver modules already Enabled");
2080 break;
2081 default:
2082 hdd_err("WLAN start invoked in wrong state! :%d\n",
2083 hdd_ctx->driver_status);
2084 goto release_lock;
2085 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302086 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302087 mutex_unlock(&hdd_ctx->iface_change_lock);
2088 EXIT();
2089 return 0;
2090
2091close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302092 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05302093
2094ol_cds_free:
2095 ol_cds_free();
2096
2097hif_close:
2098 hdd_hif_close(p_cds_context->pHIFContext);
2099power_down:
2100 if (!reinit && !unint)
2101 pld_power_off(qdf_dev->dev);
2102release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302103 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05302104 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05302105 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05302106 return -EINVAL;
2107}
2108
Naveen Rawat910726a2017-03-06 11:42:51 -08002109#ifdef WIFI_POS_CONVERGED
2110static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2111{
2112 int ret = os_if_wifi_pos_register_nl();
2113
2114 if (ret)
2115 hdd_err("os_if_wifi_pos_register_nl failed");
2116
2117 return ret;
2118}
2119
2120static int hdd_deactivate_wifi_pos(void)
2121{
2122 int ret = os_if_wifi_pos_deregister_nl();
2123
2124 if (ret)
2125 hdd_err("os_if_wifi_pos_deregister_nl failed");
2126
2127 return ret;
2128}
2129
2130/**
2131 * hdd_populate_wifi_pos_cfg - populates wifi_pos parameters
2132 * @hdd_ctx: hdd context
2133 *
2134 * Return: status of operation
2135 */
2136static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2137{
2138 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2139 struct hdd_config *cfg = hdd_ctx->config;
2140
2141 wifi_pos_set_oem_target_type(psoc, hdd_ctx->target_type);
2142 wifi_pos_set_oem_fw_version(psoc, hdd_ctx->target_fw_version);
2143 wifi_pos_set_drv_ver_major(psoc, QWLAN_VERSION_MAJOR);
2144 wifi_pos_set_drv_ver_minor(psoc, QWLAN_VERSION_MINOR);
2145 wifi_pos_set_drv_ver_patch(psoc, QWLAN_VERSION_PATCH);
2146 wifi_pos_set_drv_ver_build(psoc, QWLAN_VERSION_BUILD);
2147 wifi_pos_set_dwell_time_min(psoc, cfg->nNeighborScanMinChanTime);
2148 wifi_pos_set_dwell_time_max(psoc, cfg->nNeighborScanMaxChanTime);
2149}
2150#else
2151static int hdd_activate_wifi_pos(hdd_context_t *hdd_ctx)
2152{
2153 return oem_activate_service(hdd_ctx);
2154}
2155
2156static int hdd_deactivate_wifi_pos(void)
2157{
2158 return 0;
2159}
2160
2161static void hdd_populate_wifi_pos_cfg(hdd_context_t *hdd_ctx)
2162{
2163}
2164#endif
2165
Arun Khandavallifae92942016-08-01 13:31:08 +05302166/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167 * __hdd_open() - HDD Open function
2168 * @dev: Pointer to net_device structure
2169 *
2170 * This is called in response to ifconfig up
2171 *
2172 * Return: 0 for success; non-zero for failure
2173 */
2174static int __hdd_open(struct net_device *dev)
2175{
2176 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2177 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2178 int ret;
2179
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002180 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302181 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05302182 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183
2184 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302185 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302187
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188
Arun Khandavallifae92942016-08-01 13:31:08 +05302189 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
2190 if (ret) {
2191 hdd_err("Failed to start WLAN modules return");
2192 return -ret;
2193 }
2194
2195
2196 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2197 ret = hdd_start_adapter(adapter);
2198 if (ret) {
2199 hdd_err("Failed to start adapter :%d",
2200 adapter->device_mode);
2201 return ret;
2202 }
2203 }
2204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002205 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2206 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302207 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 /* Enable TX queues only when we are connected */
2209 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05302210 WLAN_START_ALL_NETIF_QUEUE,
2211 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 }
2213
Naveen Rawat286def52016-09-23 15:38:02 -07002214 /* Enable carrier and transmit queues for NDI */
2215 if (WLAN_HDD_IS_NDI(adapter)) {
2216 hdd_notice("Enabling Tx Queues");
2217 wlan_hdd_netif_queue_control(adapter,
2218 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
2219 WLAN_CONTROL_PATH);
2220 }
2221
Naveen Rawat910726a2017-03-06 11:42:51 -08002222 hdd_populate_wifi_pos_cfg(hdd_ctx);
2223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224 return ret;
2225}
2226
Arun Khandavallifae92942016-08-01 13:31:08 +05302227
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228/**
2229 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
2230 * @dev: Pointer to net_device structure
2231 *
2232 * This is called in response to ifconfig up
2233 *
2234 * Return: 0 for success; non-zero for failure
2235 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002236static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237{
2238 int ret;
2239
2240 cds_ssr_protect(__func__);
2241 ret = __hdd_open(dev);
2242 cds_ssr_unprotect(__func__);
2243
2244 return ret;
2245}
2246
2247/**
2248 * __hdd_stop() - HDD stop function
2249 * @dev: Pointer to net_device structure
2250 *
2251 * This is called in response to ifconfig down
2252 *
2253 * Return: 0 for success; non-zero for failure
2254 */
2255static int __hdd_stop(struct net_device *dev)
2256{
2257 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2258 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2259 int ret;
2260
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002261 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302263 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264 adapter->sessionId, adapter->device_mode));
2265
2266 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302267 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002268 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269
2270 /* Nothing to be done if the interface is not opened */
2271 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002272 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002273 return -ENODEV;
2274 }
2275
2276 /* Make sure the interface is marked as closed */
2277 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002278 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279
2280 /*
2281 * Disable TX on the interface, after this hard_start_xmit() will not
2282 * be called on that interface
2283 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002284 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002285 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2286 WLAN_CONTROL_PATH);
2287
2288 /*
Naveen Rawat286def52016-09-23 15:38:02 -07002289 * NAN data interface is different in some sense. The traffic on NDI is
2290 * bursty in nature and depends on the need to transfer. The service
2291 * layer may down the interface after the usage and up again when
2292 * required. In some sense, the NDI is expected to be available
2293 * (like SAP) iface until NDI delete request is issued by the service
2294 * layer. Skip BSS termination and adapter deletion for NAN Data
2295 * interface (NDI).
2296 */
2297 if (WLAN_HDD_IS_NDI(adapter))
2298 return 0;
2299
2300 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 * The interface is marked as down for outside world (aka kernel)
2302 * But the driver is pretty much alive inside. The driver needs to
2303 * tear down the existing connection on the netdev (session)
2304 * cleanup the data pipes and wait until the control plane is stabilized
2305 * for this interface. The call also needs to wait until the above
2306 * mentioned actions are completed before returning to the caller.
2307 * Notice that the hdd_stop_adapter is requested not to close the session
2308 * That is intentional to be able to scan if it is a STA/P2P interface
2309 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302310 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311
2312 /* DeInit the adapter. This ensures datapath cleanup as well */
2313 hdd_deinit_adapter(hdd_ctx, adapter, true);
2314
Arun Khandavallifae92942016-08-01 13:31:08 +05302315
2316 /*
2317 * Find if any iface is up. If any iface is up then can't put device to
2318 * sleep/power save mode
2319 */
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05302320 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Arun Khandavallifae92942016-08-01 13:31:08 +05302321 hdd_info("Closing all modules from the hdd_stop");
2322 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2323 hdd_ctx->config->iface_change_wait_time
2324 * 50000);
2325 }
2326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 EXIT();
2328 return 0;
2329}
2330
2331/**
2332 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2333 * @dev: pointer to net_device structure
2334 *
2335 * This is called in response to ifconfig down
2336 *
2337 * Return: 0 for success and error number for failure
2338 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002339static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002340{
2341 int ret;
2342
2343 cds_ssr_protect(__func__);
2344 ret = __hdd_stop(dev);
2345 cds_ssr_unprotect(__func__);
2346
2347 return ret;
2348}
2349
2350/**
2351 * __hdd_uninit() - HDD uninit function
2352 * @dev: Pointer to net_device structure
2353 *
2354 * This is called during the netdev unregister to uninitialize all data
2355 * associated with the device
2356 *
2357 * Return: None
2358 */
2359static void __hdd_uninit(struct net_device *dev)
2360{
2361 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2362
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002363 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364
2365 do {
2366 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002367 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 break;
2369 }
2370
2371 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002372 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 break;
2374 }
2375
2376 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002377 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 /*
2379 * we haven't validated all cases so let this go for
2380 * now
2381 */
2382 }
2383
2384 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2385
2386 /* after uninit our adapter structure will no longer be valid */
2387 adapter->dev = NULL;
2388 adapter->magic = 0;
2389 } while (0);
2390
2391 EXIT();
2392}
2393
2394/**
2395 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2396 * @dev: pointer to net_device structure
2397 *
2398 * This is called during the netdev unregister to uninitialize all data
2399 * associated with the device
2400 *
2401 * Return: none
2402 */
2403static void hdd_uninit(struct net_device *dev)
2404{
2405 cds_ssr_protect(__func__);
2406 __hdd_uninit(dev);
2407 cds_ssr_unprotect(__func__);
2408}
2409
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002410static int hdd_open_cesium_nl_sock(void)
2411{
2412#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2413 struct netlink_kernel_cfg cfg = {
2414 .groups = WLAN_NLINK_MCAST_GRP_ID,
2415 .input = NULL
2416 };
2417#endif
2418 int ret = 0;
2419
2420#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2421 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2422#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2423 THIS_MODULE,
2424#endif
2425 &cfg);
2426#else
2427 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2428 WLAN_NLINK_MCAST_GRP_ID,
2429 NULL, NULL, THIS_MODULE);
2430#endif
2431
2432 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002433 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002434 ret = -ECONNREFUSED;
2435 }
2436
2437 return ret;
2438}
2439
2440static void hdd_close_cesium_nl_sock(void)
2441{
2442 if (NULL != cesium_nl_srv_sock) {
2443 netlink_kernel_release(cesium_nl_srv_sock);
2444 cesium_nl_srv_sock = NULL;
2445 }
2446}
2447
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448/**
2449 * __hdd_set_mac_address() - set the user specified mac address
2450 * @dev: Pointer to the net device.
2451 * @addr: Pointer to the sockaddr.
2452 *
2453 * This function sets the user specified mac address using
2454 * the command ifconfig wlanX hw ether <mac adress>.
2455 *
2456 * Return: 0 for success, non zero for failure
2457 */
2458static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2459{
2460 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2461 hdd_context_t *hdd_ctx;
2462 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302463 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 int ret;
2465
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002466 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467
2468 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2469 ret = wlan_hdd_validate_context(hdd_ctx);
2470 if (0 != ret)
2471 return ret;
2472
2473 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2474 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2475
2476 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302477 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478}
2479
2480/**
2481 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2482 * function from SSR
2483 * @dev: pointer to net_device structure
2484 * @addr: Pointer to the sockaddr
2485 *
2486 * This function sets the user specified mac address using
2487 * the command ifconfig wlanX hw ether <mac adress>.
2488 *
2489 * Return: 0 for success.
2490 */
2491static int hdd_set_mac_address(struct net_device *dev, void *addr)
2492{
2493 int ret;
2494
2495 cds_ssr_protect(__func__);
2496 ret = __hdd_set_mac_address(dev, addr);
2497 cds_ssr_unprotect(__func__);
2498
2499 return ret;
2500}
2501
2502uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2503{
2504 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302505 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2507 break;
2508 }
2509
Anurag Chouhan6d760662016-02-20 16:05:43 +05302510 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511 return NULL;
2512
2513 hdd_ctx->config->intfAddrMask |= (1 << i);
2514 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2515}
2516
2517void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2518{
2519 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302520 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 if (!memcmp(releaseAddr,
2522 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2523 6)) {
2524 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2525 break;
2526 }
2527 }
2528 return;
2529}
2530
2531#ifdef WLAN_FEATURE_PACKET_FILTERING
2532/**
2533 * __hdd_set_multicast_list() - set the multicast address list
2534 * @dev: Pointer to the WLAN device.
2535 * @skb: Pointer to OS packet (sk_buff).
2536 *
2537 * This funciton sets the multicast address list.
2538 *
2539 * Return: None
2540 */
2541static void __hdd_set_multicast_list(struct net_device *dev)
2542{
2543 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 int i = 0, status;
2545 struct netdev_hw_addr *ha;
2546 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302547 struct pmo_mc_addr_list_params *mc_list_request = NULL;
2548 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
2549 int mc_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002551 ENTER_DEV(dev);
Anurag Chouhan6d760662016-02-20 16:05:43 +05302552 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302553 goto out;
Mukul Sharma51c44942015-10-30 19:30:19 +05302554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302556 if (0 != status)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302557 goto out;
2558
2559 mc_list_request = qdf_mem_malloc(sizeof(*mc_list_request));
2560 if (!mc_list_request) {
2561 hdd_notice("Cannot allocate mc_list_request");
2562 goto out;
2563 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564
2565 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002566 hdd_notice("allow all multicast frames");
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302567 hdd_disable_and_flush_mc_addr_list(adapter,
2568 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 } else {
2570 mc_count = netdev_mc_count(dev);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302571 if (mc_count > pmo_ucfg_max_mc_addr_supported(psoc)) {
Dustin Brown61269462016-09-19 13:25:45 -07002572 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302573 pmo_ucfg_max_mc_addr_supported(psoc));
2574 hdd_disable_and_flush_mc_addr_list(adapter,
2575 pmo_mc_list_change_notify);
2576 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302579 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2580 i, MAC_ADDR_ARRAY(ha->addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 if (i == mc_count)
2582 break;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302583 memset(&(mc_list_request->mc_addr[i].bytes),
2584 0, ETH_ALEN);
2585 memcpy(&(mc_list_request->mc_addr[i].bytes),
2586 ha->addr, ETH_ALEN);
2587 hdd_info("mlist[%d] = %pM", i,
2588 mc_list_request->mc_addr[i].bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 i++;
2590 }
2591 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302592
2593 mc_list_request->psoc = psoc;
2594 mc_list_request->vdev_id = adapter->sessionId;
2595 mc_list_request->count = mc_count;
2596 status = hdd_cache_mc_addr_list(mc_list_request);
2597 if (status == 0) {
2598 hdd_enable_mc_addr_filtering(adapter,
2599 pmo_mc_list_change_notify);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 } else {
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302601 hdd_err("error while caching mc list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 }
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302603out:
2604 if (mc_list_request)
2605 qdf_mem_free(mc_list_request);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302606 EXIT();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302607
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002608}
2609
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05302610
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611/**
2612 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2613 * @dev: pointer to net_device
2614 *
2615 * Return: none
2616 */
2617static void hdd_set_multicast_list(struct net_device *dev)
2618{
2619 cds_ssr_protect(__func__);
2620 __hdd_set_multicast_list(dev);
2621 cds_ssr_unprotect(__func__);
2622}
2623#endif
2624
2625/**
2626 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2627 * @dev: Pointer to the WLAN device.
2628 * @skb: Pointer to OS packet (sk_buff).
2629 *
2630 * This function is registered with the Linux OS for network
2631 * core to decide which queue to use first.
2632 *
2633 * Return: ac, Queue Index/access category corresponding to UP in IP header
2634 */
2635static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2636#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2637 , void *accel_priv
2638#endif
2639#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2640 , select_queue_fallback_t fallback
2641#endif
2642)
2643{
2644 return hdd_wmm_select_queue(dev, skb);
2645}
2646
2647static struct net_device_ops wlan_drv_ops = {
2648 .ndo_open = hdd_open,
2649 .ndo_stop = hdd_stop,
2650 .ndo_uninit = hdd_uninit,
2651 .ndo_start_xmit = hdd_hard_start_xmit,
2652 .ndo_tx_timeout = hdd_tx_timeout,
2653 .ndo_get_stats = hdd_get_stats,
2654 .ndo_do_ioctl = hdd_ioctl,
2655 .ndo_set_mac_address = hdd_set_mac_address,
2656 .ndo_select_queue = hdd_select_queue,
2657#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002659#endif
2660};
2661
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002662/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2663static struct net_device_ops wlan_mon_drv_ops = {
2664 .ndo_open = hdd_mon_open,
2665 .ndo_stop = hdd_stop,
2666 .ndo_get_stats = hdd_get_stats,
2667};
2668
2669/**
2670 * hdd_set_station_ops() - update net_device ops for monitor mode
2671 * @pWlanDev: Handle to struct net_device to be updated.
2672 * Return: None
2673 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674void hdd_set_station_ops(struct net_device *pWlanDev)
2675{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002676 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2677 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2678 else
2679 pWlanDev->netdev_ops = &wlan_drv_ops;
2680}
2681
Komal Seelama89be8d2016-09-29 11:09:26 +05302682#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302683/**
2684 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2685 * @hdd_ctx: HDD context
2686 *
2687 * Return: None
2688 */
2689static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2690{
2691 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2692
2693 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302694 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302695 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302696}
2697
2698/**
2699 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2700 * @hdd_ctx: HDD Context
2701 *
2702 * Return: None
2703 */
2704static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2705{
2706 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2707
2708 qdf_runtime_lock_deinit(ctx->scan);
2709 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302710 qdf_runtime_lock_deinit(ctx->roc);
2711 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302712 qdf_runtime_lock_deinit(ctx->dfs);
2713 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302714}
2715
Komal Seelama89be8d2016-09-29 11:09:26 +05302716static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2717{
2718 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2719
2720 ctx->connect = qdf_runtime_lock_init("connect");
2721}
2722
2723static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2724{
2725 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2726
2727 qdf_runtime_lock_deinit(ctx->connect);
2728 ctx->connect = NULL;
2729}
2730#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302731static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2732static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302733static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2734static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2735#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002736/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002737 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2738 * @hdd_ctx: global hdd context
2739 * @macAddr: mac address to assign to the interface
2740 * @name: User-visible name of the interface
2741 *
2742 * hdd adapter pointer would point to the netdev->priv space, this function
2743 * would retrive the pointer, and setup the hdd adapter configuration.
2744 *
2745 * Return: the pointer to hdd adapter, otherwise NULL
2746 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2748 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002749 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 const char *name)
2751{
2752 struct net_device *pWlanDev = NULL;
2753 hdd_adapter_t *adapter = NULL;
2754 /*
2755 * cfg80211 initialization and registration....
2756 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002757 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2758#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2759 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002761 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2762 hdd_mon_mode_ether_setup : ether_setup),
2763 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764
2765 if (pWlanDev != NULL) {
2766
2767 /* Save the pointer to the net_device in the HDD adapter */
2768 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2769
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302770 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002771
2772 adapter->dev = pWlanDev;
2773 adapter->pHddCtx = hdd_ctx;
2774 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302775 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776
2777 init_completion(&adapter->session_open_comp_var);
2778 init_completion(&adapter->session_close_comp_var);
2779 init_completion(&adapter->disconnect_comp_var);
2780 init_completion(&adapter->linkup_event_var);
2781 init_completion(&adapter->cancel_rem_on_chan_var);
2782 init_completion(&adapter->rem_on_chan_ready_event);
2783 init_completion(&adapter->sta_authorized_event);
2784 init_completion(&adapter->offchannel_tx_event);
2785 init_completion(&adapter->tx_action_cnf_event);
2786#ifdef FEATURE_WLAN_TDLS
2787 init_completion(&adapter->tdls_add_station_comp);
2788 init_completion(&adapter->tdls_del_station_comp);
2789 init_completion(&adapter->tdls_mgmt_comp);
2790 init_completion(&adapter->tdls_link_establish_req_comp);
2791#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002792 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 init_completion(&adapter->change_country_code);
2794
2795
2796 init_completion(&adapter->scan_info.abortscan_event_var);
2797
2798 adapter->offloads_configured = false;
2799 adapter->isLinkUpSvcNeeded = false;
2800 adapter->higherDtimTransition = true;
2801 /* Init the net_device structure */
2802 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2803
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302804 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302806 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 sizeof(tSirMacAddr));
2808 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809
2810 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2811 pWlanDev->features |=
2812 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2813 pWlanDev->features |= NETIF_F_RXCSUM;
2814
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002815 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2816
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 hdd_set_station_ops(adapter->dev);
2818
2819 pWlanDev->destructor = free_netdev;
2820 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002821 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822 adapter->wdev.wiphy = hdd_ctx->wiphy;
2823 adapter->wdev.netdev = pWlanDev;
2824 /* set pWlanDev's parent to underlying device */
2825 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2826 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302827 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302829 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 }
2831
2832 return adapter;
2833}
2834
Jeff Johnson590e2012016-10-05 16:16:24 -07002835static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2836 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837{
2838 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002840 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2842 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002843 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302844 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002845 }
2846 }
2847 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002848 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302849 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002850 }
2851 } else {
2852 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002853 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302854 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002855 }
2856 }
2857 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2858
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302859 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002860}
2861
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002862QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863{
2864 hdd_adapter_t *adapter = pContext;
2865
2866 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002867 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302868 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002869 }
2870
2871 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002872 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302873 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874 }
2875
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002876 /*
2877 * For NAN Data interface, the close session results in the final
2878 * indication to the userspace
2879 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002880 if (adapter->device_mode == QDF_NDI_MODE)
2881 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002882
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2884
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885 /*
2886 * We can be blocked while waiting for scheduled work to be
2887 * flushed, and the adapter structure can potentially be freed, in
2888 * which case the magic will have been reset. So make sure the
2889 * magic is still good, and hence the adapter structure is still
2890 * valid, before signaling completion
2891 */
2892 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2893 complete(&adapter->session_close_comp_var);
2894
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302895 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896}
2897
Krunal Soni8c37e322016-02-03 16:08:37 -08002898/**
2899 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2900 * @adapter: pointer to device adapter
Krunal Soni8c37e322016-02-03 16:08:37 -08002901 *
2902 * This routine will check the mode of adapter and if it is required then it
2903 * will initialize the TDLS operations
2904 *
2905 * Return: QDF_STATUS
2906 */
2907#ifdef FEATURE_WLAN_TDLS
Dustin Brownd28772b2017-03-17 14:16:07 -07002908static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002909{
Dustin Brownd28772b2017-03-17 14:16:07 -07002910 if (adapter->device_mode == QDF_IBSS_MODE)
2911 return QDF_STATUS_SUCCESS;
2912
2913 if (wlan_hdd_tdls_init(adapter)) {
2914 hdd_err("wlan_hdd_tdls_init failed");
2915 return QDF_STATUS_E_FAILURE;
Krunal Soni8c37e322016-02-03 16:08:37 -08002916 }
Dustin Brownd28772b2017-03-17 14:16:07 -07002917 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2918
Krunal Soni8c37e322016-02-03 16:08:37 -08002919 return QDF_STATUS_SUCCESS;
2920}
2921#else
Dustin Brownd28772b2017-03-17 14:16:07 -07002922static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter)
Krunal Soni8c37e322016-02-03 16:08:37 -08002923{
2924 return QDF_STATUS_SUCCESS;
2925}
2926#endif
2927
Dustin Brownd28772b2017-03-17 14:16:07 -07002928int hdd_vdev_ready(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929{
Dustin Brownd28772b2017-03-17 14:16:07 -07002930 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931
Dustin Brownd28772b2017-03-17 14:16:07 -07002932 status = pmo_vdev_ready(adapter->hdd_vdev);
2933
2934 return qdf_status_to_os_return(status);
2935}
2936
2937int hdd_vdev_destroy(hdd_adapter_t *adapter)
2938{
2939 QDF_STATUS status;
2940 int errno;
2941 hdd_context_t *hdd_ctx;
2942 unsigned long rc;
2943
2944 hdd_info("destroying vdev %d", adapter->sessionId);
2945
2946 /* vdev created sanity check */
2947 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2948 hdd_err("vdev for Id %d does not exist", adapter->sessionId);
2949 return -EINVAL;
2950 }
2951
Dustin Brown0d2eeae2017-03-24 15:21:32 -07002952 /* do vdev logical destroy via objmgr */
2953 errno = hdd_objmgr_destroy_vdev(adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07002954 if (errno) {
2955 hdd_err("failed to destroy objmgr vdev: %d", errno);
2956 return errno;
2957 }
2958
2959 /* close sme session (destroy vdev in firmware via legacy API) */
2960 INIT_COMPLETION(adapter->session_close_comp_var);
2961 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2962 status = sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2963 hdd_sme_close_session_callback, adapter);
2964 if (QDF_IS_STATUS_ERROR(status)) {
2965 hdd_err("failed to close sme session: %d", status);
2966 return qdf_status_to_os_return(status);
2967 }
2968
2969 /* block on a completion variable until sme session is closed */
2970 rc = wait_for_completion_timeout(
2971 &adapter->session_close_comp_var,
2972 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2973 if (!rc) {
2974 hdd_err("timed out waiting for close sme session: %ld", rc);
2975 if (adapter->device_mode == QDF_NDI_MODE)
2976 hdd_ndp_session_end_handler(adapter);
2977 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2978 return -ETIMEDOUT;
2979 }
2980
Dustin Brown0d2eeae2017-03-24 15:21:32 -07002981 /* now that sme session is closed, allow physical vdev destroy */
2982 errno = hdd_objmgr_release_vdev(adapter);
2983 if (errno) {
2984 hdd_err("failed to release objmgr vdev: %d", errno);
2985 return errno;
2986 }
2987
Dustin Brownd28772b2017-03-17 14:16:07 -07002988 hdd_info("vdev destroyed successfully");
2989
2990 return 0;
2991}
2992
2993int hdd_vdev_create(hdd_adapter_t *adapter)
2994{
2995 QDF_STATUS status;
2996 int errno;
2997 hdd_context_t *hdd_ctx;
2998 uint32_t type;
2999 uint32_t sub_type;
3000 unsigned long rc;
3001
3002 hdd_info("creating new vdev");
3003
3004 /* determine vdev (sub)type */
3005 status = cds_get_vdev_types(adapter->device_mode, &type, &sub_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303006 if (QDF_STATUS_SUCCESS != status) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003007 hdd_err("failed to get vdev type: %d", status);
3008 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003009 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003010
3011 /* do vdev create via objmgr */
3012 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown7d043f62017-03-27 12:07:36 -07003013 errno = hdd_objmgr_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
Dustin Brownd28772b2017-03-17 14:16:07 -07003014 if (errno) {
3015 hdd_err("failed to create objmgr vdev: %d", errno);
3016 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003018
3019 /* Open a SME session (prepare vdev in firmware via legacy API) */
3020 INIT_COMPLETION(adapter->session_open_comp_var);
3021 status = sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
3022 (uint8_t *)&adapter->macAddressCurrent,
3023 adapter->sessionId, type, sub_type);
3024 if (QDF_IS_STATUS_ERROR(status)) {
3025 hdd_err("failed to open sme session: %d", status);
3026 errno = qdf_status_to_os_return(status);
3027 goto objmgr_vdev_destroy;
3028 }
3029
3030 /* block on a completion variable until sme session is opened */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 rc = wait_for_completion_timeout(
3032 &adapter->session_open_comp_var,
3033 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3034 if (!rc) {
Dustin Brownd28772b2017-03-17 14:16:07 -07003035 hdd_err("timed out waiting for open sme session: %ld", rc);
3036 errno = -ETIMEDOUT;
3037 goto objmgr_vdev_destroy;
3038 }
3039
3040 /* firmware ready for component communication, raise vdev_ready event */
3041 errno = hdd_vdev_ready(adapter);
3042 if (errno) {
3043 hdd_err("failed to dispatch vdev ready event: %d", errno);
3044 goto hdd_vdev_destroy;
3045 }
3046
3047 hdd_info("vdev %d created successfully", adapter->sessionId);
3048
3049 return 0;
3050
3051 /*
3052 * Due to legacy constraints, we need to destroy in the same order as
3053 * create. So, split error handling into 2 cases to accommodate.
3054 */
3055
3056objmgr_vdev_destroy:
Dustin Brown7d043f62017-03-27 12:07:36 -07003057 QDF_BUG(!hdd_objmgr_release_and_destroy_vdev(adapter));
Dustin Brownd28772b2017-03-17 14:16:07 -07003058
3059 return errno;
3060
3061hdd_vdev_destroy:
3062 QDF_BUG(!hdd_vdev_destroy(adapter));
3063
3064 return errno;
3065}
3066
3067QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
3068{
3069 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
3070 hdd_context_t *hdd_ctx;
3071 QDF_STATUS status;
3072 int ret_val;
3073
3074 ret_val = hdd_vdev_create(adapter);
3075 if (ret_val) {
3076 hdd_err("failed to create vdev: %d", ret_val);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303077 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 }
3079
Dustin Brownd28772b2017-03-17 14:16:07 -07003080 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3081 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
3082 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Naveen Rawata410c5a2016-09-19 14:22:33 -07003083 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Dustin Brownd28772b2017-03-17 14:16:07 -07003084
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003085 /* Register wireless extensions */
Dustin Brownd28772b2017-03-17 14:16:07 -07003086 status = hdd_register_wext(adapter->dev);
3087 if (QDF_IS_STATUS_ERROR(status)) {
3088 hdd_err("failed to register wireless extensions: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 goto error_register_wext;
3090 }
Dustin Brownd28772b2017-03-17 14:16:07 -07003091
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07003093 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003094 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
3095
Deepak Dhamdherea2785822016-11-17 01:17:45 -08003096 /* set fast roaming capability in sme session */
3097 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
3098 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 /* Set the default operation channel */
3100 pHddStaCtx->conn_info.operationChannel =
3101 hdd_ctx->config->OperatingChannel;
3102
3103 /* Make the default Auth Type as OPEN */
3104 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
3105
3106 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303107 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07003108 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 status, status);
3110 goto error_init_txrx;
3111 }
3112
3113 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3114
3115 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303116 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07003117 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118 status, status);
3119 goto error_wmm_init;
3120 }
3121
3122 set_bit(WMM_INIT_DONE, &adapter->event_flags);
3123
3124 ret_val = wma_cli_set_command(adapter->sessionId,
3125 WMI_PDEV_PARAM_BURST_ENABLE,
3126 hdd_ctx->config->enableSifsBurst,
3127 PDEV_CMD);
Dustin Brownd28772b2017-03-17 14:16:07 -07003128 if (ret_val)
3129 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d", ret_val);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130
Dustin Brownd28772b2017-03-17 14:16:07 -07003131 status = hdd_check_and_init_tdls(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08003132 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003133 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303135 status = hdd_lro_enable(hdd_ctx, adapter);
3136 if (status != QDF_STATUS_SUCCESS)
3137 goto error_lro_enable;
3138
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303139 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303141error_lro_enable:
3142 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003143error_tdls_init:
3144 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3145 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146error_wmm_init:
3147 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3148 hdd_deinit_tx_rx(adapter);
3149error_init_txrx:
Dustin Brownd28772b2017-03-17 14:16:07 -07003150 hdd_unregister_wext(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003151error_register_wext:
Dustin Brownd28772b2017-03-17 14:16:07 -07003152 QDF_BUG(!hdd_vdev_destroy(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 return status;
3155}
3156
3157void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
3158{
3159 hdd_cfg80211_state_t *cfgState;
3160
3161 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3162
3163 if (NULL != cfgState->buf) {
3164 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165 rc = wait_for_completion_timeout(
3166 &adapter->tx_action_cnf_event,
3167 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
3168 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003169 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05303170 /*
3171 * Inform tx status as FAILURE to upper layer and free
3172 * cfgState->buf
3173 */
3174 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 }
3176 }
3177 return;
3178}
3179
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303180/**
3181 * hdd_station_adapter_deinit() - De-initialize the station adapter
3182 * @hdd_ctx: global hdd context
3183 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07003184 * @rtnl_held: Used to indicate whether or not the caller is holding
3185 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303186 *
3187 * This function De-initializes the STA/P2P/OCB adapter.
3188 *
3189 * Return: None.
3190 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003191static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
3192 hdd_adapter_t *adapter,
3193 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303194{
3195 ENTER_DEV(adapter->dev);
3196
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303197 if (adapter->dev) {
3198 if (rtnl_held)
3199 adapter->dev->wireless_handlers = NULL;
3200 else {
3201 rtnl_lock();
3202 adapter->dev->wireless_handlers = NULL;
3203 rtnl_unlock();
3204 }
3205 }
3206
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303207 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
3208 hdd_deinit_tx_rx(adapter);
3209 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
3210 }
3211
3212 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3213 hdd_wmm_adapter_close(adapter);
3214 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3215 }
3216
3217 hdd_cleanup_actionframe(hdd_ctx, adapter);
3218 wlan_hdd_tdls_exit(adapter);
3219
3220 EXIT();
3221}
3222
3223/**
3224 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
3225 * @hdd_ctx: global hdd context
3226 * @adapter: HDD adapter
3227 * @rtnl_held: the rtnl lock hold flag
3228 * This function De-initializes the AP/P2PGo adapter.
3229 *
3230 * Return: None.
3231 */
Jeff Johnson590e2012016-10-05 16:16:24 -07003232static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
3233 hdd_adapter_t *adapter,
3234 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303235{
3236 ENTER_DEV(adapter->dev);
3237
3238 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3239 hdd_wmm_adapter_close(adapter);
3240 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3241 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04003242 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303243
3244 hdd_cleanup_actionframe(hdd_ctx, adapter);
3245
3246 hdd_unregister_hostapd(adapter, rtnl_held);
3247
3248 EXIT();
3249}
3250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3252 bool rtnl_held)
3253{
3254 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003257 case QDF_STA_MODE:
3258 case QDF_P2P_CLIENT_MODE:
3259 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05303261 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003262 break;
3263 }
3264
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003265 case QDF_SAP_MODE:
3266 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 {
3268
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303269 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 break;
3271 }
3272
3273 default:
3274 break;
3275 }
3276
3277 EXIT();
3278}
3279
Jeff Johnson590e2012016-10-05 16:16:24 -07003280static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
3281 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282{
3283 struct net_device *pWlanDev = NULL;
3284
3285 if (adapter)
3286 pWlanDev = adapter->dev;
3287 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003288 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 return;
3290 }
3291
Rajeev Kumardca5f812016-02-04 17:28:06 -08003292 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303293
3294 if (adapter->scan_info.default_scan_ies) {
3295 qdf_mem_free(adapter->scan_info.default_scan_ies);
3296 adapter->scan_info.default_scan_ies = NULL;
3297 }
3298
Komal Seelama89be8d2016-09-29 11:09:26 +05303299 hdd_adapter_runtime_suspend_denit(adapter);
3300
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003301 /*
3302 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
3303 * the driver is almost closed and cannot handle either control
3304 * messages or data. However, unregister_netdevice() call above will
3305 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
3306 * to close the active connections (basically excites control path) which
3307 * is not right. Setting this flag helps hdd_stop() to recognize that
3308 * the interface is closed and restricts any operations on that
3309 */
3310 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
3311
3312 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
3313 if (rtnl_held) {
3314 unregister_netdevice(pWlanDev);
3315 } else {
3316 unregister_netdev(pWlanDev);
3317 }
3318 /*
3319 * Note that the adapter is no longer valid at this point
3320 * since the memory has been reclaimed
3321 */
3322 }
3323}
3324
Jeff Johnson590e2012016-10-05 16:16:24 -07003325static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
3326 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327{
3328 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3329 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303330 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303332 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333 adapter = adapterNode->pAdapter;
3334 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303335 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303337 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 }
3339 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3340 adapterNode = pNext;
3341 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303342 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343}
Ryan Hsu07495ea2016-01-21 15:25:39 -08003344
Arun Khandavalli2358d522016-05-16 18:05:37 +05303345#ifdef CONFIG_FW_LOGS_BASED_ON_INI
3346/**
3347 * hdd_set_fw_log_params() - Set log parameters to FW
3348 * @hdd_ctx: HDD Context
3349 * @adapter: HDD Adapter
3350 *
3351 * This function set the FW Debug log level based on the INI.
3352 *
3353 * Return: None
3354 */
3355static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3356 hdd_adapter_t *adapter)
3357{
3358 uint8_t count = 0, numentries = 0,
3359 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
3360 uint32_t value = 0;
3361 int ret;
3362
Arun Khandavallifae92942016-08-01 13:31:08 +05303363 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3364 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303365 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
3366 return;
3367 }
3368
Arun Khandavallifae92942016-08-01 13:31:08 +05303369 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303370 hdd_ctx->fw_log_settings.dl_type =
3371 hdd_ctx->config->enableFwLogType;
3372 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303373 WMI_DBGLOG_TYPE,
3374 hdd_ctx->config->enableFwLogType,
3375 DBG_CMD);
3376 if (ret != 0)
3377 hdd_err("Failed to enable FW log type ret %d",
3378 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303379
3380 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303381 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303382 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303383 WMI_DBGLOG_LOG_LEVEL,
3384 hdd_ctx->config->enableFwLogLevel,
3385 DBG_CMD);
3386 if (ret != 0)
3387 hdd_err("Failed to enable FW log level ret %d",
3388 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303389
3390 hdd_string_to_u8_array(
3391 hdd_ctx->config->enableFwModuleLogLevel,
3392 moduleloglevel,
3393 &numentries,
3394 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3395
3396 while (count < numentries) {
3397 /*
3398 * FW module log level input string looks like
3399 * below:
3400 * gFwDebugModuleLoglevel=<FW Module ID>,
3401 * <Log Level>,...
3402 * For example:
3403 * gFwDebugModuleLoglevel=
3404 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3405 * Above input string means :
3406 * For FW module ID 1 enable log level 0
3407 * For FW module ID 2 enable log level 1
3408 * For FW module ID 3 enable log level 2
3409 * For FW module ID 4 enable log level 3
3410 * For FW module ID 5 enable log level 4
3411 * For FW module ID 6 enable log level 5
3412 * For FW module ID 7 enable log level 6
3413 */
3414
Nishank Aggarwale239d962017-03-03 12:26:02 +05303415 if ((moduleloglevel[count] > WLAN_MODULE_ID_MAX)
3416 || (moduleloglevel[count + 1] > DBGLOG_LVL_MAX)) {
3417 hdd_err("Module id %d and dbglog level %d input length is more than max",
3418 moduleloglevel[count],
3419 moduleloglevel[count + 1]);
3420 return;
3421 }
3422
3423 value = moduleloglevel[count] << 16;
3424 value |= moduleloglevel[count + 1];
Arun Khandavalli2358d522016-05-16 18:05:37 +05303425 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303426 WMI_DBGLOG_MOD_LOG_LEVEL,
3427 value, DBG_CMD);
3428 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303429 hdd_err("Failed to enable FW module log level %d ret %d",
3430 value, ret);
3431
3432 count += 2;
3433 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303434
Arun Khandavalli2358d522016-05-16 18:05:37 +05303435}
3436#else
3437static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3438 hdd_adapter_t *adapter)
3439{
3440}
3441
3442#endif
3443
3444/**
3445 * hdd_set_fw_params() - Set parameters to firmware
3446 * @adapter: HDD adapter
3447 *
3448 * This function Sets various parameters to fw once the
3449 * adapter is started.
3450 *
3451 * Return: 0 on success or errno on failure
3452 */
3453int hdd_set_fw_params(hdd_adapter_t *adapter)
3454{
3455 int ret;
3456 hdd_context_t *hdd_ctx;
3457
3458 ENTER_DEV(adapter->dev);
3459
3460 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3461 if (!hdd_ctx)
3462 return -EINVAL;
3463
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003464 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303465 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303466#define HDD_DTIM_1CHAIN_RX_ID 0x5
3467#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003468 /*
3469 * Disable DTIM 1 chain Rx when in 1x1,
3470 * we are passing two value
3471 * as param_id << 29 | param_value.
3472 * Below param_value = 0(disable)
3473 */
3474 ret = wma_cli_set_command(adapter->sessionId,
3475 WMI_STA_SMPS_PARAM_CMDID,
3476 HDD_DTIM_1CHAIN_RX_ID <<
3477 HDD_SMPS_PARAM_VALUE_S,
3478 VDEV_CMD);
3479 if (ret) {
3480 hdd_err("DTIM 1 chain set failed %d", ret);
3481 goto error;
3482 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303483
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003484 ret = wma_cli_set_command(adapter->sessionId,
3485 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3486 hdd_ctx->config->txchainmask1x1,
3487 PDEV_CMD);
3488 if (ret) {
3489 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3490 ret);
3491 goto error;
3492 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303493
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003494 ret = wma_cli_set_command(adapter->sessionId,
3495 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3496 hdd_ctx->config->rxchainmask1x1,
3497 PDEV_CMD);
3498 if (ret) {
3499 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3500 ret);
3501 goto error;
3502 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303503#undef HDD_DTIM_1CHAIN_RX_ID
3504#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003505 } else {
3506 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3507 }
3508
Arun Khandavallifae92942016-08-01 13:31:08 +05303509 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3510 ret = wma_cli_set_command(adapter->sessionId,
3511 WMI_PDEV_PARAM_HYST_EN,
3512 hdd_ctx->config->enableMemDeepSleep,
3513 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303514
Arun Khandavallifae92942016-08-01 13:31:08 +05303515 if (ret) {
3516 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3517 ret);
3518 goto error;
3519 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303520
3521 ret = wma_cli_set_command(adapter->sessionId,
3522 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3523 hdd_ctx->config->rts_profile,
3524 VDEV_CMD);
3525 if (ret) {
3526 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3527 goto error;
3528 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303529 }
3530
3531 hdd_set_fw_log_params(hdd_ctx, adapter);
3532
3533 EXIT();
3534 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303535
Arun Khandavalli2358d522016-05-16 18:05:37 +05303536error:
3537 return -EINVAL;
3538}
3539
Ryan Hsu07495ea2016-01-21 15:25:39 -08003540/**
3541 * hdd_open_adapter() - open and setup the hdd adatper
3542 * @hdd_ctx: global hdd context
3543 * @session_type: type of the interface to be created
3544 * @iface_name: User-visible name of the interface
3545 * @macAddr: MAC address to assign to the interface
3546 * @name_assign_type: the name of assign type of the netdev
3547 * @rtnl_held: the rtnl lock hold flag
3548 *
3549 * This function open and setup the hdd adpater according to the device
3550 * type request, assign the name, the mac address assigned, and then prepared
3551 * the hdd related parameters, queue, lock and ready to start.
3552 *
3553 * Return: the pointer of hdd adapter, otherwise NULL.
3554 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3556 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003557 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003558 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559{
3560 hdd_adapter_t *adapter = NULL;
3561 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303562 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003563 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003564
Arun Khandavallifae92942016-08-01 13:31:08 +05303565 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566
3567 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3568 /*
3569 * Max limit reached on the number of vdevs configured by the
3570 * host. Return error
3571 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303572 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3573 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574 return NULL;
3575 }
3576
3577 if (macAddr == NULL) {
3578 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303579 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580 return NULL;
3581 }
3582 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303583 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303584 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3585 " already exists",
3586 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587 return NULL;
3588 }
3589
3590 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003591 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 /* Reset locally administered bit if the device mode is STA */
3593 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3594 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003595 case QDF_P2P_CLIENT_MODE:
3596 case QDF_P2P_DEVICE_MODE:
3597 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003598 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303599 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003600 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3601 name_assign_type,
3602 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003603
3604 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303605 hdd_err("failed to allocate adapter for session %d",
3606 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 return NULL;
3608 }
3609
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003610 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003612 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303614 else if (QDF_MONITOR_MODE == session_type)
3615 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 else
3617 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3618
3619 adapter->device_mode = session_type;
3620
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303621 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003622 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303623 if (QDF_STATUS_SUCCESS != status)
3624 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303625 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 /*
3628 * Workqueue which gets scheduled in IPv4 notification
3629 * callback
3630 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003631 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3632 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633
3634#ifdef WLAN_NS_OFFLOAD
3635 /*
3636 * Workqueue which gets scheduled in IPv6
3637 * notification callback.
3638 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003639 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3640 hdd_ipv6_notifier_work_queue);
3641#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303643 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303645 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646 }
3647
3648 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303649 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303651 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3652 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003653 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303654
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003656 case QDF_P2P_GO_MODE:
3657 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003658 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3659 name_assign_type,
3660 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303662 hdd_alert("failed to allocate adapter for session %d",
3663 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 return NULL;
3665 }
3666
3667 adapter->wdev.iftype =
3668 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003669 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670 NL80211_IFTYPE_P2P_GO;
3671 adapter->device_mode = session_type;
3672
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303674 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003675 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3676 goto err_free_netdev;
3677 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303678 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303680 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3681 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303683 case QDF_FTM_MODE:
3684 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3685 name_assign_type,
3686 "wlan0");
3687 if (NULL == adapter) {
3688 hdd_err("Failed to allocate adapter for FTM mode");
3689 return NULL;
3690 }
3691 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3692 adapter->device_mode = session_type;
3693 status = hdd_register_interface(adapter, rtnl_held);
3694 if (QDF_STATUS_SUCCESS != status) {
3695 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3696 goto err_free_netdev;
3697 }
3698 /* Stop the Interface TX queue. */
3699 hdd_info("Disabling queues");
3700 wlan_hdd_netif_queue_control(adapter,
3701 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3702 WLAN_CONTROL_PATH);
3703 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303705 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303706 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 return NULL;
3708 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709
3710 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3711 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3712
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303713 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003714 /* Add it to the hdd's session list. */
3715 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303716 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003717 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303718 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003719 } else {
3720 pHddAdapterNode->pAdapter = adapter;
3721 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3722 }
3723 }
3724
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303725 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 if (NULL != adapter) {
3727 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3728 adapter = NULL;
3729 }
3730 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303731 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 }
3733 return NULL;
3734 }
3735
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303736 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003737 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
3738 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739
3740 /* Initialize the WoWL service */
3741 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003742 hdd_alert("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303743 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003744 }
3745
3746 /* Adapter successfully added. Increment the vdev count */
3747 hdd_ctx->current_intf_count++;
3748
Jeff Johnson5880d792016-08-15 13:32:30 -07003749 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750 hdd_ctx->current_intf_count);
3751
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08003752 hdd_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003753 }
3754
Rajeev Kumardca5f812016-02-04 17:28:06 -08003755 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3756 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757
3758 return adapter;
3759
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303760err_close_adapter:
3761 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003763 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303764 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765
3766 return NULL;
3767}
3768
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303769QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003770 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771{
3772 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303773 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774
3775 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303776 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003777 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 status);
3779 return status;
3780 }
3781
3782 while (pCurrent->pAdapter != adapter) {
3783 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303784 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 break;
3786
3787 pCurrent = pNext;
3788 }
3789 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303790 if (QDF_STATUS_SUCCESS == status) {
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303791 hdd_info("wait for bus bw work to flush");
Dustin Brown5ec6b552017-03-31 12:11:40 -07003792 hdd_bus_bw_compute_timer_stop(hdd_ctx);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303793 cancel_work_sync(&hdd_ctx->bus_bw_work);
Dustin Brown5ec6b552017-03-31 12:11:40 -07003794
3795 /* cleanup adapter */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08003796 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
3797 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003799 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303800 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 adapterNode = NULL;
3802
Dustin Brown5ec6b552017-03-31 12:11:40 -07003803 /* conditionally restart the bw timer */
3804 hdd_bus_bw_compute_timer_try_start(hdd_ctx);
3805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806 /* Adapter removed. Decrement vdev count */
3807 if (hdd_ctx->current_intf_count != 0)
3808 hdd_ctx->current_intf_count--;
3809
3810 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303811 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303813
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303814 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815}
3816
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003817/**
3818 * hdd_close_all_adapters - Close all open adapters
3819 * @hdd_ctx: Hdd context
3820 * rtnl_held: True if RTNL lock held
3821 *
3822 * Close all open adapters.
3823 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303824 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003825 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303826QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827{
3828 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303829 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830
3831 ENTER();
3832
3833 do {
3834 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303835 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303836 wlan_hdd_release_intf_addr(hdd_ctx,
3837 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003839 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303840 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303841 /* Adapter removed. Decrement vdev count */
3842 if (hdd_ctx->current_intf_count != 0)
3843 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003844 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303845 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846
3847 EXIT();
3848
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303849 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850}
3851
3852void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3853{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303854 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 tSirUpdateIE updateIE;
3856 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003857 case QDF_STA_MODE:
3858 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859 {
3860 hdd_station_ctx_t *pHddStaCtx =
3861 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003862 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003863 break;
3864 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003865 case QDF_SAP_MODE:
3866 case QDF_P2P_GO_MODE:
3867 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003869 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003870 break;
3871 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003872 case QDF_FTM_MODE:
3873 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 default:
3875 /*
3876 * wlan_hdd_reset_prob_rspies should not have been called
3877 * for these kind of devices
3878 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003879 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880 pHostapdAdapter->device_mode);
3881 return;
3882 }
3883
Anurag Chouhanc5548422016-02-24 18:33:27 +05303884 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3886 updateIE.ieBufferlength = 0;
3887 updateIE.pAdditionIEBuffer = NULL;
3888 updateIE.append = true;
3889 updateIE.notify = false;
3890 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3891 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303892 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003893 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 }
3895}
3896
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303897QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 const bool bCloseSession)
3899{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303900 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003901 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3902 union iwreq_data wrqu;
3903 tSirUpdateIE updateIE;
3904 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303905 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003906
3907 ENTER();
3908
Sachin Ahuja988fd102016-09-15 17:16:25 +05303909 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003910 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003911 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3912 WLAN_CONTROL_PATH);
3913 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003914 case QDF_STA_MODE:
3915 case QDF_P2P_CLIENT_MODE:
3916 case QDF_IBSS_MODE:
3917 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003918 case QDF_NDI_MODE:
3919 if ((QDF_NDI_MODE == adapter->device_mode) ||
3920 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3922 hdd_is_connecting(
3923 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003924 INIT_COMPLETION(adapter->disconnect_comp_var);
3925 /*
3926 * For NDI do not use pWextState from sta_ctx, if needed
3927 * extract from ndi_ctx.
3928 */
3929 if (QDF_NDI_MODE == adapter->device_mode)
3930 qdf_ret_status = sme_roam_disconnect(
3931 hdd_ctx->hHal,
3932 adapter->sessionId,
3933 eCSR_DISCONNECT_REASON_NDI_DELETE);
3934 else if (pWextState->roamProfile.BSSType ==
3935 eCSR_BSS_TYPE_START_IBSS)
3936 qdf_ret_status = sme_roam_disconnect(
3937 hdd_ctx->hHal,
3938 adapter->sessionId,
3939 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003940 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003941 qdf_ret_status = sme_roam_disconnect(
3942 hdd_ctx->hHal,
3943 adapter->sessionId,
3944 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303946 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003947 rc = wait_for_completion_timeout(
3948 &adapter->disconnect_comp_var,
3949 msecs_to_jiffies
3950 (WLAN_WAIT_TIME_DISCONNECT));
3951 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003952 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003953 }
3954 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003955 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003956 }
3957 memset(&wrqu, '\0', sizeof(wrqu));
3958 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3959 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3960 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3961 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303962 }
3963 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303964 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003965 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303966 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303967 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003968
3969#ifdef WLAN_OPEN_SOURCE
3970 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3971#endif
3972
3973 hdd_deregister_tx_flow_control(adapter);
3974
3975#ifdef WLAN_NS_OFFLOAD
3976#ifdef WLAN_OPEN_SOURCE
3977 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3978#endif
3979#endif
3980
3981 /*
3982 * It is possible that the caller of this function does not
3983 * wish to close the session
3984 */
Krunal Soni985b8132017-02-10 18:49:08 -08003985 if (true == bCloseSession) {
3986 if (0 != wlan_hdd_try_disconnect(adapter)) {
3987 hdd_err("Error: Can't disconnect adapter");
3988 return QDF_STATUS_E_FAILURE;
3989 }
Dustin Brown0d2eeae2017-03-24 15:21:32 -07003990 hdd_vdev_destroy(adapter);
Krunal Soni985b8132017-02-10 18:49:08 -08003991 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 break;
3993
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003994 case QDF_SAP_MODE:
3995 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003996 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003997 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3999
4000 hdd_deregister_tx_flow_control(adapter);
4001
4002 mutex_lock(&hdd_ctx->sap_lock);
4003 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304004 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05304005 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006
4007 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 status = wlansap_stop_bss(
4009 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304011 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004012 hdd_hostapd_state_t *hostapd_state =
4013 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304014 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304015 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05304016 qdf_status =
4017 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08004018 qdf_stop_bss_event,
4019 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020
Anurag Chouhance0dc992016-02-16 18:18:03 +05304021 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004022 hdd_err("failure waiting for wlansap_stop_bss %d",
4023 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 }
4025 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07004026 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 }
4028 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004029 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4030 adapter->device_mode,
4031 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032
Anurag Chouhanc5548422016-02-24 18:33:27 +05304033 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08004034 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035 updateIE.smeSessionId = adapter->sessionId;
4036 updateIE.ieBufferlength = 0;
4037 updateIE.pAdditionIEBuffer = NULL;
4038 updateIE.append = false;
4039 updateIE.notify = false;
4040 /* Probe bcn reset */
4041 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4042 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304043 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004044 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045 }
4046 /* Assoc resp reset */
4047 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
4048 &updateIE,
4049 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304050 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004051 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004052 }
4053 /* Reset WNI_CFG_PROBE_RSP Flags */
4054 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304055 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 adapter->sessionCtx.ap.beacon = NULL;
4057 }
Peng Xu66162de2016-02-11 17:01:20 -08004058 if (true == bCloseSession)
Dustin Brown0d2eeae2017-03-24 15:21:32 -07004059 hdd_vdev_destroy(adapter);
Manikandan Mohan5df78272017-03-22 16:28:50 -07004060 mutex_unlock(&hdd_ctx->sap_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004062 case QDF_OCB_MODE:
Krishna Kumaar Natarajane58b4092017-01-25 15:47:35 -08004063 cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004064 (struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
Leo Changfdb45c32016-10-28 11:09:23 -07004065 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 break;
4067 default:
4068 break;
4069 }
4070
4071 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304072 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073}
4074
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05304075/**
4076 * hdd_deinit_all_adapters - deinit all adapters
4077 * @hdd_ctx: HDD context
4078 * @rtnl_held: True if RTNL lock held
4079 *
4080 */
4081void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
4082{
4083 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4084 QDF_STATUS status;
4085 hdd_adapter_t *adapter;
4086
4087 ENTER();
4088
4089 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4090
4091 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4092 adapter = adapter_node->pAdapter;
4093 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
4094 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4095 adapter_node = next;
4096 }
4097
4098 EXIT();
4099}
4100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304101QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102{
4103 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304104 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105 hdd_adapter_t *adapter;
4106
4107 ENTER();
4108
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304109 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4112
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304113 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 adapter = adapterNode->pAdapter;
4115 hdd_stop_adapter(hdd_ctx, adapter, true);
4116 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4117 adapterNode = pNext;
4118 }
4119
4120 EXIT();
4121
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304122 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123}
4124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304125QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126{
4127 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304128 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129 hdd_adapter_t *adapter;
4130
4131 ENTER();
4132
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05304133 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
4134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4136
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304137 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07004139 hdd_notice("Disabling queues");
Arun Khandavallicc544b32017-01-30 19:52:16 +05304140 if (hdd_ctx->config->sap_internal_restart &&
4141 adapter->device_mode == QDF_SAP_MODE) {
4142 wlan_hdd_netif_queue_control(adapter,
4143 WLAN_NETIF_TX_DISABLE,
4144 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004145 if (test_bit(SOFTAP_BSS_STARTED,
4146 &adapter->event_flags)) {
4147 hdd_sap_indicate_disconnect_for_sta(adapter);
4148 hdd_cleanup_actionframe(hdd_ctx, adapter);
4149 hdd_sap_destroy_events(adapter);
4150 }
4151 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
4152 } else {
Arun Khandavallicc544b32017-01-30 19:52:16 +05304153 wlan_hdd_netif_queue_control(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004154 WLAN_NETIF_TX_DISABLE_N_CARRIER,
4155 WLAN_CONTROL_PATH);
Manikandan Mohan0a44ec82017-02-17 15:06:11 -08004156 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157
4158 adapter->sessionCtx.station.hdd_ReassocScenario = false;
4159
4160 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08004161 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
4162 adapter->device_mode, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
4164 hdd_wmm_adapter_close(adapter);
4165 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
4166 }
4167
Wu Gao36717432016-11-21 15:09:48 +08004168 /*
4169 * If adapter is SAP, set session ID to invalid since SAP
4170 * session will be cleanup during SSR.
4171 */
4172 if (adapter->device_mode == QDF_SAP_MODE)
4173 wlansap_set_invalid_session(
4174 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
4175
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4177 adapterNode = pNext;
4178 }
4179
4180 EXIT();
4181
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304182 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183}
4184
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +05304185bool hdd_check_for_opened_interfaces(hdd_context_t *hdd_ctx)
4186{
4187 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4188 QDF_STATUS status;
4189 bool close_modules = true;
4190
4191 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4192 while ((NULL != adapter_node) && (QDF_STATUS_SUCCESS == status)) {
4193 if (test_bit(DEVICE_IFACE_OPENED,
4194 &adapter_node->pAdapter->event_flags)) {
4195 hdd_info("Still other ifaces are up cannot close modules");
4196 close_modules = false;
4197 break;
4198 }
4199 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4200 adapter_node = next;
4201 }
4202
4203 return close_modules;
4204}
4205
Arun Khandavallifae92942016-08-01 13:31:08 +05304206/**
4207 * hdd_is_interface_up()- Checkfor interface up before ssr
4208 * @hdd_ctx: HDD context
4209 *
4210 * check if there are any wlan interfaces before SSR accordingly start
4211 * the interface.
4212 *
4213 * Return: 0 if interface was opened else false
4214 */
4215static bool hdd_is_interface_up(hdd_adapter_t *adapter)
4216{
4217 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
4218 return true;
4219 else
4220 return false;
4221}
4222
Anurag Chouhanc4092922016-09-08 15:56:11 +05304223#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
Abhishek Singhb5e38ef2017-01-02 12:09:34 +05304224 && !defined(WITH_BACKPORTS)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304225struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4226 struct ieee80211_channel *channel,
4227 const u8 *bssid, const u8 *ssid,
4228 size_t ssid_len)
4229{
4230 return cfg80211_get_bss(wiphy, channel, bssid,
4231 ssid, ssid_len,
4232 WLAN_CAPABILITY_ESS,
4233 WLAN_CAPABILITY_ESS);
4234}
4235#else
4236struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
4237 struct ieee80211_channel *channel,
4238 const u8 *bssid, const u8 *ssid,
4239 size_t ssid_len)
4240{
4241 return cfg80211_get_bss(wiphy, channel, bssid,
4242 ssid, ssid_len,
4243 IEEE80211_BSS_TYPE_ESS,
4244 IEEE80211_PRIVACY_ANY);
4245}
4246#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304247
Abhishek Singha84d3952016-09-13 13:45:05 +05304248#if defined CFG80211_CONNECT_BSS
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304249#if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
4250 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
4251/**
4252 * hdd_convert_timeout_reason() - Convert to kernel specific enum
4253 * @timeout_reason: reason for connect timeout
4254 *
4255 * This function is used to convert host timeout
4256 * reason enum to kernel specific enum.
4257 *
4258 * Return: nl timeout enum
4259 */
4260static enum nl80211_timeout_reason hdd_convert_timeout_reason(
4261 tSirResultCodes timeout_reason)
4262{
4263 switch (timeout_reason) {
4264 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
4265 return NL80211_TIMEOUT_SCAN;
4266 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
4267 return NL80211_TIMEOUT_AUTH;
4268 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
4269 return NL80211_TIMEOUT_ASSOC;
4270 default:
4271 return NL80211_TIMEOUT_UNSPECIFIED;
4272 }
4273}
4274
4275/**
4276 * hdd_cfg80211_connect_timeout() - API to send connection timeout reason
4277 * @dev: network device
4278 * @bssid: bssid to which we want to associate
4279 * @timeout_reason: reason for connect timeout
4280 *
4281 * This API is used to send connection timeout reason to supplicant
4282 *
4283 * Return: void
4284 */
4285static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4286 const u8 *bssid,
4287 tSirResultCodes timeout_reason)
4288{
4289 enum nl80211_timeout_reason nl_timeout_reason;
4290 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4291
4292 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL,
4293 nl_timeout_reason);
4294}
4295
4296/**
4297 * __hdd_connect_bss() - API to send connection status to supplicant
4298 * @dev: network device
4299 * @bssid: bssid to which we want to associate
4300 * @req_ie: Request Information Element
4301 * @req_ie_len: len of the req IE
4302 * @resp_ie: Response IE
4303 * @resp_ie_len: len of ht response IE
4304 * @status: status
4305 * @gfp: Kernel Flag
4306 * @timeout_reason: reason for connect timeout
4307 *
4308 * Return: void
4309 */
4310static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4311 struct cfg80211_bss *bss, const u8 *req_ie,
4312 size_t req_ie_len, const u8 *resp_ie,
4313 size_t resp_ie_len, int status, gfp_t gfp,
4314 tSirResultCodes timeout_reason)
4315{
4316 enum nl80211_timeout_reason nl_timeout_reason;
4317 nl_timeout_reason = hdd_convert_timeout_reason(timeout_reason);
4318
4319 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4320 resp_ie, resp_ie_len, status, gfp,
4321 nl_timeout_reason);
4322}
4323#else
4324#if defined CFG80211_CONNECT_TIMEOUT
4325static void hdd_cfg80211_connect_timeout(struct net_device *dev,
4326 const u8 *bssid,
4327 tSirResultCodes timeout_reason)
4328{
4329 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
4330}
4331#endif
4332
4333static void __hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4334 struct cfg80211_bss *bss, const u8 *req_ie,
4335 size_t req_ie_len, const u8 *resp_ie,
4336 size_t resp_ie_len, int status, gfp_t gfp,
4337 tSirResultCodes timeout_reason)
4338{
4339 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
4340 resp_ie, resp_ie_len, status, gfp);
4341}
4342#endif
4343
Abhishek Singha84d3952016-09-13 13:45:05 +05304344/**
4345 * hdd_connect_bss() - API to send connection status to supplicant
4346 * @dev: network device
4347 * @bssid: bssid to which we want to associate
4348 * @req_ie: Request Information Element
4349 * @req_ie_len: len of the req IE
4350 * @resp_ie: Response IE
4351 * @resp_ie_len: len of ht response IE
4352 * @status: status
4353 * @gfp: Kernel Flag
4354 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304355 * @timeout_reason: reason for connect timeout
Abhishek Singha84d3952016-09-13 13:45:05 +05304356 *
4357 * The API is a wrapper to send connection status to supplicant
4358 *
4359 * Return: Void
4360 */
4361#if defined CFG80211_CONNECT_TIMEOUT
4362static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4363 struct cfg80211_bss *bss, const u8 *req_ie,
4364 size_t req_ie_len, const u8 *resp_ie,
4365 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304366 bool connect_timeout,
4367 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304368{
4369 if (connect_timeout)
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304370 hdd_cfg80211_connect_timeout(dev, bssid, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304371 else
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304372 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4373 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304374}
4375#else
4376static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
4377 struct cfg80211_bss *bss, const u8 *req_ie,
4378 size_t req_ie_len, const u8 *resp_ie,
4379 size_t resp_ie_len, int status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304380 bool connect_timeout,
4381 tSirResultCodes timeout_reason)
Abhishek Singha84d3952016-09-13 13:45:05 +05304382{
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304383 __hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie,
4384 resp_ie_len, status, gfp, timeout_reason);
Abhishek Singha84d3952016-09-13 13:45:05 +05304385}
4386#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05304387
4388/**
4389 * hdd_connect_result() - API to send connection status to supplicant
4390 * @dev: network device
4391 * @bssid: bssid to which we want to associate
4392 * @roam_info: information about connected bss
4393 * @req_ie: Request Information Element
4394 * @req_ie_len: len of the req IE
4395 * @resp_ie: Response IE
4396 * @resp_ie_len: len of ht response IE
4397 * @status: status
4398 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05304399 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304400 * @timeout_reason: reason for connect timeout
Anurag Chouhanc4092922016-09-08 15:56:11 +05304401 *
4402 * The API is a wrapper to send connection status to supplicant
4403 * and allow runtime suspend
4404 *
4405 * Return: Void
4406 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304407void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4408 tCsrRoamInfo *roam_info, const u8 *req_ie,
4409 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304410 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304411 bool connect_timeout,
4412 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304413{
4414 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4415 struct cfg80211_bss *bss = NULL;
4416
4417 if (WLAN_STATUS_SUCCESS == status) {
4418 struct ieee80211_channel *chan;
4419 int freq;
4420 int chan_no = roam_info->pBssDesc->channelId;
4421
4422 if (chan_no <= 14)
4423 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004424 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304425 else
4426 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07004427 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304428
4429 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
4430 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
4431 roam_info->u.pConnectedProfile->SSID.ssId,
4432 roam_info->u.pConnectedProfile->SSID.length);
4433 }
Komal Seelama89be8d2016-09-29 11:09:26 +05304434
Abhishek Singha84d3952016-09-13 13:45:05 +05304435 hdd_connect_bss(dev, bssid, bss, req_ie,
4436 req_ie_len, resp_ie, resp_ie_len,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304437 status, gfp, connect_timeout, timeout_reason);
Komal Seelama89be8d2016-09-29 11:09:26 +05304438
4439 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304440}
4441#else
4442void hdd_connect_result(struct net_device *dev, const u8 *bssid,
4443 tCsrRoamInfo *roam_info, const u8 *req_ie,
4444 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05304445 size_t resp_ie_len, u16 status, gfp_t gfp,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304446 bool connect_timeout,
4447 tSirResultCodes timeout_reason)
Anurag Chouhanc4092922016-09-08 15:56:11 +05304448{
Komal Seelama89be8d2016-09-29 11:09:26 +05304449 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
4450
Anurag Chouhanc4092922016-09-08 15:56:11 +05304451 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
4452 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05304453 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05304454}
4455#endif
4456
4457
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304458QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459{
4460 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304461 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 hdd_adapter_t *adapter;
4463#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304464 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004465#endif
4466 eConnectionState connState;
4467
4468 ENTER();
4469
4470 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304471 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004472 adapter = adapterNode->pAdapter;
4473
Arun Khandavallifae92942016-08-01 13:31:08 +05304474 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304475 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004477 hdd_wmm_init(adapter);
4478
4479 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004480 case QDF_STA_MODE:
4481 case QDF_P2P_CLIENT_MODE:
4482 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483
4484 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4485 ->conn_info.connState;
4486
4487 hdd_init_station_mode(adapter);
4488 /* Open the gates for HDD to receive Wext commands */
4489 adapter->isLinkUpSvcNeeded = false;
4490 adapter->scan_info.mScanPending = false;
4491
4492 /* Indicate disconnect event to supplicant if associated previously */
4493 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004494 eConnectionState_IbssConnected == connState ||
4495 eConnectionState_NotConnected == connState ||
4496 eConnectionState_IbssDisconnected == connState ||
4497 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 union iwreq_data wrqu;
4499 memset(&wrqu, '\0', sizeof(wrqu));
4500 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4501 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4502 wireless_send_event(adapter->dev, SIOCGIWAP,
4503 &wrqu, NULL);
4504 adapter->sessionCtx.station.
4505 hdd_ReassocScenario = false;
4506
4507 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304508 wlan_hdd_cfg80211_indicate_disconnect(
4509 adapter->dev, false,
4510 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004511 } else if (eConnectionState_Connecting == connState) {
4512 /*
4513 * Indicate connect failure to supplicant if we were in the
4514 * process of connecting
4515 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304516 hdd_connect_result(adapter->dev, NULL, NULL,
yeshwanth sriram guntukaaf7b73f2017-02-22 17:35:32 +05304517 NULL, 0, NULL, 0,
4518 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
4519 GFP_KERNEL, false,
4520 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 }
4522
4523 hdd_register_tx_flow_control(adapter,
4524 hdd_tx_resume_timer_expired_handler,
4525 hdd_tx_resume_cb);
4526
4527 break;
4528
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004529 case QDF_SAP_MODE:
Arun Khandavallicc544b32017-01-30 19:52:16 +05304530 if (hdd_ctx->config->sap_internal_restart)
4531 hdd_init_ap_mode(adapter, true);
4532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 break;
4534
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004535 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07004537 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4539#else
Jeff Johnson5880d792016-08-15 13:32:30 -07004540 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004541 /* event supplicant to restart */
4542 cfg80211_del_sta(adapter->dev,
4543 (const u8 *)&bcastMac.bytes[0],
4544 GFP_KERNEL);
4545#endif
4546 break;
4547
4548 default:
4549 break;
4550 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304551get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4553 adapterNode = pNext;
4554 }
4555
4556 EXIT();
4557
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304558 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559}
4560
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304561QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004562 hdd_adapter_list_node_t **padapterNode)
4563{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304564 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004565 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304566 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4567 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004568 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004569 return status;
4570}
4571
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304572QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 hdd_adapter_list_node_t *adapterNode,
4574 hdd_adapter_list_node_t **pNextAdapterNode)
4575{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304576 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004577 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304578 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4579 (qdf_list_node_t *) adapterNode,
4580 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004582 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 return status;
4584}
4585
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304586QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004587 hdd_adapter_list_node_t *adapterNode)
4588{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304589 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004590 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304591 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004593 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594 return status;
4595}
4596
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304597QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004598 hdd_adapter_list_node_t **padapterNode)
4599{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304600 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004601 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304602 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4603 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004604 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 return status;
4606}
4607
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304608QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 hdd_adapter_list_node_t *adapterNode)
4610{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304611 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004612 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304613 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4614 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004615 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616 return status;
4617}
4618
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304619QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 hdd_adapter_list_node_t *adapterNode)
4621{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304622 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004623 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304624 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4625 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004626 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004627 return status;
4628}
4629
4630hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4631 tSirMacAddr macAddr)
4632{
4633 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4634 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304635 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004636
4637 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4638
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304639 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004640 adapter = adapterNode->pAdapter;
4641
4642 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304643 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644 macAddr, sizeof(tSirMacAddr))) {
4645 return adapter;
4646 }
4647 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4648 adapterNode = pNext;
4649 }
4650
4651 return NULL;
4652
4653}
4654
4655hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4656 uint32_t vdev_id)
4657{
4658 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4659 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304660 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304662 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304664 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 adapter = adapterNode->pAdapter;
4666
4667 if (adapter->sessionId == vdev_id)
4668 return adapter;
4669
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304670 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004671 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4672 adapterNode = pNext;
4673 }
4674
Jeff Johnson5880d792016-08-15 13:32:30 -07004675 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676
4677 return NULL;
4678}
4679
Abhishek Singh7996eb72015-12-30 17:24:02 +05304680/**
4681 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4682 * the sessionid
4683 * @hdd_ctx: hdd context.
4684 * @sme_session_id: sme session is for the adapter to get.
4685 *
4686 * This function is used to get the adapter with provided session id
4687 *
4688 * Return: adapter pointer if found
4689 *
4690 */
4691hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4692 uint32_t sme_session_id)
4693{
4694 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4695 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304696 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304697
4698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304699 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304700
4701 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304702 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304703 adapter = adapter_node->pAdapter;
4704
4705 if (adapter &&
4706 adapter->sessionId == sme_session_id)
4707 return adapter;
4708
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304709 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304710 hdd_get_next_adapter(hdd_ctx,
4711 adapter_node, &next);
4712 adapter_node = next;
4713 }
4714 return NULL;
4715}
4716
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004717/**
4718 * hdd_get_adapter() - to get adapter matching the mode
4719 * @hdd_ctx: hdd context
4720 * @mode: adapter mode
4721 *
4722 * This routine will return the pointer to adapter matching
4723 * with the passed mode.
4724 *
4725 * Return: pointer to adapter or null
4726 */
4727hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4728 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729{
4730 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4731 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304732 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004733
4734 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4735
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304736 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004737 adapter = adapterNode->pAdapter;
4738
4739 if (adapter && (mode == adapter->device_mode))
4740 return adapter;
4741
4742 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4743 adapterNode = pNext;
4744 }
4745
4746 return NULL;
4747
4748}
4749
4750/**
4751 * hdd_get_operating_channel() - return operating channel of the device mode
4752 * @hdd_ctx: Pointer to the HDD context.
4753 * @mode: Device mode for which operating channel is required.
4754 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004755 * QDF_STA_MODE,
4756 * QDF_P2P_CLIENT_MODE,
4757 * QDF_SAP_MODE,
4758 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004759 *
4760 * This API returns the operating channel of the requested device mode
4761 *
4762 * Return: channel number. "0" id the requested device is not found OR it is
4763 * not connected.
4764 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004765uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4766 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767{
4768 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304769 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 hdd_adapter_t *adapter;
4771 uint8_t operatingChannel = 0;
4772
4773 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4774
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304775 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 adapter = adapterNode->pAdapter;
4777
4778 if (mode == adapter->device_mode) {
4779 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004780 case QDF_STA_MODE:
4781 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004782 if (hdd_conn_is_connected
4783 (WLAN_HDD_GET_STATION_CTX_PTR
4784 (adapter))) {
4785 operatingChannel =
4786 (WLAN_HDD_GET_STATION_CTX_PTR
4787 (adapter))->conn_info.
4788 operationChannel;
4789 }
4790 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004791 case QDF_SAP_MODE:
4792 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793 /* softap connection info */
4794 if (test_bit
4795 (SOFTAP_BSS_STARTED,
4796 &adapter->event_flags))
4797 operatingChannel =
4798 (WLAN_HDD_GET_AP_CTX_PTR
4799 (adapter))->operatingChannel;
4800 break;
4801 default:
4802 break;
4803 }
4804
4805 break; /* Found the device of interest. break the loop */
4806 }
4807
4808 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4809 adapterNode = pNext;
4810 }
4811 return operatingChannel;
4812}
4813
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304814static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 hdd_ctx)
4816{
4817 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304818 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 hdd_adapter_t *adapter;
4820
4821 ENTER();
4822
4823 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4824
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304825 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004827 if ((adapter->device_mode == QDF_STA_MODE) ||
4828 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4829 (adapter->device_mode == QDF_IBSS_MODE) ||
4830 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4831 (adapter->device_mode == QDF_SAP_MODE) ||
4832 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833 wlan_hdd_cfg80211_deregister_frames(adapter);
4834 hdd_unregister_wext(adapter->dev);
4835 }
4836 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4837 adapterNode = pNext;
4838 }
4839
4840 EXIT();
4841
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304842 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843}
4844
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304845QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004846{
4847 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304848 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 hdd_adapter_t *adapter;
4850
4851 ENTER();
4852
4853 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4854
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304855 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004856 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004857 if ((adapter->device_mode == QDF_STA_MODE) ||
4858 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4859 (adapter->device_mode == QDF_IBSS_MODE) ||
4860 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4861 (adapter->device_mode == QDF_SAP_MODE) ||
4862 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05304864 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 eCSR_SCAN_ABORT_DEFAULT);
4866 }
4867 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4868 adapterNode = pNext;
4869 }
4870
4871 EXIT();
4872
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304873 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874}
4875
Dustin Brownf27bce82016-11-03 12:52:27 -07004876/**
4877 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4878 * adapters
4879 * @hdd_ctx: The HDD context containing the adapters to operate on
4880 *
4881 * return: QDF_STATUS_SUCCESS
4882 */
4883static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4884{
4885 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4886 QDF_STATUS status;
4887 hdd_adapter_t *adapter;
4888 int err;
4889
4890 ENTER();
4891
4892 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4893
4894 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4895 adapter = adapter_node->pAdapter;
4896 if ((adapter->device_mode == QDF_STA_MODE) ||
4897 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4898 (adapter->device_mode == QDF_IBSS_MODE) ||
4899 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4900 (adapter->device_mode == QDF_SAP_MODE) ||
4901 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4902 err = wlan_hdd_sched_scan_stop(adapter->dev);
4903 if (err)
4904 hdd_err("Unable to stop scheduled scan");
4905 }
4906 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node);
4907 adapter_node = next_node;
4908 }
4909
4910 EXIT();
4911
4912 return QDF_STATUS_SUCCESS;
4913}
4914
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004915#ifdef WLAN_NS_OFFLOAD
4916/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004917 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 * @hdd_ctx: Pointer to hdd context
4919 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004920 * Unregister for IPv6 address change notifications.
4921 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922 * Return: None
4923 */
4924static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4925{
4926 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4927
4928 return;
4929}
4930
4931/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004932 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004933 * @hdd_ctx: Pointer to hdd context
4934 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004935 * Register for IPv6 address change notifications.
4936 *
4937 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004939static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940{
4941 int ret;
4942
4943 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4944 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004945 if (ret) {
4946 hdd_err("Failed to register IPv6 notifier: %d", ret);
4947 goto out;
4948 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004950 hdd_info("Registered IPv6 notifier");
4951out:
4952 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953}
4954#else
4955/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004956 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004957 * @hdd_ctx: Pointer to hdd context
4958 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004959 * Unregister for IPv6 address change notifications.
4960 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004961 * Return: None
4962 */
4963static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4964{
4965}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004967/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004968 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004969 * @hdd_ctx: Pointer to hdd context
4970 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004971 * Register for IPv6 address change notifications.
4972 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004973 * Return: None
4974 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004975static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004977 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004978}
4979#endif
4980
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304981#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4982/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004983 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304984 * @hdd_ctx: HDD context
4985 *
4986 * Activates the logging service
4987 *
4988 * Return: Zero in case of success, negative value otherwise
4989 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004990static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304991{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004992 int ret;
4993 struct hdd_config *config = hdd_ctx->config;
4994
4995 if (!config->wlanLoggingEnable)
4996 return 0;
4997
4998 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4999 config->wlanLoggingNumBuf);
5000 if (ret)
5001 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
5002 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305003}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005004
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305005/**
5006 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
5007 * @hdd_ctx: HDD context
5008 *
5009 * Deactivates the logging service
5010 *
5011 * Return: 0 on deactivating the logging service
5012 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005013static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305014{
5015 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
5016 return wlan_logging_sock_deactivate_svc();
5017
5018 return 0;
5019}
5020#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005021static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305022{
5023 return 0;
5024}
5025
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005026static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05305027{
5028 return 0;
5029}
5030#endif
5031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005033 * hdd_register_notifiers - Register netdev notifiers.
5034 * @hdd_ctx: HDD context
5035 *
5036 * Register netdev notifiers like IPv4 and IPv6.
5037 *
5038 * Return: 0 on success and errno on failure
5039 */
5040static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
5041{
5042 int ret;
5043
5044 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5045 if (ret) {
5046 hdd_err("register_netdevice_notifier failed: %d", ret);
5047 goto out;
5048 }
5049
5050 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
5051 if (ret)
5052 goto unregister_notifier;
5053
5054 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5055 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5056 if (ret) {
5057 hdd_err("Failed to register IPv4 notifier: %d", ret);
5058 goto unregister_ip6_notifier;
5059 }
5060
5061 return 0;
5062
5063unregister_ip6_notifier:
5064 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5065unregister_notifier:
5066 unregister_netdevice_notifier(&hdd_netdev_notifier);
5067out:
5068 return ret;
5069
5070}
5071
5072/**
5073 * hdd_unregister_notifiers - Unregister netdev notifiers.
5074 * @hdd_ctx: HDD context
5075 *
5076 * Unregister netdev notifiers like IPv4 and IPv6.
5077 *
5078 * Return: None.
5079 */
5080static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
5081{
5082 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
5083
5084 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5085
5086 unregister_netdevice_notifier(&hdd_netdev_notifier);
5087}
5088
5089/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005090 * hdd_exit_netlink_services - Exit netlink services
5091 * @hdd_ctx: HDD context
5092 *
5093 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
5094 * nl service.
5095 *
5096 * Return: None.
5097 */
5098static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
5099{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005100 hdd_close_cesium_nl_sock();
Naveen Rawat910726a2017-03-06 11:42:51 -08005101 hdd_deactivate_wifi_pos();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005102 ptt_sock_deactivate_svc();
5103
5104 nl_srv_exit();
5105}
5106
5107/**
5108 * hdd_init_netlink_services- Init netlink services
5109 * @hdd_ctx: HDD context
5110 *
5111 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
5112 * nl service.
5113 *
5114 * Return: 0 on success and errno on failure.
5115 */
5116static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
5117{
5118 int ret;
5119
Ryan Hsuceddceb2016-04-28 10:20:14 -07005120 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005121 if (ret) {
5122 hdd_alert("nl_srv_init failed: %d", ret);
5123 goto out;
5124 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07005125 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005126
Naveen Rawat910726a2017-03-06 11:42:51 -08005127 ret = hdd_activate_wifi_pos(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005128 if (ret) {
Naveen Rawat910726a2017-03-06 11:42:51 -08005129 hdd_alert("hdd_activate_wifi_pos failed: %d", ret);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005130 goto err_nl_srv;
5131 }
5132
5133 ret = ptt_sock_activate_svc();
5134 if (ret) {
5135 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
5136 goto err_nl_srv;
5137 }
5138
5139 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07005140 if (ret)
5141 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005142
5143 ret = cnss_diag_activate_service();
5144 if (ret) {
5145 hdd_alert("cnss_diag_activate_service failed: %d", ret);
5146 goto err_close_cesium;
5147 }
5148
5149 return 0;
5150
5151err_close_cesium:
5152 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005153 ptt_sock_deactivate_svc();
5154err_nl_srv:
5155 nl_srv_exit();
5156out:
5157 return ret;
5158}
5159
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005160/**
5161 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
5162 * @hdd_ctx: HDD context.
5163 *
5164 * Destroy RX wakelock.
5165 *
5166 * Return: None.
5167 */
5168static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
5169{
5170 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
5171}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08005172
5173/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005174 * hdd_rx_wake_lock_create() - Create RX wakelock
5175 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005176 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005177 * Create RX wakelock.
5178 *
5179 * Return: None.
5180 */
5181static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
5182{
5183 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5184}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005185
5186/**
5187 * hdd_roc_context_init() - Init ROC context
5188 * @hdd_ctx: HDD context.
5189 *
5190 * Initialize ROC context.
5191 *
5192 * Return: 0 on success and errno on failure.
5193 */
5194static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
5195{
5196 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
5197 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
5198
5199 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5200
5201 return 0;
5202}
5203
5204/**
5205 * hdd_roc_context_destroy() - Destroy ROC context
5206 * @hdd_ctx: HDD context.
5207 *
5208 * Destroy roc list and flush the pending roc work.
5209 *
5210 * Return: None.
5211 */
5212static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
5213{
5214 flush_delayed_work(&hdd_ctx->roc_req_work);
5215 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
Houston Hoffman2eac7c42016-12-12 12:22:52 -08005216 qdf_spinlock_destroy(&hdd_ctx->hdd_roc_req_q_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005217}
5218
5219/**
Houston Hoffman160db392016-10-10 17:37:51 -07005220 * hdd_context_deinit() - Deinitialize HDD context
5221 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005222 *
Houston Hoffman160db392016-10-10 17:37:51 -07005223 * Deinitialize HDD context along with all the feature specific contexts but
5224 * do not free hdd context itself. Caller of this API is supposed to free
5225 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005226 *
Houston Hoffman160db392016-10-10 17:37:51 -07005227 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005228 */
Houston Hoffman160db392016-10-10 17:37:51 -07005229static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005230{
Houston Hoffman160db392016-10-10 17:37:51 -07005231 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005232
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005233 hdd_roc_context_destroy(hdd_ctx);
5234
5235 hdd_sap_context_destroy(hdd_ctx);
5236
5237 hdd_rx_wake_lock_destroy(hdd_ctx);
5238
5239 hdd_tdls_context_destroy(hdd_ctx);
5240
5241 hdd_scan_context_destroy(hdd_ctx);
5242
5243 qdf_list_destroy(&hdd_ctx->hddAdapters);
5244
Houston Hoffman160db392016-10-10 17:37:51 -07005245 return 0;
5246}
5247
5248/**
5249 * hdd_context_destroy() - Destroy HDD context
5250 * @hdd_ctx: HDD context to be destroyed.
5251 *
5252 * Free config and HDD context as well as destroy all the resources.
5253 *
5254 * Return: None
5255 */
5256static void hdd_context_destroy(hdd_context_t *hdd_ctx)
5257{
5258 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
5259 hdd_logging_sock_deactivate_svc(hdd_ctx);
5260
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05305261 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5262
Houston Hoffman160db392016-10-10 17:37:51 -07005263 hdd_context_deinit(hdd_ctx);
5264
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305265 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005266 hdd_ctx->config = NULL;
5267
5268 wiphy_free(hdd_ctx->wiphy);
5269}
5270
5271/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272 * hdd_wlan_exit() - HDD WLAN exit function
5273 * @hdd_ctx: Pointer to the HDD Context
5274 *
5275 * This is the driver exit point (invoked during rmmod)
5276 *
5277 * Return: None
5278 */
Jeff Johnson590e2012016-10-05 16:16:24 -07005279static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280{
5281 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305282 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05305284 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285
5286 ENTER();
5287
Arun Khandavallifae92942016-08-01 13:31:08 +05305288 if (QDF_TIMER_STATE_RUNNING ==
5289 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
5290 hdd_info("Stpp interface change timer");
5291 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 }
5293
Arun Khandavallifae92942016-08-01 13:31:08 +05305294 if (!QDF_IS_STATUS_SUCCESS
5295 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
5296 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07005297
Arun Khandavallifae92942016-08-01 13:31:08 +05305298
5299 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300
Nitesh Shah61c10d92016-10-19 19:29:15 +05305301 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
5302
Prashanth Bhattaab004382016-10-11 16:08:11 -07005303 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304
5305#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305306 if (QDF_TIMER_STATE_RUNNING ==
5307 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
5308 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309 }
5310
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305311 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05305312 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005313 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 }
Liangwei Dongaef84342016-10-21 05:28:00 -04005315 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5316 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5317 hdd_ctx->last_acs_channel_list = NULL;
5318 hdd_ctx->num_of_channels = 0;
5319 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321
Arun Khandavallifae92942016-08-01 13:31:08 +05305322 mutex_lock(&hdd_ctx->iface_change_lock);
5323 driver_status = hdd_ctx->driver_status;
5324 mutex_unlock(&hdd_ctx->iface_change_lock);
5325
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005326 /*
5327 * Powersave Offload Case
5328 * Disable Idle Power Save Mode
5329 */
5330 hdd_set_idle_ps_config(hdd_ctx, false);
5331
Arun Khandavallifae92942016-08-01 13:31:08 +05305332 if (driver_status != DRIVER_MODULES_CLOSED) {
5333 hdd_unregister_wext_all_adapters(hdd_ctx);
5334 /*
5335 * Cancel any outstanding scan requests. We are about to close
5336 * all of our adapters, but an adapter structure is what SME
5337 * passes back to our callback function. Hence if there
5338 * are any outstanding scan requests then there is a
5339 * race condition between when the adapter is closed and
5340 * when the callback is invoked. We try to resolve that
5341 * race condition here by canceling any outstanding scans
5342 * before we close the adapters.
5343 * Note that the scans may be cancelled in an asynchronous
5344 * manner, so ideally there needs to be some kind of
5345 * synchronization. Rather than introduce a new
5346 * synchronization here, we will utilize the fact that we are
5347 * about to Request Full Power, and since that is synchronized,
5348 * the expectation is that by the time Request Full Power has
5349 * completed, all scans will be cancelled
5350 */
Sandeep Puligilla1fcdb772017-02-22 21:14:59 -08005351#ifndef NAPIER_SCAN
Jeff Johnsonf337b0c2017-03-10 10:48:30 -08005352 hdd_cleanup_scan_queue(hdd_ctx);
Sandeep Puligilla1fcdb772017-02-22 21:14:59 -08005353#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05305354 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07005355 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05305356 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 }
5358
5359 /*
5360 * Close the scheduler before calling cds_close to make sure no thread
5361 * is scheduled after the each module close is called i.e after all the
5362 * data structures are freed.
5363 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305364 qdf_status = cds_sched_close(p_cds_context);
5365 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005366 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305367 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005369
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07005370 hdd_wlan_stop_modules(hdd_ctx, false);
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05305371
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305372 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
5373 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
5374 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
5375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 /*
5377 * Close CDS
5378 * This frees pMac(HAL) context. There should not be any call
5379 * that requires pMac access after this.
5380 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07005382 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08005383 hdd_request_manager_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005384
Komal Seelam8634b772016-09-29 12:12:24 +05305385 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005386 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387
5388 hdd_ipa_cleanup(hdd_ctx);
5389
5390 /* Free up RoC request queue and flush workqueue */
5391 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005392
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05305393 wlansap_global_deinit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05305394 wlan_hdd_deinit_chan_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05305396 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005397
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07005398 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07005399
Arun Khandavallifae92942016-08-01 13:31:08 +05305400 hdd_exit_netlink_services(hdd_ctx);
5401 mutex_destroy(&hdd_ctx->iface_change_lock);
Abhishek Singhe9068f12017-03-31 14:14:52 +05305402
5403 driver_status = hdd_objmgr_release_and_destroy_pdev(hdd_ctx);
5404 if (driver_status)
5405 hdd_err("Pdev delete failed");
5406
5407 driver_status = hdd_objmgr_release_and_destroy_psoc(hdd_ctx);
5408 if (driver_status)
5409 hdd_err("Psoc delete failed");
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005410 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005411}
5412
5413void __hdd_wlan_exit(void)
5414{
5415 hdd_context_t *hdd_ctx;
5416
5417 ENTER();
5418
Anurag Chouhan6d760662016-02-20 16:05:43 +05305419 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07005421 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422 EXIT();
5423 return;
5424 }
5425
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005426 /* Check IPA HW Pipe shutdown */
5427 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
5428
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005429 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05305430 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005431
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005432 /* Do all the cleanup before deregistering the driver */
5433 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07005434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005435 EXIT();
5436}
5437
5438#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04005439/**
5440 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
5441 * @data: pointer to hdd_context_t
5442 *
5443 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
5444 * Then new ACS request will do a fresh scan without reusing the cached
5445 * scan information.
5446 *
5447 * Return: void
5448 */
Tang Yingying523322d2017-01-17 23:28:43 +08005449static void hdd_skip_acs_scan_timer_handler(void *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450{
5451 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
5452
Jeff Johnson760350b2016-08-15 14:01:52 -07005453 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04005455 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
5456 qdf_mem_free(hdd_ctx->last_acs_channel_list);
5457 hdd_ctx->last_acs_channel_list = NULL;
5458 hdd_ctx->num_of_channels = 0;
5459 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460
5461 if (!hdd_ctx->hHal)
5462 return;
5463 sme_scan_flush_result(hdd_ctx->hHal);
5464}
5465#endif
5466
5467#ifdef QCA_HT_2040_COEX
5468/**
5469 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
5470 * @adapter: pointer to adapter
5471 * @staId: station id
5472 * @macAddrSTA: station MAC address
5473 * @channel_type: channel type
5474 *
5475 * This function notifies FW with HT20/HT40 mode
5476 *
5477 * Return: 0 if successful, error number otherwise
5478 */
5479int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305480 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481{
5482 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305483 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005484 hdd_context_t *hdd_ctx = NULL;
5485
5486 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5487
5488 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305489 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005490 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305491
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492 if (!hdd_ctx->hHal)
5493 return -EINVAL;
5494
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305495 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305497 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005498 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005499 return -EINVAL;
5500 }
5501
5502 return 0;
5503}
5504#endif
5505
5506/**
5507 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5508 * @state: state
5509 *
5510 * This function notifies FW with modem power status
5511 *
5512 * Return: 0 if successful, error number otherwise
5513 */
5514int hdd_wlan_notify_modem_power_state(int state)
5515{
5516 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305517 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 hdd_context_t *hdd_ctx;
5519
Anurag Chouhan6d760662016-02-20 16:05:43 +05305520 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305522 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305524
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 if (!hdd_ctx->hHal)
5526 return -EINVAL;
5527
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305528 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5529 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005530 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 state);
5532 return -EINVAL;
5533 }
5534 return 0;
5535}
5536
5537/**
5538 *
5539 * hdd_post_cds_enable_config() - HDD post cds start config helper
5540 * @adapter - Pointer to the HDD
5541 *
5542 * Return: None
5543 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305544QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005545{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305546 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005547
5548 /*
5549 * Send ready indication to the HDD. This will kick off the MAC
5550 * into a 'running' state and should kick off an initial scan.
5551 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305552 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5553 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005554 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5555 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305556 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 }
5558
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305559 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560}
5561
5562/* wake lock APIs for HDD */
5563void hdd_prevent_suspend(uint32_t reason)
5564{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305565 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566}
5567
5568void hdd_allow_suspend(uint32_t reason)
5569{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305570 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571}
5572
5573void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5574{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305575 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5576 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577}
5578
5579/**
5580 * hdd_exchange_version_and_caps() - exchange version and capability with target
5581 * @hdd_ctx: Pointer to HDD context
5582 *
5583 * This is the HDD function to exchange version and capability information
5584 * between Host and Target
5585 *
5586 * This function gets reported version of FW.
5587 * It also finds the version of target headers used to compile the host;
5588 * It compares the above two and prints a warning if they are different;
5589 * It gets the SW and HW version string;
5590 * Finally, it exchanges capabilities between host and target i.e. host
5591 * and target exchange a msg indicating the features they support through a
5592 * bitmap
5593 *
5594 * Return: None
5595 */
5596void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5597{
5598
5599 tSirVersionType versionCompiled;
5600 tSirVersionType versionReported;
5601 tSirVersionString versionString;
5602 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305603 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604
5605 memset(&versionCompiled, 0, sizeof(versionCompiled));
5606 memset(&versionReported, 0, sizeof(versionReported));
5607
5608 /* retrieve and display WCNSS version information */
5609 do {
5610
5611 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5612 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305613 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005614 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615 break;
5616 }
5617
5618 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5619 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305620 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005621 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005622 break;
5623 }
5624
5625 if ((versionCompiled.major != versionReported.major) ||
5626 (versionCompiled.minor != versionReported.minor) ||
5627 (versionCompiled.version != versionReported.version) ||
5628 (versionCompiled.revision != versionReported.revision)) {
5629 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5630 "Host expected %u.%u.%u.%u\n",
5631 WLAN_MODULE_NAME,
5632 (int)versionReported.major,
5633 (int)versionReported.minor,
5634 (int)versionReported.version,
5635 (int)versionReported.revision,
5636 (int)versionCompiled.major,
5637 (int)versionCompiled.minor,
5638 (int)versionCompiled.version,
5639 (int)versionCompiled.revision);
5640 } else {
5641 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5642 WLAN_MODULE_NAME,
5643 (int)versionReported.major,
5644 (int)versionReported.minor,
5645 (int)versionReported.version,
5646 (int)versionReported.revision);
5647 }
5648
5649 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5650 versionString,
5651 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305652 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005653 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654 break;
5655 }
5656
5657 pr_info("%s: WCNSS software version %s\n",
5658 WLAN_MODULE_NAME, versionString);
5659
5660 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5661 versionString,
5662 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305663 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005664 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 break;
5666 }
5667
5668 pr_info("%s: WCNSS hardware version %s\n",
5669 WLAN_MODULE_NAME, versionString);
5670
5671 /*
5672 * 1.Check if FW version is greater than 0.1.1.0. Only then
5673 * send host-FW capability exchange message
5674 * 2.Host-FW capability exchange message is only present on
5675 * target 1.1 so send the message only if it the target is 1.1
5676 * minor numbers for different target branches:
5677 * 0 -> (1.0)Mainline Build
5678 * 1 -> (1.1)Mainline Build
5679 * 2->(1.04) Stability Build
5680 */
5681 if (((versionReported.major > 0) || (versionReported.minor > 1)
5682 || ((versionReported.minor >= 1)
5683 && (versionReported.version >= 1)))
5684 && ((versionReported.major == 1)
5685 && (versionReported.minor >= 1)))
5686 fwFeatCapsMsgSupported = 1;
5687
5688 if (fwFeatCapsMsgSupported) {
5689 /*
5690 * Indicate if IBSS heartbeat monitoring needs to be
5691 * offloaded
5692 */
5693 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5694 sme_disable_feature_capablity
5695 (IBSS_HEARTBEAT_OFFLOAD);
5696 }
5697
5698 sme_feature_caps_exchange(hdd_ctx->hHal);
5699 }
5700
5701 } while (0);
5702
5703}
5704
5705/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305706QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005707{
5708 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5709 hdd_ctx->reg.cc_src);
5710}
5711
5712/**
5713 * hdd_is_5g_supported() - check if hardware supports 5GHz
5714 * @hdd_ctx: Pointer to the hdd context
5715 *
5716 * HDD function to know if hardware supports 5GHz
5717 *
5718 * Return: true if hardware supports 5GHz
5719 */
5720bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5721{
zdingf54169a2016-10-12 17:08:45 +08005722 if (!hdd_ctx || !hdd_ctx->config)
5723 return true;
5724
5725 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5726 return true;
5727 else
5728 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005729}
5730
Amar Singhale4f28ee2015-10-21 14:36:56 -07005731static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005732{
5733 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005734 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735
5736 wiphy = hdd_ctx->wiphy;
5737
5738 /*
5739 * The channel information in
5740 * wiphy needs to be initialized before wiphy registration
5741 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005742 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5743 if (ret_val) {
5744 hdd_alert("regulatory init failed");
5745 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005746 }
5747
5748#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5749 wiphy->wowlan = &wowlan_support_reg_init;
5750#else
5751 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5752 WIPHY_WOWLAN_MAGIC_PKT |
5753 WIPHY_WOWLAN_DISCONNECT |
5754 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5755 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5756 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5757 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5758 WIPHY_WOWLAN_RFKILL_RELEASE;
5759
5760 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5761 WOW_MAX_FILTERS_PER_LIST);
5762 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5763 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5764#endif
5765
5766 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005767 ret_val = wlan_hdd_cfg80211_register(wiphy);
5768 if (0 > ret_val)
5769 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005770
Amar Singhale4f28ee2015-10-21 14:36:56 -07005771 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005772}
5773
Ravi Joshie2331e82015-07-01 18:18:54 -07005774/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005775 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005776 * @hdd_ctx - handle to hdd context
5777 * @tx_packets - transmit packet count
5778 * @rx_packets - receive packet count
5779 *
5780 * The function controls the bus bandwidth and dynamic control of
5781 * tcp delayed ack configuration
5782 *
5783 * Returns: None
5784 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005785#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005786static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5787 const uint64_t tx_packets,
5788 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005789{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005791 uint64_t temp_rx = 0;
5792 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005793 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005794 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5795 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005796 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005799 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005801 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005802 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005803 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005804 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005805 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806
Mohit Khannae71e2262015-11-10 09:37:24 -08005807 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5808 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809
5810 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005811 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5812 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005813 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005814 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305815 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305816 if (hdd_ctx->hbw_requested) {
5817 pld_remove_pm_qos(hdd_ctx->parent_dev);
5818 hdd_ctx->hbw_requested = false;
5819 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305820 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005821 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305822 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305823 if (!hdd_ctx->hbw_requested) {
5824 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5825 hdd_ctx->hbw_requested = true;
5826 }
5827
Nirav Shah3bbfa512016-05-12 16:43:49 +05305828 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005829 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305830 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005831 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005833
5834 /* fine-tuning parameters for RX Flows */
5835 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005837 hdd_ctx->prev_rx = rx_packets;
Ravi Joshifed83572016-10-07 16:20:37 -07005838 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5839 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5840 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5841 next_rx_level = WLAN_SVC_TP_HIGH;
5842 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005843 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005844 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005845 hdd_ctx->rx_high_ind_cnt = 0;
5846 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005847
Mohit Khannae71e2262015-11-10 09:37:24 -08005848 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5849 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850
5851 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005852 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853 next_rx_level, temp_rx);
5854 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005855 /* Send throughput indication only if it is enabled.
5856 * Disabling tcp_del_ack will revert the tcp stack behavior
5857 * to default delayed ack. Note that this will disable the
5858 * dynamic delayed ack mechanism across the system
5859 */
5860 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305861 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5862 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005863 &next_rx_level,
5864 sizeof(next_rx_level));
5865 }
5866
Mohit Khannae71e2262015-11-10 09:37:24 -08005867 /* fine-tuning parameters for TX Flows */
5868 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5869 hdd_ctx->prev_tx = tx_packets;
5870 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5871 next_tx_level = WLAN_SVC_TP_HIGH;
5872 else
5873 next_tx_level = WLAN_SVC_TP_LOW;
5874
5875 if (hdd_ctx->cur_tx_level != next_tx_level) {
5876 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5877 next_tx_level, temp_tx);
5878 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305879 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5880 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005881 &next_tx_level,
5882 sizeof(next_tx_level));
5883 }
5884
5885 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5886 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005887 hdd_ctx->hdd_txrx_hist_idx++;
5888 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005889}
5890
5891#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305892static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305894 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5895 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005896 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305897 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305898 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5899 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900 uint64_t total_tx = 0, total_rx = 0;
5901 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305902 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305903 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005904 bool connected = false;
5905 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5906
Prashanth Bhattaab004382016-10-11 16:08:11 -07005907 if (wlan_hdd_validate_context(hdd_ctx))
5908 return;
5909
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005910 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305911 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005912 status =
5913 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5914
5915 if (adapterNode->pAdapter == NULL)
5916 continue;
5917 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305918 /*
5919 * Validate magic so we don't end up accessing
5920 * an invalid adapter.
5921 */
5922 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5923 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005925 if ((adapter->device_mode == QDF_STA_MODE ||
5926 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5928 != eConnectionState_Associated) {
5929
5930 continue;
5931 }
5932
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005933 if ((adapter->device_mode == QDF_SAP_MODE ||
5934 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005935 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5936
5937 continue;
5938 }
5939
5940 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5941 adapter->prev_tx_packets);
5942 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5943 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305944
5945 if (adapter->device_mode == QDF_SAP_MODE ||
5946 adapter->device_mode == QDF_P2P_GO_MODE ||
5947 adapter->device_mode == QDF_IBSS_MODE) {
5948
Dhanashri Atrea8f82f22017-01-23 12:58:24 -08005949 ret = cdp_get_intra_bss_fwd_pkts_count(
5950 cds_get_context(QDF_MODULE_ID_SOC),
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305951 adapter->sessionId,
5952 &fwd_tx_packets, &fwd_rx_packets);
5953 if (ret == A_OK) {
5954 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5955 fwd_tx_packets,
5956 adapter->prev_fwd_tx_packets);
5957 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5958 fwd_tx_packets,
5959 adapter->prev_fwd_rx_packets);
5960 }
5961 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962
5963 total_rx += adapter->stats.rx_packets;
5964 total_tx += adapter->stats.tx_packets;
5965
5966 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5967 adapter->prev_tx_packets = adapter->stats.tx_packets;
5968 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305969 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5970 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5972 connected = true;
5973 }
5974
5975 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5976 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5977 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5978 rx_packets;
5979 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5980 tx_packets;
5981
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305982 /* add intra bss forwarded tx and rx packets */
5983 tx_packets += fwd_tx_packets_diff;
5984 rx_packets += fwd_rx_packets_diff;
5985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5987 tx_packets += (uint64_t)ipa_tx_packets;
5988 rx_packets += (uint64_t)ipa_rx_packets;
5989
5990 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005991 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005992 return;
5993 }
5994
Yuanyuan Liu13738502016-04-06 17:41:37 -07005995 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005996
5997 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5998 hdd_ipa_uc_stat_request(adapter, 2);
5999
Dustin Brown2ed60362017-01-18 12:25:50 -08006000 /* ensure periodic timer should still be running before restarting it */
Dustin Brownfce08d12017-01-17 16:29:38 -08006001 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown2ed60362017-01-18 12:25:50 -08006002 if (hdd_ctx->bus_bw_timer_running)
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05306003 qdf_timer_mod(&hdd_ctx->bus_bw_timer,
Dustin Brownfce08d12017-01-17 16:29:38 -08006004 hdd_ctx->config->busBandwidthComputeInterval);
Dustin Brownfce08d12017-01-17 16:29:38 -08006005 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006006}
Prashanth Bhattaab004382016-10-11 16:08:11 -07006007
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306008/**
6009 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
6010 * @arg: Argument of timer function
6011 *
6012 * Schedule a workqueue in this function where all the processing is done.
6013 *
6014 * Return: None.
6015 */
6016static void __hdd_bus_bw_cbk(void *arg)
6017{
6018 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
6019
6020 if (wlan_hdd_validate_context(hdd_ctx))
6021 return;
6022
6023 schedule_work(&hdd_ctx->bus_bw_work);
6024}
6025
6026/**
6027 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
6028 * @arg: Argument of timer function
6029 *
6030 * Return: None.
6031 */
6032static void hdd_bus_bw_cbk(void *arg)
6033{
6034 cds_ssr_protect(__func__);
6035 __hdd_bus_bw_cbk(arg);
6036 cds_ssr_unprotect(__func__);
6037}
6038
Prashanth Bhattaab004382016-10-11 16:08:11 -07006039int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
6040{
6041 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306042 INIT_WORK(&hdd_ctx->bus_bw_work,
6043 hdd_bus_bw_work_handler);
Dustin Brownfce08d12017-01-17 16:29:38 -08006044 hdd_ctx->bus_bw_timer_running = false;
6045 qdf_spinlock_create(&hdd_ctx->bus_bw_timer_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306046 qdf_timer_init(NULL,
6047 &hdd_ctx->bus_bw_timer,
6048 hdd_bus_bw_cbk, (void *)hdd_ctx,
6049 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006050
6051 return 0;
6052}
6053
6054void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
6055{
Dustin Brownfce08d12017-01-17 16:29:38 -08006056 if (hdd_ctx->bus_bw_timer_running)
Prashanth Bhattaab004382016-10-11 16:08:11 -07006057 hdd_reset_tcp_delack(hdd_ctx);
6058
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05306059 hdd_info("wait for bus bw work to flush");
6060 cancel_work_sync(&hdd_ctx->bus_bw_work);
6061 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Dustin Brownfce08d12017-01-17 16:29:38 -08006062 hdd_ctx->bus_bw_timer_running = false;
6063 qdf_spinlock_destroy(&hdd_ctx->bus_bw_timer_lock);
Prashanth Bhattaab004382016-10-11 16:08:11 -07006064}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006065#endif
6066
6067/**
Nirav Shahed34b212016-04-25 10:59:16 +05306068 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
6069 * @hdd_ctx: hdd context
6070 *
6071 * Return: 0 for success or error code
6072 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006073static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05306074{
6075 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
6076 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
6077 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006078 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05306079 return -ENOMEM;
6080 }
6081 return 0;
6082}
6083
6084/**
6085 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
6086 * @hdd_ctx: hdd context
6087 *
6088 * Return: none
6089 */
6090void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
6091{
6092 if (hdd_ctx->hdd_txrx_hist) {
6093 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
6094 hdd_ctx->hdd_txrx_hist = NULL;
6095 }
6096}
6097
Nirav Shahda008342016-05-17 18:50:40 +05306098static uint8_t *convert_level_to_string(uint32_t level)
6099{
6100 switch (level) {
6101 /* initialize the wlan sub system */
6102 case WLAN_SVC_TP_NONE:
6103 return "NONE";
6104 case WLAN_SVC_TP_LOW:
6105 return "LOW";
6106 case WLAN_SVC_TP_MEDIUM:
6107 return "MED";
6108 case WLAN_SVC_TP_HIGH:
6109 return "HIGH";
6110 default:
6111 return "INVAL";
6112 }
6113}
6114
Nirav Shahed34b212016-04-25 10:59:16 +05306115
6116/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006117 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
6118 * @hdd_ctx: hdd context
6119 *
6120 * Return: none
6121 */
6122void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
6123{
6124 int i;
6125
6126#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07006127 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05306128 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07006129 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006130 hdd_ctx->config->busBandwidthHighThreshold,
6131 hdd_ctx->config->busBandwidthMediumThreshold,
6132 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07006133 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306134 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07006135 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006136 hdd_ctx->config->tcpDelackThresholdHigh,
6137 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07006138 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05306139 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006140#endif
6141
Jeff Johnson760350b2016-08-15 14:01:52 -07006142 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05306143 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
6144
Jeff Johnson760350b2016-08-15 14:01:52 -07006145 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 -08006146
6147 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006148 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006149 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
6150 hdd_ctx->hdd_txrx_hist[i].interval_rx,
6151 hdd_ctx->hdd_txrx_hist[i].total_tx,
6152 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05306153 convert_level_to_string(
6154 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
6155 convert_level_to_string(
6156 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
6157 convert_level_to_string(
6158 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006159 }
6160 return;
6161}
6162
6163/**
6164 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
6165 * @hdd_ctx: hdd context
6166 *
6167 * Return: none
6168 */
6169void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
6170{
6171 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05306172 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
6173 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174}
6175
6176/**
6177 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
6178 * @pHddCtx: hdd context
6179 *
6180 * Return: none
6181 */
6182void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
6183{
6184
6185 hdd_adapter_t *adapter = NULL;
6186 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306187 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006188 int i;
Nirav Shahda008342016-05-17 18:50:40 +05306189 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006190
6191 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306192 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006193 adapter = adapter_node->pAdapter;
6194
Jeff Johnson760350b2016-08-15 14:01:52 -07006195 hdd_err("\nNetif queue operation statistics:");
6196 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05306197 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07006198 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05306199 curr_time = qdf_system_ticks();
6200 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05306201 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05306202 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05306203 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306204 unpause = adapter->total_unpause_time;
6205 } else {
Nirav Shahda008342016-05-17 18:50:40 +05306206 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05306207 pause = adapter->total_pause_time;
6208 }
Jeff Johnson760350b2016-08-15 14:01:52 -07006209 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05306210 qdf_system_ticks_to_msecs(total),
6211 qdf_system_ticks_to_msecs(pause),
6212 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07006213 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006214
Nirav Shahda008342016-05-17 18:50:40 +05306215 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
6216 qdf_time_t pause_delta = 0;
6217
6218 if (adapter->pause_map & (1 << i))
6219 pause_delta = delta;
6220
Jeff Johnson760350b2016-08-15 14:01:52 -07006221 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006222 hdd_reason_type_to_string(i),
6223 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05306224 adapter->queue_oper_stats[i].unpause_count,
6225 qdf_system_ticks_to_msecs(
6226 adapter->queue_oper_stats[i].total_pause_time +
6227 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006228 }
6229
Jeff Johnson760350b2016-08-15 14:01:52 -07006230 hdd_err("\nNetif queue operation history:");
6231 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05306232 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
6233
Jeff Johnson760350b2016-08-15 14:01:52 -07006234 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006235
6236 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07006237 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05306238 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239 adapter->queue_oper_history[i].time),
6240 hdd_action_type_to_string(
6241 adapter->queue_oper_history[i].netif_action),
6242 hdd_reason_type_to_string(
6243 adapter->queue_oper_history[i].netif_reason),
6244 adapter->queue_oper_history[i].pause_map);
6245 }
6246
6247 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6248 adapter_node = next;
6249 }
6250
6251
6252}
6253
6254/**
6255 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
6256 * @hdd_ctx: hdd context
6257 *
6258 * Return: none
6259 */
6260void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
6261{
6262 hdd_adapter_t *adapter = NULL;
6263 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306264 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006265
6266 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306267 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006268 adapter = adapter_node->pAdapter;
6269
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306270 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006271 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306272 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006273 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05306274 adapter->history_index = 0;
6275 adapter->start_time = adapter->last_time = qdf_system_ticks();
6276 adapter->total_pause_time = 0;
6277 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006278 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
6279 adapter_node = next;
6280 }
6281}
6282
6283/**
6284 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
6285 * @halHandle: Hal handle
6286 * @pContext: Pointer to the context
6287 * @sessionId: Session ID
6288 * @scanId: Scan ID
6289 * @status: Status
6290 *
6291 * This is the callback to be executed when 11d scan is completed to flush out
6292 * the scan results
6293 *
6294 * 11d scan is done during driver load and is a passive scan on all
6295 * channels supported by the device, 11d scans may find some APs on
6296 * frequencies which are forbidden to be used in the regulatory domain
6297 * the device is operating in. If these APs are notified to the supplicant
6298 * it may try to connect to these APs, thus flush out all the scan results
6299 * which are present in SME after 11d scan is done.
6300 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306301 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006302 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306303static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006304 uint8_t sessionId, uint32_t scanId,
6305 eCsrScanStatus status)
6306{
6307 ENTER();
6308
6309 sme_scan_flush_result(halHandle);
6310
6311 EXIT();
6312
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306313 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006314}
6315
6316#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
6317/**
6318 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
6319 * @hdd_ctx: hdd global context
6320 *
6321 * Return: none
6322 */
6323static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6324{
6325 uint8_t i;
6326
6327 mutex_init(&hdd_ctx->op_ctx.op_lock);
6328 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
6329 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
6330 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
6331 }
6332}
6333#else
6334static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
6335{
6336}
6337#endif
6338
Yingying Tang95409972016-10-20 15:16:15 +08006339#ifdef WLAN_FEATURE_WOW_PULSE
6340/**
6341 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
6342 * @phddctx: hdd_context_t structure pointer
6343 * @enable: enable or disable this behaviour
6344 *
6345 * Return: int
6346 */
6347static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6348{
6349 struct hdd_config *pcfg_ini = phddctx->config;
6350 struct wow_pulse_mode wow_pulse_set_info;
6351 QDF_STATUS status;
6352
6353 hdd_notice("wow pulse enable flag is %d", enable);
6354
6355 if (false == phddctx->config->wow_pulse_support)
6356 return 0;
6357
6358 /* prepare the request to send to SME */
6359 if (enable == true) {
6360 wow_pulse_set_info.wow_pulse_enable = true;
6361 wow_pulse_set_info.wow_pulse_pin =
6362 pcfg_ini->wow_pulse_pin;
6363 wow_pulse_set_info.wow_pulse_interval_low =
6364 pcfg_ini->wow_pulse_interval_low;
6365 wow_pulse_set_info.wow_pulse_interval_high =
6366 pcfg_ini->wow_pulse_interval_high;
6367 } else {
6368 wow_pulse_set_info.wow_pulse_enable = false;
6369 wow_pulse_set_info.wow_pulse_pin = 0;
6370 wow_pulse_set_info.wow_pulse_interval_low = 0;
6371 wow_pulse_set_info.wow_pulse_interval_high = 0;
6372 }
6373 hdd_notice("enable %d pin %d low %d high %d",
6374 wow_pulse_set_info.wow_pulse_enable,
6375 wow_pulse_set_info.wow_pulse_pin,
6376 wow_pulse_set_info.wow_pulse_interval_low,
6377 wow_pulse_set_info.wow_pulse_interval_high);
6378
6379 status = sme_set_wow_pulse(&wow_pulse_set_info);
6380 if (QDF_STATUS_E_FAILURE == status) {
6381 hdd_notice("sme_set_wow_pulse failure!");
6382 return -EIO;
6383 }
6384 hdd_notice("sme_set_wow_pulse success!");
6385 return 0;
6386}
6387#else
6388static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
6389{
6390 return 0;
6391}
6392#endif
6393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006394#ifdef WLAN_FEATURE_FASTPATH
6395/**
6396 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
6397 * @hdd_cfg: hdd config
6398 * @context: lower layer context
6399 *
6400 * Return: none
6401 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306402void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006403 void *context)
6404{
6405 if (hdd_cfg->fastpath_enable)
6406 hif_enable_fastpath(context);
6407}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006408#endif
6409
Yuanyuan Liu13738502016-04-06 17:41:37 -07006410#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006411/**
6412 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006413 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006414 * @level: thermal level
6415 *
6416 * Change IPA data path to SW path when the thermal throttle level greater
6417 * than 0, and restore the original data path when throttle level is 0
6418 *
6419 * Return: none
6420 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006421static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006422{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006423 hdd_context_t *hdd_ctx = context;
6424
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006425 /* Change IPA to SW path when throttle level greater than 0 */
6426 if (level > THROTTLE_LEVEL_0)
6427 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
6428 else
6429 /* restore original concurrency mode */
6430 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
6431}
6432
6433/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306434 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
6435 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05306436 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006437 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306438 * Get a safe channel to restart SAP. PCL already takes into account the
6439 * unsafe channels. So, the PCL is validated with the ACS range to provide
6440 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006441 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306442 * Return: Channel number to restart SAP in case of success. In case of any
6443 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006444 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306445static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
6446 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006447{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306448 struct sir_pcl_list pcl;
6449 QDF_STATUS status;
6450 uint32_t i, j;
6451 tHalHandle *hal_handle;
6452 hdd_context_t *hdd_ctx;
6453 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006454
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306455 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6456 if (!hdd_ctx) {
6457 hdd_err("invalid HDD context");
6458 return INVALID_CHANNEL_ID;
6459 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006460
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05306461 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6462 if (!hal_handle) {
6463 hdd_err("invalid HAL handle");
6464 return INVALID_CHANNEL_ID;
6465 }
6466
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006467 status = policy_mgr_get_pcl_for_existing_conn(hdd_ctx->hdd_psoc,
6468 PM_SAP_MODE, pcl.pcl_list, &pcl.pcl_len,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306469 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
6470 if (QDF_IS_STATUS_ERROR(status)) {
6471 hdd_err("Get PCL failed");
6472 return INVALID_CHANNEL_ID;
6473 }
6474
6475 if (!pcl.pcl_len) {
6476 hdd_alert("pcl length is zero. this is not expected");
6477 return INVALID_CHANNEL_ID;
6478 }
6479
6480 hdd_info("start:%d end:%d",
6481 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6482 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6483
6484 /* PCL already takes unsafe channel into account */
6485 for (i = 0; i < pcl.pcl_len; i++) {
6486 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6487 if ((pcl.pcl_list[i] >=
6488 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6489 (pcl.pcl_list[i] <=
6490 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6491 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
6492 return pcl.pcl_list[i];
6493 }
6494 }
6495
6496 hdd_info("no safe channel from PCL found in ACS range");
6497
6498 /* Try for safe channel from all valid channel */
6499 pcl.pcl_len = MAX_NUM_CHAN;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006500 status = sme_get_cfg_valid_channels(pcl.pcl_list,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306501 &pcl.pcl_len);
6502 if (QDF_IS_STATUS_ERROR(status)) {
6503 hdd_err("error in getting valid channel list");
6504 return INVALID_CHANNEL_ID;
6505 }
6506
6507 for (i = 0; i < pcl.pcl_len; i++) {
6508 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6509 found = false;
6510 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006511 if (pcl.pcl_list[i] ==
6512 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306513 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
6514 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006515 break;
6516 }
6517 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306518
6519 if (found)
6520 continue;
6521
6522 if ((pcl.pcl_list[i] >=
6523 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6524 (pcl.pcl_list[i] <=
6525 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6526 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
6527 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006528 }
6529 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306530
6531 return INVALID_CHANNEL_ID;
6532}
6533
6534/**
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006535 * hdd_switch_sap_channel() - Move SAP to the given channel
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306536 * @adapter: AP adapter
6537 * @channel: Channel
6538 *
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006539 * Moves the SAP interface by invoking the function which
6540 * executes the callback to perform channel switch using (E)CSA.
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306541 *
6542 * Return: None
6543 */
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006544void hdd_switch_sap_channel(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306545{
6546 hdd_ap_ctx_t *hdd_ap_ctx;
6547 tHalHandle *hal_handle;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006548 hdd_context_t *hdd_ctx;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306549
6550 if (!adapter) {
6551 hdd_err("invalid adapter");
6552 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006553 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306554
6555 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6556
6557 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6558 if (!hal_handle) {
6559 hdd_err("invalid HAL handle");
6560 return;
6561 }
6562
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006563 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6564
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306565 hdd_ap_ctx->sapConfig.channel = channel;
6566 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6567 hdd_ap_ctx->sapConfig.ch_width_orig;
6568
6569 hdd_info("chan:%d width:%d",
6570 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6571
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006572 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306573 hdd_ap_ctx->sapConfig.sec_ch,
6574 &hdd_ap_ctx->sapConfig.ch_params);
6575
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08006576 policy_mgr_change_sap_channel_with_csa(hdd_ctx->hdd_psoc,
6577 adapter->sessionId, channel,
6578 hdd_ap_ctx->sapConfig.ch_width_orig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006579}
Kapil Gupta8878ad92017-02-13 11:56:04 +05306580
6581int hdd_update_acs_timer_reason(hdd_adapter_t *adapter, uint8_t reason)
6582{
6583 struct hdd_external_acs_timer_context *timer_context;
6584
6585 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6586
6587 if (QDF_TIMER_STATE_RUNNING ==
6588 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
6589 ap.vendor_acs_timer)) {
6590 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
6591 }
6592 timer_context = (struct hdd_external_acs_timer_context *)
6593 adapter->sessionCtx.ap.vendor_acs_timer.user_data;
6594 timer_context->reason = reason;
6595 qdf_mc_timer_start(&adapter->sessionCtx.ap.vendor_acs_timer,
6596 WLAN_VENDOR_ACS_WAIT_TIME);
6597 /* Update config to application */
6598 hdd_cfg80211_update_acs_config(adapter, reason);
6599 hdd_notice("Updated ACS config to nl with reason %d", reason);
6600
6601 return 0;
6602}
6603
Agrawal Ashish467dde42016-09-08 18:44:22 +05306604/**
6605 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6606 * @hdd_ctx: hdd context pointer
6607 *
6608 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6609 * and if ACS is enabled, driver will ask userspace to restart the
6610 * sap. User space on LTE coex indication restart driver.
6611 *
6612 * Return - none
6613 */
6614void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6615{
6616 QDF_STATUS status;
6617 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6618 hdd_adapter_t *adapter_temp;
6619 uint32_t i;
6620 bool found = false;
6621 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006622
Agrawal Ashish467dde42016-09-08 18:44:22 +05306623 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6624 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6625 adapter_temp = adapter_node->pAdapter;
6626
6627 if (!adapter_temp) {
6628 hdd_err("adapter is NULL, moving to next one");
6629 goto next_adapater;
6630 }
6631
6632 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6633 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
6634 hdd_info("skip device mode:%d acs:%d",
6635 adapter_temp->device_mode,
6636 adapter_temp->sessionCtx.ap.sapConfig.
6637 acs_cfg.acs_mode);
6638 goto next_adapater;
6639 }
6640
6641 found = false;
6642 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006643 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306644 hdd_ctxt->unsafe_channel_list[i]) {
6645 found = true;
6646 hdd_info("operating ch:%d is unsafe",
6647 adapter_temp->sessionCtx.ap.operatingChannel);
6648 break;
6649 }
6650 }
6651
6652 if (!found) {
6653 hdd_info("ch:%d is safe. no need to change channel",
6654 adapter_temp->sessionCtx.ap.operatingChannel);
6655 goto next_adapater;
6656 }
6657
Kapil Gupta8878ad92017-02-13 11:56:04 +05306658 if (hdd_ctxt->config->vendor_acs_support &&
6659 hdd_ctxt->config->acs_support_for_dfs_ltecoex) {
6660 hdd_update_acs_timer_reason(adapter_temp,
6661 QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX);
6662 goto next_adapater;
6663 } else
6664 restart_chan =
6665 hdd_get_safe_channel_from_pcl_and_acs_range(
Agrawal Ashish467dde42016-09-08 18:44:22 +05306666 adapter_temp);
6667 if (!restart_chan) {
6668 hdd_alert("fail to restart SAP");
6669 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006670 /*
6671 * SAP restart due to unsafe channel. While
6672 * restarting the SAP, make sure to clear
6673 * acs_channel, channel to reset to
6674 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306675 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006676 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306677 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6678 adapter_temp->sessionCtx.ap.sapConfig.channel =
6679 AUTO_CHANNEL_SELECT;
Agrawal Ashish467dde42016-09-08 18:44:22 +05306680 hdd_info("sending coex indication");
6681 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6682 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006683 hdd_switch_sap_channel(adapter_temp, restart_chan);
Agrawal Ashish467dde42016-09-08 18:44:22 +05306684 }
6685
6686next_adapater:
6687 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6688 adapter_node = next;
6689 }
6690}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691/**
6692 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6693 * @adapter: HDD adapter pointer
6694 * @indParam: Channel avoid notification parameter
6695 *
6696 * Avoid channel notification from FW handler.
6697 * FW will send un-safe channel list to avoid over wrapping.
6698 * hostapd should not use notified channel
6699 *
6700 * Return: None
6701 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306702void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006704 hdd_context_t *hdd_ctxt;
6705 tSirChAvoidIndType *ch_avoid_indi;
6706 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006707 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6708 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006709 uint16_t start_channel;
6710 uint16_t end_channel;
6711 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006712 tHddAvoidFreqList hdd_avoid_freq_list;
6713 uint32_t i;
6714
6715 /* Basic sanity */
6716 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006717 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006718 return;
6719 }
6720
6721 hdd_ctxt = (hdd_context_t *) hdd_context;
6722 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6723 cds_context = hdd_ctxt->pcds_context;
6724
6725 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006726 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006727 ch_avoid_indi->avoid_range_count);
6728
6729 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306730 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006731 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6732 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6733 ch_avoid_indi->avoid_freq_range[i].start_freq;
6734 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6735 ch_avoid_indi->avoid_freq_range[i].end_freq;
6736 }
6737 hdd_avoid_freq_list.avoidFreqRangeCount =
6738 ch_avoid_indi->avoid_range_count;
6739
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740 /* clear existing unsafe channel cache */
6741 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306742 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006743 sizeof(hdd_ctxt->unsafe_channel_list));
6744
6745 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6746 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006747 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006748 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006749 break;
6750 }
6751
6752 start_channel = ieee80211_frequency_to_channel(
6753 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6754 end_channel = ieee80211_frequency_to_channel(
6755 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006756 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006757 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6758 start_channel,
6759 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6760 end_channel);
6761
6762 /* do not process frequency bands that are not mapped to
6763 * predefined channels
6764 */
6765 if (start_channel == 0 || end_channel == 0)
6766 continue;
6767
Amar Singhalb8d4f152016-02-10 10:21:43 -08006768 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6769 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006770 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006771 ch_avoid_indi->avoid_freq_range[
6772 range_loop].start_freq) {
6773 start_channel_idx = channel_loop;
6774 break;
6775 }
6776 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006777 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6778 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006779 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006780 ch_avoid_indi->avoid_freq_range[
6781 range_loop].end_freq) {
6782 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006783 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006784 ch_avoid_indi->avoid_freq_range[
6785 range_loop].end_freq)
6786 end_channel_idx--;
6787 break;
6788 }
6789 }
6790
Amar Singhalb8d4f152016-02-10 10:21:43 -08006791 if (start_channel_idx == INVALID_CHANNEL ||
6792 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006793 continue;
6794
6795 for (channel_loop = start_channel_idx; channel_loop <=
6796 end_channel_idx; channel_loop++) {
6797 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006798 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006799 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006800 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006801 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006802 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006803 break;
6804 }
6805 }
6806 }
6807
Jeff Johnson34c88b72016-08-15 14:27:11 -07006808 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006809 hdd_ctxt->unsafe_channel_count);
6810
Yuanyuan Liu13738502016-04-06 17:41:37 -07006811 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6812 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006813 hdd_ctxt->unsafe_channel_count)) {
6814 hdd_err("Failed to set unsafe channel");
6815
6816 /* clear existing unsafe channel cache */
6817 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306818 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006819 sizeof(hdd_ctxt->unsafe_channel_list));
6820
6821 return;
6822 }
6823
6824 for (channel_loop = 0;
6825 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006826 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006827 hdd_ctxt->unsafe_channel_list[channel_loop]);
6828 }
6829
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306830 /*
6831 * first update the unsafe channel list to the platform driver and
6832 * send the avoid freq event to the application
6833 */
6834 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6835
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306836 if (!hdd_ctxt->unsafe_channel_count) {
6837 hdd_info("no unsafe channels - not restarting SAP");
6838 return;
6839 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306840 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006841 return;
6842}
6843
6844/**
6845 * hdd_init_channel_avoidance() - Initialize channel avoidance
6846 * @hdd_ctx: HDD global context
6847 *
6848 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006849 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006850 * down to the lower layers. Then subscribe to subsequent channel
6851 * avoidance events.
6852 *
6853 * Return: None
6854 */
6855static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6856{
6857 uint16_t unsafe_channel_count;
6858 int index;
6859
Yuanyuan Liu13738502016-04-06 17:41:37 -07006860 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6861 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006862 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006863 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006864
Jeff Johnson34c88b72016-08-15 14:27:11 -07006865 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006866 hdd_ctx->unsafe_channel_count);
6867
Anurag Chouhan6d760662016-02-20 16:05:43 +05306868 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006869 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006870
6871 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006872 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873 hdd_ctx->unsafe_channel_list[index]);
6874
6875 }
6876
6877 /* Plug in avoid channel notification callback */
6878 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6879}
6880#else
6881static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6882{
6883}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006884static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006885{
6886}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006887#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006888
6889/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006890 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6891 * user space
6892 * @frame_ind: Management frame data to be informed.
6893 *
6894 * This function is used to indicate management frame to
6895 * user space
6896 *
6897 * Return: None
6898 *
6899 */
6900void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6901{
6902 hdd_context_t *hdd_ctx = NULL;
6903 hdd_adapter_t *adapter = NULL;
6904 void *cds_context = NULL;
6905 int i;
6906
6907 /* Get the global VOSS context.*/
6908 cds_context = cds_get_global_context();
6909 if (!cds_context) {
6910 hdd_err("Global CDS context is Null");
6911 return;
6912 }
6913 /* Get the HDD context.*/
6914 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6915
6916 if (0 != wlan_hdd_validate_context(hdd_ctx))
6917 return;
6918
6919 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6920 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6921 adapter =
6922 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6923 if (adapter)
6924 break;
6925 }
6926 } else {
6927 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6928 frame_ind->sessionId);
6929 }
6930
6931 if ((NULL != adapter) &&
6932 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6933 __hdd_indicate_mgmt_frame(adapter,
6934 frame_ind->frame_len,
6935 frame_ind->frameBuf,
6936 frame_ind->frameType,
6937 frame_ind->rxChan,
6938 frame_ind->rxRssi);
6939 return;
6940}
6941
Kapil Gupta8878ad92017-02-13 11:56:04 +05306942static void hdd_lte_coex_restart_sap(hdd_adapter_t *adapter,
6943 hdd_context_t *hdd_ctx)
6944{
6945 uint8_t restart_chan = 0;
6946
6947 restart_chan =
6948 hdd_get_safe_channel_from_pcl_and_acs_range(adapter);
6949 if (!restart_chan) {
6950 hdd_alert("fail to restart SAP");
6951 } else {
6952 /* SAP restart due to unsafe channel. While restarting
6953 * the SAP, make sure to clear acs_channel, channel to
6954 * reset to 0. Otherwise these settings will override
6955 * the ACS while restart.
6956 */
6957 hdd_ctx->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6958 adapter->sessionCtx.ap.sapConfig.channel =
6959 AUTO_CHANNEL_SELECT;
6960 hdd_info("sending coex indication");
6961 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
6962 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08006963 hdd_switch_sap_channel(adapter, restart_chan);
Kapil Gupta8878ad92017-02-13 11:56:04 +05306964 }
6965}
6966
6967void hdd_acs_response_timeout_handler(void *context)
6968{
6969 struct hdd_external_acs_timer_context *timer_context =
6970 (struct hdd_external_acs_timer_context *)context;
6971 hdd_adapter_t *adapter;
6972 hdd_context_t *hdd_ctx;
6973 uint8_t reason;
6974
6975 ENTER();
6976 if (!timer_context) {
6977 hdd_err("invlaid timer context");
6978 return;
6979 }
6980 adapter = timer_context->adapter;
6981 reason = timer_context->reason;
6982
6983
6984 if ((!adapter) ||
6985 (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
6986 hdd_err("invalid adapter or adapter has invalid magic");
6987 return;
6988 }
6989 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6990 if (wlan_hdd_validate_context(hdd_ctx))
6991 return;
6992
6993 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
6994 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
6995 else
6996 return;
6997
6998 hdd_err("ACS timeout happened for %s reason %d",
6999 adapter->dev->name, reason);
7000 switch (reason) {
7001 /* SAP init case */
7002 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
7003 wlan_sap_set_vendor_acs(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7004 false);
7005 wlan_hdd_cfg80211_start_acs(adapter);
7006 break;
7007 /* DFS detected on current channel */
7008 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
7009 wlan_sap_update_next_channel(
7010 WLAN_HDD_GET_SAP_CTX_PTR(adapter), 0, 0);
7011 sme_update_new_channel_event(WLAN_HDD_GET_HAL_CTX(adapter),
7012 adapter->sessionId);
7013 break;
7014 /* LTE coex event on current channel */
7015 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
7016 hdd_lte_coex_restart_sap(adapter, hdd_ctx);
7017 break;
7018 default:
7019 hdd_info("invalid reason for timer invoke");
7020
7021 }
7022}
7023
Rajeev Kumard004abc2016-02-17 12:09:56 -08007024/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007025 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
7026 * @hdd_ctx: HDD context
7027 *
7028 * Disables all the dual mac features like DBS, Agile DFS etc.
7029 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307030 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007031 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307032static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007033{
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007034 struct policy_mgr_dual_mac_config cfg = {0};
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307035 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007036
7037 if (!hdd_ctx) {
7038 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307039 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007040 }
7041
7042 cfg.scan_config = 0;
7043 cfg.fw_mode_config = 0;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007044 cfg.set_dual_mac_cb = policy_mgr_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007045
7046 hdd_debug("Disabling all dual mac features...");
7047
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08007048 status = sme_soc_set_dual_mac_config(cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307049 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007050 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
7051 return status;
7052 }
7053
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307054 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007055}
7056
7057/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007058 * hdd_override_ini_config - Override INI config
7059 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007060 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007061 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007062 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007063 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007064 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007065static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007066{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007067
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007068 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
7069 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
7070 hdd_notice("Module enable_dfs_chan_scan set to %d",
7071 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007072 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007073 if (0 == enable_11d || 1 == enable_11d) {
7074 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
7075 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007076 }
Leo Chang11545d62016-10-17 14:53:50 -07007077
7078 if (!hdd_ipa_is_present(hdd_ctx))
7079 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007080}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007081
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007082/**
7083 * hdd_set_trace_level_for_each - Set trace level for each INI config
7084 * @hdd_ctx - HDD context
7085 *
7086 * Set trace level for each module based on INI config.
7087 *
7088 * Return: None
7089 */
7090static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
7091{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307092 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
7093 hdd_ctx->config->qdf_trace_enable_wdi);
7094 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
7095 hdd_ctx->config->qdf_trace_enable_hdd);
7096 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
7097 hdd_ctx->config->qdf_trace_enable_sme);
7098 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
7099 hdd_ctx->config->qdf_trace_enable_pe);
7100 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
7101 hdd_ctx->config->qdf_trace_enable_wma);
7102 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
7103 hdd_ctx->config->qdf_trace_enable_sys);
7104 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
7105 hdd_ctx->config->qdf_trace_enable_qdf);
7106 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
7107 hdd_ctx->config->qdf_trace_enable_sap);
7108 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
7109 hdd_ctx->config->qdf_trace_enable_hdd_sap);
7110 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
7111 hdd_ctx->config->qdf_trace_enable_bmi);
7112 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
7113 hdd_ctx->config->qdf_trace_enable_cfg);
7114 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
7115 hdd_ctx->config->qdf_trace_enable_epping);
7116 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
7117 hdd_ctx->config->qdf_trace_enable_qdf_devices);
7118 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05307119 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307120 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
7121 hdd_ctx->config->qdf_trace_enable_htc);
7122 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
7123 hdd_ctx->config->qdf_trace_enable_hif);
7124 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
7125 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
7126 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
7127 hdd_ctx->config->qdf_trace_enable_hdd_data);
Naveen Rawat7df31862017-03-01 17:09:30 -08007128 hdd_qdf_trace_enable(QDF_MODULE_ID_WIFIPOS,
7129 hdd_ctx->config->qdf_trace_enable_wifi_pos);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007130 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007131}
7132
7133/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007134 * hdd_context_init() - Initialize HDD context
7135 * @hdd_ctx: HDD context.
7136 *
7137 * Initialize HDD context along with all the feature specific contexts.
7138 *
7139 * return: 0 on success and errno on failure.
7140 */
7141static int hdd_context_init(hdd_context_t *hdd_ctx)
7142{
7143 int ret;
7144
7145 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
7146 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
7147
7148 hdd_init_ll_stats_ctx();
7149
7150 init_completion(&hdd_ctx->mc_sus_event_var);
7151 init_completion(&hdd_ctx->ready_to_suspend);
7152
7153 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307154 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007155 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05307156
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007157 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
7158
7159 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
7160
7161 ret = hdd_scan_context_init(hdd_ctx);
7162 if (ret)
7163 goto list_destroy;
7164
Nitesh Shahd1266d72017-01-25 22:07:07 +05307165 hdd_tdls_context_init(hdd_ctx, false);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007166
7167 hdd_rx_wake_lock_create(hdd_ctx);
7168
7169 ret = hdd_sap_context_init(hdd_ctx);
7170 if (ret)
7171 goto scan_destroy;
7172
7173 ret = hdd_roc_context_init(hdd_ctx);
7174 if (ret)
7175 goto sap_destroy;
7176
7177 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
7178
7179 hdd_init_offloaded_packets_ctx(hdd_ctx);
7180
7181 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
7182 hdd_ctx->config);
7183 if (ret)
7184 goto roc_destroy;
7185
7186 return 0;
7187
7188roc_destroy:
7189 hdd_roc_context_destroy(hdd_ctx);
7190
7191sap_destroy:
7192 hdd_sap_context_destroy(hdd_ctx);
7193
7194scan_destroy:
7195 hdd_scan_context_destroy(hdd_ctx);
7196 hdd_rx_wake_lock_destroy(hdd_ctx);
7197 hdd_tdls_context_destroy(hdd_ctx);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007198list_destroy:
7199 qdf_list_destroy(&hdd_ctx->hddAdapters);
Sandeep Puligillad0004212017-02-26 18:34:56 -08007200
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007201 return ret;
7202}
7203
7204/**
7205 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05307206 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007207 *
7208 * Allocate and initialize HDD context. HDD context is allocated as part of
7209 * wiphy allocation and then context is initialized.
7210 *
7211 * Return: HDD context on success and ERR_PTR on failure
7212 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007213static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007214{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307215 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007216 int ret = 0;
7217 hdd_context_t *hdd_ctx;
7218 v_CONTEXT_t p_cds_context;
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307219 int qdf_print_idx = -1;
7220
7221 struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
7222 [QDF_MODULE_ID_TLSHIM] = {QDF_TRACE_LEVEL_ALL},
7223 [QDF_MODULE_ID_WMI] = {QDF_TRACE_LEVEL_ALL},
7224 [QDF_MODULE_ID_HTT] = {QDF_TRACE_LEVEL_ALL},
7225 [QDF_MODULE_ID_HDD] = {QDF_TRACE_LEVEL_ALL},
7226 [QDF_MODULE_ID_SME] = {QDF_TRACE_LEVEL_ALL},
7227 [QDF_MODULE_ID_PE] = {QDF_TRACE_LEVEL_ALL},
7228 [QDF_MODULE_ID_WMA] = {QDF_TRACE_LEVEL_ALL},
7229 [QDF_MODULE_ID_SYS] = {QDF_TRACE_LEVEL_ALL},
7230 [QDF_MODULE_ID_QDF] = {QDF_TRACE_LEVEL_ALL},
7231 [QDF_MODULE_ID_SAP] = {QDF_TRACE_LEVEL_ALL},
7232 [QDF_MODULE_ID_HDD_SOFTAP] = {QDF_TRACE_LEVEL_ALL},
7233 [QDF_MODULE_ID_HDD_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7234 [QDF_MODULE_ID_HDD_SAP_DATA] = {QDF_DATA_PATH_TRACE_LEVEL},
7235 [QDF_MODULE_ID_HIF] = {QDF_DATA_PATH_TRACE_LEVEL},
7236 [QDF_MODULE_ID_HTC] = {QDF_DATA_PATH_TRACE_LEVEL},
7237 [QDF_MODULE_ID_TXRX] = {QDF_DATA_PATH_TRACE_LEVEL},
7238 [QDF_MODULE_ID_QDF_DEVICE] = {QDF_TRACE_LEVEL_ALL},
7239 [QDF_MODULE_ID_CFG] = {QDF_TRACE_LEVEL_ALL},
7240 [QDF_MODULE_ID_BMI] = {QDF_TRACE_LEVEL_ALL},
7241 [QDF_MODULE_ID_EPPING] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiyaf928edf2017-02-06 14:43:24 +05307242 [QDF_MODULE_ID_QVIT] = {QDF_TRACE_LEVEL_ALL},
7243 [QDF_MODULE_ID_DP] = {QDF_TRACE_LEVEL_ALL},
7244 [QDF_MODULE_ID_SOC] = {QDF_TRACE_LEVEL_ALL},
7245 [QDF_MODULE_ID_OS_IF] = {QDF_TRACE_LEVEL_ALL},
7246 [QDF_MODULE_ID_TARGET_IF] = {QDF_TRACE_LEVEL_ALL},
7247 [QDF_MODULE_ID_SCHEDULER] = {QDF_TRACE_LEVEL_ALL},
Mukul Sharma4d7d6b02017-02-13 20:45:22 +05307248 [QDF_MODULE_ID_MGMT_TXRX] = {QDF_TRACE_LEVEL_ALL},
Abhishek Singh9679dbf2017-02-15 11:35:41 +05307249 [QDF_MODULE_ID_PMO] = {QDF_TRACE_LEVEL_ALL},
Tushnim Bhattacharyya6796d8d2017-03-17 11:06:03 -07007250 [QDF_MODULE_ID_SCAN] = {QDF_TRACE_LEVEL_ALL},
7251 [QDF_MODULE_ID_POLICY_MGR] = {QDF_TRACE_LEVEL_ALL},
Wu Gao9a704f42017-03-10 18:42:11 +08007252 [QDF_MODULE_ID_P2P] = {QDF_TRACE_LEVEL_ALL},
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +05307253 };
7254
7255 status = qdf_print_setup();
7256 if (status != QDF_STATUS_SUCCESS) {
7257 pr_err("QDF print control object setup failed\n");
7258 ret = -EINVAL;
7259 goto err_out;
7260 }
7261 /* Register the module here with QDF */
7262 qdf_print_idx = qdf_print_ctrl_register(cinfo, NULL, NULL,
7263 "MCL_WLAN");
7264
7265 /* if qdf_print_idx is negative */
7266 if (qdf_print_idx < 0) {
7267 pr_err("QDF print control can not be registered %d\n",
7268 qdf_print_idx);
7269 ret = -EINVAL;
7270 goto err_out;
7271 }
7272
7273 /* Store the qdf_pidx information into qdf module */
7274 qdf_set_pidx(qdf_print_idx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007275
7276 ENTER();
7277
7278 p_cds_context = cds_get_global_context();
7279 if (p_cds_context == NULL) {
7280 hdd_alert("Failed to get CDS global context");
7281 ret = -EINVAL;
7282 goto err_out;
7283 }
7284
7285 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
7286
7287 if (hdd_ctx == NULL) {
7288 ret = -ENOMEM;
7289 goto err_out;
7290 }
7291
7292 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007293 hdd_ctx->parent_dev = dev;
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05307294 hdd_ctx->last_scan_reject_session_id = 0xFF;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007295
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307296 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007297 if (hdd_ctx->config == NULL) {
7298 hdd_alert("Failed to alloc memory for HDD config!");
7299 ret = -ENOMEM;
7300 goto err_free_hdd_context;
7301 }
7302
7303 /* Read and parse the qcom_cfg.ini file */
7304 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307305 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05307306 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007307 WLAN_INI_FILE);
7308 ret = -EINVAL;
7309 goto err_free_config;
7310 }
7311
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007312 hdd_notice("Setting configuredMcastBcastFilter: %d",
7313 hdd_ctx->config->mcastBcastFilterSetting);
7314
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307315 if (hdd_ctx->config->fhostNSOffload)
7316 hdd_ctx->ns_offload_enable = true;
7317
Abhishek Singh5ea86532016-04-27 14:10:53 +05307318 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
7319
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007320 hdd_override_ini_config(hdd_ctx);
7321
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007322 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007323
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007324 ret = hdd_context_init(hdd_ctx);
7325
7326 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007327 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007328
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007329
Yuanyuan Liu7a97b8f2017-01-27 10:42:52 -08007330 pld_set_fw_log_mode(hdd_ctx->parent_dev,
7331 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007332
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007333
7334 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05307335 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007336
Anurag Chouhan6d760662016-02-20 16:05:43 +05307337 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007338 goto skip_multicast_logging;
7339
7340 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
7341
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007342 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
7343 if (ret)
7344 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05307345
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007346 ret = hdd_logging_sock_activate_svc(hdd_ctx);
7347 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05307348 goto err_free_histogram;
7349
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007350skip_multicast_logging:
7351 hdd_set_trace_level_for_each(hdd_ctx);
7352
7353 return hdd_ctx;
7354
Nirav Shahed34b212016-04-25 10:59:16 +05307355err_free_histogram:
7356 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
7357
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07007358err_deinit_hdd_context:
7359 hdd_context_deinit(hdd_ctx);
7360
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007361err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307362 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007363
7364err_free_hdd_context:
7365 wiphy_free(hdd_ctx->wiphy);
7366
7367err_out:
7368 return ERR_PTR(ret);
7369}
7370
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007371#ifdef WLAN_OPEN_P2P_INTERFACE
7372/**
7373 * hdd_open_p2p_interface - Open P2P interface
7374 * @hdd_ctx: HDD context
7375 * @rtnl_held: True if RTNL lock held
7376 *
7377 * Open P2P interface during probe. This function called to open the P2P
7378 * interface at probe along with STA interface.
7379 *
7380 * Return: 0 on success and errno on failure
7381 */
7382static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7383{
7384 hdd_adapter_t *adapter;
7385 uint8_t *p2p_dev_addr;
7386
7387 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
7388 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307389 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007390 hdd_ctx->config->intfMacAddr[0].bytes,
7391 sizeof(tSirMacAddr));
7392
7393 /*
7394 * Generate the P2P Device Address. This consists of
7395 * the device's primary MAC address with the locally
7396 * administered bit set.
7397 */
7398 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
7399 } else {
7400 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7401 if (p2p_dev_addr == NULL) {
7402 hdd_alert("Failed to allocate mac_address for p2p_device");
7403 return -ENOSPC;
7404 }
7405
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307406 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307407 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007408 }
7409
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007410 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007411 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08007412 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007413
7414 if (NULL == adapter) {
7415 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
7416 return -ENOSPC;
7417 }
7418
7419 return 0;
7420}
7421#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05307422static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007423 bool rtnl_held)
7424{
7425 return 0;
7426}
7427#endif
7428
Jeff Johnson957bc272017-02-02 08:54:48 -08007429static int hdd_open_ocb_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
7430{
7431 hdd_adapter_t *adapter;
7432 int ret = 0;
7433
7434 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
7435 wlan_hdd_get_intf_addr(hdd_ctx),
7436 NET_NAME_UNKNOWN, rtnl_held);
7437 if (adapter == NULL) {
7438 hdd_err("Failed to open 802.11p interface");
7439 ret = -ENOSPC;
7440 }
7441
7442 return ret;
7443}
7444
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007445/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307446 * hdd_start_station_adapter()- Start the Station Adapter
7447 * @adapter: HDD adapter
7448 *
7449 * This function initializes the adapter for the station mode.
7450 *
7451 * Return: 0 on success or errno on failure.
7452 */
7453int hdd_start_station_adapter(hdd_adapter_t *adapter)
7454{
7455 QDF_STATUS status;
7456
7457 ENTER_DEV(adapter->dev);
7458
7459 status = hdd_init_station_mode(adapter);
7460
7461 if (QDF_STATUS_SUCCESS != status) {
7462 hdd_err("Error Initializing station mode: %d", status);
7463 return qdf_status_to_os_return(status);
7464 }
7465
Arun Khandavallifae92942016-08-01 13:31:08 +05307466 hdd_register_tx_flow_control(adapter,
7467 hdd_tx_resume_timer_expired_handler,
7468 hdd_tx_resume_cb);
7469
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307470 EXIT();
7471 return 0;
7472}
7473
7474/**
7475 * hdd_start_ap_adapter()- Start AP Adapter
7476 * @adapter: HDD adapter
7477 *
7478 * This function initializes the adapter for the AP mode.
7479 *
7480 * Return: 0 on success errno on failure.
7481 */
7482int hdd_start_ap_adapter(hdd_adapter_t *adapter)
7483{
7484 QDF_STATUS status;
7485
7486 ENTER();
7487
Arun Khandavallicc544b32017-01-30 19:52:16 +05307488 status = hdd_init_ap_mode(adapter, false);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307489
7490 if (QDF_STATUS_SUCCESS != status) {
7491 hdd_err("Error Initializing the AP mode: %d", status);
7492 return qdf_status_to_os_return(status);
7493 }
7494
Arun Khandavallifae92942016-08-01 13:31:08 +05307495 hdd_register_tx_flow_control(adapter,
7496 hdd_softap_tx_resume_timer_expired_handler,
7497 hdd_softap_tx_resume_cb);
7498
Arun Khandavalli7e857c32016-06-26 12:07:16 +05307499 EXIT();
7500 return 0;
7501}
7502
7503/**
7504 * hdd_start_ftm_adapter()- Start FTM adapter
7505 * @adapter: HDD adapter
7506 *
7507 * This function initializes the adapter for the FTM mode.
7508 *
7509 * Return: 0 on success or errno on failure.
7510 */
7511int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
7512{
7513 QDF_STATUS qdf_status;
7514
7515 ENTER_DEV(adapter->dev);
7516
7517 qdf_status = hdd_init_tx_rx(adapter);
7518
7519 if (QDF_STATUS_SUCCESS != qdf_status) {
7520 hdd_err("Failed to start FTM adapter: %d", qdf_status);
7521 return qdf_status_to_os_return(qdf_status);
7522 }
7523
7524 return 0;
7525 EXIT();
7526}
7527
7528/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007529 * hdd_open_interfaces - Open all required interfaces
7530 * hdd_ctx: HDD context
7531 * rtnl_held: True if RTNL lock is held
7532 *
7533 * Open all the interfaces like STA, P2P and OCB based on the configuration.
7534 *
Jeff Johnson957bc272017-02-02 08:54:48 -08007535 * Return: 0 if all interfaces were created, otherwise negative errno
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007536 */
Jeff Johnson957bc272017-02-02 08:54:48 -08007537static int hdd_open_interfaces(hdd_context_t *hdd_ctx, bool rtnl_held)
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007538{
Jeff Johnson957bc272017-02-02 08:54:48 -08007539 hdd_adapter_t *adapter;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007540 int ret;
7541
Jeff Johnson957bc272017-02-02 08:54:48 -08007542 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
Arun Khandavallifae92942016-08-01 13:31:08 +05307543 /* Create only 802.11p interface */
Jeff Johnson957bc272017-02-02 08:54:48 -08007544 return hdd_open_ocb_interface(hdd_ctx, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007545
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007546 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007547 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08007548 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007549
7550 if (adapter == NULL)
Jeff Johnson957bc272017-02-02 08:54:48 -08007551 return -ENOSPC;
7552
Deepak Dhamdherea2785822016-11-17 01:17:45 -08007553 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
7554 adapter->fast_roaming_allowed = true;
7555
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007556 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
7557 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08007558 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007559
7560 /* Open 802.11p Interface */
7561 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Jeff Johnson957bc272017-02-02 08:54:48 -08007562 ret = hdd_open_ocb_interface(hdd_ctx, rtnl_held);
7563 if (ret)
7564 goto err_close_adapters;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007565 }
7566
Jeff Johnson957bc272017-02-02 08:54:48 -08007567 return 0;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007568
Jeff Johnson957bc272017-02-02 08:54:48 -08007569err_close_adapters:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007570 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Jeff Johnson957bc272017-02-02 08:54:48 -08007571 return ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007572}
7573
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007574/**
7575 * hdd_update_country_code - Update country code
7576 * @hdd_ctx: HDD context
7577 * @adapter: Primary adapter context
7578 *
7579 * Update country code based on module parameter country_code at SME and wait
7580 * for the settings to take effect.
7581 *
7582 * Return: 0 on success and errno on failure
7583 */
7584static int hdd_update_country_code(hdd_context_t *hdd_ctx,
7585 hdd_adapter_t *adapter)
7586{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307587 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007588 int ret = 0;
7589 unsigned long rc;
7590
7591 if (country_code == NULL)
7592 return 0;
7593
7594 INIT_COMPLETION(adapter->change_country_code);
7595
7596 status = sme_change_country_code(hdd_ctx->hHal,
7597 wlan_hdd_change_country_code_callback,
7598 country_code, adapter,
7599 hdd_ctx->pcds_context, eSIR_TRUE,
7600 eSIR_TRUE);
7601
7602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307603 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007604 hdd_err("SME Change Country code from module param fail ret=%d",
7605 ret);
7606 return -EINVAL;
7607 }
7608
7609 rc = wait_for_completion_timeout(&adapter->change_country_code,
7610 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
7611 if (!rc) {
7612 hdd_err("SME while setting country code timed out");
7613 ret = -ETIMEDOUT;
7614 }
7615
7616 return ret;
7617}
7618
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307619#ifdef QCA_LL_TX_FLOW_CONTROL_V2
7620/**
7621 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
7622 * @cds_cfg: CDS Configuration
7623 * @hdd_ctx: Pointer to hdd context
7624 *
7625 * Return: none
7626 */
7627static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7628 *cds_cfg,
7629 hdd_context_t *hdd_ctx)
7630{
7631 cds_cfg->tx_flow_stop_queue_th =
7632 hdd_ctx->config->TxFlowStopQueueThreshold;
7633 cds_cfg->tx_flow_start_queue_offset =
7634 hdd_ctx->config->TxFlowStartQueueOffset;
7635}
7636#else
7637static inline void hdd_txrx_populate_cds_config(struct cds_config_info
7638 *cds_cfg,
7639 hdd_context_t *hdd_ctx)
7640{
7641}
7642#endif
7643
7644#ifdef FEATURE_WLAN_RA_FILTERING
7645/**
7646 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7647 * @cds_cfg: CDS Configuration
7648 * @hdd_ctx: Pointer to hdd context
7649 *
7650 * Return: none
7651 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307652static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307653 hdd_context_t *hdd_ctx)
7654{
7655 cds_cfg->ra_ratelimit_interval =
7656 hdd_ctx->config->RArateLimitInterval;
7657 cds_cfg->is_ra_ratelimit_enabled =
7658 hdd_ctx->config->IsRArateLimitEnabled;
7659}
7660#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307661static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307662 hdd_context_t *hdd_ctx)
7663{
7664}
7665#endif
7666
7667/**
7668 * hdd_update_cds_config() - API to update cds configuration parameters
7669 * @hdd_ctx: HDD Context
7670 *
7671 * Return: 0 for Success, errno on failure
7672 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007673static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307674{
7675 struct cds_config_info *cds_cfg;
7676
7677 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7678 if (!cds_cfg) {
7679 hdd_err("failed to allocate cds config");
7680 return -ENOMEM;
7681 }
7682
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307683 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08007684 if (!hdd_ctx->config->nMaxPsPoll ||
7685 !hdd_ctx->config->enablePowersaveOffload) {
7686 cds_cfg->powersave_offload_enabled =
7687 hdd_ctx->config->enablePowersaveOffload;
7688 } else {
7689 if ((hdd_ctx->config->enablePowersaveOffload ==
7690 PS_QPOWER_NODEEPSLEEP) ||
7691 (hdd_ctx->config->enablePowersaveOffload ==
7692 PS_LEGACY_NODEEPSLEEP))
7693 cds_cfg->powersave_offload_enabled =
7694 PS_LEGACY_NODEEPSLEEP;
7695 else
7696 cds_cfg->powersave_offload_enabled =
7697 PS_LEGACY_DEEPSLEEP;
7698 hdd_info("Qpower disabled in cds config, %d",
7699 cds_cfg->powersave_offload_enabled);
7700 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307701 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7702 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7703 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7704 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7705 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7706
7707 /* Here ol_ini_info is used to store ini status of arp offload
7708 * ns offload and others. Currently 1st bit is used for arp
7709 * off load and 2nd bit for ns offload currently, rest bits are unused
7710 */
7711 if (hdd_ctx->config->fhostArpOffload)
7712 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7713 if (hdd_ctx->config->fhostNSOffload)
7714 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7715
7716 /*
7717 * Copy the DFS Phyerr Filtering Offload status.
7718 * This parameter reflects the value of the
7719 * dfs_phyerr_filter_offload flag as set in the ini.
7720 */
7721 cds_cfg->dfs_phyerr_filter_offload =
7722 hdd_ctx->config->fDfsPhyerrFilterOffload;
7723 if (hdd_ctx->config->ssdp)
7724 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7725
7726 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7727 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7728
7729 cds_cfg->ap_maxoffload_reorderbuffs =
7730 hdd_ctx->config->apMaxOffloadReorderBuffs;
7731
7732 cds_cfg->ap_disable_intrabss_fwd =
7733 hdd_ctx->config->apDisableIntraBssFwd;
7734
7735 cds_cfg->dfs_pri_multiplier =
7736 hdd_ctx->config->dfsRadarPriMultiplier;
7737 cds_cfg->reorder_offload =
7738 hdd_ctx->config->reorderOffloadSupport;
7739
7740 /* IPA micro controller data path offload resource config item */
7741 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007742 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7743 /* IpaUcTxBufCount should be power of 2 */
7744 hdd_err("Round down IpaUcTxBufCount %d to nearest power of 2",
7745 hdd_ctx->config->IpaUcTxBufCount);
7746 hdd_ctx->config->IpaUcTxBufCount =
7747 rounddown_pow_of_two(
7748 hdd_ctx->config->IpaUcTxBufCount);
7749 if (!hdd_ctx->config->IpaUcTxBufCount) {
7750 hdd_err("Failed to round down IpaUcTxBufCount");
7751 return -EINVAL;
7752 }
7753 hdd_err("IpaUcTxBufCount rounded down to %d",
7754 hdd_ctx->config->IpaUcTxBufCount);
7755 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307756 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7757 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007758 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7759 /* IpaUcRxIndRingCount should be power of 2 */
7760 hdd_err("Round down IpaUcRxIndRingCount %d to nearest power of 2",
7761 hdd_ctx->config->IpaUcRxIndRingCount);
7762 hdd_ctx->config->IpaUcRxIndRingCount =
7763 rounddown_pow_of_two(
7764 hdd_ctx->config->IpaUcRxIndRingCount);
7765 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7766 hdd_err("Failed to round down IpaUcRxIndRingCount");
7767 return -EINVAL;
7768 }
7769 hdd_err("IpaUcRxIndRingCount rounded down to %d",
7770 hdd_ctx->config->IpaUcRxIndRingCount);
7771 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307772 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007773 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307774 cds_cfg->uc_tx_partition_base =
7775 hdd_ctx->config->IpaUcTxPartitionBase;
7776 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7777
7778 cds_cfg->ip_tcp_udp_checksum_offload =
7779 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307780 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307781 cds_cfg->ce_classify_enabled =
7782 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007783 cds_cfg->bpf_packet_filter_enable =
7784 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307785 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7786 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7787 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007788 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007789 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007790 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007791 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Dustin Brown13995f02017-01-12 15:38:42 -08007792 cds_cfg->active_bpf_mode = hdd_ctx->config->active_bpf_mode;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307793
7794 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7795 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7796 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007797 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307798 cds_init_ini_config(cds_cfg);
7799 return 0;
7800}
7801
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007802/**
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007803 * hdd_update_user_config() - API to update user configuration
7804 * parameters to obj mgr which are used by multiple components
7805 * @hdd_ctx: HDD Context
7806 *
7807 * Return: 0 for Success, errno on failure
7808 */
7809static int hdd_update_user_config(hdd_context_t *hdd_ctx)
7810{
7811 struct wlan_objmgr_psoc_user_config *user_config;
7812
7813 user_config = qdf_mem_malloc(sizeof(*user_config));
7814 if (user_config == NULL) {
7815 hdd_alert("Failed to alloc memory for user_config!");
7816 return -ENOMEM;
7817 }
7818
7819 user_config->dot11_mode = hdd_ctx->config->dot11Mode;
7820 user_config->dual_mac_feature_disable =
7821 hdd_ctx->config->dual_mac_feature_disable;
7822 user_config->indoor_channel_support =
7823 hdd_ctx->config->indoor_channel_support;
7824 user_config->is_11d_support_enabled =
7825 hdd_ctx->config->Is11dSupportEnabled;
7826 user_config->is_11h_support_enabled =
7827 hdd_ctx->config->Is11hSupportEnabled;
7828 user_config->optimize_chan_avoid_event =
7829 hdd_ctx->config->goptimize_chan_avoid_event;
7830 user_config->skip_dfs_chnl_in_p2p_search =
7831 hdd_ctx->config->skipDfsChnlInP2pSearch;
Naveen Rawat222b2e92017-03-16 09:52:21 -07007832 user_config->band_capability = hdd_ctx->config->nBandCapability;
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -08007833 wlan_objmgr_psoc_set_user_config(hdd_ctx->hdd_psoc, user_config);
7834
7835 qdf_mem_free(user_config);
7836 return 0;
7837}
7838
7839/**
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007840 * hdd_init_thermal_info - Initialize thermal level
7841 * @hdd_ctx: HDD context
7842 *
7843 * Initialize thermal level at SME layer and set the thermal level callback
7844 * which would be called when a configured thermal threshold is hit.
7845 *
7846 * Return: 0 on success and errno on failure
7847 */
7848static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7849{
7850 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307851 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007852
7853 thermal_param.smeThermalMgmtEnabled =
7854 hdd_ctx->config->thermalMitigationEnable;
7855 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7856
Poddar, Siddarth83905022016-04-16 17:56:08 -07007857 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7858 hdd_ctx->config->throttle_dutycycle_level0;
7859 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7860 hdd_ctx->config->throttle_dutycycle_level1;
7861 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7862 hdd_ctx->config->throttle_dutycycle_level2;
7863 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7864 hdd_ctx->config->throttle_dutycycle_level3;
7865
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007866 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7867 hdd_ctx->config->thermalTempMinLevel0;
7868 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7869 hdd_ctx->config->thermalTempMaxLevel0;
7870 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7871 hdd_ctx->config->thermalTempMinLevel1;
7872 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7873 hdd_ctx->config->thermalTempMaxLevel1;
7874 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7875 hdd_ctx->config->thermalTempMinLevel2;
7876 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7877 hdd_ctx->config->thermalTempMaxLevel2;
7878 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7879 hdd_ctx->config->thermalTempMinLevel3;
7880 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7881 hdd_ctx->config->thermalTempMaxLevel3;
7882
7883 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7884
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307885 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307886 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007887
7888 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7889 hdd_set_thermal_level_cb);
7890
7891 return 0;
7892
7893}
7894
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007895#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7896/**
7897 * hdd_hold_rtnl_lock - Hold RTNL lock
7898 *
7899 * Hold RTNL lock
7900 *
7901 * Return: True if held and false otherwise
7902 */
7903static inline bool hdd_hold_rtnl_lock(void)
7904{
7905 rtnl_lock();
7906 return true;
7907}
7908
7909/**
7910 * hdd_release_rtnl_lock - Release RTNL lock
7911 *
7912 * Release RTNL lock
7913 *
7914 * Return: None
7915 */
7916static inline void hdd_release_rtnl_lock(void)
7917{
7918 rtnl_unlock();
7919}
7920#else
7921static inline bool hdd_hold_rtnl_lock(void) { return false; }
7922static inline void hdd_release_rtnl_lock(void) { }
7923#endif
7924
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007925#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007926
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307927/* MAX iwpriv command support */
7928#define PKTLOG_SET_BUFF_SIZE 3
7929#define MAX_PKTLOG_SIZE 16
7930
7931/**
7932 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7933 * @hdd_ctx: hdd context
7934 * @set_value2: pktlog buffer size value
7935 *
7936 *
7937 * Return: 0 for success or error.
7938 */
7939static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7940{
7941 struct sir_wifi_start_log start_log = { 0 };
7942 QDF_STATUS status;
7943
7944 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7945 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7946 start_log.ini_triggered = cds_is_packet_log_enabled();
7947 start_log.user_triggered = 1;
7948 start_log.size = set_value2;
7949
7950 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7951 if (!QDF_IS_STATUS_SUCCESS(status)) {
7952 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7953 EXIT();
7954 return -EINVAL;
7955 }
7956
7957 return 0;
7958}
7959
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007960/**
7961 * hdd_process_pktlog_command() - process pktlog command
7962 * @hdd_ctx: hdd context
7963 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307964 * @set_value2: pktlog buffer size value
7965 *
7966 * This function process pktlog command.
7967 * set_value2 only matters when set_value is 3 (set buff size)
7968 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007969 *
7970 * Return: 0 for success or error.
7971 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307972int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
7973 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007974{
7975 int ret;
7976 bool enable;
7977 uint8_t user_triggered = 0;
7978
7979 ret = wlan_hdd_validate_context(hdd_ctx);
7980 if (0 != ret)
7981 return ret;
7982
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307983 hdd_info("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007984
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307985 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007986 hdd_err("invalid pktlog value %d", set_value);
7987 return -EINVAL;
7988 }
7989
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307990 if (set_value == PKTLOG_SET_BUFF_SIZE) {
7991 if (set_value2 <= 0) {
7992 hdd_err("invalid pktlog size %d", set_value2);
7993 return -EINVAL;
7994 } else if (set_value2 > MAX_PKTLOG_SIZE) {
7995 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
7996 return -EINVAL;
7997 }
7998 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
7999 }
8000
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008001 /*
8002 * set_value = 0 then disable packetlog
8003 * set_value = 1 enable packetlog forcefully
8004 * set_vlaue = 2 then disable packetlog if disabled through ini or
8005 * enable packetlog with AUTO type.
8006 */
8007 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
8008 true : false;
8009
8010 if (1 == set_value) {
8011 enable = true;
8012 user_triggered = 1;
8013 }
8014
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308015 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008016}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008017/**
8018 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
8019 * @hdd_ctx: HDD context
8020 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308021 * @user_triggered: triggered through iwpriv
8022 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008023 *
8024 * Return: 0 on success; error number otherwise
8025 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008026int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308027 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008028{
8029 struct sir_wifi_start_log start_log;
8030 QDF_STATUS status;
8031
8032 start_log.ring_id = RING_ID_PER_PACKET_STATS;
8033 start_log.verbose_level =
8034 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08008035 start_log.ini_triggered = cds_is_packet_log_enabled();
8036 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308037 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05308038 /*
8039 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
8040 * commands. Host uses this flag to decide whether to send pktlog
8041 * disable command to fw without sending pktlog enable command
8042 * previously. For eg, If vendor sends pktlog disable command without
8043 * sending pktlog enable command, then host discards the packet
8044 * but for iwpriv command, host will send it to fw.
8045 */
8046 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008047 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
8048 if (!QDF_IS_STATUS_SUCCESS(status)) {
8049 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
8050 EXIT();
8051 return -EINVAL;
8052 }
8053
8054 return 0;
8055}
8056#endif /* REMOVE_PKT_LOG */
8057
Komal Seelam92fff912016-03-24 11:51:41 +05308058/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008059 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
8060 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05308061 * @dev: Device Pointer
8062 * @num: Number of Valid Mac address
8063 *
8064 * Return: Pointer to MAC address buffer
8065 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008066static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
8067 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05308068{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008069 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05308070}
Komal Seelam92fff912016-03-24 11:51:41 +05308071
8072/**
8073 * hdd_populate_random_mac_addr() - API to populate random mac addresses
8074 * @hdd_ctx: HDD Context
8075 * @num: Number of random mac addresses needed
8076 *
8077 * Generate random addresses using bit manipulation on the base mac address
8078 *
8079 * Return: None
8080 */
8081static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
8082{
8083 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
8084 uint32_t iter;
8085 struct hdd_config *ini = hdd_ctx->config;
8086 uint8_t *buf = NULL;
8087 uint8_t macaddr_b3, tmp_br3;
8088 uint8_t *src = ini->intfMacAddr[0].bytes;
8089
8090 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
8091 buf = ini->intfMacAddr[iter].bytes;
8092 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
8093 macaddr_b3 = buf[3];
8094 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
8095 INTF_MACADDR_MASK;
8096 macaddr_b3 += tmp_br3;
8097 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
8098 buf[0] |= 0x02;
8099 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07008100 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308101 }
8102}
8103
8104/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008105 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05308106 * @hdd_ctx: HDD Context
8107 *
8108 * API to get mac addresses from platform driver and update the driver
8109 * structures and configure FW with the base mac address.
8110 * Return: int
8111 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008112static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05308113{
8114 uint32_t no_of_mac_addr, iter;
8115 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
8116 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
8117 uint8_t *addr, *buf;
8118 struct device *dev = hdd_ctx->parent_dev;
8119 struct hdd_config *ini = hdd_ctx->config;
8120 tSirMacAddr mac_addr;
8121 QDF_STATUS status;
8122
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008123 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05308124
8125 if (no_of_mac_addr == 0 || !addr) {
8126 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
8127 return -EINVAL;
8128 }
8129
8130 if (no_of_mac_addr > max_mac_addr)
8131 no_of_mac_addr = max_mac_addr;
8132
8133 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
8134
8135 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
8136 buf = ini->intfMacAddr[iter].bytes;
8137 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07008138 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05308139 }
8140
8141 status = sme_set_custom_mac_addr(mac_addr);
8142
8143 if (!QDF_IS_STATUS_SUCCESS(status))
8144 return -EAGAIN;
8145 if (no_of_mac_addr < max_mac_addr)
8146 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
8147 no_of_mac_addr);
8148 return 0;
8149}
8150
8151/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008152 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
8153 * @hdd_ctx: HDD Context
8154 *
8155 * Update MAC address to FW. If MAC address passed by FW is invalid, host
8156 * will generate its own MAC and update it to FW.
8157 *
8158 * Return: 0 for success
8159 * Non-zero error code for failure
8160 */
8161static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
8162{
8163 tSirMacAddr customMacAddr;
8164 QDF_STATUS status;
8165
8166 qdf_mem_copy(&customMacAddr,
8167 &hdd_ctx->config->intfMacAddr[0].bytes[0],
8168 sizeof(tSirMacAddr));
8169 status = sme_set_custom_mac_addr(customMacAddr);
8170 if (!QDF_IS_STATUS_SUCCESS(status))
8171 return -EAGAIN;
8172 return 0;
8173}
8174
8175/**
Komal Seelam92fff912016-03-24 11:51:41 +05308176 * hdd_initialize_mac_address() - API to get wlan mac addresses
8177 * @hdd_ctx: HDD Context
8178 *
8179 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
8180 * is provisioned with mac addresses, driver uses it, else it will use
8181 * wlan_mac.bin to update HW MAC addresses.
8182 *
8183 * Return: None
8184 */
8185static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
8186{
8187 QDF_STATUS status;
8188 int ret;
8189
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08008190 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05308191 if (ret == 0)
8192 return;
8193
8194 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
8195
8196 status = hdd_update_mac_config(hdd_ctx);
8197
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008198 if (QDF_IS_STATUS_SUCCESS(status))
8199 return;
8200
8201 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
8202
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008203 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008204 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08008205 if (ret != 0) {
8206 hdd_err("MAC address out-of-sync, ret:%d", ret);
8207 QDF_ASSERT(ret);
8208 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07008209 }
Komal Seelam92fff912016-03-24 11:51:41 +05308210}
8211
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008212/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008213 * hdd_tsf_init() - Initialize the TSF synchronization interface
8214 * @hdd_ctx: HDD global context
8215 *
8216 * When TSF synchronization via GPIO is supported by the driver and
8217 * has been enabled in the configuration file, this function plumbs
8218 * the GPIO value down to firmware via SME.
8219 *
8220 * Return: None
8221 */
8222#ifdef WLAN_FEATURE_TSF
8223static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8224{
8225 QDF_STATUS status;
8226
8227 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
8228 return;
8229
8230 status = sme_set_tsf_gpio(hdd_ctx->hHal,
8231 hdd_ctx->config->tsf_gpio_pin);
8232 if (!QDF_IS_STATUS_SUCCESS(status))
8233 hdd_err("Set tsf GPIO failed, status: %d", status);
8234}
8235#else
8236static void hdd_tsf_init(hdd_context_t *hdd_ctx)
8237{
8238}
8239#endif
8240
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008241static int hdd_set_smart_chainmask_enabled(hdd_context_t *hdd_ctx)
8242{
8243 int vdev_id = 0;
8244 int param_id = WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME;
8245 int value = hdd_ctx->config->smart_chainmask_enabled;
8246 int vpdev = PDEV_CMD;
8247 int ret;
8248
8249 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8250 if (ret)
8251 hdd_err("WMI_PDEV_PARAM_SMART_CHAINMASK_SCHEME failed %d", ret);
8252
8253 return ret;
8254}
8255
8256static int hdd_set_alternative_chainmask_enabled(hdd_context_t *hdd_ctx)
8257{
8258 int vdev_id = 0;
8259 int param_id = WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME;
8260 int value = hdd_ctx->config->alternative_chainmask_enabled;
8261 int vpdev = PDEV_CMD;
8262 int ret;
8263
8264 ret = wma_cli_set_command(vdev_id, param_id, value, vpdev);
8265 if (ret)
8266 hdd_err("WMI_PDEV_PARAM_ALTERNATIVE_CHAINMASK_SCHEME failed %d",
8267 ret);
8268
8269 return ret;
8270}
8271
Jeff Johnson89c66ff2016-04-22 15:21:37 -07008272/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07008273 * hdd_pre_enable_configure() - Configurations prior to cds_enable
8274 * @hdd_ctx: HDD context
8275 *
8276 * Pre configurations to be done at lower layer before calling cds enable.
8277 *
8278 * Return: 0 on success and errno on failure.
8279 */
8280static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
8281{
8282 int ret;
8283 QDF_STATUS status;
8284 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07008285 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008286
Leo Changfdb45c32016-10-28 11:09:23 -07008287 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07008288 /*
8289 * Set 802.11p config
8290 * TODO-OCB: This has been temporarily added here to ensure this
8291 * parameter is set in CSR when we init the channel list. This should
8292 * be removed once the 5.9 GHz channels are added to the regulatory
8293 * domain.
8294 */
8295 hdd_set_dot11p_config(hdd_ctx);
8296
8297 /*
8298 * Note that the cds_pre_enable() sequence triggers the cfg download.
8299 * The cfg download must occur before we update the SME config
8300 * since the SME config operation must access the cfg database
8301 */
8302 status = hdd_set_sme_config(hdd_ctx);
8303
8304 if (QDF_STATUS_SUCCESS != status) {
8305 hdd_alert("Failed hdd_set_sme_config: %d", status);
8306 ret = qdf_status_to_os_return(status);
8307 goto out;
8308 }
8309
Tushnim Bhattacharyyaba8ee932017-03-23 09:27:40 -07008310 status = hdd_set_policy_mgr_user_cfg(hdd_ctx);
8311 if (QDF_STATUS_SUCCESS != status) {
8312 hdd_alert("Failed hdd_set_policy_mgr_user_cfg: %d", status);
8313 ret = qdf_status_to_os_return(status);
8314 goto out;
8315 }
8316
Prashanth Bhatta07998752016-04-28 12:35:33 -07008317 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
8318 hdd_ctx->config->tx_chain_mask_1ss,
8319 PDEV_CMD);
8320 if (0 != ret) {
8321 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
8322 goto out;
8323 }
8324
Jeff Johnsona89e25d2017-02-24 12:25:07 -08008325 ret = hdd_set_smart_chainmask_enabled(hdd_ctx);
8326 if (ret)
8327 goto out;
8328
8329 ret = hdd_set_alternative_chainmask_enabled(hdd_ctx);
8330 if (ret)
8331 goto out;
8332
Prashanth Bhatta07998752016-04-28 12:35:33 -07008333 hdd_program_country_code(hdd_ctx);
8334
Srinivas Girigowda70e169a2017-03-07 23:55:57 -08008335 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
8336 hdd_ctx->config->arp_ac_category,
8337 PDEV_CMD);
8338 if (0 != ret) {
8339 hdd_err("WMI_PDEV_PARAM_ARP_AC_OVERRIDE ac: %d ret: %d",
8340 hdd_ctx->config->arp_ac_category, ret);
8341 goto out;
8342 }
8343
8344
Prashanth Bhatta07998752016-04-28 12:35:33 -07008345 status = hdd_set_sme_chan_list(hdd_ctx);
8346 if (status != QDF_STATUS_SUCCESS) {
8347 hdd_alert("Failed to init channel list: %d", status);
8348 ret = qdf_status_to_os_return(status);
8349 goto out;
8350 }
8351
8352 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07008353 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07008354 hdd_alert("config update failed");
8355 ret = -EINVAL;
8356 goto out;
8357 }
8358
Prashanth Bhatta07998752016-04-28 12:35:33 -07008359 /*
8360 * Set the MAC Address Currently this is used by HAL to add self sta.
8361 * Remove this once self sta is added as part of session open.
8362 */
8363 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
8364 hdd_ctx->config->intfMacAddr[0].bytes,
8365 sizeof(hdd_ctx->config->intfMacAddr[0]));
8366
8367 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
8368 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
8369 hal_status, hal_status);
8370 ret = -EINVAL;
8371 goto out;
8372 }
8373
8374 hdd_init_channel_avoidance(hdd_ctx);
8375
8376out:
8377 return ret;
8378}
8379
8380/**
Peng Xu8fdaa492016-06-22 10:20:47 -07008381 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
8382 * @context_ptr - hdd context pointer
8383 * @event_ptr - event structure pointer
8384 *
8385 * This is the p2p listen offload stop event handler, it sends vendor
8386 * event back to supplicant to notify the stop reason.
8387 *
8388 * Return: None
8389 */
8390static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
8391 void *event_ptr)
8392{
8393 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
8394 struct sir_p2p_lo_event *evt = event_ptr;
8395 struct sk_buff *vendor_event;
8396
8397 ENTER();
8398
8399 if (hdd_ctx == NULL) {
8400 hdd_err("Invalid HDD context pointer");
8401 return;
8402 }
8403
8404 vendor_event =
8405 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8406 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
8407 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
8408 GFP_KERNEL);
8409
8410 if (!vendor_event) {
8411 hdd_err("cfg80211_vendor_event_alloc failed");
8412 return;
8413 }
8414
8415 if (nla_put_u32(vendor_event,
8416 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
8417 evt->reason_code)) {
8418 hdd_err("nla put failed");
8419 kfree_skb(vendor_event);
8420 return;
8421 }
8422
8423 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8424}
8425
8426/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308427 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
8428 * @hdd_ctx: HDD context
8429 *
8430 * This function sends the adaptive dwell time config configuration to the
8431 * firmware via WMA
8432 *
8433 * Return: 0 - success, < 0 - failure
8434 */
8435static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
8436{
8437 QDF_STATUS status;
8438 struct adaptive_dwelltime_params dwelltime_params;
8439
8440 dwelltime_params.is_enabled =
8441 hdd_ctx->config->adaptive_dwell_mode_enabled;
8442 dwelltime_params.dwelltime_mode =
8443 hdd_ctx->config->global_adapt_dwelltime_mode;
8444 dwelltime_params.lpf_weight =
8445 hdd_ctx->config->adapt_dwell_lpf_weight;
8446 dwelltime_params.passive_mon_intval =
8447 hdd_ctx->config->adapt_dwell_passive_mon_intval;
8448 dwelltime_params.wifi_act_threshold =
8449 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
8450
8451 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
8452 &dwelltime_params);
8453
8454 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
8455 if (!QDF_IS_STATUS_SUCCESS(status)) {
8456 hdd_err("Failed to send Adaptive Dwelltime configuration!");
8457 return -EAGAIN;
8458 }
8459 return 0;
8460}
8461
Arun Khandavallid4349a92016-07-25 11:10:43 +05308462#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8463/**
8464 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
8465 * @hdd_ctx: HDD context
8466 *
8467 * Set auto shutdown callback to get indications from firmware to indicate
8468 * userspace to shutdown WLAN after a configured amount of inactivity.
8469 *
8470 * Return: 0 on success and errno on failure.
8471 */
8472static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8473{
8474 QDF_STATUS status;
8475
8476 if (!hdd_ctx->config->WlanAutoShutdown)
8477 return 0;
8478
8479 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
8480 wlan_hdd_auto_shutdown_cb);
8481 if (status != QDF_STATUS_SUCCESS)
8482 hdd_err("Auto shutdown feature could not be enabled: %d",
8483 status);
8484
8485 return qdf_status_to_os_return(status);
8486}
8487#else
8488static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
8489{
8490 return 0;
8491}
8492#endif
8493
8494/**
8495 * hdd_features_init() - Init features
8496 * @hdd_ctx: HDD context
8497 * @adapter: Primary adapter context
8498 *
8499 * Initialize features and their feature context after WLAN firmware is up.
8500 *
8501 * Return: 0 on success and errno on failure.
8502 */
8503static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8504{
8505 tSirTxPowerLimit hddtxlimit;
8506 QDF_STATUS status;
8507 int ret;
8508
8509 ENTER();
8510
8511 ret = hdd_update_country_code(hdd_ctx, adapter);
8512 if (ret) {
8513 hdd_err("Failed to update country code: %d", ret);
8514 goto out;
8515 }
8516
8517 /* FW capabilities received, Set the Dot11 mode */
8518 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07008519 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
8520 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05308521
Arun Khandavallid4349a92016-07-25 11:10:43 +05308522
8523 if (hdd_ctx->config->fIsImpsEnabled)
8524 hdd_set_idle_ps_config(hdd_ctx, true);
8525 else
8526 hdd_set_idle_ps_config(hdd_ctx, false);
8527
Agrawal Ashish642ec9b2017-02-22 14:45:30 +05308528 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8529 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
8530
Arun Khandavallid4349a92016-07-25 11:10:43 +05308531 if (hdd_lro_init(hdd_ctx))
8532 hdd_err("Unable to initialize LRO in fw");
8533
8534 if (hdd_adaptive_dwelltime_init(hdd_ctx))
8535 hdd_err("Unable to send adaptive dwelltime setting to FW");
8536
8537 ret = hdd_init_thermal_info(hdd_ctx);
8538 if (ret) {
8539 hdd_err("Error while initializing thermal information");
8540 goto deregister_frames;
8541 }
8542
Poddar, Siddarth66a46592017-02-22 11:44:44 +05308543 if (cds_is_packet_log_enabled())
8544 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
8545
Arun Khandavallid4349a92016-07-25 11:10:43 +05308546 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
8547 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
8548 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
8549 if (!QDF_IS_STATUS_SUCCESS(status))
8550 hdd_err("Error setting txlimit in sme: %d", status);
8551
8552 hdd_tsf_init(hdd_ctx);
8553
Arun Khandavallid4349a92016-07-25 11:10:43 +05308554 ret = hdd_register_cb(hdd_ctx);
8555 if (ret) {
8556 hdd_err("Failed to register HDD callbacks!");
8557 goto deregister_frames;
8558 }
8559
8560 if (hdd_ctx->config->dual_mac_feature_disable) {
8561 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
8562 if (status != QDF_STATUS_SUCCESS) {
8563 hdd_err("Failed to disable dual mac features");
8564 goto deregister_cb;
8565 }
8566 }
Selvaraj, Sridhar371f55e2017-02-21 10:36:15 +05308567 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8568 status = sme_enable_disable_chanavoidind_event(
8569 hdd_ctx->hHal, 0);
8570 if (!QDF_IS_STATUS_SUCCESS(status)) {
8571 hdd_err("Failed to disable Chan Avoidance Indication");
8572 goto deregister_cb;
8573 }
8574 }
Arun Khandavallid4349a92016-07-25 11:10:43 +05308575
8576 /* register P2P Listen Offload event callback */
8577 if (wma_is_p2p_lo_capable())
8578 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
8579 wlan_hdd_p2p_lo_event_callback);
8580
8581 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
8582
8583 if (ret)
8584 goto deregister_cb;
8585
8586 EXIT();
8587 return 0;
8588
8589deregister_cb:
8590 hdd_deregister_cb(hdd_ctx);
8591deregister_frames:
8592 wlan_hdd_cfg80211_deregister_frames(adapter);
8593out:
8594 return -EINVAL;
8595
8596}
8597
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308598#ifdef NAPIER_SCAN
8599/**
8600 *
8601 * hdd_post_cds_enable_config() - HDD post cds start config helper
8602 * @adapter - Pointer to the HDD
8603 *
8604 * Return: None
8605 */
8606static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8607{
8608 QDF_STATUS status;
8609
8610 status = ucfg_scan_register_bcn_cb(hdd_ctx->hdd_psoc,
8611 wlan_cfg80211_inform_bss_frame,
8612 SCAN_CB_TYPE_INFORM_BCN);
8613 if (!QDF_IS_STATUS_SUCCESS(status)) {
8614 hdd_err("failed with status code %08d [x%08x]",
8615 status, status);
8616 return status;
8617 }
8618
8619 return QDF_STATUS_SUCCESS;
8620}
8621#else
8622static inline QDF_STATUS hdd_register_bcn_cb(hdd_context_t *hdd_ctx)
8623{
8624 return QDF_STATUS_SUCCESS;
8625}
8626
8627#endif
Arun Khandavallid4349a92016-07-25 11:10:43 +05308628
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05308629/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308630 * hdd_configure_cds() - Configure cds modules
8631 * @hdd_ctx: HDD context
8632 * @adapter: Primary adapter context
8633 *
8634 * Enable Cds modules after WLAN firmware is up.
8635 *
8636 * Return: 0 on success and errno on failure.
8637 */
8638int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
8639{
8640 int ret;
8641 QDF_STATUS status;
Arun Khandavallifae92942016-08-01 13:31:08 +05308642
8643 ret = hdd_pre_enable_configure(hdd_ctx);
8644 if (ret) {
8645 hdd_err("Failed to pre-configure cds");
8646 goto out;
8647 }
8648
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08008649 /* Always get latest IPA resources allocated from cds_open and configure
8650 * IPA module before configuring them to FW. Sequence required as crash
8651 * observed otherwise.
8652 */
8653 if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
8654 if (hdd_ipa_uc_ol_init(hdd_ctx)) {
8655 hdd_err("Failed to setup pipes");
8656 goto out;
8657 }
8658 }
8659
Arun Khandavallifae92942016-08-01 13:31:08 +05308660 /*
8661 * Start CDS which starts up the SME/MAC/HAL modules and everything
8662 * else
8663 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308664 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308665
8666 if (!QDF_IS_STATUS_SUCCESS(status)) {
8667 hdd_alert("cds_enable failed");
8668 goto out;
8669 }
8670
8671 status = hdd_post_cds_enable_config(hdd_ctx);
8672 if (!QDF_IS_STATUS_SUCCESS(status)) {
8673 hdd_alert("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008674 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308675 }
Abhishek Singh6092fbb2017-01-25 18:10:31 +05308676 status = hdd_register_bcn_cb(hdd_ctx);
8677 if (!QDF_IS_STATUS_SUCCESS(status)) {
8678 hdd_alert("hdd_post_cds_enable_config failed");
8679 goto cds_disable;
8680 }
Arun Khandavallifae92942016-08-01 13:31:08 +05308681
8682 ret = hdd_features_init(hdd_ctx, adapter);
8683 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008684 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05308685
Arun Khandavallifae92942016-08-01 13:31:08 +05308686
8687 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008688
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008689cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308690 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07008691
Arun Khandavallifae92942016-08-01 13:31:08 +05308692out:
8693 return -EINVAL;
8694}
8695
8696/**
8697 * hdd_deconfigure_cds() -De-Configure cds
8698 * @hdd_ctx: HDD context
8699 *
8700 * Deconfigure Cds modules before WLAN firmware is down.
8701 *
8702 * Return: 0 on success and errno on failure.
8703 */
Jeff Johnson590e2012016-10-05 16:16:24 -07008704static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05308705{
8706 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07008707 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308708
8709 ENTER();
8710 /* De-register the SME callbacks */
8711 hdd_deregister_cb(hdd_ctx);
8712
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308713 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308714 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8715 hdd_err("Failed to Disable the CDS Modules! :%d",
8716 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07008717 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308718 }
8719
8720 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07008721 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308722}
8723
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008724#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
8725static void hdd_deregister_policy_manager_callback(
8726 struct wlan_objmgr_psoc *psoc)
8727{
8728 if (QDF_STATUS_SUCCESS !=
8729 policy_mgr_deregister_hdd_cb(psoc)) {
8730 hdd_err("HDD callback deregister with policy manager failed");
8731 }
8732}
8733#else
8734static void hdd_deregister_policy_manager_callback(
8735 struct wlan_objmgr_psoc *psoc)
8736{
8737}
8738#endif
Arun Khandavallifae92942016-08-01 13:31:08 +05308739
8740/**
8741 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
8742 * @hdd_ctx: HDD context
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008743 * @ftm_mode: ftm mode
Arun Khandavallifae92942016-08-01 13:31:08 +05308744 *
8745 * This function maintains the driver state machine it will be invoked from
8746 * exit, shutdown and con_mode change handler. Depending on the driver state
8747 * shall perform the stopping/closing of the modules.
8748 *
8749 * Return: 0 for success; non-zero for failure
8750 */
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008751int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool ftm_mode)
Arun Khandavallifae92942016-08-01 13:31:08 +05308752{
8753 void *hif_ctx;
8754 qdf_device_t qdf_ctx;
8755 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308756 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05308757 p_cds_sched_context cds_sched_context = NULL;
Dustin Brown70111822017-03-30 15:31:40 -07008758 bool is_idle_stop = !cds_is_driver_unloading() &&
8759 !cds_is_driver_recovering();
8760 int active_threads;
Arun Khandavallifae92942016-08-01 13:31:08 +05308761
8762 ENTER();
8763
Archana Ramachandranea34c4f2017-03-19 18:56:18 -07008764 hdd_deregister_policy_manager_callback(hdd_ctx->hdd_psoc);
8765
Arun Khandavallifae92942016-08-01 13:31:08 +05308766 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8767 if (!qdf_ctx) {
8768 hdd_err("QDF device context NULL");
8769 return -EINVAL;
8770 }
8771
8772 cds_sched_context = get_cds_sched_ctxt();
8773 if (!cds_sched_context) {
8774 hdd_err("cds scheduler context NULL");
8775 return -EINVAL;
8776 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308777 mutex_lock(&hdd_ctx->iface_change_lock);
8778 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05308779
Dustin Brown70111822017-03-30 15:31:40 -07008780 active_threads = cds_return_external_threads_count();
8781 if (active_threads > 0 || hdd_ctx->isWiphySuspended) {
Rajeev Kumar86177c22017-03-16 19:44:39 -07008782 hdd_warn("External threads %d wiphy suspend %d",
Dustin Brown70111822017-03-30 15:31:40 -07008783 active_threads, hdd_ctx->isWiphySuspended);
8784
8785 cds_print_external_threads();
8786
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008787 if (is_idle_stop && !ftm_mode) {
Dustin Brown70111822017-03-30 15:31:40 -07008788 mutex_unlock(&hdd_ctx->iface_change_lock);
8789 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008790 hdd_ctx->config->iface_change_wait_time);
8791 hdd_ctx->stop_modules_in_progress = false;
Dustin Brown70111822017-03-30 15:31:40 -07008792 return 0;
8793 }
Rajeev Kumar86177c22017-03-16 19:44:39 -07008794 }
8795
Arun Khandavallifae92942016-08-01 13:31:08 +05308796 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
8797
8798 switch (hdd_ctx->driver_status) {
8799 case DRIVER_MODULES_UNINITIALIZED:
8800 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308801 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308802 case DRIVER_MODULES_CLOSED:
8803 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308804 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308805 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05308806 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308807 if (hdd_deconfigure_cds(hdd_ctx)) {
8808 hdd_alert("Failed to de-configure CDS");
8809 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308810 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308811 }
8812 hdd_info("successfully Disabled the CDS modules!");
8813 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8814 break;
8815 case DRIVER_MODULES_OPENED:
8816 hdd_info("Closing CDS modules!");
8817 break;
8818 default:
8819 hdd_err("Trying to stop wlan in a wrong state: %d",
8820 hdd_ctx->driver_status);
8821 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308822 ret = -EINVAL;
8823 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308824 }
8825
Govind Singhb048e872016-09-27 22:07:43 +05308826 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8827 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8828 hdd_err("Failed to process post CDS disable Modules! :%d",
8829 qdf_status);
8830 ret = -EINVAL;
8831 QDF_ASSERT(0);
8832 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308833 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308834 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8835 hdd_warn("Failed to stop CDS:%d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308836 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308837 QDF_ASSERT(0);
8838 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008839
Arun Khandavallifae92942016-08-01 13:31:08 +05308840 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8841 if (!hif_ctx) {
8842 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308843 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308844 }
8845
8846 hdd_hif_close(hif_ctx);
8847
8848 ol_cds_free();
8849
Dustin Brown70111822017-03-30 15:31:40 -07008850 if (is_idle_stop) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308851 ret = pld_power_off(qdf_ctx->dev);
8852 if (ret)
8853 hdd_err("CNSS power down failed put device into Low power mode:%d",
8854 ret);
8855 }
8856 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
8857
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308858done:
8859 hdd_ctx->stop_modules_in_progress = false;
8860 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308861 EXIT();
8862
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308863 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308864
8865}
8866
8867/**
8868 * hdd_iface_change_callback() - Function invoked when stop modules expires
8869 * @priv: pointer to hdd context
8870 *
8871 * This function is invoked when the timer waiting for the interface change
8872 * expires, it shall cut-down the power to wlan and stop all the modules.
8873 *
8874 * Return: void
8875 */
8876static void hdd_iface_change_callback(void *priv)
8877{
8878 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
8879 int ret;
8880 int status = wlan_hdd_validate_context(hdd_ctx);
8881
8882 if (status)
8883 return;
8884
8885 ENTER();
8886 hdd_info("Interface change timer expired close the modules!");
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07008887 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05308888 if (ret)
8889 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05308890 EXIT();
8891}
8892
8893/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308894 * hdd_state_info_dump() - prints state information of hdd layer
8895 * @buf: buffer pointer
8896 * @size: size of buffer to be filled
8897 *
8898 * This function is used to dump state information of hdd layer
8899 *
8900 * Return: None
8901 */
8902static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
8903{
8904 hdd_context_t *hdd_ctx;
8905 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8906 QDF_STATUS status;
8907 hdd_station_ctx_t *hdd_sta_ctx;
8908 hdd_adapter_t *adapter;
8909 uint16_t len = 0;
8910 char *buf = *buf_ptr;
8911
8912 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8913 if (!hdd_ctx) {
8914 hdd_err("Failed to get hdd context ");
8915 return;
8916 }
8917
8918 hdd_notice("size of buffer: %d", *size);
8919
8920 len += scnprintf(buf + len, *size - len,
8921 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8922 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008923 "\n is_scheduler_suspended %d",
8924 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308925
8926 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8927
8928 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8929 adapter = adapter_node->pAdapter;
8930 if (adapter->dev)
8931 len += scnprintf(buf + len, *size - len,
8932 "\n device name: %s", adapter->dev->name);
8933 len += scnprintf(buf + len, *size - len,
8934 "\n device_mode: %d", adapter->device_mode);
8935 switch (adapter->device_mode) {
8936 case QDF_STA_MODE:
8937 case QDF_P2P_CLIENT_MODE:
8938 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8939 len += scnprintf(buf + len, *size - len,
8940 "\n connState: %d",
8941 hdd_sta_ctx->conn_info.connState);
8942 break;
8943
8944 default:
8945 break;
8946 }
8947 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
8948 adapter_node = next;
8949 }
8950
8951 *size -= len;
8952 *buf_ptr += len;
8953}
8954
8955/**
8956 * hdd_register_debug_callback() - registration function for hdd layer
8957 * to print hdd state information
8958 *
8959 * Return: None
8960 */
8961static void hdd_register_debug_callback(void)
8962{
8963 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
8964}
8965
8966/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008967 * hdd_wlan_startup() - HDD init function
8968 * @dev: Pointer to the underlying device
8969 *
8970 * This is the driver startup code executed once a WLAN device has been detected
8971 *
8972 * Return: 0 for success, < 0 for failure
8973 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308974int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008975{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308976 QDF_STATUS status;
Jeff Johnson957bc272017-02-02 08:54:48 -08008977 hdd_context_t *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008978 int ret;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008979 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308980 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008981
8982 ENTER();
8983
Arun Khandavallifae92942016-08-01 13:31:08 +05308984 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008985
8986 if (IS_ERR(hdd_ctx))
8987 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008988
Abhishek Singhe9068f12017-03-31 14:14:52 +05308989 ret = hdd_objmgr_create_and_store_psoc(hdd_ctx,
8990 DEFAULT_PSOC_ID);
8991 if (ret) {
8992 hdd_err("Psoc creation fails!");
8993 QDF_BUG(0);
8994 goto err_hdd_free_context;
8995 }
8996
Arun Khandavallifae92942016-08-01 13:31:08 +05308997 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
8998 hdd_iface_change_callback, (void *)hdd_ctx);
8999
9000 mutex_init(&hdd_ctx->iface_change_lock);
9001
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009002 ret = hdd_init_netlink_services(hdd_ctx);
9003 if (ret)
9004 goto err_hdd_free_context;
9005
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009006 hdd_request_manager_init();
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07009007 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309008
Jeff Johnson957bc272017-02-02 08:54:48 -08009009 ret = hdd_wlan_start_modules(hdd_ctx, NULL, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309010 if (ret) {
9011 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009012 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009013 }
9014
Yingying Tang80e15f32016-09-27 18:23:01 +08009015 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009016
Yingying Tang95409972016-10-20 15:16:15 +08009017 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
9018 hdd_notice("Failed to set wow pulse");
9019
Anurag Chouhan6d760662016-02-20 16:05:43 +05309020 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009021
9022 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009023 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05309024 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009025 }
9026
Prashanth Bhatta07998752016-04-28 12:35:33 -07009027 ret = hdd_wiphy_init(hdd_ctx);
9028 if (ret) {
9029 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05309030 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009031 }
9032
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05309033 if (hdd_ctx->config->enable_dp_trace)
9034 qdf_dp_trace_init();
9035
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309036 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009037 goto err_wiphy_unregister;
9038
Kapil Gupta4f0c0c12017-02-07 15:21:15 +05309039 wlan_hdd_init_chan_info(hdd_ctx);
9040
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07009041 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08009042
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009043 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009044
Jeff Johnson957bc272017-02-02 08:54:48 -08009045 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
9046 if (ret) {
9047 hdd_alert("Failed to open interfaces: %d", ret);
Jeff Johnson46bde382017-02-01 15:31:16 -08009048 goto err_release_rtnl_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009049 }
9050
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08009051 hdd_release_rtnl_lock();
9052 rtnl_held = false;
9053
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009054 wlan_hdd_update_11n_mode(hdd_ctx->config);
9055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009056#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05309057 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309058 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009059 hdd_skip_acs_scan_timer_handler,
9060 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309061 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07009062 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04009063 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009064#endif
9065
Nitesh Shah61c10d92016-10-19 19:29:15 +05309066 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
9067 QDF_TIMER_TYPE_SW,
9068 wlan_hdd_change_tdls_mode,
9069 hdd_ctx);
9070
Prashanth Bhattaab004382016-10-11 16:08:11 -07009071 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009072
Jeff Johnson9afc5012016-09-23 13:56:27 -07009073 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009074
Nirav Shahbd36b062016-07-18 11:12:59 +05309075 if (hdd_ctx->rps)
9076 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07009077
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009078 ret = hdd_register_notifiers(hdd_ctx);
9079 if (ret)
Jeff Johnson957bc272017-02-02 08:54:48 -08009080 goto err_close_adapters;
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05309081
9082 status = wlansap_global_init();
9083 if (QDF_IS_STATUS_ERROR(status))
Jeff Johnson957bc272017-02-02 08:54:48 -08009084 goto err_close_adapters;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07009085
Komal Seelam8634b772016-09-29 12:12:24 +05309086 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009087 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309088 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009089
bings612b9c42016-11-07 10:52:03 +08009090 if (hdd_enable_egap(hdd_ctx))
9091 hdd_err("enhance green ap is not enabled");
9092
Arun Khandavallifae92942016-08-01 13:31:08 +05309093 if (hdd_ctx->config->fIsImpsEnabled)
9094 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309095
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05309096 if (hdd_ctx->config->sifs_burst_duration) {
9097 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
9098 hdd_ctx->config->sifs_burst_duration;
9099
9100 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
9101 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
9102 set_value, PDEV_CMD);
9103 }
9104
Arun Khandavallifae92942016-08-01 13:31:08 +05309105 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
9106 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309107
Selvaraj, Sridhar1ffa0ec2017-03-10 09:52:12 +05309108 complete(&wlan_start_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009109 goto success;
9110
Jeff Johnson957bc272017-02-02 08:54:48 -08009111err_close_adapters:
Jeff Johnson46bde382017-02-01 15:31:16 -08009112 hdd_close_all_adapters(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113
Jeff Johnson46bde382017-02-01 15:31:16 -08009114err_release_rtnl_lock:
Arun Khandavallid4349a92016-07-25 11:10:43 +05309115 if (rtnl_held)
9116 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117
Anurag Chouhance6a4052016-09-14 18:20:42 +05309118 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08009119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009120err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009121 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009122
Arun Khandavallifae92942016-08-01 13:31:08 +05309123err_stop_modules:
Rajeev Kumar3fef4e82017-03-31 20:25:23 -07009124 hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309125
Himanshu Agarwal0b9bbc32017-02-23 16:23:05 +05309126err_exit_nl_srv:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009127 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309128 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009129 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309130 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009131 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009132
Houston Hoffman47a4a052016-11-14 23:22:44 -08009133 hdd_green_ap_deinit(hdd_ctx);
Jeff Johnsonce0032c2017-01-20 07:18:27 -08009134 hdd_request_manager_deinit();
Ryan Hsucfef0ae2016-04-28 10:20:46 -07009135 hdd_exit_netlink_services(hdd_ctx);
9136
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309137 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009138err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05309139 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
9140 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07009141 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309142 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009144 return -EIO;
9145
9146success:
9147 EXIT();
9148 return 0;
9149}
9150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009151/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309152 * hdd_wlan_update_target_info() - update target type info
9153 * @hdd_ctx: HDD context
9154 * @context: hif context
9155 *
9156 * Update target info received from firmware in hdd context
9157 * Return:None
9158 */
9159
9160void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
9161{
9162 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
9163
9164 if (!tgt_info) {
9165 hdd_err("Target info is Null");
9166 return;
9167 }
9168
9169 hdd_ctx->target_type = tgt_info->target_type;
9170}
9171
9172/**
9173 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309174 * @hdd_ctx: HDD context
9175 *
9176 * Register the HDD callbacks to CDS/SME.
9177 *
9178 * Return: 0 for success or Error code for failure
9179 */
9180int hdd_register_cb(hdd_context_t *hdd_ctx)
9181{
9182 QDF_STATUS status;
9183 int ret = 0;
9184
9185 ENTER();
9186
9187 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
9188
9189 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
9190 hdd_send_oem_data_rsp_msg);
9191
9192 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
9193 wlan_hdd_cfg80211_fw_mem_dump_cb);
9194 if (!QDF_IS_STATUS_SUCCESS(status)) {
9195 hdd_err("Failed to register memdump callback");
9196 ret = -EINVAL;
9197 return ret;
9198 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05309199 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
9200 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309201 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
9202 sme_nan_register_callback(hdd_ctx->hHal,
9203 wlan_hdd_cfg80211_nan_callback);
9204 sme_stats_ext_register_callback(hdd_ctx->hHal,
9205 wlan_hdd_cfg80211_stats_ext_callback);
9206
9207 sme_ext_scan_register_callback(hdd_ctx->hHal,
9208 wlan_hdd_cfg80211_extscan_callback);
9209
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309210 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
9211 hdd_rssi_threshold_breached);
9212
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309213 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
9214 wlan_hdd_cfg80211_link_layer_stats_callback);
9215
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05309216 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
9217 hdd_lost_link_info_cb);
9218 /* print error and not block the startup process */
9219 if (!QDF_IS_STATUS_SUCCESS(status))
9220 hdd_err("set lost link info callback failed");
9221
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309222 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
9223
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009224 sme_register_set_connection_info_cb(hdd_ctx->hHal,
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009225 hdd_set_connection_in_progress,
9226 hdd_is_connection_in_progress);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309227 EXIT();
9228
9229 return ret;
9230}
9231
9232/**
9233 * hdd_deregister_cb() - De-Register HDD callbacks.
9234 * @hdd_ctx: HDD context
9235 *
9236 * De-Register the HDD callbacks to CDS/SME.
9237 *
9238 * Return: void
9239 */
9240void hdd_deregister_cb(hdd_context_t *hdd_ctx)
9241{
9242 QDF_STATUS status;
9243
9244 ENTER();
9245
9246 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
9247 if (!QDF_IS_STATUS_SUCCESS(status))
9248 hdd_err("De-register of dcc stats callback failed: %d",
9249 status);
9250
9251 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309252 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
9253
Arun Khandavalli4b55da72016-07-19 19:55:01 +05309254 sme_stats_ext_register_callback(hdd_ctx->hHal,
9255 wlan_hdd_cfg80211_stats_ext_callback);
9256
9257 sme_nan_deregister_callback(hdd_ctx->hHal);
9258 status = sme_reset_tsfcb(hdd_ctx->hHal);
9259 if (!QDF_IS_STATUS_SUCCESS(status))
9260 hdd_err("Failed to de-register tsfcb the callback:%d",
9261 status);
9262 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
9263 if (!QDF_IS_STATUS_SUCCESS(status))
9264 hdd_err("Failed to de-register the fw mem dump callback: %d",
9265 status);
9266
9267 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
9268 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
9269
9270 EXIT();
9271}
9272
9273/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009274 * hdd_softap_sta_deauth() - handle deauth req from HDD
9275 * @adapter: Pointer to the HDD
9276 * @enable: bool value
9277 *
9278 * This to take counter measure to handle deauth req from HDD
9279 *
9280 * Return: None
9281 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309282QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009283 struct tagCsrDelStaParams *pDelStaParams)
9284{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309285 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009286
9287 ENTER();
9288
Jeff Johnson34c88b72016-08-15 14:27:11 -07009289 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009290 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9291
9292 /* Ignore request to deauth bcmc station */
9293 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309294 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009295
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309296 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009297 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9298 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299
9300 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309301 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009302}
9303
9304/**
9305 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
9306 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309307 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009308 *
9309 * This to take counter measure to handle deauth req from HDD
9310 *
9311 * Return: None
9312 */
9313void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309314 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009315{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009316 ENTER();
9317
Jeff Johnson34c88b72016-08-15 14:27:11 -07009318 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009319 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9320
9321 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309322 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009323 return;
9324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009325 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05309326 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009327}
9328
9329void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
9330 bool enable)
9331{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009332 ENTER();
9333
Jeff Johnson34c88b72016-08-15 14:27:11 -07009334 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009335 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
9336
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009337 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9338 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009339}
9340
9341/**
9342 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
9343 * @hdd_ctx: HDD Context
9344 *
9345 * API to find if there is any STA or P2P-Client is connected
9346 *
9347 * Return: true if connected; false otherwise
9348 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309349QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009350{
9351 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
9352}
9353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009354/**
9355 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
9356 * @adapter: HDD adapter pointer
9357 *
9358 * This function loop through each adapter and disable roaming on each STA
9359 * device mode except the input adapter.
9360 *
9361 * Note: On the input adapter roaming is not enabled yet hence no need to
9362 * disable.
9363 *
9364 * Return: None
9365 */
9366void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
9367{
9368 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9369 hdd_adapter_t *adapterIdx = NULL;
9370 hdd_adapter_list_node_t *adapterNode = NULL;
9371 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309372 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009373
9374 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009375 hdd_ctx->config->isRoamOffloadScanEnabled &&
9376 QDF_STA_MODE == adapter->device_mode &&
9377 policy_mgr_is_sta_active_connection_exists(
9378 hdd_ctx->hdd_psoc)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009379 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009380 adapter->sessionId);
9381 /*
9382 * Loop through adapter and disable roaming for each STA device
9383 * mode except the input adapter.
9384 */
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 adapterIdx = adapterNode->pAdapter;
9389
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009390 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009391 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009392 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009393 adapterIdx->sessionId);
9394 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
9395 (adapterIdx),
9396 adapterIdx->sessionId, 0);
9397 }
9398
9399 status = hdd_get_next_adapter(hdd_ctx,
9400 adapterNode,
9401 &pNext);
9402 adapterNode = pNext;
9403 }
9404 }
9405}
9406
9407/**
9408 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
9409 * @adapter: HDD adapter pointer
9410 *
9411 * This function loop through each adapter and enable roaming on each STA
9412 * device mode except the input adapter.
9413 * Note: On the input adapter no need to enable roaming because link got
9414 * disconnected on this.
9415 *
9416 * Return: None
9417 */
9418void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
9419{
9420 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9421 hdd_adapter_t *adapterIdx = NULL;
9422 hdd_adapter_list_node_t *adapterNode = NULL;
9423 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309424 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009425
9426 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009427 hdd_ctx->config->isRoamOffloadScanEnabled &&
9428 QDF_STA_MODE == adapter->device_mode &&
9429 policy_mgr_is_sta_active_connection_exists(
9430 hdd_ctx->hdd_psoc)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009431 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009432 adapter->sessionId);
9433 /*
9434 * Loop through adapter and enable roaming for each STA device
9435 * mode except the input adapter.
9436 */
9437 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9438
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309439 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440 adapterIdx = adapterNode->pAdapter;
9441
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009442 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009443 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009444 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009445 adapterIdx->sessionId);
9446 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
9447 (adapterIdx),
9448 adapterIdx->sessionId,
9449 REASON_CONNECT);
9450 }
9451
9452 status = hdd_get_next_adapter(hdd_ctx,
9453 adapterNode,
9454 &pNext);
9455 adapterNode = pNext;
9456 }
9457 }
9458}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009459
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309460/**
9461 * nl_srv_bcast_svc() - Wrapper function to send bcast msgs to SVC mcast group
9462 * @skb: sk buffer pointer
9463 *
9464 * Sends the bcast message to SVC multicast group with generic nl socket
9465 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send.
9466 *
9467 * Return: None
9468 */
9469static void nl_srv_bcast_svc(struct sk_buff *skb)
9470{
9471#ifdef CNSS_GENL
9472 nl_srv_bcast(skb, CLD80211_MCGRP_SVC_MSGS, WLAN_NL_MSG_SVC);
9473#else
9474 nl_srv_bcast(skb);
9475#endif
9476}
9477
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309478void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009479{
9480 struct sk_buff *skb;
9481 struct nlmsghdr *nlh;
9482 tAniMsgHdr *ani_hdr;
9483 void *nl_data = NULL;
9484 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309485 struct radio_index_tlv *radio_info;
9486 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009487
9488 if (in_interrupt() || irqs_disabled() || in_atomic())
9489 flags = GFP_ATOMIC;
9490
9491 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
9492
9493 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07009494 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009495 return;
9496 }
9497
9498 nlh = (struct nlmsghdr *)skb->data;
9499 nlh->nlmsg_pid = 0; /* from kernel */
9500 nlh->nlmsg_flags = 0;
9501 nlh->nlmsg_seq = 0;
9502 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
9503
9504 ani_hdr = NLMSG_DATA(nlh);
9505 ani_hdr->type = type;
9506
9507 switch (type) {
9508 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05309509 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009511 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009512 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009513 ani_hdr->length = 0;
9514 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009515 break;
9516 case WLAN_SVC_WLAN_STATUS_IND:
9517 case WLAN_SVC_WLAN_VERSION_IND:
9518 case WLAN_SVC_DFS_CAC_START_IND:
9519 case WLAN_SVC_DFS_CAC_END_IND:
9520 case WLAN_SVC_DFS_RADAR_DETECT_IND:
9521 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
9522 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08009523 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05309524 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009525 ani_hdr->length = len;
9526 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
9527 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
9528 memcpy(nl_data, data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009529 break;
9530
9531 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07009532 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009533 type);
9534 kfree_skb(skb);
9535 return;
9536 }
9537
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309538 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08009539 * Add radio index at the end of the svc event in TLV format
9540 * to maintain the backward compatibility with userspace
9541 * applications.
9542 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309543
9544 tlv_len = 0;
9545
9546 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
9547 < WLAN_NL_MAX_PAYLOAD) {
9548 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
9549 sizeof(*ani_hdr) + len);
9550 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
9551 radio_info->length = (unsigned short) sizeof(radio_info->radio);
9552 radio_info->radio = radio;
9553 tlv_len = sizeof(*radio_info);
9554 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
9555 "Added radio index tlv - radio index %d",
9556 radio_info->radio);
9557 }
9558
9559 nlh->nlmsg_len += tlv_len;
9560 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
9561
Selvaraj, Sridhar046d77d2017-03-07 14:53:13 +05309562 nl_srv_bcast_svc(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009563
9564 return;
9565}
9566
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009567#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
9568void wlan_hdd_auto_shutdown_cb(void)
9569{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07009570 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309571
9572 if (!hdd_ctx)
9573 return;
9574
Jeff Johnson28f8a772016-08-15 15:30:36 -07009575 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309576 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
9577 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009578}
9579
9580void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
9581{
9582 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309583 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009584 hdd_adapter_t *adapter;
9585 bool ap_connected = false, sta_connected = false;
9586 tHalHandle hal_handle;
9587
9588 hal_handle = hdd_ctx->hHal;
9589 if (hal_handle == NULL)
9590 return;
9591
9592 if (hdd_ctx->config->WlanAutoShutdown == 0)
9593 return;
9594
9595 if (enable == false) {
9596 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309597 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009598 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009599 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05309600 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07009601 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009602 return;
9603 }
9604
9605 /* To enable shutdown timer check conncurrency */
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009606 if (policy_mgr_concurrent_open_sessions_running(
9607 hdd_ctx->hdd_psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009608 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
9609
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309610 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009611 adapter = adapterNode->pAdapter;
9612 if (adapter
9613 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009614 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009615 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9616 conn_info.connState ==
9617 eConnectionState_Associated) {
9618 sta_connected = true;
9619 break;
9620 }
9621 }
9622 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009623 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009624 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
9625 bApActive == true) {
9626 ap_connected = true;
9627 break;
9628 }
9629 }
9630 status = hdd_get_next_adapter(hdd_ctx,
9631 adapterNode,
9632 &pNext);
9633 adapterNode = pNext;
9634 }
9635 }
9636
9637 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009638 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009639 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009640 }
Jeff Johnson68755312017-02-10 11:46:55 -08009641
9642 if (sme_set_auto_shutdown_timer(hal_handle,
9643 hdd_ctx->config->WlanAutoShutdown)
9644 != QDF_STATUS_SUCCESS)
9645 hdd_err("Failed to start wlan auto shutdown timer");
9646 else
9647 hdd_notice("Auto Shutdown timer for %d seconds enabled",
9648 hdd_ctx->config->WlanAutoShutdown);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009649}
9650#endif
9651
9652hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
9653 bool check_start_bss)
9654{
9655 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
9656 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309657 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009658 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
9659
9660 con_sap_adapter = NULL;
9661
9662 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309663 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009664 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009665 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
9666 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667 adapter != this_sap_adapter) {
9668 if (check_start_bss) {
9669 if (test_bit(SOFTAP_BSS_STARTED,
9670 &adapter->event_flags)) {
9671 con_sap_adapter = adapter;
9672 break;
9673 }
9674 } else {
9675 con_sap_adapter = adapter;
9676 break;
9677 }
9678 }
9679 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
9680 adapterNode = pNext;
9681 }
9682
9683 return con_sap_adapter;
9684}
9685
9686#ifdef MSM_PLATFORM
Dustin Brown5ec6b552017-03-31 12:11:40 -07009687static inline bool hdd_adapter_is_sta(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009688{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009689 return adapter->device_mode == QDF_STA_MODE ||
9690 adapter->device_mode == QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009691}
9692
Dustin Brown5ec6b552017-03-31 12:11:40 -07009693static inline bool hdd_adapter_is_ap(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009694{
Dustin Brown5ec6b552017-03-31 12:11:40 -07009695 return adapter->device_mode == QDF_SAP_MODE ||
9696 adapter->device_mode == QDF_P2P_GO_MODE;
9697}
9698
9699static bool hdd_any_adapter_is_assoc(hdd_context_t *hdd_ctx)
9700{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309701 QDF_STATUS status;
Dustin Brown5ec6b552017-03-31 12:11:40 -07009702 hdd_adapter_list_node_t *node;
9703
9704 status = hdd_get_front_adapter(hdd_ctx, &node);
9705 while (QDF_IS_STATUS_SUCCESS(status) && node) {
9706 hdd_adapter_t *adapter = node->pAdapter;
9707
9708 if (adapter &&
9709 hdd_adapter_is_sta(adapter) &&
9710 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
9711 conn_info.connState == eConnectionState_Associated) {
9712 return true;
9713 }
9714
9715 if (adapter &&
9716 hdd_adapter_is_ap(adapter) &&
9717 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive) {
9718 return true;
9719 }
9720
9721 status = hdd_get_next_adapter(hdd_ctx, node, &node);
9722 }
9723
9724 return false;
9725}
9726
9727static bool hdd_bus_bw_compute_timer_is_running(hdd_context_t *hdd_ctx)
9728{
9729 bool is_running;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009730
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309731 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
Dustin Brown5ec6b552017-03-31 12:11:40 -07009732 is_running = hdd_ctx->bus_bw_timer_running;
Poddar, Siddarth57f4d3f2017-01-27 12:58:37 +05309733 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734
Dustin Brown5ec6b552017-03-31 12:11:40 -07009735 return is_running;
9736}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009737
Dustin Brown5ec6b552017-03-31 12:11:40 -07009738static void __hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9739{
9740 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9741 hdd_ctx->bus_bw_timer_running = true;
9742 qdf_timer_start(&hdd_ctx->bus_bw_timer,
9743 hdd_ctx->config->busBandwidthComputeInterval);
9744 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9745}
9746
9747void hdd_bus_bw_compute_timer_start(hdd_context_t *hdd_ctx)
9748{
9749 ENTER();
9750
9751 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9752 hdd_debug("Bandwidth compute timer already started");
9753 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009754 }
9755
Dustin Brown5ec6b552017-03-31 12:11:40 -07009756 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9757
9758 EXIT();
9759}
9760
9761void hdd_bus_bw_compute_timer_try_start(hdd_context_t *hdd_ctx)
9762{
9763 ENTER();
9764
9765 if (hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9766 hdd_debug("Bandwidth compute timer already started");
9767 return;
Ravi Joshib89e7f72016-09-07 13:43:15 -07009768 }
Dustin Brown5ec6b552017-03-31 12:11:40 -07009769
9770 if (hdd_any_adapter_is_assoc(hdd_ctx))
9771 __hdd_bus_bw_compute_timer_start(hdd_ctx);
9772
9773 EXIT();
9774}
9775
9776static void __hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9777{
9778 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
9779
9780 qdf_spinlock_acquire(&hdd_ctx->bus_bw_timer_lock);
9781 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
9782 hdd_ctx->bus_bw_timer_running = false;
9783 qdf_spinlock_release(&hdd_ctx->bus_bw_timer_lock);
9784
9785 hdd_reset_tcp_delack(hdd_ctx);
9786}
9787
9788void hdd_bus_bw_compute_timer_stop(hdd_context_t *hdd_ctx)
9789{
9790 ENTER();
9791
9792 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9793 hdd_debug("Bandwidth compute timer already stopped");
9794 return;
9795 }
9796
9797 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9798
9799 EXIT();
9800}
9801
9802void hdd_bus_bw_compute_timer_try_stop(hdd_context_t *hdd_ctx)
9803{
9804 ENTER();
9805
9806 if (!hdd_bus_bw_compute_timer_is_running(hdd_ctx)) {
9807 hdd_debug("Bandwidth compute timer already stopped");
9808 return;
9809 }
9810
9811 if (!hdd_any_adapter_is_assoc(hdd_ctx))
9812 __hdd_bus_bw_compute_timer_stop(hdd_ctx);
9813
9814 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009815}
9816#endif
9817
9818/**
9819 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
9820 * and sta's operating channel.
9821 * @sta_adapter: Describe the first argument to foobar.
9822 * @ap_adapter: Describe the second argument to foobar.
9823 * @roam_profile: Roam profile of AP to which STA wants to connect.
9824 * @concurrent_chnl_same: If both SAP and STA channels are same then
9825 * set this flag to true else false.
9826 *
9827 * This function checks the sap's operating channel and sta's operating channel.
9828 * if both are same then it will return false else it will restart the sap in
9829 * sta's channel and return true.
9830 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309831 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009832 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309833QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834 hdd_adapter_t *ap_adapter,
9835 tCsrRoamProfile *roam_profile,
9836 tScanResultHandle *scan_cache,
9837 bool *concurrent_chnl_same)
9838{
9839 hdd_ap_ctx_t *hdd_ap_ctx;
9840 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309841 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009842 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009843 *concurrent_chnl_same = true;
9844
9845 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9846 status =
Archana Ramachandran2eb7a612017-03-23 22:58:42 -07009847 sme_get_ap_channel_from_scan_cache(roam_profile,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009848 scan_cache,
9849 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309850 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009851 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009852 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9853 if (hdd_ap_ctx->operatingChannel != channel_id) {
9854 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009855 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009856 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009857 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009858 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
9859 if (hdd_ap_ctx->operatingChannel != channel_id) {
9860 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009861 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009862 }
9863 }
9864 } else {
9865 /*
9866 * Lets handle worst case scenario here, Scan cache lookup is
9867 * failed so we have to stop the SAP to avoid any channel
9868 * discrepancy between SAP's channel and STA's channel.
9869 * Return the status as failure so caller function could know
9870 * that scan look up is failed.
9871 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07009872 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309873 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009874 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309875 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009876}
9877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009878/**
9879 * wlan_hdd_stop_sap() - This function stops bss of SAP.
9880 * @ap_adapter: SAP adapter
9881 *
9882 * This function will process the stopping of sap adapter.
9883 *
9884 * Return: None
9885 */
9886void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
9887{
9888 hdd_ap_ctx_t *hdd_ap_ctx;
9889 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309890 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009891 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009892
9893 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009894 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009895 return;
9896 }
9897
9898 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9899 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309900 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009901 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009903 mutex_lock(&hdd_ctx->sap_lock);
9904 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08009905 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009906 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
9907 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009908 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309909 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309910 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009911 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309912 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08009913 qdf_stop_bss_event,
9914 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309915 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009916 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009917 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009918 return;
9919 }
9920 }
9921 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009922 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
9923 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009924 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009925 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009926 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009927 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009928 }
9929 mutex_unlock(&hdd_ctx->sap_lock);
9930 return;
9931}
9932
9933/**
9934 * wlan_hdd_start_sap() - this function starts bss of SAP.
9935 * @ap_adapter: SAP adapter
9936 *
9937 * This function will process the starting of sap adapter.
9938 *
9939 * Return: None
9940 */
Arun Khandavallicc544b32017-01-30 19:52:16 +05309941void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009942{
9943 hdd_ap_ctx_t *hdd_ap_ctx;
9944 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309945 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009946 hdd_context_t *hdd_ctx;
9947 tsap_Config_t *sap_config;
9948
9949 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009950 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009951 return;
9952 }
9953
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009954 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07009955 hdd_err("SoftAp role has not been enabled");
9956 return;
9957 }
9958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009959 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
9960 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9961 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9962 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
9963
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009964 mutex_lock(&hdd_ctx->sap_lock);
9965 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
9966 goto end;
9967
9968 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009969 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009970 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9971 goto end;
9972 }
9973
Wei Song2f76f642016-11-18 16:32:53 +08009974 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009975 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
9976 &hdd_ap_ctx->sapConfig,
9977 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309978 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009979 goto end;
9980
Jeff Johnson28f8a772016-08-15 15:30:36 -07009981 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309982 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -08009983 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309984 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009985 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 goto end;
9987 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07009988 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009989 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -08009990 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -08009991 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
9992 ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009993 ap_adapter->sessionId);
9994 hostapd_state->bCommit = true;
9995
9996end:
9997 mutex_unlock(&hdd_ctx->sap_lock);
9998 return;
9999}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010000
10001/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -080010002 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
10003 * mac scan config
10004 * @status: Status of set antenna mode
10005 *
10006 * Callback on setting the dual mac configuration
10007 *
10008 * Return: None
10009 */
10010void wlan_hdd_soc_set_antenna_mode_cb(
10011 enum set_antenna_mode_status status)
10012{
10013 hdd_context_t *hdd_ctx;
10014
10015 hdd_info("Status: %d", status);
10016
10017 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10018 if (0 != wlan_hdd_validate_context(hdd_ctx))
10019 return;
10020
10021 /* Signal the completion of set dual mac config */
10022 complete(&hdd_ctx->set_antenna_mode_cmpl);
10023}
10024
10025/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010026 * hdd_get_fw_version() - Get FW version
10027 * @hdd_ctx: pointer to HDD context.
10028 * @major_spid: FW version - major spid.
10029 * @minor_spid: FW version - minor spid
10030 * @ssid: FW version - ssid
10031 * @crmid: FW version - crmid
10032 *
10033 * This function is called to get the firmware build version stored
10034 * as part of the HDD context
10035 *
10036 * Return: None
10037 */
10038void hdd_get_fw_version(hdd_context_t *hdd_ctx,
10039 uint32_t *major_spid, uint32_t *minor_spid,
10040 uint32_t *siid, uint32_t *crmid)
10041{
10042 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
10043 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
10044 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
10045 *crmid = hdd_ctx->target_fw_version & 0x7fff;
10046}
10047
10048#ifdef QCA_CONFIG_SMP
10049/**
10050 * wlan_hdd_get_cpu() - get cpu_index
10051 *
10052 * Return: cpu_index
10053 */
10054int wlan_hdd_get_cpu(void)
10055{
10056 int cpu_index = get_cpu();
10057 put_cpu();
10058 return cpu_index;
10059}
10060#endif
10061
10062/**
10063 * hdd_get_fwpath() - get framework path
10064 *
10065 * This function is used to get the string written by
10066 * userspace to start the wlan driver
10067 *
10068 * Return: string
10069 */
10070const char *hdd_get_fwpath(void)
10071{
10072 return fwpath.string;
10073}
10074
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010075/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010076 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010077 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010078 * This function initilizes CDS global context with the help of cds_init. This
10079 * has to be the first function called after probe to get a valid global
10080 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010081 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010082 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010083 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010084int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010085{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010086 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010087 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010088
Houston Hoffman9e06e542016-12-12 12:06:26 -080010089 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010090#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10091 wlan_logging_sock_init_svc();
10092#endif
10093
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010094 if (p_cds_context == NULL) {
10095 hdd_alert("Failed to allocate CDS context");
10096 ret = -ENOMEM;
10097 goto err_out;
10098 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010099
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010100 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +053010101 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010102
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010103err_out:
10104 return ret;
10105}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010106
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010107/**
10108 * hdd_deinit() - Deinitialize Driver
10109 *
10110 * This function frees CDS global context with the help of cds_deinit. This
10111 * has to be the last function call in remove callback to free the global
10112 * context.
10113 */
10114void hdd_deinit(void)
10115{
10116 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010117
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010118#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10119 wlan_logging_sock_deinit_svc();
10120#endif
10121}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010122
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010123#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010124
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010125/**
10126 * __hdd_module_init - Module init helper
10127 *
10128 * Module init helper function used by both module and static driver.
10129 *
10130 * Return: 0 for success, errno on failure
10131 */
10132static int __hdd_module_init(void)
10133{
10134 int ret = 0;
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010135 unsigned long rc;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010136
Arun Khandavallifae92942016-08-01 13:31:08 +053010137 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010138 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010139
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010140 pld_init();
10141
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010142 ret = hdd_init();
10143 if (ret) {
10144 pr_err("hdd_init failed %x\n", ret);
10145 goto err_hdd_init;
10146 }
10147
Rajeev Kumar97767a02016-11-30 11:20:40 -080010148 dispatcher_init();
10149
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010150 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010151
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010152 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010153
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010154 init_completion(&wlan_start_comp);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010155 ret = wlan_hdd_register_driver();
10156 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -070010157 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
10158 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010159 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010160 }
10161
Arun Khandavalli13cb5da2017-01-19 15:43:52 +053010162 rc = wait_for_completion_timeout(&wlan_start_comp,
10163 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
10164
10165 if (!rc) {
10166 hdd_alert("Timed-out waiting for wlan_hdd_register_driver");
10167 QDF_BUG(0);
10168 goto out;
10169 }
10170
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010171 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010172
10173 return 0;
10174out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010175 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -080010176 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010177 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010178
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010179err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010180 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -080010181
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010182 return ret;
10183}
10184
10185/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010186 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
10187 *
10188 * Block the unloading of the driver until the cds recovery is completed
10189 *
10190 * Return: None
10191 */
10192static void hdd_wait_for_recovery_completion(void)
10193{
10194 int retry = 0;
10195
10196 /* Wait for recovery to complete */
10197 while (cds_is_driver_recovering()) {
10198 hdd_alert("Recovery in progress; wait here!!!");
10199 msleep(1000);
10200 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
10201 hdd_alert("SSR never completed, fatal error");
10202 QDF_BUG(0);
10203 }
10204 }
10205}
10206
10207/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010208 * __hdd_module_exit - Module exit helper
10209 *
10210 * Module exit helper function used by both module and static driver.
10211 */
10212static void __hdd_module_exit(void)
10213{
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010214 int qdf_print_idx = -1;
10215
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010216 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
10217 QWLAN_VERSIONSTR);
10218
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +053010219 hdd_wait_for_recovery_completion();
10220
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010221 wlan_hdd_unregister_driver();
10222
Anurag Chouhana37b5b72016-02-21 14:53:42 +053010223 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010224
Rajeev Kumar97767a02016-11-30 11:20:40 -080010225 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010226 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070010227 pld_deinit();
10228
Ashish Kumar Dhanotiya7a031ce2017-01-23 13:11:30 +053010229 qdf_print_idx = qdf_get_pidx();
10230 qdf_print_ctrl_cleanup(qdf_print_idx);
10231
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010232 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010233}
10234
Arun Khandavallifae92942016-08-01 13:31:08 +053010235#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010236/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010237 * wlan_boot_cb() - Wlan boot callback
10238 * @kobj: object whose directory we're creating the link in.
10239 * @attr: attribute the user is interacting with
10240 * @buff: the buffer containing the user data
10241 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010242 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010243 * This callback is invoked when the fs is ready to start the
10244 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010245 *
Arun Khandavallifae92942016-08-01 13:31:08 +053010246 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010247 */
Arun Khandavallifae92942016-08-01 13:31:08 +053010248static ssize_t wlan_boot_cb(struct kobject *kobj,
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010249 struct kobj_attribute *attr,
10250 const char *buf,
10251 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010252{
Arun Khandavallifae92942016-08-01 13:31:08 +053010253
Arun Khandavallifae92942016-08-01 13:31:08 +053010254 if (wlan_loader->loaded_state) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010255 pr_err("%s: wlan driver already initialized\n", __func__);
10256 return -EALREADY;
Arun Khandavallifae92942016-08-01 13:31:08 +053010257 }
10258
Arun Khandavallifae92942016-08-01 13:31:08 +053010259 if (__hdd_module_init()) {
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010260 pr_err("%s: wlan driver initialization failed\n", __func__);
10261 return -EIO;
10262 }
10263
10264 wlan_loader->loaded_state = MODULE_INITIALIZED;
Arun Khandavallifae92942016-08-01 13:31:08 +053010265
10266 return count;
10267
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010268}
Arun Khandavallifae92942016-08-01 13:31:08 +053010269
10270/**
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010271 * hdd_sysfs_cleanup() - cleanup sysfs
10272 *
10273 * Return: None
10274 *
10275 */
10276static void hdd_sysfs_cleanup(void)
10277{
10278
10279 /* remove from group */
10280 if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group)
10281 sysfs_remove_group(wlan_loader->boot_wlan_obj,
10282 wlan_loader->attr_group);
10283
10284 /* unlink the object from parent */
10285 kobject_del(wlan_loader->boot_wlan_obj);
10286
10287 /* free the object */
10288 kobject_put(wlan_loader->boot_wlan_obj);
10289
10290 kfree(wlan_loader->attr_group);
10291 kfree(wlan_loader);
10292
10293 wlan_loader = NULL;
10294}
10295
10296/**
Arun Khandavallifae92942016-08-01 13:31:08 +053010297 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
10298 * ready
10299 *
10300 * This is creates the syfs entry boot_wlan. Which shall be invoked
10301 * when the filesystem is ready.
10302 *
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010303 * QDF API cannot be used here since this function is called even before
10304 * initializing WLAN driver.
10305 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010306 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +053010307 */
10308static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010309{
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010310 int ret = -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010311
10312 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
10313 if (!wlan_loader) {
10314 pr_err("%s: memory alloc failed\n", __func__);
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010315 return -ENOMEM;
Arun Khandavallifae92942016-08-01 13:31:08 +053010316 }
10317
10318 wlan_loader->boot_wlan_obj = NULL;
10319 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
10320 GFP_KERNEL);
10321 if (!wlan_loader->attr_group) {
10322 pr_err("%s: malloc attr_group failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010323 goto error_return;
10324 }
10325
10326 wlan_loader->loaded_state = 0;
10327 wlan_loader->attr_group->attrs = attrs;
10328
10329 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
10330 kernel_kobj);
10331 if (!wlan_loader->boot_wlan_obj) {
10332 pr_err("%s: sysfs create and add failed\n", __func__);
Arun Khandavallifae92942016-08-01 13:31:08 +053010333 goto error_return;
10334 }
10335
10336 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
10337 wlan_loader->attr_group);
10338 if (ret) {
10339 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
10340 goto error_return;
10341 }
10342
10343 return 0;
10344
10345error_return:
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010346 hdd_sysfs_cleanup();
Arun Khandavallifae92942016-08-01 13:31:08 +053010347
10348 return ret;
10349}
10350
10351/**
10352 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
10353 *
10354 * Return: 0 on success or errno on failure
10355 */
10356static int wlan_deinit_sysfs(void)
10357{
Arun Khandavallifae92942016-08-01 13:31:08 +053010358 if (!wlan_loader) {
10359 hdd_alert("wlan loader context is Null!");
10360 return -EINVAL;
10361 }
10362
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010363 hdd_sysfs_cleanup();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010364 return 0;
10365}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010366
Mahesh Kumar Kalikot Veetil5a3dec62016-11-02 12:46:40 -070010367#endif /* MODULE */
Arun Khandavallifae92942016-08-01 13:31:08 +053010368
10369#ifdef MODULE
10370/**
10371 * __hdd_module_init - Module init helper
10372 *
10373 * Module init helper function used by both module and static driver.
10374 *
10375 * Return: 0 for success, errno on failure
10376 */
10377static int hdd_module_init(void)
10378{
10379 int ret = 0;
10380
10381 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
10382 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
10383
10384 if (__hdd_module_init()) {
10385 pr_err("%s: Failed to register handler\n", __func__);
10386 ret = -EINVAL;
10387 }
10388
10389 return ret;
10390}
10391#else
10392static int __init hdd_module_init(void)
10393{
10394 int ret = -EINVAL;
10395
10396 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -070010397 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +053010398 pr_err("Failed to create sysfs entry for loading wlan");
10399
10400 return ret;
10401}
10402#endif
10403
10404
10405#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010406/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010407 * hdd_module_exit() - Exit function
10408 *
10409 * This is the driver exit point (invoked when module is unloaded using rmmod)
10410 *
10411 * Return: None
10412 */
10413static void __exit hdd_module_exit(void)
10414{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010415 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010416}
Arun Khandavallifae92942016-08-01 13:31:08 +053010417#else
10418static void __exit hdd_module_exit(void)
10419{
10420 __hdd_module_exit();
10421 wlan_deinit_sysfs();
10422}
10423#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010424
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010425static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
10426{
10427 return param_set_copystring(kmessage, kp);
10428}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080010429
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010430/**
10431 * is_con_mode_valid() check con mode is valid or not
10432 * @mode: global con mode
10433 *
10434 * Return: TRUE on success FALSE on failure
10435 */
10436static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
10437{
10438 switch (mode) {
10439 case QDF_GLOBAL_MONITOR_MODE:
10440 case QDF_GLOBAL_FTM_MODE:
10441 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010442 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010443 return true;
10444 default:
10445 return false;
10446 }
10447}
10448
10449/**
10450 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
10451 * @mode: global con mode
10452 *
10453 * Return: adapter mode
10454 */
10455static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
10456 enum tQDF_GLOBAL_CON_MODE mode)
10457{
10458
10459 switch (mode) {
10460 case QDF_GLOBAL_MISSION_MODE:
10461 return QDF_STA_MODE;
10462 case QDF_GLOBAL_MONITOR_MODE:
10463 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010464 case QDF_GLOBAL_EPPING_MODE:
10465 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010466 case QDF_GLOBAL_FTM_MODE:
10467 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010468 case QDF_GLOBAL_QVIT_MODE:
10469 return QDF_QVIT_MODE;
10470 default:
10471 return QDF_MAX_NO_OF_MODE;
10472 }
10473}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010474
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010475static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
10476 enum tQDF_GLOBAL_CON_MODE curr_mode)
10477{
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010478 int driver_status;
10479
10480 driver_status = hdd_ctx->driver_status;
10481
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010482 switch (curr_mode) {
10483 case QDF_GLOBAL_MISSION_MODE:
10484 case QDF_GLOBAL_MONITOR_MODE:
10485 case QDF_GLOBAL_FTM_MODE:
Ashish Kumar Dhanotiya00243132017-01-24 16:37:34 +053010486 if (driver_status != DRIVER_MODULES_CLOSED) {
10487 hdd_abort_mac_scan_all_adapters(hdd_ctx);
10488 hdd_stop_all_adapters(hdd_ctx);
10489 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010490 hdd_deinit_all_adapters(hdd_ctx, false);
10491 hdd_close_all_adapters(hdd_ctx, false);
10492 break;
10493 case QDF_GLOBAL_EPPING_MODE:
10494 epping_disable();
10495 epping_close();
10496 break;
10497 default:
10498 return;
10499 }
10500}
10501
10502static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
10503 enum tQDF_GLOBAL_CON_MODE mode)
10504{
10505 hdd_adapter_t *adapter;
10506 int ret = 0;
10507 bool rtnl_held;
10508 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
10509 QDF_STATUS status;
10510
10511 if (!qdf_dev) {
10512 hdd_err("qdf device context is Null return!");
10513 return -EINVAL;
10514 }
10515
10516 rtnl_held = hdd_hold_rtnl_lock();
10517 switch (mode) {
10518 case QDF_GLOBAL_MISSION_MODE:
Jeff Johnson957bc272017-02-02 08:54:48 -080010519 ret = hdd_open_interfaces(hdd_ctx, rtnl_held);
10520 if (ret)
10521 hdd_alert("Failed to open interfaces: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010522 break;
10523 case QDF_GLOBAL_FTM_MODE:
10524 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
10525 wlan_hdd_get_intf_addr(hdd_ctx),
10526 NET_NAME_UNKNOWN, rtnl_held);
10527 if (adapter == NULL)
10528 ret = -EINVAL;
10529 break;
10530 case QDF_GLOBAL_MONITOR_MODE:
10531 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
10532 wlan_hdd_get_intf_addr(hdd_ctx),
10533 NET_NAME_UNKNOWN, rtnl_held);
10534 if (adapter == NULL)
10535 ret = -EINVAL;
10536 break;
10537 case QDF_GLOBAL_EPPING_MODE:
10538 status = epping_open();
10539 if (status != QDF_STATUS_SUCCESS) {
10540 hdd_err("Failed to open in eeping mode: %d", status);
10541 ret = -EINVAL;
10542 break;
10543 }
10544 ret = epping_enable(qdf_dev->dev);
10545 if (ret) {
10546 hdd_err("Failed to enable in epping mode : %d", ret);
10547 epping_close();
10548 }
10549 break;
10550 default:
10551 hdd_info("Mode not supported");
10552 ret = -ENOTSUPP;
10553 break;
10554 }
10555 hdd_release_rtnl_lock();
10556 rtnl_held = false;
10557 return ret;
10558}
10559
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010560/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010561 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010562 * @kmessage: con mode name on which driver to be bring up
10563 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010564 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010565 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010566 * This function is invoked when user updates con mode using sys entry,
10567 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010568 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010569 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010570 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010571static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
10572 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010573{
10574 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +053010575 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010576 enum tQDF_GLOBAL_CON_MODE curr_mode;
10577 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010578
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +053010579 ret = wlan_hdd_validate_context(hdd_ctx);
10580 if (ret)
10581 return ret;
10582
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010583 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010584
Arun Khandavallifae92942016-08-01 13:31:08 +053010585 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010586 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +053010587
Arun Khandavallifae92942016-08-01 13:31:08 +053010588
Arun Khandavallia172c3e2016-08-26 17:33:13 +053010589
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010590 if (!(is_con_mode_valid(con_mode))) {
10591 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010592 ret = -EINVAL;
10593 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010594 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010595
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010596 curr_mode = hdd_get_conparam();
10597 if (curr_mode == con_mode) {
10598 hdd_err("curr mode: %d is same as user triggered mode %d",
10599 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010600 ret = 0;
10601 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010602 }
10603
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010604 /* Cleanup present mode before switching to new mode */
10605 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +053010606
Rajeev Kumar3fef4e82017-03-31 20:25:23 -070010607 ret = hdd_wlan_stop_modules(hdd_ctx, true);
Arun Khandavallifae92942016-08-01 13:31:08 +053010608 if (ret) {
10609 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010610 goto reset_flags;
10611 }
10612
10613 hdd_set_conparam(con_mode);
10614
10615 /* Register for new con_mode & then kick_start modules again */
10616 ret = hdd_register_req_mode(hdd_ctx, con_mode);
10617 if (ret) {
10618 hdd_err("Failed to register for new mode");
10619 goto reset_flags;
10620 }
10621
10622 adapter_mode = hdd_get_adpter_mode(con_mode);
10623 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
10624 hdd_err("invalid adapter");
10625 ret = -EINVAL;
10626 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010627 }
10628
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +053010629 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +053010630 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010631 hdd_err("Failed to get adapter:%d", adapter_mode);
10632 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010633 }
10634
10635 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
10636 if (ret) {
10637 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010638 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +053010639 }
10640
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010641 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
10642 con_mode == QDF_GLOBAL_FTM_MODE) {
10643 if (hdd_start_adapter(adapter)) {
10644 hdd_err("Failed to start %s adapter", kmessage);
10645 ret = -EINVAL;
10646 goto reset_flags;
10647 }
Arun Khandavallifae92942016-08-01 13:31:08 +053010648 }
10649
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +053010650 hdd_info("Mode successfully changed to %s", kmessage);
10651 ret = 0;
10652
10653reset_flags:
10654 cds_set_load_in_progress(false);
10655 return ret;
10656}
10657
10658
10659static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
10660{
10661 int ret;
10662 hdd_context_t *hdd_ctx;
10663
10664 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10665 ret = wlan_hdd_validate_context(hdd_ctx);
10666 if (ret)
10667 return ret;
10668
10669 cds_ssr_protect(__func__);
10670 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
10671 cds_ssr_unprotect(__func__);
10672
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010673 return ret;
10674}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010675
10676/**
10677 * hdd_get_conparam() - driver exit point
10678 *
10679 * This is the driver exit point (invoked when module is unloaded using rmmod)
10680 *
Anurag Chouhan6d760662016-02-20 16:05:43 +053010681 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010682 */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010683enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010684{
Anurag Chouhan6d760662016-02-20 16:05:43 +053010685 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010686}
10687
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010688void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010689{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -080010690 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -080010691}
10692
Komal Seelamc11bb222016-01-27 18:57:10 +053010693/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010694 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
10695 * @hdd_ctx: HDD context
10696 *
10697 * Cleans up the pre cac interface, if it exists
10698 *
10699 * Return: None
10700 */
10701void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
10702{
10703 uint8_t session_id;
10704 QDF_STATUS status;
10705 struct hdd_adapter_s *precac_adapter;
10706
10707 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
10708 if (QDF_IS_STATUS_ERROR(status)) {
10709 hdd_err("failed to get pre cac vdev id");
10710 return;
10711 }
10712
10713 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
10714 if (!precac_adapter) {
10715 hdd_err("invalid pre cac adapater");
10716 return;
10717 }
10718
10719 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
10720 wlan_hdd_sap_pre_cac_failure,
10721 (void *)precac_adapter);
10722 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
10723
10724}
10725
10726/**
Komal Seelamec702b02016-02-24 18:42:16 +053010727 * hdd_update_ol_config - API to update ol configuration parameters
10728 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +053010729 *
Komal Seelamc11bb222016-01-27 18:57:10 +053010730 * Return: void
10731 */
Komal Seelamec702b02016-02-24 18:42:16 +053010732static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +053010733{
Komal Seelamec702b02016-02-24 18:42:16 +053010734 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010735 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +053010736
Komal Seelamec702b02016-02-24 18:42:16 +053010737 if (!ol_ctx)
10738 return;
10739
10740 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
10741 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
10742 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
10743 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -070010744 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +053010745
10746 ol_init_ini_config(ol_ctx, &cfg);
10747}
10748
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010749#ifdef FEATURE_RUNTIME_PM
10750/**
10751 * hdd_populate_runtime_cfg() - populate runtime configuration
10752 * @hdd_ctx: hdd context
10753 * @cfg: pointer to the configuration memory being populated
10754 *
10755 * Return: void
10756 */
10757static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10758 struct hif_config_info *cfg)
10759{
10760 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
10761 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
10762}
10763#else
10764static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
10765 struct hif_config_info *cfg)
10766{
10767}
10768#endif
10769
Komal Seelamec702b02016-02-24 18:42:16 +053010770/**
10771 * hdd_update_hif_config - API to update HIF configuration parameters
10772 * @hdd_ctx: HDD Context
10773 *
10774 * Return: void
10775 */
10776static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
10777{
Anurag Chouhandf2b2682016-02-29 14:15:27 +053010778 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +053010779 struct hif_config_info cfg;
10780
10781 if (!scn)
10782 return;
10783
10784 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -070010785 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +053010786 hif_init_ini_config(scn, &cfg);
10787}
10788
10789/**
10790 * hdd_update_config() - Initialize driver per module ini parameters
10791 * @hdd_ctx: HDD Context
10792 *
10793 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010794 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +053010795 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010796int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +053010797{
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010798 int ret;
10799
Komal Seelamec702b02016-02-24 18:42:16 +053010800 hdd_update_ol_config(hdd_ctx);
10801 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010802 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
10803 ret = hdd_update_cds_config_ftm(hdd_ctx);
10804 else
10805 ret = hdd_update_cds_config(hdd_ctx);
Tushnim Bhattacharyya329514d2017-02-07 09:14:25 -080010806 ret = hdd_update_user_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +053010807
10808 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +053010809}
10810
Mukul Sharma9d797a02017-01-05 20:26:03 +053010811#ifdef FEATURE_WLAN_RA_FILTERING
10812/**
10813 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
10814 * @psoc_cfg: pmo psoc Configuration
10815 * @hdd_ctx: Pointer to hdd context
10816 *
10817 * Return: none
10818 */
10819static inline void hdd_ra_populate_pmo_config(
10820 struct pmo_psoc_cfg *psoc_cfg,
10821 hdd_context_t *hdd_ctx)
10822{
10823 psoc_cfg->ra_ratelimit_interval =
10824 hdd_ctx->config->RArateLimitInterval;
10825 psoc_cfg->ra_ratelimit_enable =
10826 hdd_ctx->config->IsRArateLimitEnabled;
10827}
10828#else
10829static inline void hdd_ra_populate_pmo_config(
10830 struct cds_config_info *cds_cfg,
10831 hdd_context_t *hdd_ctx)
10832{
10833}
10834#endif
10835/**
10836 * hdd_update_pmo_config - API to update pmo configuration parameters
10837 * @hdd_ctx: HDD context
10838 *
10839 * Return: void
10840 */
10841static int hdd_update_pmo_config(hdd_context_t *hdd_ctx)
10842{
10843 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10844 struct pmo_psoc_cfg psoc_cfg;
10845 QDF_STATUS status;
10846
10847 /*
10848 * Value of hdd_ctx->wowEnable can be,
10849 * 0 - Disable both magic pattern match and pattern byte match.
10850 * 1 - Enable magic pattern match on all interfaces.
10851 * 2 - Enable pattern byte match on all interfaces.
10852 * 3 - Enable both magic patter and pattern byte match on
10853 * all interfaces.
10854 */
10855 psoc_cfg.magic_ptrn_enable =
10856 (hdd_ctx->config->wowEnable & 0x01) ? true : false;
10857 psoc_cfg.ptrn_match_enable_all_vdev =
10858 (hdd_ctx->config->wowEnable & 0x02) ? true : false;
10859 psoc_cfg.bpf_enable =
10860 hdd_ctx->config->bpf_packet_filter_enable;
10861 psoc_cfg.arp_offload_enable = hdd_ctx->config->fhostArpOffload;
10862 psoc_cfg.ns_offload_enable_static = hdd_ctx->config->fhostNSOffload;
10863 if (hdd_ctx->config->fhostNSOffload)
10864 psoc_cfg.ns_offload_enable_dynamic = true;
10865 psoc_cfg.ssdp = hdd_ctx->config->ssdp;
10866 psoc_cfg.enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
10867 psoc_cfg.active_mode_offload =
10868 hdd_ctx->config->active_mode_offload;
10869 psoc_cfg.ap_arpns_support = hdd_ctx->ap_arpns_support;
10870 psoc_cfg.max_wow_filters = hdd_ctx->config->maxWoWFilters;
Mukul Sharma9223f232017-03-08 18:42:27 +053010871 psoc_cfg.sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
10872 psoc_cfg.sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
10873 psoc_cfg.sta_max_li_mod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
10874 psoc_cfg.power_save_mode =
10875 hdd_ctx->config->enablePowersaveOffload;
Mukul Sharma9d797a02017-01-05 20:26:03 +053010876
10877 hdd_ra_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9223f232017-03-08 18:42:27 +053010878 hdd_nan_populate_pmo_config(&psoc_cfg, hdd_ctx);
10879 hdd_lpass_populate_pmo_config(&psoc_cfg, hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053010880 status = pmo_ucfg_update_psoc_config(psoc, &psoc_cfg);
10881 if (status != QDF_STATUS_SUCCESS) {
10882 hdd_err("failed pmo psoc configuration");
10883 return -EINVAL;
10884 }
10885
10886 return 0;
10887}
10888
Abhishek Singh257a9482017-03-06 16:52:39 +053010889#ifdef NAPIER_SCAN
10890/**
10891 * hdd_update_scan_config - API to update scan configuration parameters
10892 * @hdd_ctx: HDD context
10893 *
10894 * Return: 0 if success else err
10895 */
10896static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
10897{
10898 struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
10899 struct scan_user_cfg scan_cfg;
10900 struct hdd_config *cfg = hdd_ctx->config;
10901 QDF_STATUS status;
10902
10903 scan_cfg.active_dwell = cfg->nActiveMaxChnTime;
10904 scan_cfg.passive_dwell = cfg->nPassiveMaxChnTime;
10905 scan_cfg.conc_active_dwell = cfg->nActiveMaxChnTimeConc;
10906 scan_cfg.conc_passive_dwell = cfg->nPassiveMaxChnTimeConc;
10907 scan_cfg.conc_max_rest_time = cfg->nRestTimeConc;
10908 scan_cfg.conc_min_rest_time = cfg->min_rest_time_conc;
10909 scan_cfg.conc_idle_time = cfg->idle_time_conc;
10910 scan_cfg.scan_cache_aging_time = cfg->scanAgingTimeout;
10911 scan_cfg.scan_dwell_time_mode = cfg->scan_adaptive_dwell_mode;
10912
10913 status = ucfg_scan_update_user_config(psoc, &scan_cfg);
10914 if (status != QDF_STATUS_SUCCESS) {
10915 hdd_err("failed pmo psoc configuration");
10916 return -EINVAL;
10917 }
10918
10919 return 0;
10920}
10921#else
10922static int hdd_update_scan_config(hdd_context_t *hdd_ctx)
10923{
10924 return 0;
10925}
10926#endif
10927
Mukul Sharma9d797a02017-01-05 20:26:03 +053010928int hdd_update_components_config(hdd_context_t *hdd_ctx)
10929{
10930 int ret;
10931
10932 ret = hdd_update_pmo_config(hdd_ctx);
Abhishek Singh257a9482017-03-06 16:52:39 +053010933 if (ret)
10934 return ret;
10935 ret = hdd_update_scan_config(hdd_ctx);
Mukul Sharma9d797a02017-01-05 20:26:03 +053010936
10937 return ret;
10938}
10939
Agrawal Ashish65634612016-08-18 13:24:32 +053010940/**
10941 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
10942 * @mode : cfg80211 DFS mode
10943 *
10944 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
10945 */
10946enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
10947{
10948 switch (mode) {
10949 case DFS_MODE_ENABLE:
10950 return ACS_DFS_MODE_ENABLE;
10951 break;
10952 case DFS_MODE_DISABLE:
10953 return ACS_DFS_MODE_DISABLE;
10954 break;
10955 case DFS_MODE_DEPRIORITIZE:
10956 return ACS_DFS_MODE_DEPRIORITIZE;
10957 break;
10958 default:
10959 hdd_err("ACS dfs mode is NONE");
10960 return ACS_DFS_MODE_NONE;
10961 }
10962}
10963
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +053010964/**
10965 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
10966 * @hddctx: pointer to hdd context
10967 * @set_value: enable/disable
10968 *
10969 * When Host sends vendor command enable, FW will send *ONE* CA ind to
10970 * Host(even though it is duplicate). When Host send vendor command
10971 * disable,FW doesn't perform any action. Whenever any change in
10972 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
10973 *
10974 * return - 0 on success, appropriate error values on failure.
10975 */
10976int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
10977{
10978 QDF_STATUS status;
10979
10980 if (0 != wlan_hdd_validate_context(hddctx)) {
10981 return -EAGAIN;
10982 }
10983
10984 if (!hddctx->config->goptimize_chan_avoid_event) {
10985 hdd_warn("goptimize_chan_avoid_event ini param disabled");
10986 return -EINVAL;
10987 }
10988
10989 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
10990 if (!QDF_IS_STATUS_SUCCESS(status)) {
10991 hdd_err("Failed to send chan avoid command to SME");
10992 return -EINVAL;
10993 }
10994 return 0;
10995}
Agrawal Ashish65634612016-08-18 13:24:32 +053010996
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010997/**
10998 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
10999 * @value: value to set
11000 *
11001 * This function will set the passed value to roaming in progress flag.
11002 *
11003 * Return: None
11004 */
11005void hdd_set_roaming_in_progress(bool value)
11006{
11007 hdd_context_t *hdd_ctx;
11008
11009 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11010 if (!hdd_ctx) {
11011 hdd_err("HDD context is NULL");
11012 return;
11013 }
11014
11015 hdd_ctx->roaming_in_progress = value;
11016 hdd_info("Roaming in Progress set to %d", value);
11017}
11018
11019/**
11020 * hdd_is_roaming_in_progress() - check if roaming is in progress
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011021 * @adapter - HDD adapter
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011022 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011023 * Return: true if roaming is in progress for STA type, else false
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011024 */
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011025bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter)
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011026{
11027 hdd_context_t *hdd_ctx;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011028 bool ret_status = false;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011029
11030 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11031 if (!hdd_ctx) {
11032 hdd_err("HDD context is NULL");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011033 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011034 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080011035 hdd_info("dev mode = %d, roaming_in_progress = %d",
11036 adapter->device_mode, hdd_ctx->roaming_in_progress);
11037 ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
11038 hdd_ctx->roaming_in_progress);
11039
11040 return ret_status;
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080011041}
11042
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011043/**
11044 * hdd_is_connection_in_progress() - check if connection is in
11045 * progress
11046 * @session_id: session id
11047 * @reason: scan reject reason
11048 *
11049 * Go through each adapter and check if Connection is in progress
11050 *
11051 * Return: true if connection is in progress else false
11052 */
11053bool hdd_is_connection_in_progress(uint8_t *session_id,
11054 enum scan_reject_states *reason)
11055{
11056 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
11057 hdd_station_ctx_t *hdd_sta_ctx = NULL;
11058 hdd_adapter_t *adapter = NULL;
11059 QDF_STATUS status = 0;
11060 uint8_t sta_id = 0;
11061 uint8_t *sta_mac = NULL;
11062 hdd_context_t *hdd_ctx;
11063
11064 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11065 if (!hdd_ctx) {
11066 hdd_err("HDD context is NULL");
11067 return false;
11068 }
11069
11070 if (true == hdd_ctx->btCoexModeSet) {
11071 hdd_info("BTCoex Mode operation in progress");
11072 return true;
11073 }
11074 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
11075 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
11076 adapter = adapter_node->pAdapter;
11077 if (!adapter)
11078 goto end;
11079
11080 hdd_info("Adapter with device mode %s(%d) exists",
11081 hdd_device_mode_to_string(adapter->device_mode),
11082 adapter->device_mode);
11083 if (((QDF_STA_MODE == adapter->device_mode)
11084 || (QDF_P2P_CLIENT_MODE == adapter->device_mode)
11085 || (QDF_P2P_DEVICE_MODE == adapter->device_mode))
11086 && (eConnectionState_Connecting ==
11087 (WLAN_HDD_GET_STATION_CTX_PTR(adapter))->
11088 conn_info.connState)) {
11089 hdd_err("%p(%d) Connection is in progress",
11090 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11091 adapter->sessionId);
11092 if (session_id && reason) {
11093 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011094 *reason = CONNECTION_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011095 }
11096 return true;
11097 }
Archana Ramachandran62886ce2017-03-24 14:46:32 -070011098 /*
11099 * sme_neighbor_middle_of_roaming is for LFR2
11100 * hdd_is_roaming_in_progress is for LFR3
11101 */
11102 if (((QDF_STA_MODE == adapter->device_mode) &&
11103 sme_neighbor_middle_of_roaming(
11104 WLAN_HDD_GET_HAL_CTX(adapter),
11105 adapter->sessionId)) ||
11106 hdd_is_roaming_in_progress(adapter)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011107 hdd_err("%p(%d) Reassociation in progress",
11108 WLAN_HDD_GET_STATION_CTX_PTR(adapter),
11109 adapter->sessionId);
11110 if (session_id && reason) {
11111 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011112 *reason = REASSOC_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011113 }
11114 return true;
11115 }
11116 if ((QDF_STA_MODE == adapter->device_mode) ||
11117 (QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
11118 (QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
11119 hdd_sta_ctx =
11120 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
11121 if ((eConnectionState_Associated ==
11122 hdd_sta_ctx->conn_info.connState)
11123 && (false ==
11124 hdd_sta_ctx->conn_info.uIsAuthenticated)) {
11125 sta_mac = (uint8_t *)
11126 &(adapter->macAddressCurrent.bytes[0]);
11127 hdd_err("client " MAC_ADDRESS_STR
11128 " is in middle of WPS/EAPOL exchange.",
11129 MAC_ADDR_ARRAY(sta_mac));
11130 if (session_id && reason) {
11131 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011132 *reason = EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011133 }
11134 return true;
11135 }
11136 } else if ((QDF_SAP_MODE == adapter->device_mode) ||
11137 (QDF_P2P_GO_MODE == adapter->device_mode)) {
11138 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
11139 sta_id++) {
11140 if (!((adapter->aStaInfo[sta_id].isUsed)
11141 && (OL_TXRX_PEER_STATE_CONN ==
11142 adapter->aStaInfo[sta_id].tlSTAState)))
11143 continue;
11144
11145 sta_mac = (uint8_t *)
11146 &(adapter->aStaInfo[sta_id].
11147 macAddrSTA.bytes[0]);
11148 hdd_err("client " MAC_ADDRESS_STR
11149 " of SAP/GO is in middle of WPS/EAPOL exchange",
11150 MAC_ADDR_ARRAY(sta_mac));
11151 if (session_id && reason) {
11152 *session_id = adapter->sessionId;
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011153 *reason = SAP_EAPOL_IN_PROGRESS;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011154 }
11155 return true;
11156 }
11157 if (hdd_ctx->connection_in_progress) {
11158 hdd_err("AP/GO: connection is in progress");
11159 return true;
11160 }
11161 }
11162end:
11163 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
11164 adapter_node = next;
11165 }
11166 return false;
11167}
11168
11169/**
11170 * hdd_restart_sap() - to restart SAP in driver internally
11171 * @ap_adapter: Pointer to SAP hdd_adapter_t structure
11172 *
11173 * Return: None
11174 */
11175void hdd_restart_sap(hdd_adapter_t *ap_adapter)
11176{
11177 hdd_ap_ctx_t *hdd_ap_ctx;
11178 hdd_hostapd_state_t *hostapd_state;
11179 QDF_STATUS qdf_status;
11180 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
11181 tsap_Config_t *sap_config;
11182 void *sap_ctx;
11183
11184 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11185 sap_config = &hdd_ap_ctx->sapConfig;
11186 sap_ctx = hdd_ap_ctx->sapContext;
11187
11188 mutex_lock(&hdd_ctx->sap_lock);
11189 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
11190 wlan_hdd_del_station(ap_adapter);
11191 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
11192 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11193 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
11194 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {
11195 qdf_status =
11196 qdf_wait_single_event(&hostapd_state->
11197 qdf_stop_bss_event,
11198 SME_CMD_TIMEOUT_VALUE);
11199
11200 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11201 cds_err("SAP Stop Failed");
11202 goto end;
11203 }
11204 }
11205 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011206 policy_mgr_decr_session_set_pcl(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011207 ap_adapter->device_mode, ap_adapter->sessionId);
11208 cds_err("SAP Stop Success");
11209
11210 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
11211 cds_err("SAP Not able to set AP IEs");
11212 wlansap_reset_sap_config_add_ie(sap_config,
11213 eUPDATE_IE_ALL);
11214 goto end;
11215 }
11216
11217 qdf_event_reset(&hostapd_state->qdf_event);
11218 if (wlansap_start_bss(sap_ctx, hdd_hostapd_sap_event_cb,
11219 sap_config,
11220 ap_adapter->dev) != QDF_STATUS_SUCCESS) {
11221 cds_err("SAP Start Bss fail");
11222 wlansap_reset_sap_config_add_ie(sap_config,
11223 eUPDATE_IE_ALL);
11224 goto end;
11225 }
11226
11227 cds_info("Waiting for SAP to start");
11228 qdf_status =
11229 qdf_wait_single_event(&hostapd_state->qdf_event,
11230 SME_CMD_TIMEOUT_VALUE);
11231 wlansap_reset_sap_config_add_ie(sap_config,
11232 eUPDATE_IE_ALL);
11233 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
11234 cds_err("SAP Start failed");
11235 goto end;
11236 }
11237 cds_err("SAP Start Success");
11238 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
11239 if (hostapd_state->bssState == BSS_START)
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011240 policy_mgr_incr_active_session(hdd_ctx->hdd_psoc,
11241 ap_adapter->device_mode,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011242 ap_adapter->sessionId);
11243 hostapd_state->bCommit = true;
11244 }
11245end:
11246 mutex_unlock(&hdd_ctx->sap_lock);
11247 return;
11248}
11249
11250/**
11251 * hdd_check_and_restart_sap_with_non_dfs_acs() - Restart SAP
11252 * with non dfs acs
11253 *
11254 * Restarts SAP in non-DFS ACS mode when STA-AP mode DFS is not supported
11255 *
11256 * Return: None
11257 */
11258void hdd_check_and_restart_sap_with_non_dfs_acs(void)
11259{
11260 hdd_adapter_t *ap_adapter;
11261 hdd_context_t *hdd_ctx;
11262 cds_context_type *cds_ctx;
11263
11264 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11265 if (!hdd_ctx) {
11266 cds_err("HDD context is NULL");
11267 return;
11268 }
11269
11270 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
11271 if (!cds_ctx) {
11272 cds_err("Invalid CDS Context");
11273 return;
11274 }
11275
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011276 if (policy_mgr_get_concurrency_mode(hdd_ctx->hdd_psoc)
11277 != (QDF_STA_MASK | QDF_SAP_MASK)) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011278 cds_info("Concurrency mode is not SAP");
11279 return;
11280 }
11281
11282 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11283 if (ap_adapter != NULL &&
11284 test_bit(SOFTAP_BSS_STARTED,
11285 &ap_adapter->event_flags)
11286 && CDS_IS_DFS_CH(ap_adapter->sessionCtx.ap.
11287 operatingChannel)) {
11288
11289 cds_warn("STA-AP Mode DFS not supported. Restart SAP with Non DFS ACS");
11290 ap_adapter->sessionCtx.ap.sapConfig.channel =
11291 AUTO_CHANNEL_SELECT;
11292 ap_adapter->sessionCtx.ap.sapConfig.
11293 acs_cfg.acs_mode = true;
11294
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080011295 hdd_restart_sap(ap_adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080011296 }
11297}
11298
11299/**
11300 * hdd_set_connection_in_progress() - to set the connection in
11301 * progress flag
11302 * @value: value to set
11303 *
11304 * This function will set the passed value to connection in progress flag.
11305 * If value is previously being set to true then no need to set it again.
11306 *
11307 * Return: true if value is being set correctly and false otherwise.
11308 */
11309bool hdd_set_connection_in_progress(bool value)
11310{
11311 bool status = true;
11312 hdd_context_t *hdd_ctx;
11313
11314 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11315 if (!hdd_ctx) {
11316 cds_err("HDD context is NULL");
11317 return false;
11318 }
11319
11320 qdf_spin_lock(&hdd_ctx->connection_status_lock);
11321 /*
11322 * if the value is set to true previously and if someone is
11323 * trying to make it true again then it could be some race
11324 * condition being triggered. Avoid this situation by returning
11325 * false
11326 */
11327 if (hdd_ctx->connection_in_progress && value)
11328 status = false;
11329 else
11330 hdd_ctx->connection_in_progress = value;
11331 qdf_spin_unlock(&hdd_ctx->connection_status_lock);
11332 return status;
11333}
11334
Archana Ramachandranb8c04f92017-03-17 20:05:47 -070011335int wlan_hdd_send_p2p_quota(hdd_adapter_t *adapter, int set_value)
11336{
11337 if (!adapter) {
11338 hdd_err("Invalid adapter");
11339 return -EINVAL;
11340 }
11341 hdd_info("Send MCC P2P QUOTA to WMA: %d", set_value);
11342 wma_cli_set_command(adapter->sessionId,
11343 WMA_VDEV_MCC_SET_TIME_QUOTA,
11344 set_value, VDEV_CMD);
11345 return 0;
11346
11347}
11348
11349int wlan_hdd_send_mcc_latency(hdd_adapter_t *adapter, int set_value)
11350{
11351 if (!adapter) {
11352 hdd_err("Invalid adapter");
11353 return -EINVAL;
11354 }
11355
11356 hdd_info("Send MCC latency WMA: %d", set_value);
11357 wma_cli_set_command(adapter->sessionId,
11358 WMA_VDEV_MCC_SET_TIME_LATENCY,
11359 set_value, VDEV_CMD);
11360 return 0;
11361}
11362
Archana Ramachandranea34c4f2017-03-19 18:56:18 -070011363hdd_adapter_t *wlan_hdd_get_adapter_from_vdev(struct wlan_objmgr_psoc
11364 *psoc, uint8_t vdev_id)
11365{
11366 hdd_adapter_t *adapter = NULL;
11367 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11368
11369 /*
11370 * Currently PSOC is not being used. But this logic will
11371 * change once we have the converged implementation of
11372 * HDD context per PSOC in place. This would break if
11373 * multiple vdev objects reuse the vdev id.
11374 */
11375 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
11376 if (!adapter)
11377 hdd_err("Get adapter by vdev id failed");
11378
11379 return adapter;
11380}
11381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382/* Register the module init/exit functions */
11383module_init(hdd_module_init);
11384module_exit(hdd_module_exit);
11385
11386MODULE_LICENSE("Dual BSD/GPL");
11387MODULE_AUTHOR("Qualcomm Atheros, Inc.");
11388MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
11389
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
11391 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392
11393module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
11394 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
11395
11396module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
11397
11398module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
11399
11400module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);