blob: 531e784055b50c18b578a8ea53976aa96dddc928 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnsond9f08602016-12-02 11:31:30 -08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053039#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#include <linux/etherdevice.h>
41#include <linux/firmware.h>
42#include <wlan_hdd_tx_rx.h>
43#include <wni_api.h>
44#include <wlan_hdd_cfg.h>
45#include <wlan_ptt_sock_svc.h>
46#include <dbglog_host.h>
47#include <wlan_logging_sock_svc.h>
48#include <wlan_hdd_wowl.h>
49#include <wlan_hdd_misc.h>
50#include <wlan_hdd_wext.h>
51#include "wlan_hdd_trace.h"
52#include "wlan_hdd_ioctl.h"
53#include "wlan_hdd_ftm.h"
54#include "wlan_hdd_power.h"
55#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070056#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053057#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053058#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070059#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080060
61#include <net/addrconf.h>
62#include <linux/wireless.h>
63#include <net/cfg80211.h>
64#include <linux/inetdevice.h>
65#include <net/addrconf.h>
66#include "wlan_hdd_cfg80211.h"
67#include "wlan_hdd_ext_scan.h"
68#include "wlan_hdd_p2p.h"
69#include <linux/rtnetlink.h>
70#include "sap_api.h"
71#include <linux/semaphore.h>
72#include <linux/ctype.h>
73#include <linux/compat.h>
74#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080075#include <soc/qcom/subsystem_restart.h>
76#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include <wlan_hdd_hostapd.h>
78#include <wlan_hdd_softap_tx_rx.h>
79#include "cfg_api.h"
80#include "qwlan_version.h"
81#include "wma_types.h"
82#include "wlan_hdd_tdls.h"
83#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053084#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080085#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080086#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070087#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080088#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089#include "wlan_hdd_nan.h"
90#include "wlan_hdd_debugfs.h"
91#include "wlan_hdd_driver_ops.h"
92#include "epping_main.h"
93#include "wlan_hdd_memdump.h"
94
95#include <wlan_hdd_ipa.h>
96#include "hif.h"
97#include "wma.h"
98#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -070099#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530101#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700102#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530103#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700104#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530105#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700106#include <wlan_hdd_napi.h>
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530107#include "wlan_hdd_disa.h"
Rajeev Kumar97767a02016-11-30 11:20:40 -0800108#include <dispatcher_init_deinit.h>
Rajeev Kumar699debf2017-01-06 14:17:00 -0800109#include "wlan_hdd_object_manager.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110
111#ifdef MODULE
112#define WLAN_MODULE_NAME module_name(THIS_MODULE)
113#else
114#define WLAN_MODULE_NAME "wlan"
115#endif
116
117#ifdef TIMER_MANAGER
118#define TIMER_MANAGER_STR " +TIMER_MANAGER"
119#else
120#define TIMER_MANAGER_STR ""
121#endif
122
123#ifdef MEMORY_DEBUG
124#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
125#else
126#define MEMORY_DEBUG_STR ""
127#endif
128
Arun Khandavallifae92942016-08-01 13:31:08 +0530129#ifndef MODULE
130static struct gwlan_loader *wlan_loader;
131static ssize_t wlan_boot_cb(struct kobject *kobj,
132 struct kobj_attribute *attr,
133 const char *buf, size_t count);
134struct gwlan_loader {
135 bool loaded_state;
136 struct kobject *boot_wlan_obj;
137 struct attribute_group *attr_group;
138};
139
140static struct kobj_attribute wlan_boot_attribute =
141 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
142
143static struct attribute *attrs[] = {
144 &wlan_boot_attribute.attr,
145 NULL,
146};
147
148#define MODULE_INITIALIZED 1
149#endif
150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151/* the Android framework expects this param even though we don't use it */
152#define BUF_LEN 20
153static char fwpath_buffer[BUF_LEN];
154static struct kparam_string fwpath = {
155 .string = fwpath_buffer,
156 .maxlen = BUF_LEN,
157};
158
159static char *country_code;
160static int enable_11d = -1;
161static int enable_dfs_chan_scan = -1;
162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163/*
164 * spinlock for synchronizing asynchronous request/response
165 * (full description of use in wlan_hdd_main.h)
166 */
167DEFINE_SPINLOCK(hdd_context_lock);
168
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800169#define WLAN_NLINK_CESIUM 30
170
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530171static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172
173#define WOW_MAX_FILTER_LISTS 1
174#define WOW_MAX_FILTERS_PER_LIST 4
175#define WOW_MIN_PATTERN_SIZE 6
176#define WOW_MAX_PATTERN_SIZE 64
177
178#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
179static const struct wiphy_wowlan_support wowlan_support_reg_init = {
180 .flags = WIPHY_WOWLAN_ANY |
181 WIPHY_WOWLAN_MAGIC_PKT |
182 WIPHY_WOWLAN_DISCONNECT |
183 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
184 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
185 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
186 WIPHY_WOWLAN_4WAY_HANDSHAKE |
187 WIPHY_WOWLAN_RFKILL_RELEASE,
188 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
189 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
190 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
191};
192#endif
193
194/* internal function declaration */
195
196struct sock *cesium_nl_srv_sock;
197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
199void wlan_hdd_auto_shutdown_cb(void);
200#endif
201
202/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530203 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
204 * @hdd_ctx: pointer to hdd_context_t
205 *
206 * Return: none
207 */
Jeff Johnson590e2012016-10-05 16:16:24 -0700208static void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
Nirav Shahbd36b062016-07-18 11:12:59 +0530209{
210 hdd_adapter_t *adapter;
211 hdd_adapter_list_node_t *adapter_node, *next;
212 QDF_STATUS status = QDF_STATUS_SUCCESS;
213
214 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
215 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
216 adapter = adapter_node->pAdapter;
217 if (NULL != adapter)
218 hdd_send_rps_ind(adapter);
219 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
220 adapter_node = next;
221 }
222}
223
224/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
226 * @vdev_id: vdev_id
227 * @action: action type
228 * @reason: reason type
229 *
230 * Return: none
231 */
232void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
233 enum netif_action_type action, enum netif_reason_type reason)
234{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530235 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236 hdd_adapter_t *adapter;
237
238 if (!hdd_ctx) {
239 hdd_err("hdd ctx is NULL");
240 return;
241 }
242 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
243
244 wlan_hdd_netif_queue_control(adapter, action, reason);
245 return;
246}
247
248/*
249 * Store WLAN driver version info in a global variable such that crash debugger
250 * can extract it from driver debug symbol and crashdump for post processing
251 */
252uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
253
254/**
255 * hdd_device_mode_to_string() - return string conversion of device mode
256 * @device_mode: device mode
257 *
258 * This utility function helps log string conversion of device mode.
259 *
260 * Return: string conversion of device mode, if match found;
261 * "Unknown" otherwise.
262 */
263const char *hdd_device_mode_to_string(uint8_t device_mode)
264{
265 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800266 CASE_RETURN_STRING(QDF_STA_MODE);
267 CASE_RETURN_STRING(QDF_SAP_MODE);
268 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
269 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
270 CASE_RETURN_STRING(QDF_FTM_MODE);
271 CASE_RETURN_STRING(QDF_IBSS_MODE);
272 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
273 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700274 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275 default:
276 return "Unknown";
277 }
278}
279
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530280/**
281 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
282 * @adapter: HDD adapter
283 * @chan_number: Channel number
284 * @chan_bw: Bandwidth
285 *
286 * Checks if the given bandwidth is valid for the given channel number.
287 *
288 * Return: 0 for success, non-zero for failure
289 */
290int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
291 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800292 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530293{
294 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
295 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
296 bool found = false;
297 tHalHandle hal;
298
299 hal = WLAN_HDD_GET_HAL_CTX(adapter);
300 if (!hal) {
301 hdd_err("Invalid HAL context");
302 return -EINVAL;
303 }
304
305 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
306 hdd_err("No valid channel list");
307 return -EOPNOTSUPP;
308 }
309
310 for (i = 0; i < len; i++) {
311 if (chan[i] == chan_number) {
312 found = true;
313 break;
314 }
315 }
316
317 if (found == false) {
318 hdd_err("Channel not in driver's valid channel list");
319 return -EOPNOTSUPP;
320 }
321
322 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
323 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
324 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
325 return -EINVAL;
326 }
327
328 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
329 if (chan_bw == CH_WIDTH_80MHZ) {
330 hdd_err("BW80 not possible in 2.4GHz band");
331 return -EINVAL;
332 }
333 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
334 (chan_bw != CH_WIDTH_MAX)) {
335 hdd_err("Only BW20 possible on channel 14");
336 return -EINVAL;
337 }
338 }
339
340 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
341 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
342 (chan_bw != CH_WIDTH_MAX)) {
343 hdd_err("Only BW20 possible on channel 165");
344 return -EINVAL;
345 }
346 }
347
348 return 0;
349}
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351static int __hdd_netdev_notifier_call(struct notifier_block *nb,
352 unsigned long state, void *data)
353{
354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
355 struct netdev_notifier_info *dev_notif_info = data;
356 struct net_device *dev = dev_notif_info->dev;
357#else
358 struct net_device *dev = data;
359#endif
360 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
361 hdd_context_t *hdd_ctx;
362
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800363 ENTER_DEV(dev);
364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 /* Make sure that this callback corresponds to our device. */
366 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
367 return NOTIFY_DONE;
368
Samuel Ahnc9c48ca2016-09-19 15:46:36 +0530369 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700371 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800372 return NOTIFY_DONE;
373 }
374
375 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700376 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 return NOTIFY_DONE;
378 }
379
380 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
381 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700382 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530383 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 return NOTIFY_DONE;
385 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800386 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 return NOTIFY_DONE;
388
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700389 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 dev->name, state);
391
392 switch (state) {
393 case NETDEV_REGISTER:
394 break;
395
396 case NETDEV_UNREGISTER:
397 break;
398
399 case NETDEV_UP:
400 sme_ch_avoid_update_req(hdd_ctx->hHal);
401 break;
402
403 case NETDEV_DOWN:
404 break;
405
406 case NETDEV_CHANGE:
407 if (true == adapter->isLinkUpSvcNeeded)
408 complete(&adapter->linkup_event_var);
409 break;
410
411 case NETDEV_GOING_DOWN:
412 if (adapter->scan_info.mScanPending != false) {
413 unsigned long rc;
414 INIT_COMPLETION(adapter->scan_info.
415 abortscan_event_var);
416 hdd_abort_mac_scan(adapter->pHddCtx,
417 adapter->sessionId,
418 eCSR_SCAN_ABORT_DEFAULT);
419 rc = wait_for_completion_timeout(
420 &adapter->scan_info.abortscan_event_var,
421 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
422 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700423 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 }
425 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700426 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800427 }
428 break;
429
430 default:
431 break;
432 }
433
434 return NOTIFY_DONE;
435}
436
437/**
438 * hdd_netdev_notifier_call() - netdev notifier callback function
439 * @nb: pointer to notifier block
440 * @state: state
441 * @ndev: ndev pointer
442 *
443 * Return: 0 on success, error number otherwise.
444 */
445static int hdd_netdev_notifier_call(struct notifier_block *nb,
446 unsigned long state,
447 void *ndev)
448{
449 int ret;
450
451 cds_ssr_protect(__func__);
452 ret = __hdd_netdev_notifier_call(nb, state, ndev);
453 cds_ssr_unprotect(__func__);
454
455 return ret;
456}
457
458struct notifier_block hdd_netdev_notifier = {
459 .notifier_call = hdd_netdev_notifier_call,
460};
461
462/* variable to hold the insmod parameters */
463static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800464
465/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530468/**
469 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
470 * @ch_width: NL channel width
471 *
472 * Converts the NL channel width to the driver's internal representation
473 *
474 * Return: Converted channel width. In case of non matching NL channel width,
475 * CH_WIDTH_MAX will be returned.
476 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800477enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530478{
479 switch (ch_width) {
480 case NL80211_CHAN_WIDTH_20_NOHT:
481 case NL80211_CHAN_WIDTH_20:
482 return CH_WIDTH_20MHZ;
483 case NL80211_CHAN_WIDTH_40:
484 return CH_WIDTH_40MHZ;
485 break;
486 case NL80211_CHAN_WIDTH_80:
487 return CH_WIDTH_80MHZ;
488 case NL80211_CHAN_WIDTH_80P80:
489 return CH_WIDTH_80P80MHZ;
490 case NL80211_CHAN_WIDTH_160:
491 return CH_WIDTH_160MHZ;
492 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800493 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530494 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800495 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530496 default:
497 hdd_err("Invalid channel width %d, setting to default",
498 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800499 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530500 }
501}
502
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530503/* wlan_hdd_find_opclass() - Find operating class for a channel
504 * @hal: handler to HAL
505 * @channel: channel id
506 * @bw_offset: bandwidth offset
507 *
508 * Function invokes sme api to find the operating class
509 *
510 * Return: operating class
511 */
512uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
513 uint8_t bw_offset)
514{
515 uint8_t opclass = 0;
516
517 sme_get_opclass(hal, channel, bw_offset, &opclass);
518 return opclass;
519}
520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530522 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523 * @moduleId: Module whose trace level is being configured
524 * @bitmask: Bitmask of log levels to be enabled
525 *
526 * Called immediately after the cfg.ini is read in order to configure
527 * the desired trace levels.
528 *
529 * Return: None
530 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530533 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534
535 /*
536 * if the bitmask is the default value, then a bitmask was not
537 * specified in cfg.ini, so leave the logging level alone (it
538 * will remain at the "compiled in" default value)
539 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530540 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 return;
542 }
543
544 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530545 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546
547 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530548 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 while (0 != bitmask) {
550 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530551 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552 }
553 level++;
554 bitmask >>= 1;
555 }
556}
557
558/**
559 * wlan_hdd_validate_context() - check the HDD context
560 * @hdd_ctx: HDD context pointer
561 *
562 * Return: 0 if the context is valid. Error code otherwise
563 */
564int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
565{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530567 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 return -ENODEV;
569 }
570
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800571 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530572 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
573 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574 return -EAGAIN;
575 }
576
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800577 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530578 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
579 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 return -EAGAIN;
581 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530582
583 if (hdd_ctx->start_modules_in_progress ||
584 hdd_ctx->stop_modules_in_progress) {
585 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
586 (void *)_RET_IP_);
587 return -EAGAIN;
588 }
589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590 return 0;
591}
592
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593/**
594 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
595 * @hdd_adapter_t Hdd adapter.
596 *
597 * This function sets the IBSS power save config parameters to WMA
598 * which will send it to firmware if FW supports IBSS power save
599 * before vdev start.
600 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530601 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 * on failure.
603 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530604QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800605{
606 int ret;
607 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
608
609 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700610 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530611 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612 }
613
614 ret = wma_cli_set_command(adapter->sessionId,
615 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
616 hdd_ctx->config->ibssATIMWinSize,
617 VDEV_CMD);
618 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700619 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530620 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800621 }
622
623 ret = wma_cli_set_command(adapter->sessionId,
624 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
625 hdd_ctx->config->isIbssPowerSaveAllowed,
626 VDEV_CMD);
627 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700628 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
629 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530630 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631 }
632
633 ret = wma_cli_set_command(adapter->sessionId,
634 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
635 hdd_ctx->config->
636 isIbssPowerCollapseAllowed, VDEV_CMD);
637 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700638 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
639 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530640 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641 }
642
643 ret = wma_cli_set_command(adapter->sessionId,
644 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
645 hdd_ctx->config->isIbssAwakeOnTxRx,
646 VDEV_CMD);
647 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700648 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530649 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650 }
651
652 ret = wma_cli_set_command(adapter->sessionId,
653 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
654 hdd_ctx->config->ibssInactivityCount,
655 VDEV_CMD);
656 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700657 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530658 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659 }
660
661 ret = wma_cli_set_command(adapter->sessionId,
662 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
663 hdd_ctx->config->ibssTxSpEndInactivityTime,
664 VDEV_CMD);
665 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700666 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
667 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530668 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 }
670
671 ret = wma_cli_set_command(adapter->sessionId,
672 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
673 hdd_ctx->config->ibssPsWarmupTime,
674 VDEV_CMD);
675 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700676 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
677 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530678 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 }
680
681 ret = wma_cli_set_command(adapter->sessionId,
682 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
683 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
684 VDEV_CMD);
685 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700686 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
687 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530688 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689 }
690
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530691 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692}
693
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694#define INTF_MACADDR_MASK 0x7
695
696/**
697 * hdd_update_macaddr() - update mac address
698 * @config: hdd configuration
699 * @hw_macaddr: mac address
700 *
701 * Mac address for multiple virtual interface is found as following
702 * i) The mac address of the first interface is just the actual hw mac address.
703 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
704 * define the mac address for the remaining interfaces and locally
705 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
706 * supported virtual interfaces, right now this is 0x07 (meaning 8
707 * interface).
708 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
709 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
710 *
711 * Return: None
712 */
713void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530714 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715{
716 int8_t i;
717 uint8_t macaddr_b3, tmp_br3;
718
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530719 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530720 QDF_MAC_ADDR_SIZE);
721 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530722 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530723 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 macaddr_b3 = config->intfMacAddr[i].bytes[3];
725 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
726 INTF_MACADDR_MASK;
727 macaddr_b3 += tmp_br3;
728
729 /* XOR-ing bit-24 of the mac address. This will give enough
730 * mac address range before collision
731 */
732 macaddr_b3 ^= (1 << 7);
733
734 /* Set locally administered bit */
735 config->intfMacAddr[i].bytes[0] |= 0x02;
736 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700737 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738 MAC_ADDRESS_STR, i,
739 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
740 }
741}
742
743static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
744 struct wma_tgt_services *cfg)
745{
746 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747
748 /* Set up UAPSD */
749 config->apUapsdEnabled &= cfg->uapsd;
750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751 /* 11AC mode support */
752 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
753 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
754 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755
756 /* ARP offload: override user setting if invalid */
757 config->fhostArpOffload &= cfg->arp_offload;
758
759#ifdef FEATURE_WLAN_SCAN_PNO
760 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700761 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762 if (cfg->pno_offload)
763 config->PnoOffload = true;
764#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800765#ifdef FEATURE_WLAN_TDLS
766 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530767 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
768 cfg->en_tdls_offchan;
769 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
770 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800771 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
772 config->fEnableTDLSSleepSta = true;
773 } else {
774 config->fEnableTDLSSleepSta = false;
775 }
776#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777#ifdef WLAN_FEATURE_ROAM_OFFLOAD
778 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
779#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700780 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781
782}
783
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700784/**
785 * hdd_update_vdev_nss() - sets the vdev nss
786 * @hdd_ctx: HDD context
787 *
788 * Sets the Nss per vdev type based on INI
789 *
790 * Return: None
791 */
792static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
793{
794 struct hdd_config *cfg_ini = hdd_ctx->config;
795 uint8_t max_supp_nss = 1;
796
797 if (cfg_ini->enable2x2)
798 max_supp_nss = 2;
799
800 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
801 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
802
803 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
804 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
805}
806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
808 struct wma_tgt_ht_cap *cfg)
809{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530810 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811 uint32_t value, val32;
812 uint16_t val16;
813 struct hdd_config *pconfig = hdd_ctx->config;
814 tSirMacHTCapabilityInfo *phtCapInfo;
815 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
816 uint8_t enable_tx_stbc;
817
818 /* check and update RX STBC */
819 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
820 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
821
822 /* get the MPDU density */
823 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
824
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530825 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700826 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827 value = 0;
828 }
829
830 /*
831 * MPDU density:
832 * override user's setting if value is larger
833 * than the one supported by target
834 */
835 if (value > cfg->mpdu_density) {
836 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
837 cfg->mpdu_density);
838
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530839 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700840 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 }
842
843 /* get the HT capability info */
844 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530845 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700846 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847 return;
848 }
849 val16 = (uint16_t) val32;
850 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
851
852 /* Set the LDPC capability */
853 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
854
855 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
856 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
857
858 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
859 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
860
861 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
862 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
863
864 enable_tx_stbc = pconfig->enableTxSTBC;
865
866 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
867 pconfig->enable2x2 = 1;
868 } else {
869 pconfig->enable2x2 = 0;
870 enable_tx_stbc = 0;
871
872 /* 1x1 */
873 /* Update Rx Highest Long GI data Rate */
874 if (sme_cfg_set_int(hdd_ctx->hHal,
875 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700876 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530877 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700878 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 }
880
881 /* Update Tx Highest Long GI data Rate */
882 if (sme_cfg_set_int
883 (hdd_ctx->hHal,
884 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700885 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530886 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700887 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 }
889 }
890 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
891 enable_tx_stbc = 0;
892 phtCapInfo->txSTBC = enable_tx_stbc;
893
894 val32 = val16;
895 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530896 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700897 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
899 value = SIZE_OF_SUPPORTED_MCS_SET;
900 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530901 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700902 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903
904 if (pconfig->enable2x2) {
905 for (value = 0; value < cfg->num_rf_chains; value++)
906 mcs_set[value] =
907 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
908
909 status =
910 sme_cfg_set_str(hdd_ctx->hHal,
911 WNI_CFG_SUPPORTED_MCS_SET,
912 mcs_set,
913 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530914 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700915 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 }
917 }
918#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
919}
920
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
922 struct wma_tgt_vht_cap *cfg)
923{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530924 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925 uint32_t value = 0;
926 struct hdd_config *pconfig = hdd_ctx->config;
927 struct wiphy *wiphy = hdd_ctx->wiphy;
928 struct ieee80211_supported_band *band_5g =
Dustin Browna30892e2016-10-12 17:28:36 -0700929 wiphy->bands[NL80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700930 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931
Dustin Brown5e06bd32016-10-04 12:49:10 -0700932 if (!band_5g) {
933 hdd_info("5GHz band disabled, skipping capability population");
934 return;
935 }
936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800937 /* Get the current MPDU length */
938 status =
939 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
940 &value);
941
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530942 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700943 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944 value = 0;
945 }
946
947 /*
948 * VHT max MPDU length:
949 * override if user configured value is too high
950 * that the target cannot support
951 */
952 if (value > cfg->vht_max_mpdu) {
953 status = sme_cfg_set_int(hdd_ctx->hHal,
954 WNI_CFG_VHT_MAX_MPDU_LENGTH,
955 cfg->vht_max_mpdu);
956
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530957 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700958 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959 }
960 }
961
962 /* Get the current supported chan width */
963 status = sme_cfg_get_int(hdd_ctx->hHal,
964 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
965 &value);
966
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530967 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700968 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969 value = 0;
970 }
971
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700972 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
973 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
974
975 if (pconfig->enable2x2)
976 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
977
978 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
979 QDF_STATUS_E_FAILURE) {
980 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
981 }
982
983 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
984 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
985 if (pconfig->enable2x2)
986 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
987
988 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
989 QDF_STATUS_E_FAILURE) {
990 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
991 }
992
993 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
994 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
995 if (pconfig->enable2x2)
996 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
997
998 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
999 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1000
1001 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1002 QDF_STATUS_E_FAILURE) {
1003 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001005 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001006 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001007 &value);
1008
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301009 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001010 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001011 value = 0;
1012 }
1013
1014 /* Set the LDPC capability */
1015 if (value && !cfg->vht_rx_ldpc) {
1016 status = sme_cfg_set_int(hdd_ctx->hHal,
1017 WNI_CFG_VHT_LDPC_CODING_CAP,
1018 cfg->vht_rx_ldpc);
1019
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301020 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001021 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001022 }
1023 }
1024
1025 /* Get current GI 80 value */
1026 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1027 &value);
1028
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301029 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001030 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 value = 0;
1032 }
1033
1034 /* set the Guard interval 80MHz */
1035 if (value && !cfg->vht_short_gi_80) {
1036 status = sme_cfg_set_int(hdd_ctx->hHal,
1037 WNI_CFG_VHT_SHORT_GI_80MHZ,
1038 cfg->vht_short_gi_80);
1039
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301040 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001041 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 }
1043 }
1044
1045 /* Get current GI 160 value */
1046 status = sme_cfg_get_int(hdd_ctx->hHal,
1047 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1048 &value);
1049
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301050 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001051 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001052 value = 0;
1053 }
1054
1055 /* Get VHT TX STBC cap */
1056 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1057
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301058 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001059 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 value = 0;
1061 }
1062
1063 /* VHT TX STBC cap */
1064 if (value && !cfg->vht_tx_stbc) {
1065 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1066 cfg->vht_tx_stbc);
1067
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301068 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001069 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001070 }
1071 }
1072
1073 /* Get VHT RX STBC cap */
1074 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1075
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301076 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001077 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 value = 0;
1079 }
1080
1081 /* VHT RX STBC cap */
1082 if (value && !cfg->vht_rx_stbc) {
1083 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1084 cfg->vht_rx_stbc);
1085
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301086 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001087 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001088 }
1089 }
1090
1091 /* Get VHT SU Beamformer cap */
1092 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1093 &value);
1094
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301095 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001096 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001097 value = 0;
1098 }
1099
1100 /* set VHT SU Beamformer cap */
1101 if (value && !cfg->vht_su_bformer) {
1102 status = sme_cfg_set_int(hdd_ctx->hHal,
1103 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1104 cfg->vht_su_bformer);
1105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301106 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001107 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 }
1109 }
1110
1111 /* check and update SU BEAMFORMEE capabality */
1112 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1113 pconfig->enableTxBF = cfg->vht_su_bformee;
1114
1115 status = sme_cfg_set_int(hdd_ctx->hHal,
1116 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1117 pconfig->enableTxBF);
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 VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 }
1122
1123 /* Get VHT MU Beamformer cap */
1124 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1125 &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 MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001129 value = 0;
1130 }
1131
1132 /* set VHT MU Beamformer cap */
1133 if (value && !cfg->vht_mu_bformer) {
1134 status = sme_cfg_set_int(hdd_ctx->hHal,
1135 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1136 cfg->vht_mu_bformer);
1137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301138 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001139 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 }
1141 }
1142
1143 /* Get VHT MU Beamformee cap */
1144 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1145 &value);
1146
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301147 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001148 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001149 value = 0;
1150 }
1151
1152 /* set VHT MU Beamformee cap */
1153 if (value && !cfg->vht_mu_bformee) {
1154 status = sme_cfg_set_int(hdd_ctx->hHal,
1155 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1156 cfg->vht_mu_bformee);
1157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301158 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001159 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 }
1161 }
1162
1163 /* Get VHT MAX AMPDU Len exp */
1164 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1165 &value);
1166
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301167 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001168 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001169 value = 0;
1170 }
1171
1172 /*
1173 * VHT max AMPDU len exp:
1174 * override if user configured value is too high
1175 * that the target cannot support.
1176 * Even though Rome publish ampdu_len=7, it can
1177 * only support 4 because of some h/w bug.
1178 */
1179
1180 if (value > cfg->vht_max_ampdu_len_exp) {
1181 status = sme_cfg_set_int(hdd_ctx->hHal,
1182 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1183 cfg->vht_max_ampdu_len_exp);
1184
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301185 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001186 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001187 }
1188 }
1189
1190 /* Get VHT TXOP PS CAP */
1191 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301193 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001194 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 value = 0;
1196 }
1197
1198 /* set VHT TXOP PS cap */
1199 if (value && !cfg->vht_txop_ps) {
1200 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1201 cfg->vht_txop_ps);
1202
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301203 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001204 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205 }
1206 }
1207
1208 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1209 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1210 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1211 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1212 else
1213 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1214
1215
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001216 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 band_5g->vht_cap.cap |=
1218 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001219 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001220 band_5g->vht_cap.cap |=
1221 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222
1223 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1224 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1225
1226 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1227 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1228 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1229 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1230
1231 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1232 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1233
1234 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1235 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1236 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1237 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1238 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1239 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1240
1241 band_5g->vht_cap.cap |=
1242 (cfg->vht_max_ampdu_len_exp <<
1243 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1244
1245 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1246 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1247 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1248 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1249 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1250 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1251 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1252 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1253
1254 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1255 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1256
1257}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001259/**
1260 * hdd_generate_macaddr_auto() - Auto-generate mac address
1261 * @hdd_ctx: Pointer to the HDD context
1262 *
1263 * Auto-generate mac address using device serial number.
1264 * Keep the first 3 bytes of OUI as before and replace
1265 * the last 3 bytes with the lower 3 bytes of serial number.
1266 *
1267 * Return: 0 for success
1268 * Non zero failure code for errors
1269 */
1270static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1271{
1272 unsigned int serialno = 0;
1273 struct qdf_mac_addr mac_addr = {
1274 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1275 };
1276
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001277 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001278 if (serialno == 0)
1279 return -EINVAL;
1280
1281 serialno &= 0x00ffffff;
1282
1283 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1284 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1285 mac_addr.bytes[5] = serialno & 0xff;
1286
1287 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1288 return 0;
1289}
1290
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301291/**
1292 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1293 * configuration to cfg_ini in HDD
1294 * @hdd_ctx: Pointer to hdd_ctx
1295 * @cfg: target configuration
1296 *
1297 * Return: None
1298 */
1299#ifdef FEATURE_WLAN_RA_FILTERING
1300static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1301 struct wma_tgt_cfg *cfg)
1302{
1303 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1304}
1305#else
1306static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1307 struct wma_tgt_cfg *cfg)
1308{
1309}
1310#endif
1311
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001312void hdd_update_tgt_cfg(void *context, void *param)
1313{
1314 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1315 struct wma_tgt_cfg *cfg = param;
1316 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001317 struct cds_config_info *cds_cfg = cds_get_ini_config();
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301318 QDF_STATUS qdf_status;
1319
1320 qdf_status = hdd_create_and_store_pdev(hdd_ctx);
1321 if (QDF_IS_STATUS_ERROR(qdf_status)) {
1322 hdd_err("Pdev creation fails!");
1323 QDF_BUG(0);
1324 }
Naveen Rawat64e477e2016-05-20 10:34:56 -07001325
1326 if (cds_cfg) {
1327 if (hdd_ctx->config->enable_sub_20_channel_width !=
1328 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1329 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1330 cds_cfg->sub_20_channel_width =
1331 WLAN_SUB_20_CH_WIDTH_NONE;
1332 } else {
1333 cds_cfg->sub_20_channel_width =
1334 hdd_ctx->config->enable_sub_20_channel_width;
1335 }
1336 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001337
1338 /* first store the INI band capability */
1339 temp_band_cap = hdd_ctx->config->nBandCapability;
1340
1341 hdd_ctx->config->nBandCapability = cfg->band_cap;
1342
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08001343 /*
1344 * now overwrite the target band capability with INI
1345 * setting if INI setting is a subset
1346 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347
1348 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1349 (temp_band_cap != eCSR_BAND_ALL))
1350 hdd_ctx->config->nBandCapability = temp_band_cap;
1351 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1352 (temp_band_cap != eCSR_BAND_ALL) &&
1353 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001354 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355 }
1356
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001357 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1359 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1360 }
1361
1362 /* This can be extended to other configurations like ht, vht cap... */
1363
Anurag Chouhanc5548422016-02-24 18:33:27 +05301364 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001366 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001368 static struct qdf_mac_addr default_mac_addr = {
1369 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1370 };
1371 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1372 &default_mac_addr)) {
1373 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1374 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1375 MAC_ADDRESS_STR,
1376 MAC_ADDR_ARRAY(hdd_ctx->config->
1377 intfMacAddr[0].bytes));
1378 } else {
1379 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1380 MAC_ADDRESS_STR,
1381 MAC_ADDR_ARRAY(hdd_ctx->config->
1382 intfMacAddr[0].bytes));
1383 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001384 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 }
1386
1387 hdd_ctx->target_fw_version = cfg->target_fw_version;
Sandeep Puligilla3d6a8e22016-10-11 18:57:14 -07001388 hdd_ctx->target_fw_vers_ext = cfg->target_fw_vers_ext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389
1390 hdd_ctx->max_intf_count = cfg->max_intf_count;
1391
Jeff Johnsonc875e242016-09-23 18:12:34 -07001392 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001393 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1396 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1397
1398 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001400 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001401
1402 hdd_update_vdev_nss(hdd_ctx);
1403
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001404 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001405 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001406 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001407 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001408
1409 hdd_ctx->current_antenna_mode =
1410 (hdd_ctx->config->enable2x2 == 0x01) ?
1411 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1412 hdd_info("Init current antenna mode: %d",
1413 hdd_ctx->current_antenna_mode);
1414
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001415 hdd_info("Target BPF %d Host BPF %d",
1416 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1417 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1418 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301419 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301420
Arun Khandavallid454d422016-08-17 12:47:05 +05301421 /*
1422 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1423 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1424 * configure the STA mode wow pattern.
1425 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301426 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301427 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301428
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301429 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1430
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001431 /* Configure NAN datapath features */
1432 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001433}
1434
1435/**
1436 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1437 * @context: HDD context pointer
1438 * @param: HDD radar indication pointer
1439 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001440 * This function is invoked in atomic context when a radar
1441 * is found on the SAP current operating channel and Data Tx
1442 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 * Actions: Stop the netif Tx queues,Indicate Radar present
1444 * in HDD context for future usage.
1445 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301446 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301448bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449{
1450 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1451 struct wma_dfs_radar_ind *hdd_radar_event =
1452 (struct wma_dfs_radar_ind *)param;
1453 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1454 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301455 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301456 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301458 if (!hdd_ctx || !hdd_radar_event ||
1459 hdd_ctx->config->disableDFSChSwitch)
1460 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461
1462 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001463 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301464 /*
1465 * Application already triggered channel switch
1466 * on current channel, so return here.
1467 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301468 return false;
1469 }
1470
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001471 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301472 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001473 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301474 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1475 if ((QDF_SAP_MODE == adapter->device_mode ||
1476 QDF_P2P_GO_MODE == adapter->device_mode) &&
1477 (CHANNEL_STATE_DFS ==
1478 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001479 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1480 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301481 hdd_info("tx blocked for session:%d",
1482 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483 }
1484
1485 status = hdd_get_next_adapter(hdd_ctx,
1486 adapterNode,
1487 &pNext);
1488 adapterNode = pNext;
1489 }
1490 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301491
1492 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001493}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494
1495/**
1496 * hdd_is_valid_mac_address() - validate MAC address
1497 * @pMacAddr: Pointer to the input MAC address
1498 *
1499 * This function validates whether the given MAC address is valid or not
1500 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1501 * where X is the hexa decimal digit character and separated by ':'
1502 * This algorithm works even if MAC address is not separated by ':'
1503 *
1504 * This code checks given input string mac contains exactly 12 hexadecimal
1505 * digits and a separator colon : appears in the input string only after
1506 * an even number of hex digits.
1507 *
1508 * Return: 1 for valid and 0 for invalid
1509 */
1510bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1511{
1512 int xdigit = 0;
1513 int separator = 0;
1514 while (*pMacAddr) {
1515 if (isxdigit(*pMacAddr)) {
1516 xdigit++;
1517 } else if (':' == *pMacAddr) {
1518 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1519 break;
1520
1521 ++separator;
1522 } else {
1523 /* Invalid MAC found */
1524 return 0;
1525 }
1526 ++pMacAddr;
1527 }
1528 return xdigit == 12 && (separator == 5 || separator == 0);
1529}
1530
1531/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301532 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1533 * @dev: Handle to struct net_device to be updated.
1534 *
1535 * Return: None
1536 */
1537static void hdd_mon_mode_ether_setup(struct net_device *dev)
1538{
1539 dev->header_ops = NULL;
1540 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1541 dev->hard_header_len = ETH_HLEN;
1542 dev->mtu = ETH_DATA_LEN;
1543 dev->addr_len = ETH_ALEN;
1544 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1545 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1546 dev->priv_flags |= IFF_TX_SKB_SHARING;
1547
1548 memset(dev->broadcast, 0xFF, ETH_ALEN);
1549}
1550
1551/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001552 * __hdd__mon_open() - HDD Open function
1553 * @dev: Pointer to net_device structure
1554 *
1555 * This is called in response to ifconfig up
1556 *
1557 * Return: 0 for success; non-zero for failure
1558 */
1559static int __hdd_mon_open(struct net_device *dev)
1560{
1561 int ret;
1562
1563 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301564 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001565 ret = hdd_set_mon_rx_cb(dev);
1566 return ret;
1567}
1568
1569/**
1570 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1571 * @dev: Pointer to net_device structure
1572 *
1573 * This is called in response to ifconfig up
1574 *
1575 * Return: 0 for success; non-zero for failure
1576 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001577static int hdd_mon_open(struct net_device *dev)
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001578{
1579 int ret;
1580
1581 cds_ssr_protect(__func__);
1582 ret = __hdd_mon_open(dev);
1583 cds_ssr_unprotect(__func__);
1584
1585 return ret;
1586}
1587
1588/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301589 * hdd_start_adapter() - Wrapper function for device specific adapter
1590 * @adapter: pointer to HDD adapter
1591 *
1592 * This function is called to start the device specific adapter for
1593 * the mode passed in the adapter's device_mode.
1594 *
1595 * Return: 0 for success; non-zero for failure
1596 */
1597int hdd_start_adapter(hdd_adapter_t *adapter)
1598{
1599
1600 int ret;
1601 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1602
1603 ENTER_DEV(adapter->dev);
1604 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1605
1606 switch (device_mode) {
1607 case QDF_P2P_CLIENT_MODE:
1608 case QDF_P2P_DEVICE_MODE:
1609 case QDF_OCB_MODE:
1610 case QDF_STA_MODE:
1611 case QDF_MONITOR_MODE:
1612 ret = hdd_start_station_adapter(adapter);
1613 if (ret)
1614 goto err_start_adapter;
1615 break;
1616 case QDF_P2P_GO_MODE:
1617 case QDF_SAP_MODE:
1618 ret = hdd_start_ap_adapter(adapter);
1619 if (ret)
1620 goto err_start_adapter;
1621 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301622 case QDF_IBSS_MODE:
1623 /*
1624 * For IBSS interface is initialized as part of
1625 * hdd_init_station_mode()
1626 */
1627 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301628 case QDF_FTM_MODE:
1629 ret = hdd_start_ftm_adapter(adapter);
1630 if (ret)
1631 goto err_start_adapter;
1632 break;
1633 default:
1634 hdd_err("Invalid session type %d", device_mode);
1635 QDF_ASSERT(0);
1636 goto err_start_adapter;
1637 }
1638 if (hdd_set_fw_params(adapter))
1639 hdd_err("Failed to set the FW params for the adapter!");
1640
1641 /*
1642 * Action frame registered in one adapter which will
1643 * applicable to all interfaces
1644 */
1645 wlan_hdd_cfg80211_register_frames(adapter);
1646 EXIT();
1647 return 0;
1648err_start_adapter:
1649 return -EINVAL;
1650}
1651
1652/**
Komal Seelamf2136bb2016-09-28 18:30:44 +05301653 * hdd_enable_power_management() - API to Enable Power Management
1654 *
1655 * API invokes Bus Interface Layer power management functionality
1656 *
1657 * Return: None
1658 */
1659static void hdd_enable_power_management(void)
1660{
1661 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1662
1663 if (!hif_ctx) {
1664 hdd_err("Bus Interface Context is Invalid");
1665 return;
1666 }
1667
1668 hif_enable_power_management(hif_ctx, cds_is_packet_log_enabled());
1669}
1670
1671/**
1672 * hdd_disable_power_management() - API to disable Power Management
1673 *
1674 * API disable Bus Interface Layer Power management functionality
1675 *
1676 * Return: None
1677 */
1678static void hdd_disable_power_management(void)
1679{
1680 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1681
1682 if (!hif_ctx) {
1683 hdd_err("Bus Interface Context is Invalid");
1684 return;
1685 }
1686
1687 hif_disable_power_management(hif_ctx);
1688}
1689
1690/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301691 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1692 * @hdd_ctx: HDD context
1693 * @adapter: HDD adapter
1694 * @reinit: flag to indicate from SSR or normal path
1695 *
1696 * This function maintains the driver state machine it will be invoked from
1697 * startup, reinit and change interface. Depending on the driver state shall
1698 * perform the opening of the modules.
1699 *
1700 * Return: 0 for success; non-zero for failure
1701 */
1702int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1703 bool reinit)
1704{
1705 int ret;
1706 qdf_device_t qdf_dev;
1707 QDF_STATUS status;
1708 p_cds_contextType p_cds_context;
1709 bool unint = false;
1710 void *hif_ctx;
1711
1712 ENTER();
1713
1714 p_cds_context = cds_get_global_context();
1715 if (!p_cds_context) {
1716 hdd_err("Global Context is NULL");
1717 QDF_ASSERT(0);
1718 return -EINVAL;
1719 }
1720
1721 hdd_info("start modules called in state! :%d reinit: %d",
1722 hdd_ctx->driver_status, reinit);
1723
1724 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1725 if (!qdf_dev) {
1726 hdd_err("QDF Device Context is Invalid return");
1727 return -EINVAL;
1728 }
1729
1730 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301731 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301732
1733 if (QDF_TIMER_STATE_RUNNING ==
1734 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1735
1736 hdd_set_idle_ps_config(hdd_ctx, false);
1737 hdd_info("Interface change Timer running Stop timer");
1738 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1739 }
1740
1741 switch (hdd_ctx->driver_status) {
1742 case DRIVER_MODULES_UNINITIALIZED:
1743 unint = true;
1744 /* Fall through dont add break here */
1745 case DRIVER_MODULES_CLOSED:
1746 if (!reinit && !unint) {
1747 ret = pld_power_on(qdf_dev->dev);
1748 if (ret) {
1749 hdd_err("Failed to Powerup the device: %d", ret);
1750 goto release_lock;
1751 }
1752 }
1753 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1754 qdf_dev->bus_type,
1755 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1756 HIF_ENABLE_TYPE_PROBE);
1757 if (ret) {
1758 hdd_err("Failed to open hif: %d", ret);
1759 goto power_down;
1760 }
1761
1762 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301763 if (!hif_ctx) {
1764 hdd_err("hif context is null!!");
1765 goto power_down;
1766 }
1767
Arun Khandavallifae92942016-08-01 13:31:08 +05301768 status = ol_cds_init(qdf_dev, hif_ctx);
1769 if (status != QDF_STATUS_SUCCESS) {
1770 hdd_err("No Memory to Create BMI Context :%d", status);
1771 goto hif_close;
1772 }
1773
Arun Khandavallif6246632016-08-17 17:43:06 +05301774 ret = hdd_update_config(hdd_ctx);
1775 if (ret) {
1776 hdd_err("Failed to update configuration :%d", ret);
1777 goto ol_cds_free;
1778 }
1779
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301780 status = hdd_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID);
1781 if (QDF_IS_STATUS_ERROR(status)) {
1782 hdd_err("Psoc creation fails!");
1783 goto ol_cds_free;
1784 }
1785
1786 status = cds_open(hdd_ctx->hdd_psoc);
Arun Khandavallifae92942016-08-01 13:31:08 +05301787 if (!QDF_IS_STATUS_SUCCESS(status)) {
1788 hdd_err("Failed to Open CDS: %d", status);
1789 goto ol_cds_free;
1790 }
1791
1792 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1793
1794 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1795
1796 status = cds_pre_enable(hdd_ctx->pcds_context);
1797 if (!QDF_IS_STATUS_SUCCESS(status)) {
1798 hdd_err("Failed to pre-enable CDS: %d", status);
1799 goto close;
1800 }
1801
1802 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1803 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1804 hdd_ftm_mc_process_msg);
1805 break;
1806 }
1807 if (unint) {
1808 hdd_info("In phase-1 initialization don't enable modules");
1809 break;
1810 }
1811 /* Fall through dont add break here */
1812 case DRIVER_MODULES_OPENED:
1813 if (!adapter) {
1814 hdd_alert("adapter is Null");
1815 goto close;
1816 }
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05301817 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1818 hdd_err("in ftm mode, no need to configure cds modules");
1819 break;
1820 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301821 if (hdd_configure_cds(hdd_ctx, adapter)) {
1822 hdd_err("Failed to Enable cds modules");
1823 goto close;
1824 }
Komal Seelamf2136bb2016-09-28 18:30:44 +05301825 hdd_enable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05301826 hdd_info("Driver Modules Successfully Enabled");
1827 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1828 break;
1829 case DRIVER_MODULES_ENABLED:
1830 hdd_info("Driver modules already Enabled");
1831 break;
1832 default:
1833 hdd_err("WLAN start invoked in wrong state! :%d\n",
1834 hdd_ctx->driver_status);
1835 goto release_lock;
1836 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301837 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301838 mutex_unlock(&hdd_ctx->iface_change_lock);
1839 EXIT();
1840 return 0;
1841
1842close:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05301843 cds_close(hdd_ctx->hdd_psoc, p_cds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05301844
1845ol_cds_free:
1846 ol_cds_free();
1847
1848hif_close:
1849 hdd_hif_close(p_cds_context->pHIFContext);
1850power_down:
1851 if (!reinit && !unint)
1852 pld_power_off(qdf_dev->dev);
1853release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301854 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301855 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301856 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301857 return -EINVAL;
1858}
1859
1860/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 * __hdd_open() - HDD Open function
1862 * @dev: Pointer to net_device structure
1863 *
1864 * This is called in response to ifconfig up
1865 *
1866 * Return: 0 for success; non-zero for failure
1867 */
1868static int __hdd_open(struct net_device *dev)
1869{
1870 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1871 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1872 int ret;
1873
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001874 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301875 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301876 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877
1878 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301879 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882
Arun Khandavallifae92942016-08-01 13:31:08 +05301883 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1884 if (ret) {
1885 hdd_err("Failed to start WLAN modules return");
1886 return -ret;
1887 }
1888
1889
1890 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1891 ret = hdd_start_adapter(adapter);
1892 if (ret) {
1893 hdd_err("Failed to start adapter :%d",
1894 adapter->device_mode);
1895 return ret;
1896 }
1897 }
1898
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1900 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301901 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 /* Enable TX queues only when we are connected */
1903 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301904 WLAN_START_ALL_NETIF_QUEUE,
1905 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 }
1907
Naveen Rawat286def52016-09-23 15:38:02 -07001908 /* Enable carrier and transmit queues for NDI */
1909 if (WLAN_HDD_IS_NDI(adapter)) {
1910 hdd_notice("Enabling Tx Queues");
1911 wlan_hdd_netif_queue_control(adapter,
1912 WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
1913 WLAN_CONTROL_PATH);
1914 }
1915
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 return ret;
1917}
1918
Arun Khandavallifae92942016-08-01 13:31:08 +05301919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920/**
1921 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1922 * @dev: Pointer to net_device structure
1923 *
1924 * This is called in response to ifconfig up
1925 *
1926 * Return: 0 for success; non-zero for failure
1927 */
Jeff Johnson590e2012016-10-05 16:16:24 -07001928static int hdd_open(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929{
1930 int ret;
1931
1932 cds_ssr_protect(__func__);
1933 ret = __hdd_open(dev);
1934 cds_ssr_unprotect(__func__);
1935
1936 return ret;
1937}
1938
1939/**
1940 * __hdd_stop() - HDD stop function
1941 * @dev: Pointer to net_device structure
1942 *
1943 * This is called in response to ifconfig down
1944 *
1945 * Return: 0 for success; non-zero for failure
1946 */
1947static int __hdd_stop(struct net_device *dev)
1948{
1949 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1950 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301951 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301953 bool close_modules = true;
1954 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001956 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301958 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959 adapter->sessionId, adapter->device_mode));
1960
1961 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301962 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964
1965 /* Nothing to be done if the interface is not opened */
1966 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001967 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return -ENODEV;
1969 }
1970
1971 /* Make sure the interface is marked as closed */
1972 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001973 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974
1975 /*
1976 * Disable TX on the interface, after this hard_start_xmit() will not
1977 * be called on that interface
1978 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001979 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1981 WLAN_CONTROL_PATH);
1982
1983 /*
Naveen Rawat286def52016-09-23 15:38:02 -07001984 * NAN data interface is different in some sense. The traffic on NDI is
1985 * bursty in nature and depends on the need to transfer. The service
1986 * layer may down the interface after the usage and up again when
1987 * required. In some sense, the NDI is expected to be available
1988 * (like SAP) iface until NDI delete request is issued by the service
1989 * layer. Skip BSS termination and adapter deletion for NAN Data
1990 * interface (NDI).
1991 */
1992 if (WLAN_HDD_IS_NDI(adapter))
1993 return 0;
1994
1995 /*
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996 * The interface is marked as down for outside world (aka kernel)
1997 * But the driver is pretty much alive inside. The driver needs to
1998 * tear down the existing connection on the netdev (session)
1999 * cleanup the data pipes and wait until the control plane is stabilized
2000 * for this interface. The call also needs to wait until the above
2001 * mentioned actions are completed before returning to the caller.
2002 * Notice that the hdd_stop_adapter is requested not to close the session
2003 * That is intentional to be able to scan if it is a STA/P2P interface
2004 */
Arun Khandavallifae92942016-08-01 13:31:08 +05302005 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006
2007 /* DeInit the adapter. This ensures datapath cleanup as well */
2008 hdd_deinit_adapter(hdd_ctx, adapter, true);
2009
Arun Khandavallifae92942016-08-01 13:31:08 +05302010
2011 /*
2012 * Find if any iface is up. If any iface is up then can't put device to
2013 * sleep/power save mode
2014 */
2015 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2016 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2017 if (test_bit(DEVICE_IFACE_OPENED,
2018 &adapternode->pAdapter->event_flags)) {
2019 hdd_info("Still other ifaces are up cannot close modules");
2020 close_modules = false;
2021 break;
2022 }
2023 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2024 adapternode = next;
2025
2026 }
2027
2028 if (close_modules) {
2029 hdd_info("Closing all modules from the hdd_stop");
2030 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2031 hdd_ctx->config->iface_change_wait_time
2032 * 50000);
2033 }
2034
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035 EXIT();
2036 return 0;
2037}
2038
2039/**
2040 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2041 * @dev: pointer to net_device structure
2042 *
2043 * This is called in response to ifconfig down
2044 *
2045 * Return: 0 for success and error number for failure
2046 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002047static int hdd_stop(struct net_device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048{
2049 int ret;
2050
2051 cds_ssr_protect(__func__);
2052 ret = __hdd_stop(dev);
2053 cds_ssr_unprotect(__func__);
2054
2055 return ret;
2056}
2057
2058/**
2059 * __hdd_uninit() - HDD uninit function
2060 * @dev: Pointer to net_device structure
2061 *
2062 * This is called during the netdev unregister to uninitialize all data
2063 * associated with the device
2064 *
2065 * Return: None
2066 */
2067static void __hdd_uninit(struct net_device *dev)
2068{
2069 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2070
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002071 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072
2073 do {
2074 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002075 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 break;
2077 }
2078
2079 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002080 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002081 break;
2082 }
2083
2084 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002085 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086 /*
2087 * we haven't validated all cases so let this go for
2088 * now
2089 */
2090 }
2091
2092 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2093
2094 /* after uninit our adapter structure will no longer be valid */
2095 adapter->dev = NULL;
2096 adapter->magic = 0;
2097 } while (0);
2098
2099 EXIT();
2100}
2101
2102/**
2103 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2104 * @dev: pointer to net_device structure
2105 *
2106 * This is called during the netdev unregister to uninitialize all data
2107 * associated with the device
2108 *
2109 * Return: none
2110 */
2111static void hdd_uninit(struct net_device *dev)
2112{
2113 cds_ssr_protect(__func__);
2114 __hdd_uninit(dev);
2115 cds_ssr_unprotect(__func__);
2116}
2117
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002118static int hdd_open_cesium_nl_sock(void)
2119{
2120#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2121 struct netlink_kernel_cfg cfg = {
2122 .groups = WLAN_NLINK_MCAST_GRP_ID,
2123 .input = NULL
2124 };
2125#endif
2126 int ret = 0;
2127
2128#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2129 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2130#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2131 THIS_MODULE,
2132#endif
2133 &cfg);
2134#else
2135 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2136 WLAN_NLINK_MCAST_GRP_ID,
2137 NULL, NULL, THIS_MODULE);
2138#endif
2139
2140 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002141 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002142 ret = -ECONNREFUSED;
2143 }
2144
2145 return ret;
2146}
2147
2148static void hdd_close_cesium_nl_sock(void)
2149{
2150 if (NULL != cesium_nl_srv_sock) {
2151 netlink_kernel_release(cesium_nl_srv_sock);
2152 cesium_nl_srv_sock = NULL;
2153 }
2154}
2155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156/**
2157 * __hdd_set_mac_address() - set the user specified mac address
2158 * @dev: Pointer to the net device.
2159 * @addr: Pointer to the sockaddr.
2160 *
2161 * This function sets the user specified mac address using
2162 * the command ifconfig wlanX hw ether <mac adress>.
2163 *
2164 * Return: 0 for success, non zero for failure
2165 */
2166static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2167{
2168 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2169 hdd_context_t *hdd_ctx;
2170 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302171 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 int ret;
2173
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002174 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175
2176 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2177 ret = wlan_hdd_validate_context(hdd_ctx);
2178 if (0 != ret)
2179 return ret;
2180
2181 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2182 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2183
2184 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302185 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186}
2187
2188/**
2189 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2190 * function from SSR
2191 * @dev: pointer to net_device structure
2192 * @addr: Pointer to the sockaddr
2193 *
2194 * This function sets the user specified mac address using
2195 * the command ifconfig wlanX hw ether <mac adress>.
2196 *
2197 * Return: 0 for success.
2198 */
2199static int hdd_set_mac_address(struct net_device *dev, void *addr)
2200{
2201 int ret;
2202
2203 cds_ssr_protect(__func__);
2204 ret = __hdd_set_mac_address(dev, addr);
2205 cds_ssr_unprotect(__func__);
2206
2207 return ret;
2208}
2209
2210uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2211{
2212 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302213 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2215 break;
2216 }
2217
Anurag Chouhan6d760662016-02-20 16:05:43 +05302218 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 return NULL;
2220
2221 hdd_ctx->config->intfAddrMask |= (1 << i);
2222 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2223}
2224
2225void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2226{
2227 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302228 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229 if (!memcmp(releaseAddr,
2230 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2231 6)) {
2232 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2233 break;
2234 }
2235 }
2236 return;
2237}
2238
2239#ifdef WLAN_FEATURE_PACKET_FILTERING
2240/**
2241 * __hdd_set_multicast_list() - set the multicast address list
2242 * @dev: Pointer to the WLAN device.
2243 * @skb: Pointer to OS packet (sk_buff).
2244 *
2245 * This funciton sets the multicast address list.
2246 *
2247 * Return: None
2248 */
2249static void __hdd_set_multicast_list(struct net_device *dev)
2250{
2251 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2252 int mc_count;
2253 int i = 0, status;
2254 struct netdev_hw_addr *ha;
2255 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2256 static const uint8_t ipv6_router_solicitation[]
2257 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2258
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002259 ENTER_DEV(dev);
2260
Anurag Chouhan6d760662016-02-20 16:05:43 +05302261 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302262 return;
2263
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302265 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002266 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267
2268 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002269 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 adapter->mc_addr_list.mc_cnt = 0;
2271 } else {
2272 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302273 hdd_notice("mc_count : %u", mc_count);
2274
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Dustin Brown61269462016-09-19 13:25:45 -07002276 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
2277 WLAN_HDD_MAX_MC_ADDR_LIST);
2278 wlan_hdd_set_mc_addr_list(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 adapter->mc_addr_list.mc_cnt = 0;
2280 return;
2281 }
2282
2283 adapter->mc_addr_list.mc_cnt = mc_count;
2284
2285 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302286 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2287 i, MAC_ADDR_ARRAY(ha->addr));
2288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 if (i == mc_count)
2290 break;
2291 /*
2292 * Skip following addresses:
2293 * 1)IPv6 router solicitation address
2294 * 2)Any other address pattern if its set during
2295 * RXFILTER REMOVE driver command based on
2296 * addr_filter_pattern
2297 */
2298 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2299 ETH_ALEN)) ||
2300 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2301 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002302 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 MAC_ADDR_ARRAY(ha->addr));
2304 adapter->mc_addr_list.mc_cnt--;
2305 continue;
2306 }
2307
2308 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2309 ETH_ALEN);
2310 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2311 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002312 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2314 i++;
2315 }
2316 }
2317 if (hdd_ctx->config->active_mode_offload) {
2318 hdd_info("enable mc filtering");
2319 wlan_hdd_set_mc_addr_list(adapter, true);
2320 } else {
2321 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2322 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302323 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 return;
2325}
2326
2327/**
2328 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2329 * @dev: pointer to net_device
2330 *
2331 * Return: none
2332 */
2333static void hdd_set_multicast_list(struct net_device *dev)
2334{
2335 cds_ssr_protect(__func__);
2336 __hdd_set_multicast_list(dev);
2337 cds_ssr_unprotect(__func__);
2338}
2339#endif
2340
2341/**
2342 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2343 * @dev: Pointer to the WLAN device.
2344 * @skb: Pointer to OS packet (sk_buff).
2345 *
2346 * This function is registered with the Linux OS for network
2347 * core to decide which queue to use first.
2348 *
2349 * Return: ac, Queue Index/access category corresponding to UP in IP header
2350 */
2351static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2352#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2353 , void *accel_priv
2354#endif
2355#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2356 , select_queue_fallback_t fallback
2357#endif
2358)
2359{
2360 return hdd_wmm_select_queue(dev, skb);
2361}
2362
2363static struct net_device_ops wlan_drv_ops = {
2364 .ndo_open = hdd_open,
2365 .ndo_stop = hdd_stop,
2366 .ndo_uninit = hdd_uninit,
2367 .ndo_start_xmit = hdd_hard_start_xmit,
2368 .ndo_tx_timeout = hdd_tx_timeout,
2369 .ndo_get_stats = hdd_get_stats,
2370 .ndo_do_ioctl = hdd_ioctl,
2371 .ndo_set_mac_address = hdd_set_mac_address,
2372 .ndo_select_queue = hdd_select_queue,
2373#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375#endif
2376};
2377
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002378/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2379static struct net_device_ops wlan_mon_drv_ops = {
2380 .ndo_open = hdd_mon_open,
2381 .ndo_stop = hdd_stop,
2382 .ndo_get_stats = hdd_get_stats,
2383};
2384
2385/**
2386 * hdd_set_station_ops() - update net_device ops for monitor mode
2387 * @pWlanDev: Handle to struct net_device to be updated.
2388 * Return: None
2389 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390void hdd_set_station_ops(struct net_device *pWlanDev)
2391{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002392 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2393 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2394 else
2395 pWlanDev->netdev_ops = &wlan_drv_ops;
2396}
2397
Komal Seelama89be8d2016-09-29 11:09:26 +05302398#ifdef FEATURE_RUNTIME_PM
Komal Seelam8634b772016-09-29 12:12:24 +05302399/**
2400 * hdd_runtime_suspend_context_init() - API to initialize HDD Runtime Contexts
2401 * @hdd_ctx: HDD context
2402 *
2403 * Return: None
2404 */
2405static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx)
2406{
2407 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2408
2409 ctx->scan = qdf_runtime_lock_init("scan");
Komal Seelamaa75f262016-09-29 12:32:13 +05302410 ctx->roc = qdf_runtime_lock_init("roc");
Komal Seelam81cb1662016-09-29 12:39:08 +05302411 ctx->dfs = qdf_runtime_lock_init("dfs");
Komal Seelam8634b772016-09-29 12:12:24 +05302412}
2413
2414/**
2415 * hdd_runtime_suspend_context_deinit() - API to deinit HDD runtime context
2416 * @hdd_ctx: HDD Context
2417 *
2418 * Return: None
2419 */
2420static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx)
2421{
2422 struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
2423
2424 qdf_runtime_lock_deinit(ctx->scan);
2425 ctx->scan = NULL;
Komal Seelamaa75f262016-09-29 12:32:13 +05302426 qdf_runtime_lock_deinit(ctx->roc);
2427 ctx->roc = NULL;
Komal Seelam81cb1662016-09-29 12:39:08 +05302428 qdf_runtime_lock_deinit(ctx->dfs);
2429 ctx->dfs = NULL;
Komal Seelam8634b772016-09-29 12:12:24 +05302430}
2431
Komal Seelama89be8d2016-09-29 11:09:26 +05302432static void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter)
2433{
2434 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2435
2436 ctx->connect = qdf_runtime_lock_init("connect");
2437}
2438
2439static void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter)
2440{
2441 struct hdd_connect_pm_context *ctx = &adapter->connect_rpm_ctx;
2442
2443 qdf_runtime_lock_deinit(ctx->connect);
2444 ctx->connect = NULL;
2445}
2446#else /* FEATURE_RUNTIME_PM */
Komal Seelam8634b772016-09-29 12:12:24 +05302447static void hdd_runtime_suspend_context_init(hdd_context_t *hdd_ctx) {}
2448static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {}
Komal Seelama89be8d2016-09-29 11:09:26 +05302449static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {}
2450static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {}
2451#endif /* FEATURE_RUNTIME_PM */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002452/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002453 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2454 * @hdd_ctx: global hdd context
2455 * @macAddr: mac address to assign to the interface
2456 * @name: User-visible name of the interface
2457 *
2458 * hdd adapter pointer would point to the netdev->priv space, this function
2459 * would retrive the pointer, and setup the hdd adapter configuration.
2460 *
2461 * Return: the pointer to hdd adapter, otherwise NULL
2462 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2464 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002465 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 const char *name)
2467{
2468 struct net_device *pWlanDev = NULL;
2469 hdd_adapter_t *adapter = NULL;
2470 /*
2471 * cfg80211 initialization and registration....
2472 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002473 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2474#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2475 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002477 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2478 hdd_mon_mode_ether_setup : ether_setup),
2479 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480
2481 if (pWlanDev != NULL) {
2482
2483 /* Save the pointer to the net_device in the HDD adapter */
2484 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2485
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302486 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487
2488 adapter->dev = pWlanDev;
2489 adapter->pHddCtx = hdd_ctx;
2490 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302491 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002492
2493 init_completion(&adapter->session_open_comp_var);
2494 init_completion(&adapter->session_close_comp_var);
2495 init_completion(&adapter->disconnect_comp_var);
2496 init_completion(&adapter->linkup_event_var);
2497 init_completion(&adapter->cancel_rem_on_chan_var);
2498 init_completion(&adapter->rem_on_chan_ready_event);
2499 init_completion(&adapter->sta_authorized_event);
2500 init_completion(&adapter->offchannel_tx_event);
2501 init_completion(&adapter->tx_action_cnf_event);
2502#ifdef FEATURE_WLAN_TDLS
2503 init_completion(&adapter->tdls_add_station_comp);
2504 init_completion(&adapter->tdls_del_station_comp);
2505 init_completion(&adapter->tdls_mgmt_comp);
2506 init_completion(&adapter->tdls_link_establish_req_comp);
2507#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002508 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 init_completion(&adapter->change_country_code);
2510
2511
2512 init_completion(&adapter->scan_info.abortscan_event_var);
2513
2514 adapter->offloads_configured = false;
2515 adapter->isLinkUpSvcNeeded = false;
2516 adapter->higherDtimTransition = true;
2517 /* Init the net_device structure */
2518 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2519
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302520 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302522 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 sizeof(tSirMacAddr));
2524 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525
2526 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2527 pWlanDev->features |=
2528 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2529 pWlanDev->features |= NETIF_F_RXCSUM;
2530
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002531 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 hdd_set_station_ops(adapter->dev);
2534
2535 pWlanDev->destructor = free_netdev;
2536 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002537 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 adapter->wdev.wiphy = hdd_ctx->wiphy;
2539 adapter->wdev.netdev = pWlanDev;
2540 /* set pWlanDev's parent to underlying device */
2541 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2542 hdd_wmm_init(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302543 hdd_adapter_runtime_suspend_init(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302545 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 }
2547
2548 return adapter;
2549}
2550
Jeff Johnson590e2012016-10-05 16:16:24 -07002551static QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
2552 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553{
2554 struct net_device *pWlanDev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002556 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2558 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002559 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302560 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 }
2562 }
2563 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002564 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302565 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 }
2567 } else {
2568 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002569 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302570 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571 }
2572 }
2573 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2574
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302575 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002576}
2577
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002578QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579{
2580 hdd_adapter_t *adapter = pContext;
2581
2582 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002583 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302584 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585 }
2586
2587 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002588 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302589 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590 }
2591
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002592 /*
2593 * For NAN Data interface, the close session results in the final
2594 * indication to the userspace
2595 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002596 if (adapter->device_mode == QDF_NDI_MODE)
2597 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002598
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601 /*
2602 * We can be blocked while waiting for scheduled work to be
2603 * flushed, and the adapter structure can potentially be freed, in
2604 * which case the magic will have been reset. So make sure the
2605 * magic is still good, and hence the adapter structure is still
2606 * valid, before signaling completion
2607 */
2608 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2609 complete(&adapter->session_close_comp_var);
2610
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302611 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612}
2613
Krunal Soni8c37e322016-02-03 16:08:37 -08002614/**
2615 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2616 * @adapter: pointer to device adapter
2617 * @type: type of interface
2618 *
2619 * This routine will check the mode of adapter and if it is required then it
2620 * will initialize the TDLS operations
2621 *
2622 * Return: QDF_STATUS
2623 */
2624#ifdef FEATURE_WLAN_TDLS
2625static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2626{
2627 if (QDF_IBSS_MODE != type) {
2628 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002629 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002630 return QDF_STATUS_E_FAILURE;
2631 }
2632 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2633 }
2634 return QDF_STATUS_SUCCESS;
2635}
2636#else
2637static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2638{
2639 return QDF_STATUS_SUCCESS;
2640}
2641#endif
2642
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302643QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644{
2645 struct net_device *pWlanDev = adapter->dev;
2646 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2647 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302648 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302649 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650 uint32_t type, subType;
2651 unsigned long rc;
2652 int ret_val;
2653
2654 INIT_COMPLETION(adapter->session_open_comp_var);
2655 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002656 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302658 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002659 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002660 goto error_sme_open;
2661 }
2662 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302663 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2665 (uint8_t *) &adapter->macAddressCurrent,
2666 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302667 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002668 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302669 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302670 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 goto error_sme_open;
2672 }
2673 /* Block on a completion variable. Can't wait forever though. */
2674 rc = wait_for_completion_timeout(
2675 &adapter->session_open_comp_var,
2676 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2677 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002678 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002679 rc);
Sandeep Puligillae8065992016-11-14 00:23:43 -08002680 adapter->sessionId = HDD_SESSION_ID_INVALID;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302681 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 }
2683
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302684 status = hdd_create_and_store_vdev(hdd_ctx->hdd_pdev, adapter);
2685 if (QDF_IS_STATUS_ERROR(status))
2686 goto error_vdev_create;
2687
Naveen Rawata410c5a2016-09-19 14:22:33 -07002688 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302690 qdf_ret_status = hdd_register_wext(pWlanDev);
2691 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002692 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302693 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302694 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 goto error_register_wext;
2696 }
2697 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002698 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2700
Deepak Dhamdherea2785822016-11-17 01:17:45 -08002701 /* set fast roaming capability in sme session */
2702 status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
2703 adapter->fast_roaming_allowed);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 /* Set the default operation channel */
2705 pHddStaCtx->conn_info.operationChannel =
2706 hdd_ctx->config->OperatingChannel;
2707
2708 /* Make the default Auth Type as OPEN */
2709 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2710
2711 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302712 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002713 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 status, status);
2715 goto error_init_txrx;
2716 }
2717
2718 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2719
2720 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302721 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002722 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723 status, status);
2724 goto error_wmm_init;
2725 }
2726
2727 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2728
2729 ret_val = wma_cli_set_command(adapter->sessionId,
2730 WMI_PDEV_PARAM_BURST_ENABLE,
2731 hdd_ctx->config->enableSifsBurst,
2732 PDEV_CMD);
2733
2734 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002735 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736 ret_val);
2737 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002738 status = hdd_check_and_init_tdls(adapter, type);
2739 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002741
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302742 status = hdd_lro_enable(hdd_ctx, adapter);
2743 if (status != QDF_STATUS_SUCCESS)
2744 goto error_lro_enable;
2745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302746 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302748error_lro_enable:
2749 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750error_tdls_init:
2751 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2752 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002753error_wmm_init:
2754 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2755 hdd_deinit_tx_rx(adapter);
2756error_init_txrx:
2757 hdd_unregister_wext(pWlanDev);
2758error_register_wext:
Rajeev Kumarba778852017-01-06 13:23:04 -08002759 status = hdd_release_and_destroy_vdev(adapter);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302760 if (QDF_IS_STATUS_ERROR(status))
2761 hdd_err("vdev delete failed");
2762error_vdev_create:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002763 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2764 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302765 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 adapter->sessionId,
2767 hdd_sme_close_session_callback,
2768 adapter)) {
2769 unsigned long rc;
2770
2771 /*
2772 * Block on a completion variable.
2773 * Can't wait forever though.
2774 */
2775 rc = wait_for_completion_timeout(
2776 &adapter->session_close_comp_var,
2777 msecs_to_jiffies
2778 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2779 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002780 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 rc);
2782 }
2783 }
2784error_sme_open:
2785 return status;
2786}
2787
2788void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2789{
2790 hdd_cfg80211_state_t *cfgState;
2791
2792 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2793
2794 if (NULL != cfgState->buf) {
2795 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 rc = wait_for_completion_timeout(
2797 &adapter->tx_action_cnf_event,
2798 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2799 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002800 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302801 /*
2802 * Inform tx status as FAILURE to upper layer and free
2803 * cfgState->buf
2804 */
2805 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 }
2807 }
2808 return;
2809}
2810
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302811/**
2812 * hdd_station_adapter_deinit() - De-initialize the station adapter
2813 * @hdd_ctx: global hdd context
2814 * @adapter: HDD adapter
Jeff Johnson590e2012016-10-05 16:16:24 -07002815 * @rtnl_held: Used to indicate whether or not the caller is holding
2816 * the kernel rtnl_mutex
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302817 *
2818 * This function De-initializes the STA/P2P/OCB adapter.
2819 *
2820 * Return: None.
2821 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002822static void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2823 hdd_adapter_t *adapter,
2824 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302825{
2826 ENTER_DEV(adapter->dev);
2827
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302828 if (adapter->dev) {
2829 if (rtnl_held)
2830 adapter->dev->wireless_handlers = NULL;
2831 else {
2832 rtnl_lock();
2833 adapter->dev->wireless_handlers = NULL;
2834 rtnl_unlock();
2835 }
2836 }
2837
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302838 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2839 hdd_deinit_tx_rx(adapter);
2840 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2841 }
2842
2843 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2844 hdd_wmm_adapter_close(adapter);
2845 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2846 }
2847
2848 hdd_cleanup_actionframe(hdd_ctx, adapter);
2849 wlan_hdd_tdls_exit(adapter);
2850
2851 EXIT();
2852}
2853
2854/**
2855 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2856 * @hdd_ctx: global hdd context
2857 * @adapter: HDD adapter
2858 * @rtnl_held: the rtnl lock hold flag
2859 * This function De-initializes the AP/P2PGo adapter.
2860 *
2861 * Return: None.
2862 */
Jeff Johnson590e2012016-10-05 16:16:24 -07002863static void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx,
2864 hdd_adapter_t *adapter,
2865 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302866{
2867 ENTER_DEV(adapter->dev);
2868
2869 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2870 hdd_wmm_adapter_close(adapter);
2871 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2872 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002873 wlan_hdd_undo_acs(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302874
2875 hdd_cleanup_actionframe(hdd_ctx, adapter);
2876
2877 hdd_unregister_hostapd(adapter, rtnl_held);
2878
2879 EXIT();
2880}
2881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2883 bool rtnl_held)
2884{
2885 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002888 case QDF_STA_MODE:
2889 case QDF_P2P_CLIENT_MODE:
2890 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302892 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 break;
2894 }
2895
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002896 case QDF_SAP_MODE:
2897 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 {
2899
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302900 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 break;
2902 }
2903
2904 default:
2905 break;
2906 }
2907
2908 EXIT();
2909}
2910
Jeff Johnson590e2012016-10-05 16:16:24 -07002911static void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2912 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913{
2914 struct net_device *pWlanDev = NULL;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302915 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916
2917 if (adapter)
2918 pWlanDev = adapter->dev;
2919 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002920 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 return;
2922 }
2923
Rajeev Kumarba778852017-01-06 13:23:04 -08002924 qdf_status = hdd_release_and_destroy_vdev(adapter);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05302925 if (QDF_IS_STATUS_ERROR(qdf_status))
2926 hdd_err("vdev delete failed");
2927
Rajeev Kumardca5f812016-02-04 17:28:06 -08002928 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05302929
2930 if (adapter->scan_info.default_scan_ies) {
2931 qdf_mem_free(adapter->scan_info.default_scan_ies);
2932 adapter->scan_info.default_scan_ies = NULL;
2933 }
2934
Komal Seelama89be8d2016-09-29 11:09:26 +05302935 hdd_adapter_runtime_suspend_denit(adapter);
2936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002937 /*
2938 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2939 * the driver is almost closed and cannot handle either control
2940 * messages or data. However, unregister_netdevice() call above will
2941 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2942 * to close the active connections (basically excites control path) which
2943 * is not right. Setting this flag helps hdd_stop() to recognize that
2944 * the interface is closed and restricts any operations on that
2945 */
2946 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2947
2948 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2949 if (rtnl_held) {
2950 unregister_netdevice(pWlanDev);
2951 } else {
2952 unregister_netdev(pWlanDev);
2953 }
2954 /*
2955 * Note that the adapter is no longer valid at this point
2956 * since the memory has been reclaimed
2957 */
2958 }
2959}
2960
Jeff Johnson590e2012016-10-05 16:16:24 -07002961static QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
2962 tSirMacAddr macAddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963{
2964 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2965 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302966 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302968 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 adapter = adapterNode->pAdapter;
2970 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302971 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002972 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302973 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002974 }
2975 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2976 adapterNode = pNext;
2977 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302978 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002980
Arun Khandavalli2358d522016-05-16 18:05:37 +05302981#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2982/**
2983 * hdd_set_fw_log_params() - Set log parameters to FW
2984 * @hdd_ctx: HDD Context
2985 * @adapter: HDD Adapter
2986 *
2987 * This function set the FW Debug log level based on the INI.
2988 *
2989 * Return: None
2990 */
2991static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2992 hdd_adapter_t *adapter)
2993{
2994 uint8_t count = 0, numentries = 0,
2995 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2996 uint32_t value = 0;
2997 int ret;
2998
Arun Khandavallifae92942016-08-01 13:31:08 +05302999 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
3000 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303001 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
3002 return;
3003 }
3004
Arun Khandavallifae92942016-08-01 13:31:08 +05303005 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05303006 hdd_ctx->fw_log_settings.dl_type =
3007 hdd_ctx->config->enableFwLogType;
3008 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303009 WMI_DBGLOG_TYPE,
3010 hdd_ctx->config->enableFwLogType,
3011 DBG_CMD);
3012 if (ret != 0)
3013 hdd_err("Failed to enable FW log type ret %d",
3014 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303015
3016 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05303017 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05303018 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303019 WMI_DBGLOG_LOG_LEVEL,
3020 hdd_ctx->config->enableFwLogLevel,
3021 DBG_CMD);
3022 if (ret != 0)
3023 hdd_err("Failed to enable FW log level ret %d",
3024 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303025
3026 hdd_string_to_u8_array(
3027 hdd_ctx->config->enableFwModuleLogLevel,
3028 moduleloglevel,
3029 &numentries,
3030 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
3031
3032 while (count < numentries) {
3033 /*
3034 * FW module log level input string looks like
3035 * below:
3036 * gFwDebugModuleLoglevel=<FW Module ID>,
3037 * <Log Level>,...
3038 * For example:
3039 * gFwDebugModuleLoglevel=
3040 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
3041 * Above input string means :
3042 * For FW module ID 1 enable log level 0
3043 * For FW module ID 2 enable log level 1
3044 * For FW module ID 3 enable log level 2
3045 * For FW module ID 4 enable log level 3
3046 * For FW module ID 5 enable log level 4
3047 * For FW module ID 6 enable log level 5
3048 * For FW module ID 7 enable log level 6
3049 */
3050
Arun Khandavallifae92942016-08-01 13:31:08 +05303051 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05303052 * Module ID * 10 + Module Log level
3053 */
3054 value = ((moduleloglevel[count] * 10) +
3055 moduleloglevel[count + 1]);
3056 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05303057 WMI_DBGLOG_MOD_LOG_LEVEL,
3058 value, DBG_CMD);
3059 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05303060 hdd_err("Failed to enable FW module log level %d ret %d",
3061 value, ret);
3062
3063 count += 2;
3064 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303065
Arun Khandavalli2358d522016-05-16 18:05:37 +05303066}
3067#else
3068static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
3069 hdd_adapter_t *adapter)
3070{
3071}
3072
3073#endif
3074
3075/**
3076 * hdd_set_fw_params() - Set parameters to firmware
3077 * @adapter: HDD adapter
3078 *
3079 * This function Sets various parameters to fw once the
3080 * adapter is started.
3081 *
3082 * Return: 0 on success or errno on failure
3083 */
3084int hdd_set_fw_params(hdd_adapter_t *adapter)
3085{
3086 int ret;
3087 hdd_context_t *hdd_ctx;
3088
3089 ENTER_DEV(adapter->dev);
3090
3091 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3092 if (!hdd_ctx)
3093 return -EINVAL;
3094
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003095 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303096 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303097#define HDD_DTIM_1CHAIN_RX_ID 0x5
3098#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003099 /*
3100 * Disable DTIM 1 chain Rx when in 1x1,
3101 * we are passing two value
3102 * as param_id << 29 | param_value.
3103 * Below param_value = 0(disable)
3104 */
3105 ret = wma_cli_set_command(adapter->sessionId,
3106 WMI_STA_SMPS_PARAM_CMDID,
3107 HDD_DTIM_1CHAIN_RX_ID <<
3108 HDD_SMPS_PARAM_VALUE_S,
3109 VDEV_CMD);
3110 if (ret) {
3111 hdd_err("DTIM 1 chain set failed %d", ret);
3112 goto error;
3113 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303114
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003115 ret = wma_cli_set_command(adapter->sessionId,
3116 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3117 hdd_ctx->config->txchainmask1x1,
3118 PDEV_CMD);
3119 if (ret) {
3120 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3121 ret);
3122 goto error;
3123 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303124
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003125 ret = wma_cli_set_command(adapter->sessionId,
3126 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3127 hdd_ctx->config->rxchainmask1x1,
3128 PDEV_CMD);
3129 if (ret) {
3130 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3131 ret);
3132 goto error;
3133 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303134#undef HDD_DTIM_1CHAIN_RX_ID
3135#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003136 } else {
3137 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3138 }
3139
Arun Khandavallifae92942016-08-01 13:31:08 +05303140 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3141 ret = wma_cli_set_command(adapter->sessionId,
3142 WMI_PDEV_PARAM_HYST_EN,
3143 hdd_ctx->config->enableMemDeepSleep,
3144 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303145
Arun Khandavallifae92942016-08-01 13:31:08 +05303146 if (ret) {
3147 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3148 ret);
3149 goto error;
3150 }
Rajeev Kumar Sirasanagandla2dab3ec2016-10-18 16:10:15 +05303151
3152 ret = wma_cli_set_command(adapter->sessionId,
3153 WMI_VDEV_PARAM_ENABLE_RTSCTS,
3154 hdd_ctx->config->rts_profile,
3155 VDEV_CMD);
3156 if (ret) {
3157 hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
3158 goto error;
3159 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303160 }
3161
3162 hdd_set_fw_log_params(hdd_ctx, adapter);
3163
3164 EXIT();
3165 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303166
Arun Khandavalli2358d522016-05-16 18:05:37 +05303167error:
3168 return -EINVAL;
3169}
3170
Ryan Hsu07495ea2016-01-21 15:25:39 -08003171/**
3172 * hdd_open_adapter() - open and setup the hdd adatper
3173 * @hdd_ctx: global hdd context
3174 * @session_type: type of the interface to be created
3175 * @iface_name: User-visible name of the interface
3176 * @macAddr: MAC address to assign to the interface
3177 * @name_assign_type: the name of assign type of the netdev
3178 * @rtnl_held: the rtnl lock hold flag
3179 *
3180 * This function open and setup the hdd adpater according to the device
3181 * type request, assign the name, the mac address assigned, and then prepared
3182 * the hdd related parameters, queue, lock and ready to start.
3183 *
3184 * Return: the pointer of hdd adapter, otherwise NULL.
3185 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3187 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003188 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003189 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190{
3191 hdd_adapter_t *adapter = NULL;
3192 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303193 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195
Arun Khandavallifae92942016-08-01 13:31:08 +05303196 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197
3198 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3199 /*
3200 * Max limit reached on the number of vdevs configured by the
3201 * host. Return error
3202 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303203 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3204 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 return NULL;
3206 }
3207
3208 if (macAddr == NULL) {
3209 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303210 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 return NULL;
3212 }
3213 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303214 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303215 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3216 " already exists",
3217 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003218 return NULL;
3219 }
3220
3221 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003222 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223 /* Reset locally administered bit if the device mode is STA */
3224 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3225 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003226 case QDF_P2P_CLIENT_MODE:
3227 case QDF_P2P_DEVICE_MODE:
3228 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003229 case QDF_NDI_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303230 case QDF_MONITOR_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003231 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3232 name_assign_type,
3233 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234
3235 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303236 hdd_err("failed to allocate adapter for session %d",
3237 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238 return NULL;
3239 }
3240
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003241 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003243 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303245 else if (QDF_MONITOR_MODE == session_type)
3246 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 else
3248 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3249
3250 adapter->device_mode = session_type;
3251
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303252 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003253 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303254 if (QDF_STATUS_SUCCESS != status)
3255 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303256 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003258 /*
3259 * Workqueue which gets scheduled in IPv4 notification
3260 * callback
3261 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003262 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3263 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264
3265#ifdef WLAN_NS_OFFLOAD
3266 /*
3267 * Workqueue which gets scheduled in IPv6
3268 * notification callback.
3269 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3271 hdd_ipv6_notifier_work_queue);
3272#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303274 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003275 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303276 goto err_free_netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 }
3278
3279 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303280 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303282 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3283 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003287 case QDF_P2P_GO_MODE:
3288 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003289 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3290 name_assign_type,
3291 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303293 hdd_alert("failed to allocate adapter for session %d",
3294 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 return NULL;
3296 }
3297
3298 adapter->wdev.iftype =
3299 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003300 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003301 NL80211_IFTYPE_P2P_GO;
3302 adapter->device_mode = session_type;
3303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303305 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3307 goto err_free_netdev;
3308 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303309 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303311 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3312 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003313 break;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303314 case QDF_FTM_MODE:
3315 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3316 name_assign_type,
3317 "wlan0");
3318 if (NULL == adapter) {
3319 hdd_err("Failed to allocate adapter for FTM mode");
3320 return NULL;
3321 }
3322 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3323 adapter->device_mode = session_type;
3324 status = hdd_register_interface(adapter, rtnl_held);
3325 if (QDF_STATUS_SUCCESS != status) {
3326 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3327 goto err_free_netdev;
3328 }
3329 /* Stop the Interface TX queue. */
3330 hdd_info("Disabling queues");
3331 wlan_hdd_netif_queue_control(adapter,
3332 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3333 WLAN_CONTROL_PATH);
3334 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303336 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303337 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 return NULL;
3339 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340
3341 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3342 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3343
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303344 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003345 /* Add it to the hdd's session list. */
3346 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303347 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303349 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003350 } else {
3351 pHddAdapterNode->pAdapter = adapter;
3352 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3353 }
3354 }
3355
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303356 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357 if (NULL != adapter) {
3358 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3359 adapter = NULL;
3360 }
3361 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303362 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003363 }
3364 return NULL;
3365 }
3366
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303367 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003368 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369
3370 /* Initialize the WoWL service */
3371 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003372 hdd_alert("hdd_init_wowl failed");
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303373 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374 }
3375
3376 /* Adapter successfully added. Increment the vdev count */
3377 hdd_ctx->current_intf_count++;
3378
Jeff Johnson5880d792016-08-15 13:32:30 -07003379 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003380 hdd_ctx->current_intf_count);
3381
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003382 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003383 }
3384
Rajeev Kumardca5f812016-02-04 17:28:06 -08003385 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3386 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387
3388 return adapter;
3389
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303390err_close_adapter:
3391 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003392err_free_netdev:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003393 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
Hanumanth Reddy Pothula00a39e72016-11-09 21:32:16 +05303394 free_netdev(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395
3396 return NULL;
3397}
3398
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303399QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003400 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003401{
3402 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303403 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404
3405 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303406 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003407 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003408 status);
3409 return status;
3410 }
3411
3412 while (pCurrent->pAdapter != adapter) {
3413 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303414 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 break;
3416
3417 pCurrent = pNext;
3418 }
3419 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303420 if (QDF_STATUS_SUCCESS == status) {
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05303421 hdd_info("wait for bus bw work to flush");
3422 cancel_work_sync(&hdd_ctx->bus_bw_work);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003423 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3425
3426 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303427 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003428 adapterNode = NULL;
3429
3430 /* Adapter removed. Decrement vdev count */
3431 if (hdd_ctx->current_intf_count != 0)
3432 hdd_ctx->current_intf_count--;
3433
3434 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303435 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303437
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303438 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003439}
3440
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003441/**
3442 * hdd_close_all_adapters - Close all open adapters
3443 * @hdd_ctx: Hdd context
3444 * rtnl_held: True if RTNL lock held
3445 *
3446 * Close all open adapters.
3447 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303448 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003449 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303450QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451{
3452 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303453 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454
3455 ENTER();
3456
3457 do {
3458 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303459 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303460 wlan_hdd_release_intf_addr(hdd_ctx,
3461 pHddAdapterNode->pAdapter->macAddressCurrent.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003463 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303464 qdf_mem_free(pHddAdapterNode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05303465 /* Adapter removed. Decrement vdev count */
3466 if (hdd_ctx->current_intf_count != 0)
3467 hdd_ctx->current_intf_count--;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303469 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470
3471 EXIT();
3472
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303473 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474}
3475
3476void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3477{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303478 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003479 tSirUpdateIE updateIE;
3480 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003481 case QDF_STA_MODE:
3482 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 {
3484 hdd_station_ctx_t *pHddStaCtx =
3485 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003486 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003487 break;
3488 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003489 case QDF_SAP_MODE:
3490 case QDF_P2P_GO_MODE:
3491 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003493 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003494 break;
3495 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003496 case QDF_FTM_MODE:
3497 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 default:
3499 /*
3500 * wlan_hdd_reset_prob_rspies should not have been called
3501 * for these kind of devices
3502 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003503 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003504 pHostapdAdapter->device_mode);
3505 return;
3506 }
3507
Anurag Chouhanc5548422016-02-24 18:33:27 +05303508 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003509 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3510 updateIE.ieBufferlength = 0;
3511 updateIE.pAdditionIEBuffer = NULL;
3512 updateIE.append = true;
3513 updateIE.notify = false;
3514 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3515 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303516 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003517 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 }
3519}
3520
Peng Xu66162de2016-02-11 17:01:20 -08003521/**
3522 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3523 * @hdd_ctx: HDD context which is already NULL validated
3524 * @adapter: HDD adapter which is already NULL validated
3525 *
3526 * Close the SME session and wait for its completion, if needed.
3527 *
3528 * Return: None
3529 */
3530static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3531 hdd_adapter_t *adapter)
3532{
3533 unsigned long rc;
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303534 QDF_STATUS qdf_status;
Peng Xu66162de2016-02-11 17:01:20 -08003535
3536 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3537 hdd_err("session is not opened:%d", adapter->sessionId);
3538 return;
3539 }
3540
3541 INIT_COMPLETION(adapter->session_close_comp_var);
3542 if (QDF_STATUS_SUCCESS ==
3543 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3544 hdd_sme_close_session_callback,
3545 adapter)) {
3546 /*
3547 * Block on a completion variable. Can't wait
3548 * forever though.
3549 */
3550 rc = wait_for_completion_timeout(
3551 &adapter->session_close_comp_var,
3552 msecs_to_jiffies
3553 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003554 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003555 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003556 if (adapter->device_mode == QDF_NDI_MODE)
3557 hdd_ndp_session_end_handler(adapter);
3558 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303559 return;
Sandeep Puligillaada72922016-09-29 19:31:21 -07003560 }
Rajeev Kumarba778852017-01-06 13:23:04 -08003561 qdf_status = hdd_release_and_destroy_vdev(adapter);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05303562 if (QDF_IS_STATUS_ERROR(qdf_status))
3563 hdd_err("vdev delete failed");
3564
Hanumanth Reddy Pothula33702122016-10-07 17:27:04 +05303565 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003566 }
3567}
3568
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303569QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570 const bool bCloseSession)
3571{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303572 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3574 union iwreq_data wrqu;
3575 tSirUpdateIE updateIE;
3576 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303577 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578
3579 ENTER();
3580
Sachin Ahuja988fd102016-09-15 17:16:25 +05303581 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003582 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003583 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3584 WLAN_CONTROL_PATH);
3585 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003586 case QDF_STA_MODE:
3587 case QDF_P2P_CLIENT_MODE:
3588 case QDF_IBSS_MODE:
3589 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003590 case QDF_NDI_MODE:
3591 if ((QDF_NDI_MODE == adapter->device_mode) ||
3592 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003593 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3594 hdd_is_connecting(
3595 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003596 INIT_COMPLETION(adapter->disconnect_comp_var);
3597 /*
3598 * For NDI do not use pWextState from sta_ctx, if needed
3599 * extract from ndi_ctx.
3600 */
3601 if (QDF_NDI_MODE == adapter->device_mode)
3602 qdf_ret_status = sme_roam_disconnect(
3603 hdd_ctx->hHal,
3604 adapter->sessionId,
3605 eCSR_DISCONNECT_REASON_NDI_DELETE);
3606 else if (pWextState->roamProfile.BSSType ==
3607 eCSR_BSS_TYPE_START_IBSS)
3608 qdf_ret_status = sme_roam_disconnect(
3609 hdd_ctx->hHal,
3610 adapter->sessionId,
3611 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003612 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003613 qdf_ret_status = sme_roam_disconnect(
3614 hdd_ctx->hHal,
3615 adapter->sessionId,
3616 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003617 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303618 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003619 rc = wait_for_completion_timeout(
3620 &adapter->disconnect_comp_var,
3621 msecs_to_jiffies
3622 (WLAN_WAIT_TIME_DISCONNECT));
3623 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003624 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 }
3626 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003627 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003628 }
3629 memset(&wrqu, '\0', sizeof(wrqu));
3630 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3631 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3632 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3633 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303634 }
3635 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303636 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303638 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303639 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003640
3641#ifdef WLAN_OPEN_SOURCE
3642 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3643#endif
3644
3645 hdd_deregister_tx_flow_control(adapter);
3646
3647#ifdef WLAN_NS_OFFLOAD
3648#ifdef WLAN_OPEN_SOURCE
3649 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3650#endif
3651#endif
3652
3653 /*
3654 * It is possible that the caller of this function does not
3655 * wish to close the session
3656 */
Peng Xu66162de2016-02-11 17:01:20 -08003657 if (true == bCloseSession)
3658 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 break;
3660
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003661 case QDF_SAP_MODE:
3662 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003663 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003664 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 /*
3666 * Before stopping the sap adapter, lets make sure there
3667 * is no sap restart work pending.
3668 */
3669 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003670 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003671 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 }
3673 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003674 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003675 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3676
3677 hdd_deregister_tx_flow_control(adapter);
3678
3679 mutex_lock(&hdd_ctx->sap_lock);
3680 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303681 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303682 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003683
3684 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003685 status = wlansap_stop_bss(
3686 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303688 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 hdd_hostapd_state_t *hostapd_state =
3690 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303691 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303692 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303693 qdf_status =
3694 qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08003695 qdf_stop_bss_event,
3696 SME_CMD_TIMEOUT_VALUE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697
Anurag Chouhance0dc992016-02-16 18:18:03 +05303698 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003699 hdd_err("failure waiting for wlansap_stop_bss %d",
3700 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 }
3702 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003703 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704 }
3705 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003706 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 adapter->device_mode,
3708 adapter->sessionId);
3709
Anurag Chouhanc5548422016-02-24 18:33:27 +05303710 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003711 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003712 updateIE.smeSessionId = adapter->sessionId;
3713 updateIE.ieBufferlength = 0;
3714 updateIE.pAdditionIEBuffer = NULL;
3715 updateIE.append = false;
3716 updateIE.notify = false;
3717 /* Probe bcn reset */
3718 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3719 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303720 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003721 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003722 }
3723 /* Assoc resp reset */
3724 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3725 &updateIE,
3726 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303727 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003728 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 }
3730 /* Reset WNI_CFG_PROBE_RSP Flags */
3731 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303732 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 adapter->sessionCtx.ap.beacon = NULL;
3734 }
3735 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003736 if (true == bCloseSession)
3737 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003738 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003739 case QDF_OCB_MODE:
Leo Changfdb45c32016-10-28 11:09:23 -07003740 cdp_peer_clear(cds_get_context(QDF_MODULE_ID_SOC),
3741 cds_get_context(QDF_MODULE_ID_TXRX),
3742 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.staId[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743 break;
3744 default:
3745 break;
3746 }
3747
3748 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303749 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750}
3751
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05303752/**
3753 * hdd_deinit_all_adapters - deinit all adapters
3754 * @hdd_ctx: HDD context
3755 * @rtnl_held: True if RTNL lock held
3756 *
3757 */
3758void hdd_deinit_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
3759{
3760 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3761 QDF_STATUS status;
3762 hdd_adapter_t *adapter;
3763
3764 ENTER();
3765
3766 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
3767
3768 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
3769 adapter = adapter_node->pAdapter;
3770 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3771 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
3772 adapter_node = next;
3773 }
3774
3775 EXIT();
3776}
3777
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303778QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003779{
3780 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303781 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 hdd_adapter_t *adapter;
3783
3784 ENTER();
3785
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303786 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3787
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3789
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303790 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003791 adapter = adapterNode->pAdapter;
3792 hdd_stop_adapter(hdd_ctx, adapter, true);
3793 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3794 adapterNode = pNext;
3795 }
3796
3797 EXIT();
3798
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303799 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800}
3801
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303802QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803{
3804 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303805 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806 hdd_adapter_t *adapter;
3807
3808 ENTER();
3809
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303810 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3813
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303814 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003816 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 wlan_hdd_netif_queue_control(adapter,
3818 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3819 WLAN_CONTROL_PATH);
3820
3821 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3822
3823 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003824 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 adapter->sessionId);
3826 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3827 hdd_wmm_adapter_close(adapter);
3828 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3829 }
3830
Wu Gao36717432016-11-21 15:09:48 +08003831 /*
3832 * If adapter is SAP, set session ID to invalid since SAP
3833 * session will be cleanup during SSR.
3834 */
3835 if (adapter->device_mode == QDF_SAP_MODE)
3836 wlansap_set_invalid_session(
3837 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3840 adapterNode = pNext;
3841 }
3842
3843 EXIT();
3844
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303845 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846}
3847
Arun Khandavallifae92942016-08-01 13:31:08 +05303848/**
3849 * hdd_is_interface_up()- Checkfor interface up before ssr
3850 * @hdd_ctx: HDD context
3851 *
3852 * check if there are any wlan interfaces before SSR accordingly start
3853 * the interface.
3854 *
3855 * Return: 0 if interface was opened else false
3856 */
3857static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3858{
3859 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3860 return true;
3861 else
3862 return false;
3863}
3864
Anurag Chouhanc4092922016-09-08 15:56:11 +05303865#if defined CFG80211_CONNECT_BSS
3866#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
3867 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
Jeff Johnson590e2012016-10-05 16:16:24 -07003868static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303869struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3870 struct ieee80211_channel *channel,
3871 const u8 *bssid, const u8 *ssid,
3872 size_t ssid_len)
3873{
3874 return cfg80211_get_bss(wiphy, channel, bssid,
3875 ssid, ssid_len,
3876 WLAN_CAPABILITY_ESS,
3877 WLAN_CAPABILITY_ESS);
3878}
3879#else
Jeff Johnson590e2012016-10-05 16:16:24 -07003880static
Anurag Chouhanc4092922016-09-08 15:56:11 +05303881struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3882 struct ieee80211_channel *channel,
3883 const u8 *bssid, const u8 *ssid,
3884 size_t ssid_len)
3885{
3886 return cfg80211_get_bss(wiphy, channel, bssid,
3887 ssid, ssid_len,
3888 IEEE80211_BSS_TYPE_ESS,
3889 IEEE80211_PRIVACY_ANY);
3890}
3891#endif
3892#endif
3893
Abhishek Singha84d3952016-09-13 13:45:05 +05303894#if defined CFG80211_CONNECT_BSS
3895/**
3896 * hdd_connect_bss() - API to send connection status to supplicant
3897 * @dev: network device
3898 * @bssid: bssid to which we want to associate
3899 * @req_ie: Request Information Element
3900 * @req_ie_len: len of the req IE
3901 * @resp_ie: Response IE
3902 * @resp_ie_len: len of ht response IE
3903 * @status: status
3904 * @gfp: Kernel Flag
3905 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
3906 *
3907 * The API is a wrapper to send connection status to supplicant
3908 *
3909 * Return: Void
3910 */
3911#if defined CFG80211_CONNECT_TIMEOUT
3912static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3913 struct cfg80211_bss *bss, const u8 *req_ie,
3914 size_t req_ie_len, const u8 *resp_ie,
3915 size_t resp_ie_len, int status, gfp_t gfp,
3916 bool connect_timeout)
3917{
3918 if (connect_timeout)
3919 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
3920 else
3921 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3922 resp_ie, resp_ie_len, status, gfp);
3923}
3924#else
3925static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3926 struct cfg80211_bss *bss, const u8 *req_ie,
3927 size_t req_ie_len, const u8 *resp_ie,
3928 size_t resp_ie_len, int status, gfp_t gfp,
3929 bool connect_timeout)
3930{
3931 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3932 resp_ie, resp_ie_len, status, gfp);
3933}
3934#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303935
3936/**
3937 * hdd_connect_result() - API to send connection status to supplicant
3938 * @dev: network device
3939 * @bssid: bssid to which we want to associate
3940 * @roam_info: information about connected bss
3941 * @req_ie: Request Information Element
3942 * @req_ie_len: len of the req IE
3943 * @resp_ie: Response IE
3944 * @resp_ie_len: len of ht response IE
3945 * @status: status
3946 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05303947 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
Anurag Chouhanc4092922016-09-08 15:56:11 +05303948 *
3949 * The API is a wrapper to send connection status to supplicant
3950 * and allow runtime suspend
3951 *
3952 * Return: Void
3953 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303954void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3955 tCsrRoamInfo *roam_info, const u8 *req_ie,
3956 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303957 size_t resp_ie_len, u16 status, gfp_t gfp,
3958 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303959{
3960 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3961 struct cfg80211_bss *bss = NULL;
3962
3963 if (WLAN_STATUS_SUCCESS == status) {
3964 struct ieee80211_channel *chan;
3965 int freq;
3966 int chan_no = roam_info->pBssDesc->channelId;
3967
3968 if (chan_no <= 14)
3969 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07003970 NL80211_BAND_2GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303971 else
3972 freq = ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -07003973 NL80211_BAND_5GHZ);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303974
3975 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
3976 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
3977 roam_info->u.pConnectedProfile->SSID.ssId,
3978 roam_info->u.pConnectedProfile->SSID.length);
3979 }
Komal Seelama89be8d2016-09-29 11:09:26 +05303980
Abhishek Singha84d3952016-09-13 13:45:05 +05303981 hdd_connect_bss(dev, bssid, bss, req_ie,
3982 req_ie_len, resp_ie, resp_ie_len,
3983 status, gfp, connect_timeout);
Komal Seelama89be8d2016-09-29 11:09:26 +05303984
3985 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303986}
3987#else
3988void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3989 tCsrRoamInfo *roam_info, const u8 *req_ie,
3990 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303991 size_t resp_ie_len, u16 status, gfp_t gfp,
3992 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303993{
Komal Seelama89be8d2016-09-29 11:09:26 +05303994 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3995
Anurag Chouhanc4092922016-09-08 15:56:11 +05303996 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
3997 resp_ie, resp_ie_len, status, gfp);
Komal Seelama89be8d2016-09-29 11:09:26 +05303998 qdf_runtime_pm_allow_suspend(padapter->connect_rpm_ctx.connect);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303999}
4000#endif
4001
4002
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304003QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004004{
4005 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304006 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007 hdd_adapter_t *adapter;
4008#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05304009 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010#endif
4011 eConnectionState connState;
4012
4013 ENTER();
4014
4015 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304016 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 adapter = adapterNode->pAdapter;
4018
Arun Khandavallifae92942016-08-01 13:31:08 +05304019 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304020 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05304021
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 hdd_wmm_init(adapter);
4023
4024 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004025 case QDF_STA_MODE:
4026 case QDF_P2P_CLIENT_MODE:
4027 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028
4029 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
4030 ->conn_info.connState;
4031
4032 hdd_init_station_mode(adapter);
4033 /* Open the gates for HDD to receive Wext commands */
4034 adapter->isLinkUpSvcNeeded = false;
4035 adapter->scan_info.mScanPending = false;
4036
4037 /* Indicate disconnect event to supplicant if associated previously */
4038 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07004039 eConnectionState_IbssConnected == connState ||
4040 eConnectionState_NotConnected == connState ||
4041 eConnectionState_IbssDisconnected == connState ||
4042 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 union iwreq_data wrqu;
4044 memset(&wrqu, '\0', sizeof(wrqu));
4045 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4046 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
4047 wireless_send_event(adapter->dev, SIOCGIWAP,
4048 &wrqu, NULL);
4049 adapter->sessionCtx.station.
4050 hdd_ReassocScenario = false;
4051
4052 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05304053 wlan_hdd_cfg80211_indicate_disconnect(
4054 adapter->dev, false,
4055 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 } else if (eConnectionState_Connecting == connState) {
4057 /*
4058 * Indicate connect failure to supplicant if we were in the
4059 * process of connecting
4060 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05304061 hdd_connect_result(adapter->dev, NULL, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062 NULL, 0, NULL, 0,
4063 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Abhishek Singha84d3952016-09-13 13:45:05 +05304064 GFP_KERNEL, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065 }
4066
4067 hdd_register_tx_flow_control(adapter,
4068 hdd_tx_resume_timer_expired_handler,
4069 hdd_tx_resume_cb);
4070
4071 break;
4072
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004073 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004074 /* softAP can handle SSR */
4075 break;
4076
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004077 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07004079 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004080 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
4081#else
Jeff Johnson5880d792016-08-15 13:32:30 -07004082 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 /* event supplicant to restart */
4084 cfg80211_del_sta(adapter->dev,
4085 (const u8 *)&bcastMac.bytes[0],
4086 GFP_KERNEL);
4087#endif
4088 break;
4089
4090 default:
4091 break;
4092 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05304093get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4095 adapterNode = pNext;
4096 }
4097
4098 EXIT();
4099
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304100 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004101}
4102
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304103QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 hdd_adapter_list_node_t **padapterNode)
4105{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304106 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004107 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304108 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
4109 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004110 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 return status;
4112}
4113
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304114QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 hdd_adapter_list_node_t *adapterNode,
4116 hdd_adapter_list_node_t **pNextAdapterNode)
4117{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304118 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004119 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304120 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
4121 (qdf_list_node_t *) adapterNode,
4122 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004124 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004125 return status;
4126}
4127
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304128QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129 hdd_adapter_list_node_t *adapterNode)
4130{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304131 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004132 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304133 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004135 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004136 return status;
4137}
4138
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304139QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 hdd_adapter_list_node_t **padapterNode)
4141{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304142 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004143 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304144 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
4145 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004146 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 return status;
4148}
4149
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304150QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151 hdd_adapter_list_node_t *adapterNode)
4152{
Anurag Chouhanffb21542016-02-17 14:33:03 +05304153 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004154 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304155 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
4156 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004157 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 return status;
4159}
4160
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304161QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162 hdd_adapter_list_node_t *adapterNode)
4163{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304164 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004165 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05304166 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
4167 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08004168 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004169 return status;
4170}
4171
4172hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
4173 tSirMacAddr macAddr)
4174{
4175 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4176 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304177 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178
4179 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4180
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304181 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004182 adapter = adapterNode->pAdapter;
4183
4184 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304185 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004186 macAddr, sizeof(tSirMacAddr))) {
4187 return adapter;
4188 }
4189 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4190 adapterNode = pNext;
4191 }
4192
4193 return NULL;
4194
4195}
4196
4197hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4198 uint32_t vdev_id)
4199{
4200 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4201 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304202 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304204 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004205
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304206 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 adapter = adapterNode->pAdapter;
4208
4209 if (adapter->sessionId == vdev_id)
4210 return adapter;
4211
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304212 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004213 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4214 adapterNode = pNext;
4215 }
4216
Jeff Johnson5880d792016-08-15 13:32:30 -07004217 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218
4219 return NULL;
4220}
4221
Abhishek Singh7996eb72015-12-30 17:24:02 +05304222/**
4223 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4224 * the sessionid
4225 * @hdd_ctx: hdd context.
4226 * @sme_session_id: sme session is for the adapter to get.
4227 *
4228 * This function is used to get the adapter with provided session id
4229 *
4230 * Return: adapter pointer if found
4231 *
4232 */
4233hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4234 uint32_t sme_session_id)
4235{
4236 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4237 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304238 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304239
4240
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304241 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304242
4243 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304244 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304245 adapter = adapter_node->pAdapter;
4246
4247 if (adapter &&
4248 adapter->sessionId == sme_session_id)
4249 return adapter;
4250
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304251 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304252 hdd_get_next_adapter(hdd_ctx,
4253 adapter_node, &next);
4254 adapter_node = next;
4255 }
4256 return NULL;
4257}
4258
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004259/**
4260 * hdd_get_adapter() - to get adapter matching the mode
4261 * @hdd_ctx: hdd context
4262 * @mode: adapter mode
4263 *
4264 * This routine will return the pointer to adapter matching
4265 * with the passed mode.
4266 *
4267 * Return: pointer to adapter or null
4268 */
4269hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4270 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004271{
4272 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4273 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304274 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275
4276 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4277
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304278 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 adapter = adapterNode->pAdapter;
4280
4281 if (adapter && (mode == adapter->device_mode))
4282 return adapter;
4283
4284 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4285 adapterNode = pNext;
4286 }
4287
4288 return NULL;
4289
4290}
4291
4292/**
4293 * hdd_get_operating_channel() - return operating channel of the device mode
4294 * @hdd_ctx: Pointer to the HDD context.
4295 * @mode: Device mode for which operating channel is required.
4296 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004297 * QDF_STA_MODE,
4298 * QDF_P2P_CLIENT_MODE,
4299 * QDF_SAP_MODE,
4300 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 *
4302 * This API returns the operating channel of the requested device mode
4303 *
4304 * Return: channel number. "0" id the requested device is not found OR it is
4305 * not connected.
4306 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004307uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4308 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004309{
4310 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304311 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 hdd_adapter_t *adapter;
4313 uint8_t operatingChannel = 0;
4314
4315 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4316
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304317 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 adapter = adapterNode->pAdapter;
4319
4320 if (mode == adapter->device_mode) {
4321 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004322 case QDF_STA_MODE:
4323 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 if (hdd_conn_is_connected
4325 (WLAN_HDD_GET_STATION_CTX_PTR
4326 (adapter))) {
4327 operatingChannel =
4328 (WLAN_HDD_GET_STATION_CTX_PTR
4329 (adapter))->conn_info.
4330 operationChannel;
4331 }
4332 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004333 case QDF_SAP_MODE:
4334 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 /* softap connection info */
4336 if (test_bit
4337 (SOFTAP_BSS_STARTED,
4338 &adapter->event_flags))
4339 operatingChannel =
4340 (WLAN_HDD_GET_AP_CTX_PTR
4341 (adapter))->operatingChannel;
4342 break;
4343 default:
4344 break;
4345 }
4346
4347 break; /* Found the device of interest. break the loop */
4348 }
4349
4350 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4351 adapterNode = pNext;
4352 }
4353 return operatingChannel;
4354}
4355
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304356static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 hdd_ctx)
4358{
4359 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304360 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 hdd_adapter_t *adapter;
4362
4363 ENTER();
4364
4365 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4366
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304367 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004369 if ((adapter->device_mode == QDF_STA_MODE) ||
4370 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4371 (adapter->device_mode == QDF_IBSS_MODE) ||
4372 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4373 (adapter->device_mode == QDF_SAP_MODE) ||
4374 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 wlan_hdd_cfg80211_deregister_frames(adapter);
4376 hdd_unregister_wext(adapter->dev);
4377 }
4378 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4379 adapterNode = pNext;
4380 }
4381
4382 EXIT();
4383
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304384 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385}
4386
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304387QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388{
4389 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304390 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 hdd_adapter_t *adapter;
4392
4393 ENTER();
4394
4395 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4396
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304397 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004399 if ((adapter->device_mode == QDF_STA_MODE) ||
4400 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4401 (adapter->device_mode == QDF_IBSS_MODE) ||
4402 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4403 (adapter->device_mode == QDF_SAP_MODE) ||
4404 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4406 eCSR_SCAN_ABORT_DEFAULT);
4407 }
4408 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4409 adapterNode = pNext;
4410 }
4411
4412 EXIT();
4413
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304414 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415}
4416
Dustin Brownf27bce82016-11-03 12:52:27 -07004417/**
4418 * hdd_abort_sched_scan_all_adapters() - stops scheduled (PNO) scans for all
4419 * adapters
4420 * @hdd_ctx: The HDD context containing the adapters to operate on
4421 *
4422 * return: QDF_STATUS_SUCCESS
4423 */
4424static QDF_STATUS hdd_abort_sched_scan_all_adapters(hdd_context_t *hdd_ctx)
4425{
4426 hdd_adapter_list_node_t *adapter_node = NULL, *next_node = NULL;
4427 QDF_STATUS status;
4428 hdd_adapter_t *adapter;
4429 int err;
4430
4431 ENTER();
4432
4433 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4434
4435 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
4436 adapter = adapter_node->pAdapter;
4437 if ((adapter->device_mode == QDF_STA_MODE) ||
4438 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4439 (adapter->device_mode == QDF_IBSS_MODE) ||
4440 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4441 (adapter->device_mode == QDF_SAP_MODE) ||
4442 (adapter->device_mode == QDF_P2P_GO_MODE)) {
4443 err = wlan_hdd_sched_scan_stop(adapter->dev);
4444 if (err)
4445 hdd_err("Unable to stop scheduled scan");
4446 }
4447 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next_node);
4448 adapter_node = next_node;
4449 }
4450
4451 EXIT();
4452
4453 return QDF_STATUS_SUCCESS;
4454}
4455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004456#ifdef WLAN_NS_OFFLOAD
4457/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004458 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459 * @hdd_ctx: Pointer to hdd context
4460 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004461 * Unregister for IPv6 address change notifications.
4462 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 * Return: None
4464 */
4465static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4466{
4467 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4468
4469 return;
4470}
4471
4472/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004473 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 * @hdd_ctx: Pointer to hdd context
4475 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004476 * Register for IPv6 address change notifications.
4477 *
4478 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004480static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004481{
4482 int ret;
4483
4484 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4485 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004486 if (ret) {
4487 hdd_err("Failed to register IPv6 notifier: %d", ret);
4488 goto out;
4489 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004491 hdd_info("Registered IPv6 notifier");
4492out:
4493 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494}
4495#else
4496/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004497 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 * @hdd_ctx: Pointer to hdd context
4499 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004500 * Unregister for IPv6 address change notifications.
4501 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 * Return: None
4503 */
4504static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4505{
4506}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004509 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510 * @hdd_ctx: Pointer to hdd context
4511 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004512 * Register for IPv6 address change notifications.
4513 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514 * Return: None
4515 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004516static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004517{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004518 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519}
4520#endif
4521
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304522#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4523/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004524 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304525 * @hdd_ctx: HDD context
4526 *
4527 * Activates the logging service
4528 *
4529 * Return: Zero in case of success, negative value otherwise
4530 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004531static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304532{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004533 int ret;
4534 struct hdd_config *config = hdd_ctx->config;
4535
4536 if (!config->wlanLoggingEnable)
4537 return 0;
4538
4539 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4540 config->wlanLoggingNumBuf);
4541 if (ret)
4542 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4543 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304544}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004545
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304546/**
4547 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4548 * @hdd_ctx: HDD context
4549 *
4550 * Deactivates the logging service
4551 *
4552 * Return: 0 on deactivating the logging service
4553 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004554static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304555{
4556 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4557 return wlan_logging_sock_deactivate_svc();
4558
4559 return 0;
4560}
4561#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004562static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304563{
4564 return 0;
4565}
4566
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004567static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304568{
4569 return 0;
4570}
4571#endif
4572
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004574 * hdd_register_notifiers - Register netdev notifiers.
4575 * @hdd_ctx: HDD context
4576 *
4577 * Register netdev notifiers like IPv4 and IPv6.
4578 *
4579 * Return: 0 on success and errno on failure
4580 */
4581static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4582{
4583 int ret;
4584
4585 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4586 if (ret) {
4587 hdd_err("register_netdevice_notifier failed: %d", ret);
4588 goto out;
4589 }
4590
4591 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4592 if (ret)
4593 goto unregister_notifier;
4594
4595 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4596 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4597 if (ret) {
4598 hdd_err("Failed to register IPv4 notifier: %d", ret);
4599 goto unregister_ip6_notifier;
4600 }
4601
4602 return 0;
4603
4604unregister_ip6_notifier:
4605 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4606unregister_notifier:
4607 unregister_netdevice_notifier(&hdd_netdev_notifier);
4608out:
4609 return ret;
4610
4611}
4612
4613/**
4614 * hdd_unregister_notifiers - Unregister netdev notifiers.
4615 * @hdd_ctx: HDD context
4616 *
4617 * Unregister netdev notifiers like IPv4 and IPv6.
4618 *
4619 * Return: None.
4620 */
4621static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4622{
4623 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4624
4625 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4626
4627 unregister_netdevice_notifier(&hdd_netdev_notifier);
4628}
4629
4630/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004631 * hdd_exit_netlink_services - Exit netlink services
4632 * @hdd_ctx: HDD context
4633 *
4634 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4635 * nl service.
4636 *
4637 * Return: None.
4638 */
4639static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4640{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004641 hdd_close_cesium_nl_sock();
4642
4643 ptt_sock_deactivate_svc();
4644
4645 nl_srv_exit();
4646}
4647
4648/**
4649 * hdd_init_netlink_services- Init netlink services
4650 * @hdd_ctx: HDD context
4651 *
4652 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4653 * nl service.
4654 *
4655 * Return: 0 on success and errno on failure.
4656 */
4657static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4658{
4659 int ret;
4660
Ryan Hsuceddceb2016-04-28 10:20:14 -07004661 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004662 if (ret) {
4663 hdd_alert("nl_srv_init failed: %d", ret);
4664 goto out;
4665 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004666 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004667
4668 ret = oem_activate_service(hdd_ctx);
4669 if (ret) {
4670 hdd_alert("oem_activate_service failed: %d", ret);
4671 goto err_nl_srv;
4672 }
4673
4674 ret = ptt_sock_activate_svc();
4675 if (ret) {
4676 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4677 goto err_nl_srv;
4678 }
4679
4680 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004681 if (ret)
4682 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004683
4684 ret = cnss_diag_activate_service();
4685 if (ret) {
4686 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4687 goto err_close_cesium;
4688 }
4689
4690 return 0;
4691
4692err_close_cesium:
4693 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004694 ptt_sock_deactivate_svc();
4695err_nl_srv:
4696 nl_srv_exit();
4697out:
4698 return ret;
4699}
4700
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004701/**
4702 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4703 * @hdd_ctx: HDD context.
4704 *
4705 * Destroy RX wakelock.
4706 *
4707 * Return: None.
4708 */
4709static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4710{
4711 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4712}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004713
4714/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004715 * hdd_rx_wake_lock_create() - Create RX wakelock
4716 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004717 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004718 * Create RX wakelock.
4719 *
4720 * Return: None.
4721 */
4722static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4723{
4724 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4725}
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004726
4727/**
4728 * hdd_roc_context_init() - Init ROC context
4729 * @hdd_ctx: HDD context.
4730 *
4731 * Initialize ROC context.
4732 *
4733 * Return: 0 on success and errno on failure.
4734 */
4735static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4736{
4737 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4738 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4739
4740 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4741
4742 return 0;
4743}
4744
4745/**
4746 * hdd_roc_context_destroy() - Destroy ROC context
4747 * @hdd_ctx: HDD context.
4748 *
4749 * Destroy roc list and flush the pending roc work.
4750 *
4751 * Return: None.
4752 */
4753static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4754{
4755 flush_delayed_work(&hdd_ctx->roc_req_work);
4756 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4757}
4758
4759/**
Houston Hoffman160db392016-10-10 17:37:51 -07004760 * hdd_context_deinit() - Deinitialize HDD context
4761 * @hdd_ctx: HDD context.
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004762 *
Houston Hoffman160db392016-10-10 17:37:51 -07004763 * Deinitialize HDD context along with all the feature specific contexts but
4764 * do not free hdd context itself. Caller of this API is supposed to free
4765 * HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004766 *
Houston Hoffman160db392016-10-10 17:37:51 -07004767 * return: 0 on success and errno on failure.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004768 */
Houston Hoffman160db392016-10-10 17:37:51 -07004769static int hdd_context_deinit(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004770{
Houston Hoffman160db392016-10-10 17:37:51 -07004771 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004772
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004773 hdd_roc_context_destroy(hdd_ctx);
4774
4775 hdd_sap_context_destroy(hdd_ctx);
4776
4777 hdd_rx_wake_lock_destroy(hdd_ctx);
4778
4779 hdd_tdls_context_destroy(hdd_ctx);
4780
4781 hdd_scan_context_destroy(hdd_ctx);
4782
4783 qdf_list_destroy(&hdd_ctx->hddAdapters);
4784
Houston Hoffman160db392016-10-10 17:37:51 -07004785 return 0;
4786}
4787
4788/**
4789 * hdd_context_destroy() - Destroy HDD context
4790 * @hdd_ctx: HDD context to be destroyed.
4791 *
4792 * Free config and HDD context as well as destroy all the resources.
4793 *
4794 * Return: None
4795 */
4796static void hdd_context_destroy(hdd_context_t *hdd_ctx)
4797{
4798 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
4799 hdd_logging_sock_deactivate_svc(hdd_ctx);
4800
Hanumantha Reddy Pothula00c74f62016-11-24 20:13:32 +05304801 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
4802
Houston Hoffman160db392016-10-10 17:37:51 -07004803 hdd_context_deinit(hdd_ctx);
4804
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304805 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004806 hdd_ctx->config = NULL;
4807
4808 wiphy_free(hdd_ctx->wiphy);
4809}
4810
4811/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004812 * hdd_wlan_exit() - HDD WLAN exit function
4813 * @hdd_ctx: Pointer to the HDD Context
4814 *
4815 * This is the driver exit point (invoked during rmmod)
4816 *
4817 * Return: None
4818 */
Jeff Johnson590e2012016-10-05 16:16:24 -07004819static void hdd_wlan_exit(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820{
4821 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304822 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304824 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825
4826 ENTER();
4827
Arun Khandavallifae92942016-08-01 13:31:08 +05304828 if (QDF_TIMER_STATE_RUNNING ==
4829 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4830 hdd_info("Stpp interface change timer");
4831 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832 }
4833
Arun Khandavallifae92942016-08-01 13:31:08 +05304834 if (!QDF_IS_STATUS_SUCCESS
4835 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4836 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004837
Arun Khandavallifae92942016-08-01 13:31:08 +05304838
4839 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004840
Nitesh Shah61c10d92016-10-19 19:29:15 +05304841 qdf_mc_timer_destroy(&hdd_ctx->tdls_source_timer);
4842
Prashanth Bhattaab004382016-10-11 16:08:11 -07004843 hdd_bus_bandwidth_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004844
4845#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304846 if (QDF_TIMER_STATE_RUNNING ==
4847 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4848 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 }
4850
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304851 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304852 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004853 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 }
Liangwei Dongaef84342016-10-21 05:28:00 -04004855 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4856 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4857 hdd_ctx->last_acs_channel_list = NULL;
4858 hdd_ctx->num_of_channels = 0;
4859 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861
Arun Khandavallifae92942016-08-01 13:31:08 +05304862 mutex_lock(&hdd_ctx->iface_change_lock);
4863 driver_status = hdd_ctx->driver_status;
4864 mutex_unlock(&hdd_ctx->iface_change_lock);
4865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 /*
4867 * Powersave Offload Case
4868 * Disable Idle Power Save Mode
4869 */
4870 hdd_set_idle_ps_config(hdd_ctx, false);
4871
Arun Khandavallifae92942016-08-01 13:31:08 +05304872 if (driver_status != DRIVER_MODULES_CLOSED) {
4873 hdd_unregister_wext_all_adapters(hdd_ctx);
4874 /*
4875 * Cancel any outstanding scan requests. We are about to close
4876 * all of our adapters, but an adapter structure is what SME
4877 * passes back to our callback function. Hence if there
4878 * are any outstanding scan requests then there is a
4879 * race condition between when the adapter is closed and
4880 * when the callback is invoked. We try to resolve that
4881 * race condition here by canceling any outstanding scans
4882 * before we close the adapters.
4883 * Note that the scans may be cancelled in an asynchronous
4884 * manner, so ideally there needs to be some kind of
4885 * synchronization. Rather than introduce a new
4886 * synchronization here, we will utilize the fact that we are
4887 * about to Request Full Power, and since that is synchronized,
4888 * the expectation is that by the time Request Full Power has
4889 * completed, all scans will be cancelled
4890 */
4891 hdd_abort_mac_scan_all_adapters(hdd_ctx);
Dustin Brownf27bce82016-11-03 12:52:27 -07004892 hdd_abort_sched_scan_all_adapters(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05304893 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004894 }
4895
4896 /*
4897 * Close the scheduler before calling cds_close to make sure no thread
4898 * is scheduled after the each module close is called i.e after all the
4899 * data structures are freed.
4900 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304901 qdf_status = cds_sched_close(p_cds_context);
4902 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004903 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304904 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906
Hanumanth Reddy Pothula709a6362016-10-18 18:19:44 +05304907 hdd_wlan_stop_modules(hdd_ctx);
4908
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304909 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4910 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4911 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913 /*
4914 * Close CDS
4915 * This frees pMac(HAL) context. There should not be any call
4916 * that requires pMac access after this.
4917 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07004919 hdd_green_ap_deinit(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920
Komal Seelam8634b772016-09-29 12:12:24 +05304921 hdd_runtime_suspend_context_deinit(hdd_ctx);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004922 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004923
4924 hdd_ipa_cleanup(hdd_ctx);
4925
4926 /* Free up RoC request queue and flush workqueue */
4927 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304929 wlansap_global_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004930 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304931 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004932
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07004933 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004934
Arun Khandavallifae92942016-08-01 13:31:08 +05304935 hdd_exit_netlink_services(hdd_ctx);
4936 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004937 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938}
4939
4940void __hdd_wlan_exit(void)
4941{
4942 hdd_context_t *hdd_ctx;
4943
4944 ENTER();
4945
Anurag Chouhan6d760662016-02-20 16:05:43 +05304946 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004948 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 EXIT();
4950 return;
4951 }
4952
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004953 /* Check IPA HW Pipe shutdown */
4954 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4955
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004956 memdump_deinit();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05304957 hdd_driver_memdump_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 /* Do all the cleanup before deregistering the driver */
4960 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962 EXIT();
4963}
4964
4965#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Liangwei Dongaef84342016-10-21 05:28:00 -04004966/**
4967 * hdd_skip_acs_scan_timer_handler() - skip ACS scan timer timeout handler
4968 * @data: pointer to hdd_context_t
4969 *
4970 * This function will reset acs_scan_status to eSAP_DO_NEW_ACS_SCAN.
4971 * Then new ACS request will do a fresh scan without reusing the cached
4972 * scan information.
4973 *
4974 * Return: void
4975 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976void hdd_skip_acs_scan_timer_handler(void *data)
4977{
4978 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4979
Jeff Johnson760350b2016-08-15 14:01:52 -07004980 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
Liangwei Dongaef84342016-10-21 05:28:00 -04004982 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
4983 qdf_mem_free(hdd_ctx->last_acs_channel_list);
4984 hdd_ctx->last_acs_channel_list = NULL;
4985 hdd_ctx->num_of_channels = 0;
4986 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987
4988 if (!hdd_ctx->hHal)
4989 return;
4990 sme_scan_flush_result(hdd_ctx->hHal);
4991}
4992#endif
4993
4994#ifdef QCA_HT_2040_COEX
4995/**
4996 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4997 * @adapter: pointer to adapter
4998 * @staId: station id
4999 * @macAddrSTA: station MAC address
5000 * @channel_type: channel type
5001 *
5002 * This function notifies FW with HT20/HT40 mode
5003 *
5004 * Return: 0 if successful, error number otherwise
5005 */
5006int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305007 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008{
5009 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305010 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 hdd_context_t *hdd_ctx = NULL;
5012
5013 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5014
5015 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305016 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005019 if (!hdd_ctx->hHal)
5020 return -EINVAL;
5021
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305022 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305024 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005025 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005026 return -EINVAL;
5027 }
5028
5029 return 0;
5030}
5031#endif
5032
5033/**
5034 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
5035 * @state: state
5036 *
5037 * This function notifies FW with modem power status
5038 *
5039 * Return: 0 if successful, error number otherwise
5040 */
5041int hdd_wlan_notify_modem_power_state(int state)
5042{
5043 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305044 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 hdd_context_t *hdd_ctx;
5046
Anurag Chouhan6d760662016-02-20 16:05:43 +05305047 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305049 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005052 if (!hdd_ctx->hHal)
5053 return -EINVAL;
5054
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305055 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
5056 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005057 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 state);
5059 return -EINVAL;
5060 }
5061 return 0;
5062}
5063
5064/**
5065 *
5066 * hdd_post_cds_enable_config() - HDD post cds start config helper
5067 * @adapter - Pointer to the HDD
5068 *
5069 * Return: None
5070 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305071QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305073 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005074
5075 /*
5076 * Send ready indication to the HDD. This will kick off the MAC
5077 * into a 'running' state and should kick off an initial scan.
5078 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305079 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
5080 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005081 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
5082 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305083 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005084 }
5085
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305086 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087}
5088
5089/* wake lock APIs for HDD */
5090void hdd_prevent_suspend(uint32_t reason)
5091{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305092 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005093}
5094
5095void hdd_allow_suspend(uint32_t reason)
5096{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305097 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098}
5099
5100void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
5101{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05305102 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
5103 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005104}
5105
5106/**
5107 * hdd_exchange_version_and_caps() - exchange version and capability with target
5108 * @hdd_ctx: Pointer to HDD context
5109 *
5110 * This is the HDD function to exchange version and capability information
5111 * between Host and Target
5112 *
5113 * This function gets reported version of FW.
5114 * It also finds the version of target headers used to compile the host;
5115 * It compares the above two and prints a warning if they are different;
5116 * It gets the SW and HW version string;
5117 * Finally, it exchanges capabilities between host and target i.e. host
5118 * and target exchange a msg indicating the features they support through a
5119 * bitmap
5120 *
5121 * Return: None
5122 */
5123void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
5124{
5125
5126 tSirVersionType versionCompiled;
5127 tSirVersionType versionReported;
5128 tSirVersionString versionString;
5129 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305130 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005131
5132 memset(&versionCompiled, 0, sizeof(versionCompiled));
5133 memset(&versionReported, 0, sizeof(versionReported));
5134
5135 /* retrieve and display WCNSS version information */
5136 do {
5137
5138 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
5139 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305140 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005141 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 break;
5143 }
5144
5145 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
5146 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305147 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005148 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 break;
5150 }
5151
5152 if ((versionCompiled.major != versionReported.major) ||
5153 (versionCompiled.minor != versionReported.minor) ||
5154 (versionCompiled.version != versionReported.version) ||
5155 (versionCompiled.revision != versionReported.revision)) {
5156 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
5157 "Host expected %u.%u.%u.%u\n",
5158 WLAN_MODULE_NAME,
5159 (int)versionReported.major,
5160 (int)versionReported.minor,
5161 (int)versionReported.version,
5162 (int)versionReported.revision,
5163 (int)versionCompiled.major,
5164 (int)versionCompiled.minor,
5165 (int)versionCompiled.version,
5166 (int)versionCompiled.revision);
5167 } else {
5168 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
5169 WLAN_MODULE_NAME,
5170 (int)versionReported.major,
5171 (int)versionReported.minor,
5172 (int)versionReported.version,
5173 (int)versionReported.revision);
5174 }
5175
5176 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
5177 versionString,
5178 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305179 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005180 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 break;
5182 }
5183
5184 pr_info("%s: WCNSS software version %s\n",
5185 WLAN_MODULE_NAME, versionString);
5186
5187 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
5188 versionString,
5189 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305190 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005191 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192 break;
5193 }
5194
5195 pr_info("%s: WCNSS hardware version %s\n",
5196 WLAN_MODULE_NAME, versionString);
5197
5198 /*
5199 * 1.Check if FW version is greater than 0.1.1.0. Only then
5200 * send host-FW capability exchange message
5201 * 2.Host-FW capability exchange message is only present on
5202 * target 1.1 so send the message only if it the target is 1.1
5203 * minor numbers for different target branches:
5204 * 0 -> (1.0)Mainline Build
5205 * 1 -> (1.1)Mainline Build
5206 * 2->(1.04) Stability Build
5207 */
5208 if (((versionReported.major > 0) || (versionReported.minor > 1)
5209 || ((versionReported.minor >= 1)
5210 && (versionReported.version >= 1)))
5211 && ((versionReported.major == 1)
5212 && (versionReported.minor >= 1)))
5213 fwFeatCapsMsgSupported = 1;
5214
5215 if (fwFeatCapsMsgSupported) {
5216 /*
5217 * Indicate if IBSS heartbeat monitoring needs to be
5218 * offloaded
5219 */
5220 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
5221 sme_disable_feature_capablity
5222 (IBSS_HEARTBEAT_OFFLOAD);
5223 }
5224
5225 sme_feature_caps_exchange(hdd_ctx->hHal);
5226 }
5227
5228 } while (0);
5229
5230}
5231
5232/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305233QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234{
5235 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
5236 hdd_ctx->reg.cc_src);
5237}
5238
5239/**
5240 * hdd_is_5g_supported() - check if hardware supports 5GHz
5241 * @hdd_ctx: Pointer to the hdd context
5242 *
5243 * HDD function to know if hardware supports 5GHz
5244 *
5245 * Return: true if hardware supports 5GHz
5246 */
5247bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5248{
zdingf54169a2016-10-12 17:08:45 +08005249 if (!hdd_ctx || !hdd_ctx->config)
5250 return true;
5251
5252 if (hdd_ctx->config->nBandCapability != eCSR_BAND_24)
5253 return true;
5254 else
5255 return false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256}
5257
Amar Singhale4f28ee2015-10-21 14:36:56 -07005258static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259{
5260 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005261 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262
5263 wiphy = hdd_ctx->wiphy;
5264
5265 /*
5266 * The channel information in
5267 * wiphy needs to be initialized before wiphy registration
5268 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005269 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5270 if (ret_val) {
5271 hdd_alert("regulatory init failed");
5272 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005273 }
5274
5275#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5276 wiphy->wowlan = &wowlan_support_reg_init;
5277#else
5278 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5279 WIPHY_WOWLAN_MAGIC_PKT |
5280 WIPHY_WOWLAN_DISCONNECT |
5281 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5282 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5283 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5284 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5285 WIPHY_WOWLAN_RFKILL_RELEASE;
5286
5287 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5288 WOW_MAX_FILTERS_PER_LIST);
5289 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5290 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5291#endif
5292
5293 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005294 ret_val = wlan_hdd_cfg80211_register(wiphy);
5295 if (0 > ret_val)
5296 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297
Amar Singhale4f28ee2015-10-21 14:36:56 -07005298 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005299}
5300
Ravi Joshie2331e82015-07-01 18:18:54 -07005301/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005302 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005303 * @hdd_ctx - handle to hdd context
5304 * @tx_packets - transmit packet count
5305 * @rx_packets - receive packet count
5306 *
5307 * The function controls the bus bandwidth and dynamic control of
5308 * tcp delayed ack configuration
5309 *
5310 * Returns: None
5311 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005312#ifdef MSM_PLATFORM
Jeff Johnson590e2012016-10-05 16:16:24 -07005313static void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
5314 const uint64_t tx_packets,
5315 const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005316{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005318 uint64_t temp_rx = 0;
5319 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005320 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005321 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5322 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005323 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005326 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005327 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005328 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005329 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005330 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005331 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005332 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005333
Mohit Khannae71e2262015-11-10 09:37:24 -08005334 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5335 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336
5337 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005338 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5339 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005341 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305342 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305343 if (hdd_ctx->hbw_requested) {
5344 pld_remove_pm_qos(hdd_ctx->parent_dev);
5345 hdd_ctx->hbw_requested = false;
5346 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305347 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005348 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305349 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305350 if (!hdd_ctx->hbw_requested) {
5351 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5352 hdd_ctx->hbw_requested = true;
5353 }
5354
Nirav Shah3bbfa512016-05-12 16:43:49 +05305355 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005356 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305357 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005358 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005360
5361 /* fine-tuning parameters for RX Flows */
5362 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 hdd_ctx->prev_rx = rx_packets;
Ravi Joshifed83572016-10-07 16:20:37 -07005365 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh) {
5366 if ((hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH) &&
5367 (++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
5368 next_rx_level = WLAN_SVC_TP_HIGH;
5369 }
Ravi Joshib89e7f72016-09-07 13:43:15 -07005370 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005371 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005372 hdd_ctx->rx_high_ind_cnt = 0;
5373 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005374
Mohit Khannae71e2262015-11-10 09:37:24 -08005375 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5376 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377
5378 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005379 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 next_rx_level, temp_rx);
5381 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005382 /* Send throughput indication only if it is enabled.
5383 * Disabling tcp_del_ack will revert the tcp stack behavior
5384 * to default delayed ack. Note that this will disable the
5385 * dynamic delayed ack mechanism across the system
5386 */
5387 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305388 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5389 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390 &next_rx_level,
5391 sizeof(next_rx_level));
5392 }
5393
Mohit Khannae71e2262015-11-10 09:37:24 -08005394 /* fine-tuning parameters for TX Flows */
5395 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5396 hdd_ctx->prev_tx = tx_packets;
5397 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5398 next_tx_level = WLAN_SVC_TP_HIGH;
5399 else
5400 next_tx_level = WLAN_SVC_TP_LOW;
5401
5402 if (hdd_ctx->cur_tx_level != next_tx_level) {
5403 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5404 next_tx_level, temp_tx);
5405 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305406 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5407 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005408 &next_tx_level,
5409 sizeof(next_tx_level));
5410 }
5411
5412 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5413 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414 hdd_ctx->hdd_txrx_hist_idx++;
5415 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416}
5417
5418#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305419static void hdd_bus_bw_work_handler(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305421 hdd_context_t *hdd_ctx = container_of(work, hdd_context_t,
5422 bus_bw_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305424 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305425 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5426 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427 uint64_t total_tx = 0, total_rx = 0;
5428 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305429 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305430 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 bool connected = false;
5432 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5433
Prashanth Bhattaab004382016-10-11 16:08:11 -07005434 if (wlan_hdd_validate_context(hdd_ctx))
5435 return;
5436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305438 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 status =
5440 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5441
5442 if (adapterNode->pAdapter == NULL)
5443 continue;
5444 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305445 /*
5446 * Validate magic so we don't end up accessing
5447 * an invalid adapter.
5448 */
5449 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5450 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005451
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005452 if ((adapter->device_mode == QDF_STA_MODE ||
5453 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5455 != eConnectionState_Associated) {
5456
5457 continue;
5458 }
5459
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005460 if ((adapter->device_mode == QDF_SAP_MODE ||
5461 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005462 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5463
5464 continue;
5465 }
5466
5467 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5468 adapter->prev_tx_packets);
5469 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5470 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305471
5472 if (adapter->device_mode == QDF_SAP_MODE ||
5473 adapter->device_mode == QDF_P2P_GO_MODE ||
5474 adapter->device_mode == QDF_IBSS_MODE) {
5475
5476 ret = ol_get_intra_bss_fwd_pkts_count(
5477 adapter->sessionId,
5478 &fwd_tx_packets, &fwd_rx_packets);
5479 if (ret == A_OK) {
5480 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5481 fwd_tx_packets,
5482 adapter->prev_fwd_tx_packets);
5483 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5484 fwd_tx_packets,
5485 adapter->prev_fwd_rx_packets);
5486 }
5487 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005488
5489 total_rx += adapter->stats.rx_packets;
5490 total_tx += adapter->stats.tx_packets;
5491
5492 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5493 adapter->prev_tx_packets = adapter->stats.tx_packets;
5494 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305495 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5496 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5498 connected = true;
5499 }
5500
5501 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5502 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5503 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5504 rx_packets;
5505 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5506 tx_packets;
5507
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305508 /* add intra bss forwarded tx and rx packets */
5509 tx_packets += fwd_tx_packets_diff;
5510 rx_packets += fwd_rx_packets_diff;
5511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005512 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5513 tx_packets += (uint64_t)ipa_tx_packets;
5514 rx_packets += (uint64_t)ipa_rx_packets;
5515
5516 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005517 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005518 return;
5519 }
5520
Yuanyuan Liu13738502016-04-06 17:41:37 -07005521 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522
5523 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5524 hdd_ipa_uc_stat_request(adapter, 2);
5525
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305526 qdf_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005527 hdd_ctx->config->busBandwidthComputeInterval);
5528}
Prashanth Bhattaab004382016-10-11 16:08:11 -07005529
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305530/**
5531 * __hdd_bus_bw_cbk() - Bus bandwidth data structure callback.
5532 * @arg: Argument of timer function
5533 *
5534 * Schedule a workqueue in this function where all the processing is done.
5535 *
5536 * Return: None.
5537 */
5538static void __hdd_bus_bw_cbk(void *arg)
5539{
5540 hdd_context_t *hdd_ctx = (hdd_context_t *) arg;
5541
5542 if (wlan_hdd_validate_context(hdd_ctx))
5543 return;
5544
5545 schedule_work(&hdd_ctx->bus_bw_work);
5546}
5547
5548/**
5549 * hdd_bus_bw_cbk() - Wrapper for bus bw callback for SSR protection.
5550 * @arg: Argument of timer function
5551 *
5552 * Return: None.
5553 */
5554static void hdd_bus_bw_cbk(void *arg)
5555{
5556 cds_ssr_protect(__func__);
5557 __hdd_bus_bw_cbk(arg);
5558 cds_ssr_unprotect(__func__);
5559}
5560
Prashanth Bhattaab004382016-10-11 16:08:11 -07005561int hdd_bus_bandwidth_init(hdd_context_t *hdd_ctx)
5562{
5563 spin_lock_init(&hdd_ctx->bus_bw_lock);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305564 INIT_WORK(&hdd_ctx->bus_bw_work,
5565 hdd_bus_bw_work_handler);
5566 qdf_timer_init(NULL,
5567 &hdd_ctx->bus_bw_timer,
5568 hdd_bus_bw_cbk, (void *)hdd_ctx,
5569 QDF_TIMER_TYPE_SW);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005570
5571 return 0;
5572}
5573
5574void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx)
5575{
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305576 if (hdd_ctx->bus_bw_timer_started)
Prashanth Bhattaab004382016-10-11 16:08:11 -07005577 hdd_reset_tcp_delack(hdd_ctx);
5578
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05305579 hdd_info("wait for bus bw work to flush");
5580 cancel_work_sync(&hdd_ctx->bus_bw_work);
5581 qdf_timer_free(&hdd_ctx->bus_bw_timer);
Prashanth Bhattaab004382016-10-11 16:08:11 -07005582}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005583#endif
5584
5585/**
Nirav Shahed34b212016-04-25 10:59:16 +05305586 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5587 * @hdd_ctx: hdd context
5588 *
5589 * Return: 0 for success or error code
5590 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005591static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305592{
5593 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5594 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5595 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005596 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305597 return -ENOMEM;
5598 }
5599 return 0;
5600}
5601
5602/**
5603 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5604 * @hdd_ctx: hdd context
5605 *
5606 * Return: none
5607 */
5608void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5609{
5610 if (hdd_ctx->hdd_txrx_hist) {
5611 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5612 hdd_ctx->hdd_txrx_hist = NULL;
5613 }
5614}
5615
Nirav Shahda008342016-05-17 18:50:40 +05305616static uint8_t *convert_level_to_string(uint32_t level)
5617{
5618 switch (level) {
5619 /* initialize the wlan sub system */
5620 case WLAN_SVC_TP_NONE:
5621 return "NONE";
5622 case WLAN_SVC_TP_LOW:
5623 return "LOW";
5624 case WLAN_SVC_TP_MEDIUM:
5625 return "MED";
5626 case WLAN_SVC_TP_HIGH:
5627 return "HIGH";
5628 default:
5629 return "INVAL";
5630 }
5631}
5632
Nirav Shahed34b212016-04-25 10:59:16 +05305633
5634/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5636 * @hdd_ctx: hdd context
5637 *
5638 * Return: none
5639 */
5640void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5641{
5642 int i;
5643
5644#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005645 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305646 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005647 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005648 hdd_ctx->config->busBandwidthHighThreshold,
5649 hdd_ctx->config->busBandwidthMediumThreshold,
5650 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005651 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305652 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005653 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654 hdd_ctx->config->tcpDelackThresholdHigh,
5655 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005656 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305657 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005658#endif
5659
Jeff Johnson760350b2016-08-15 14:01:52 -07005660 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305661 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5662
Jeff Johnson760350b2016-08-15 14:01:52 -07005663 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 -08005664
5665 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005666 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5668 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5669 hdd_ctx->hdd_txrx_hist[i].total_tx,
5670 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305671 convert_level_to_string(
5672 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5673 convert_level_to_string(
5674 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5675 convert_level_to_string(
5676 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005677 }
5678 return;
5679}
5680
5681/**
5682 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5683 * @hdd_ctx: hdd context
5684 *
5685 * Return: none
5686 */
5687void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5688{
5689 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305690 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5691 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692}
5693
5694/**
5695 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5696 * @pHddCtx: hdd context
5697 *
5698 * Return: none
5699 */
5700void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5701{
5702
5703 hdd_adapter_t *adapter = NULL;
5704 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305705 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005706 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305707 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005708
5709 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305710 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005711 adapter = adapter_node->pAdapter;
5712
Jeff Johnson760350b2016-08-15 14:01:52 -07005713 hdd_err("\nNetif queue operation statistics:");
5714 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305715 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005716 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305717 curr_time = qdf_system_ticks();
5718 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305719 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305720 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305721 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305722 unpause = adapter->total_unpause_time;
5723 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305724 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305725 pause = adapter->total_pause_time;
5726 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005727 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305728 qdf_system_ticks_to_msecs(total),
5729 qdf_system_ticks_to_msecs(pause),
5730 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005731 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005732
Nirav Shahda008342016-05-17 18:50:40 +05305733 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5734 qdf_time_t pause_delta = 0;
5735
5736 if (adapter->pause_map & (1 << i))
5737 pause_delta = delta;
5738
Jeff Johnson760350b2016-08-15 14:01:52 -07005739 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005740 hdd_reason_type_to_string(i),
5741 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305742 adapter->queue_oper_stats[i].unpause_count,
5743 qdf_system_ticks_to_msecs(
5744 adapter->queue_oper_stats[i].total_pause_time +
5745 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005746 }
5747
Jeff Johnson760350b2016-08-15 14:01:52 -07005748 hdd_err("\nNetif queue operation history:");
5749 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305750 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5751
Jeff Johnson760350b2016-08-15 14:01:52 -07005752 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753
5754 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005755 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305756 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757 adapter->queue_oper_history[i].time),
5758 hdd_action_type_to_string(
5759 adapter->queue_oper_history[i].netif_action),
5760 hdd_reason_type_to_string(
5761 adapter->queue_oper_history[i].netif_reason),
5762 adapter->queue_oper_history[i].pause_map);
5763 }
5764
5765 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5766 adapter_node = next;
5767 }
5768
5769
5770}
5771
5772/**
5773 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5774 * @hdd_ctx: hdd context
5775 *
5776 * Return: none
5777 */
5778void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5779{
5780 hdd_adapter_t *adapter = NULL;
5781 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305782 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005783
5784 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305785 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005786 adapter = adapter_node->pAdapter;
5787
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305788 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005789 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305790 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305792 adapter->history_index = 0;
5793 adapter->start_time = adapter->last_time = qdf_system_ticks();
5794 adapter->total_pause_time = 0;
5795 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5797 adapter_node = next;
5798 }
5799}
5800
5801/**
5802 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5803 * @halHandle: Hal handle
5804 * @pContext: Pointer to the context
5805 * @sessionId: Session ID
5806 * @scanId: Scan ID
5807 * @status: Status
5808 *
5809 * This is the callback to be executed when 11d scan is completed to flush out
5810 * the scan results
5811 *
5812 * 11d scan is done during driver load and is a passive scan on all
5813 * channels supported by the device, 11d scans may find some APs on
5814 * frequencies which are forbidden to be used in the regulatory domain
5815 * the device is operating in. If these APs are notified to the supplicant
5816 * it may try to connect to these APs, thus flush out all the scan results
5817 * which are present in SME after 11d scan is done.
5818 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305819 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305821static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 uint8_t sessionId, uint32_t scanId,
5823 eCsrScanStatus status)
5824{
5825 ENTER();
5826
5827 sme_scan_flush_result(halHandle);
5828
5829 EXIT();
5830
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305831 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832}
5833
5834#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5835/**
5836 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5837 * @hdd_ctx: hdd global context
5838 *
5839 * Return: none
5840 */
5841static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5842{
5843 uint8_t i;
5844
5845 mutex_init(&hdd_ctx->op_ctx.op_lock);
5846 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5847 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5848 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5849 }
5850}
5851#else
5852static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5853{
5854}
5855#endif
5856
Yingying Tang95409972016-10-20 15:16:15 +08005857#ifdef WLAN_FEATURE_WOW_PULSE
5858/**
5859 * wlan_hdd_set_wow_pulse() - call SME to send wmi cmd of wow pulse
5860 * @phddctx: hdd_context_t structure pointer
5861 * @enable: enable or disable this behaviour
5862 *
5863 * Return: int
5864 */
5865static int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
5866{
5867 struct hdd_config *pcfg_ini = phddctx->config;
5868 struct wow_pulse_mode wow_pulse_set_info;
5869 QDF_STATUS status;
5870
5871 hdd_notice("wow pulse enable flag is %d", enable);
5872
5873 if (false == phddctx->config->wow_pulse_support)
5874 return 0;
5875
5876 /* prepare the request to send to SME */
5877 if (enable == true) {
5878 wow_pulse_set_info.wow_pulse_enable = true;
5879 wow_pulse_set_info.wow_pulse_pin =
5880 pcfg_ini->wow_pulse_pin;
5881 wow_pulse_set_info.wow_pulse_interval_low =
5882 pcfg_ini->wow_pulse_interval_low;
5883 wow_pulse_set_info.wow_pulse_interval_high =
5884 pcfg_ini->wow_pulse_interval_high;
5885 } else {
5886 wow_pulse_set_info.wow_pulse_enable = false;
5887 wow_pulse_set_info.wow_pulse_pin = 0;
5888 wow_pulse_set_info.wow_pulse_interval_low = 0;
5889 wow_pulse_set_info.wow_pulse_interval_high = 0;
5890 }
5891 hdd_notice("enable %d pin %d low %d high %d",
5892 wow_pulse_set_info.wow_pulse_enable,
5893 wow_pulse_set_info.wow_pulse_pin,
5894 wow_pulse_set_info.wow_pulse_interval_low,
5895 wow_pulse_set_info.wow_pulse_interval_high);
5896
5897 status = sme_set_wow_pulse(&wow_pulse_set_info);
5898 if (QDF_STATUS_E_FAILURE == status) {
5899 hdd_notice("sme_set_wow_pulse failure!");
5900 return -EIO;
5901 }
5902 hdd_notice("sme_set_wow_pulse success!");
5903 return 0;
5904}
5905#else
5906static inline int wlan_hdd_set_wow_pulse(hdd_context_t *phddctx, bool enable)
5907{
5908 return 0;
5909}
5910#endif
5911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005912#ifdef WLAN_FEATURE_FASTPATH
5913/**
5914 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5915 * @hdd_cfg: hdd config
5916 * @context: lower layer context
5917 *
5918 * Return: none
5919 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305920void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921 void *context)
5922{
5923 if (hdd_cfg->fastpath_enable)
5924 hif_enable_fastpath(context);
5925}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926#endif
5927
Yuanyuan Liu13738502016-04-06 17:41:37 -07005928#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929/**
5930 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005931 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005932 * @level: thermal level
5933 *
5934 * Change IPA data path to SW path when the thermal throttle level greater
5935 * than 0, and restore the original data path when throttle level is 0
5936 *
5937 * Return: none
5938 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005939static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005941 hdd_context_t *hdd_ctx = context;
5942
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943 /* Change IPA to SW path when throttle level greater than 0 */
5944 if (level > THROTTLE_LEVEL_0)
5945 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5946 else
5947 /* restore original concurrency mode */
5948 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5949}
5950
5951/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305952 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5953 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305954 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005955 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305956 * Get a safe channel to restart SAP. PCL already takes into account the
5957 * unsafe channels. So, the PCL is validated with the ACS range to provide
5958 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005959 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305960 * Return: Channel number to restart SAP in case of success. In case of any
5961 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305963static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5964 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005965{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305966 struct sir_pcl_list pcl;
5967 QDF_STATUS status;
5968 uint32_t i, j;
5969 tHalHandle *hal_handle;
5970 hdd_context_t *hdd_ctx;
5971 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305973 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5974 if (!hdd_ctx) {
5975 hdd_err("invalid HDD context");
5976 return INVALID_CHANNEL_ID;
5977 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305979 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5980 if (!hal_handle) {
5981 hdd_err("invalid HAL handle");
5982 return INVALID_CHANNEL_ID;
5983 }
5984
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305985 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5986 pcl.pcl_list, &pcl.pcl_len,
5987 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5988 if (QDF_IS_STATUS_ERROR(status)) {
5989 hdd_err("Get PCL failed");
5990 return INVALID_CHANNEL_ID;
5991 }
5992
5993 if (!pcl.pcl_len) {
5994 hdd_alert("pcl length is zero. this is not expected");
5995 return INVALID_CHANNEL_ID;
5996 }
5997
5998 hdd_info("start:%d end:%d",
5999 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
6000 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
6001
6002 /* PCL already takes unsafe channel into account */
6003 for (i = 0; i < pcl.pcl_len; i++) {
6004 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6005 if ((pcl.pcl_list[i] >=
6006 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6007 (pcl.pcl_list[i] <=
6008 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6009 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
6010 return pcl.pcl_list[i];
6011 }
6012 }
6013
6014 hdd_info("no safe channel from PCL found in ACS range");
6015
6016 /* Try for safe channel from all valid channel */
6017 pcl.pcl_len = MAX_NUM_CHAN;
6018 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
6019 &pcl.pcl_len);
6020 if (QDF_IS_STATUS_ERROR(status)) {
6021 hdd_err("error in getting valid channel list");
6022 return INVALID_CHANNEL_ID;
6023 }
6024
6025 for (i = 0; i < pcl.pcl_len; i++) {
6026 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
6027 found = false;
6028 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006029 if (pcl.pcl_list[i] ==
6030 hdd_ctx->unsafe_channel_list[j]) {
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306031 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
6032 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006033 break;
6034 }
6035 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306036
6037 if (found)
6038 continue;
6039
6040 if ((pcl.pcl_list[i] >=
6041 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
6042 (pcl.pcl_list[i] <=
6043 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
6044 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
6045 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 }
6047 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306048
6049 return INVALID_CHANNEL_ID;
6050}
6051
6052/**
6053 * hdd_restart_sap() - Restarts SAP on the given channel
6054 * @adapter: AP adapter
6055 * @channel: Channel
6056 *
6057 * Restarts the SAP interface by invoking the function which executes the
6058 * callback to perform channel switch using (E)CSA.
6059 *
6060 * Return: None
6061 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006062static void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306063{
6064 hdd_ap_ctx_t *hdd_ap_ctx;
6065 tHalHandle *hal_handle;
6066
6067 if (!adapter) {
6068 hdd_err("invalid adapter");
6069 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006070 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306071
6072 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
6073
6074 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
6075 if (!hal_handle) {
6076 hdd_err("invalid HAL handle");
6077 return;
6078 }
6079
6080 hdd_ap_ctx->sapConfig.channel = channel;
6081 hdd_ap_ctx->sapConfig.ch_params.ch_width =
6082 hdd_ap_ctx->sapConfig.ch_width_orig;
6083
6084 hdd_info("chan:%d width:%d",
6085 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
6086
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006087 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306088 hdd_ap_ctx->sapConfig.sec_ch,
6089 &hdd_ap_ctx->sapConfig.ch_params);
6090
6091 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006092}
Agrawal Ashish467dde42016-09-08 18:44:22 +05306093/**
6094 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
6095 * @hdd_ctx: hdd context pointer
6096 *
6097 * hdd_unsafe_channel_restart_sap check all unsafe channel list
6098 * and if ACS is enabled, driver will ask userspace to restart the
6099 * sap. User space on LTE coex indication restart driver.
6100 *
6101 * Return - none
6102 */
6103void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
6104{
6105 QDF_STATUS status;
6106 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
6107 hdd_adapter_t *adapter_temp;
6108 uint32_t i;
6109 bool found = false;
6110 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006111
Agrawal Ashish467dde42016-09-08 18:44:22 +05306112 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
6113 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
6114 adapter_temp = adapter_node->pAdapter;
6115
6116 if (!adapter_temp) {
6117 hdd_err("adapter is NULL, moving to next one");
6118 goto next_adapater;
6119 }
6120
6121 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
6122 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
6123 hdd_info("skip device mode:%d acs:%d",
6124 adapter_temp->device_mode,
6125 adapter_temp->sessionCtx.ap.sapConfig.
6126 acs_cfg.acs_mode);
6127 goto next_adapater;
6128 }
6129
6130 found = false;
6131 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
Krunal Soni15f0db12016-10-11 18:53:37 -07006132 if (adapter_temp->sessionCtx.ap.operatingChannel ==
Agrawal Ashish467dde42016-09-08 18:44:22 +05306133 hdd_ctxt->unsafe_channel_list[i]) {
6134 found = true;
6135 hdd_info("operating ch:%d is unsafe",
6136 adapter_temp->sessionCtx.ap.operatingChannel);
6137 break;
6138 }
6139 }
6140
6141 if (!found) {
6142 hdd_info("ch:%d is safe. no need to change channel",
6143 adapter_temp->sessionCtx.ap.operatingChannel);
6144 goto next_adapater;
6145 }
6146
6147 restart_chan =
6148 hdd_get_safe_channel_from_pcl_and_acs_range(
6149 adapter_temp);
6150 if (!restart_chan) {
6151 hdd_alert("fail to restart SAP");
6152 } else {
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006153 /*
6154 * SAP restart due to unsafe channel. While
6155 * restarting the SAP, make sure to clear
6156 * acs_channel, channel to reset to
6157 * 0. Otherwise these settings will override
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306158 * the ACS while restart.
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08006159 */
Kondabattini, Ganesh2836c5a2016-09-20 17:10:19 +05306160 hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
6161 adapter_temp->sessionCtx.ap.sapConfig.channel =
6162 AUTO_CHANNEL_SELECT;
Agrawal Ashish467dde42016-09-08 18:44:22 +05306163 hdd_info("sending coex indication");
6164 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
6165 WLAN_SVC_LTE_COEX_IND, NULL, 0);
6166 hdd_restart_sap(adapter_temp, restart_chan);
6167 }
6168
6169next_adapater:
6170 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
6171 adapter_node = next;
6172 }
6173}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174/**
6175 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
6176 * @adapter: HDD adapter pointer
6177 * @indParam: Channel avoid notification parameter
6178 *
6179 * Avoid channel notification from FW handler.
6180 * FW will send un-safe channel list to avoid over wrapping.
6181 * hostapd should not use notified channel
6182 *
6183 * Return: None
6184 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05306185void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006186{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006187 hdd_context_t *hdd_ctxt;
6188 tSirChAvoidIndType *ch_avoid_indi;
6189 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08006190 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
6191 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006192 uint16_t start_channel;
6193 uint16_t end_channel;
6194 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006195 tHddAvoidFreqList hdd_avoid_freq_list;
6196 uint32_t i;
6197
6198 /* Basic sanity */
6199 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006200 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006201 return;
6202 }
6203
6204 hdd_ctxt = (hdd_context_t *) hdd_context;
6205 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
6206 cds_context = hdd_ctxt->pcds_context;
6207
6208 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07006209 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006210 ch_avoid_indi->avoid_range_count);
6211
6212 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306213 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006214 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
6215 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
6216 ch_avoid_indi->avoid_freq_range[i].start_freq;
6217 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
6218 ch_avoid_indi->avoid_freq_range[i].end_freq;
6219 }
6220 hdd_avoid_freq_list.avoidFreqRangeCount =
6221 ch_avoid_indi->avoid_range_count;
6222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006223 /* clear existing unsafe channel cache */
6224 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306225 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006226 sizeof(hdd_ctxt->unsafe_channel_list));
6227
6228 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
6229 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08006230 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006231 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006232 break;
6233 }
6234
6235 start_channel = ieee80211_frequency_to_channel(
6236 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
6237 end_channel = ieee80211_frequency_to_channel(
6238 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006239 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006240 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
6241 start_channel,
6242 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
6243 end_channel);
6244
6245 /* do not process frequency bands that are not mapped to
6246 * predefined channels
6247 */
6248 if (start_channel == 0 || end_channel == 0)
6249 continue;
6250
Amar Singhalb8d4f152016-02-10 10:21:43 -08006251 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6252 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006253 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254 ch_avoid_indi->avoid_freq_range[
6255 range_loop].start_freq) {
6256 start_channel_idx = channel_loop;
6257 break;
6258 }
6259 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08006260 for (channel_loop = CHAN_ENUM_1; channel_loop <=
6261 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006262 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006263 ch_avoid_indi->avoid_freq_range[
6264 range_loop].end_freq) {
6265 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07006266 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267 ch_avoid_indi->avoid_freq_range[
6268 range_loop].end_freq)
6269 end_channel_idx--;
6270 break;
6271 }
6272 }
6273
Amar Singhalb8d4f152016-02-10 10:21:43 -08006274 if (start_channel_idx == INVALID_CHANNEL ||
6275 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006276 continue;
6277
6278 for (channel_loop = start_channel_idx; channel_loop <=
6279 end_channel_idx; channel_loop++) {
6280 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07006281 hdd_ctxt->unsafe_channel_count++] =
Krunal Soni15f0db12016-10-11 18:53:37 -07006282 CDS_CHANNEL_NUM(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006283 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08006284 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006285 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006286 break;
6287 }
6288 }
6289 }
6290
Jeff Johnson34c88b72016-08-15 14:27:11 -07006291 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006292 hdd_ctxt->unsafe_channel_count);
6293
Yuanyuan Liu13738502016-04-06 17:41:37 -07006294 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
6295 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006296 hdd_ctxt->unsafe_channel_count)) {
6297 hdd_err("Failed to set unsafe channel");
6298
6299 /* clear existing unsafe channel cache */
6300 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306301 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006302 sizeof(hdd_ctxt->unsafe_channel_list));
6303
6304 return;
6305 }
6306
6307 for (channel_loop = 0;
6308 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006309 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006310 hdd_ctxt->unsafe_channel_list[channel_loop]);
6311 }
6312
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05306313 /*
6314 * first update the unsafe channel list to the platform driver and
6315 * send the avoid freq event to the application
6316 */
6317 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
6318
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05306319 if (!hdd_ctxt->unsafe_channel_count) {
6320 hdd_info("no unsafe channels - not restarting SAP");
6321 return;
6322 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05306323 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006324 return;
6325}
6326
6327/**
6328 * hdd_init_channel_avoidance() - Initialize channel avoidance
6329 * @hdd_ctx: HDD global context
6330 *
6331 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07006332 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006333 * down to the lower layers. Then subscribe to subsequent channel
6334 * avoidance events.
6335 *
6336 * Return: None
6337 */
6338static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6339{
6340 uint16_t unsafe_channel_count;
6341 int index;
6342
Yuanyuan Liu13738502016-04-06 17:41:37 -07006343 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
6344 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006345 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08006346 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347
Jeff Johnson34c88b72016-08-15 14:27:11 -07006348 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006349 hdd_ctx->unsafe_channel_count);
6350
Anurag Chouhan6d760662016-02-20 16:05:43 +05306351 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08006352 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006353
6354 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07006355 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006356 hdd_ctx->unsafe_channel_list[index]);
6357
6358 }
6359
6360 /* Plug in avoid channel notification callback */
6361 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
6362}
6363#else
6364static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
6365{
6366}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006367static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006368{
6369}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006370#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006371
6372/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006373 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6374 * user space
6375 * @frame_ind: Management frame data to be informed.
6376 *
6377 * This function is used to indicate management frame to
6378 * user space
6379 *
6380 * Return: None
6381 *
6382 */
6383void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6384{
6385 hdd_context_t *hdd_ctx = NULL;
6386 hdd_adapter_t *adapter = NULL;
6387 void *cds_context = NULL;
6388 int i;
6389
6390 /* Get the global VOSS context.*/
6391 cds_context = cds_get_global_context();
6392 if (!cds_context) {
6393 hdd_err("Global CDS context is Null");
6394 return;
6395 }
6396 /* Get the HDD context.*/
6397 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6398
6399 if (0 != wlan_hdd_validate_context(hdd_ctx))
6400 return;
6401
6402 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6403 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6404 adapter =
6405 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6406 if (adapter)
6407 break;
6408 }
6409 } else {
6410 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6411 frame_ind->sessionId);
6412 }
6413
6414 if ((NULL != adapter) &&
6415 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6416 __hdd_indicate_mgmt_frame(adapter,
6417 frame_ind->frame_len,
6418 frame_ind->frameBuf,
6419 frame_ind->frameType,
6420 frame_ind->rxChan,
6421 frame_ind->rxRssi);
6422 return;
6423}
6424
6425/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006426 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6427 * @hdd_ctx: HDD context
6428 *
6429 * Disables all the dual mac features like DBS, Agile DFS etc.
6430 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306431 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006432 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306433static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006434{
6435 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306436 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006437
6438 if (!hdd_ctx) {
6439 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306440 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006441 }
6442
6443 cfg.scan_config = 0;
6444 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306445 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006446
6447 hdd_debug("Disabling all dual mac features...");
6448
6449 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306450 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006451 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6452 return status;
6453 }
6454
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306455 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006456}
6457
6458/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006459 * hdd_override_ini_config - Override INI config
6460 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006461 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006462 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006463 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006464 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006465 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006466static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006467{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006468
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006469 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6470 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6471 hdd_notice("Module enable_dfs_chan_scan set to %d",
6472 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006473 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006474 if (0 == enable_11d || 1 == enable_11d) {
6475 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6476 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006477 }
Leo Chang11545d62016-10-17 14:53:50 -07006478
6479 if (!hdd_ipa_is_present(hdd_ctx))
6480 hdd_ctx->config->IpaConfig = 0;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006481}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006483/**
6484 * hdd_set_trace_level_for_each - Set trace level for each INI config
6485 * @hdd_ctx - HDD context
6486 *
6487 * Set trace level for each module based on INI config.
6488 *
6489 * Return: None
6490 */
6491static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6492{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306493 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6494 hdd_ctx->config->qdf_trace_enable_wdi);
6495 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6496 hdd_ctx->config->qdf_trace_enable_hdd);
6497 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6498 hdd_ctx->config->qdf_trace_enable_sme);
6499 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6500 hdd_ctx->config->qdf_trace_enable_pe);
6501 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6502 hdd_ctx->config->qdf_trace_enable_wma);
6503 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6504 hdd_ctx->config->qdf_trace_enable_sys);
6505 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6506 hdd_ctx->config->qdf_trace_enable_qdf);
6507 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6508 hdd_ctx->config->qdf_trace_enable_sap);
6509 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6510 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6511 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6512 hdd_ctx->config->qdf_trace_enable_bmi);
6513 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6514 hdd_ctx->config->qdf_trace_enable_cfg);
6515 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6516 hdd_ctx->config->qdf_trace_enable_epping);
6517 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6518 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6519 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306520 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306521 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6522 hdd_ctx->config->qdf_trace_enable_htc);
6523 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6524 hdd_ctx->config->qdf_trace_enable_hif);
6525 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6526 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6527 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6528 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006530 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006531}
6532
6533/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006534 * hdd_context_init() - Initialize HDD context
6535 * @hdd_ctx: HDD context.
6536 *
6537 * Initialize HDD context along with all the feature specific contexts.
6538 *
6539 * return: 0 on success and errno on failure.
6540 */
6541static int hdd_context_init(hdd_context_t *hdd_ctx)
6542{
6543 int ret;
6544
6545 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6546 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6547
6548 hdd_init_ll_stats_ctx();
6549
6550 init_completion(&hdd_ctx->mc_sus_event_var);
6551 init_completion(&hdd_ctx->ready_to_suspend);
6552
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306553 hdd_init_bpf_completion();
6554
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006555 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306556 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006557 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306558
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006559 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6560
6561 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6562
6563 ret = hdd_scan_context_init(hdd_ctx);
6564 if (ret)
6565 goto list_destroy;
6566
6567 hdd_tdls_context_init(hdd_ctx);
6568
6569 hdd_rx_wake_lock_create(hdd_ctx);
6570
6571 ret = hdd_sap_context_init(hdd_ctx);
6572 if (ret)
6573 goto scan_destroy;
6574
6575 ret = hdd_roc_context_init(hdd_ctx);
6576 if (ret)
6577 goto sap_destroy;
6578
6579 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6580
6581 hdd_init_offloaded_packets_ctx(hdd_ctx);
6582
6583 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6584 hdd_ctx->config);
6585 if (ret)
6586 goto roc_destroy;
6587
6588 return 0;
6589
6590roc_destroy:
6591 hdd_roc_context_destroy(hdd_ctx);
6592
6593sap_destroy:
6594 hdd_sap_context_destroy(hdd_ctx);
6595
6596scan_destroy:
6597 hdd_scan_context_destroy(hdd_ctx);
6598 hdd_rx_wake_lock_destroy(hdd_ctx);
6599 hdd_tdls_context_destroy(hdd_ctx);
6600
6601list_destroy:
6602 qdf_list_destroy(&hdd_ctx->hddAdapters);
6603 return ret;
6604}
6605
6606/**
6607 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306608 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006609 *
6610 * Allocate and initialize HDD context. HDD context is allocated as part of
6611 * wiphy allocation and then context is initialized.
6612 *
6613 * Return: HDD context on success and ERR_PTR on failure
6614 */
Jeff Johnson590e2012016-10-05 16:16:24 -07006615static hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006616{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306617 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006618 int ret = 0;
6619 hdd_context_t *hdd_ctx;
6620 v_CONTEXT_t p_cds_context;
6621
6622 ENTER();
6623
6624 p_cds_context = cds_get_global_context();
6625 if (p_cds_context == NULL) {
6626 hdd_alert("Failed to get CDS global context");
6627 ret = -EINVAL;
6628 goto err_out;
6629 }
6630
6631 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6632
6633 if (hdd_ctx == NULL) {
6634 ret = -ENOMEM;
6635 goto err_out;
6636 }
6637
6638 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006639 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006640
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306641 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006642 if (hdd_ctx->config == NULL) {
6643 hdd_alert("Failed to alloc memory for HDD config!");
6644 ret = -ENOMEM;
6645 goto err_free_hdd_context;
6646 }
6647
6648 /* Read and parse the qcom_cfg.ini file */
6649 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306650 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306651 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006652 WLAN_INI_FILE);
6653 ret = -EINVAL;
6654 goto err_free_config;
6655 }
6656
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006657 hdd_ctx->configuredMcastBcastFilter =
6658 hdd_ctx->config->mcastBcastFilterSetting;
6659
6660 hdd_notice("Setting configuredMcastBcastFilter: %d",
6661 hdd_ctx->config->mcastBcastFilterSetting);
6662
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306663 if (hdd_ctx->config->fhostNSOffload)
6664 hdd_ctx->ns_offload_enable = true;
6665
Abhishek Singh5ea86532016-04-27 14:10:53 +05306666 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6667
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006668 hdd_override_ini_config(hdd_ctx);
6669
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006670 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006671
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006672 ret = hdd_context_init(hdd_ctx);
6673
6674 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006675 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006676
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006677
Yuanyuan Liu13738502016-04-06 17:41:37 -07006678 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6679 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006680
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006681
6682 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306683 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006684
Anurag Chouhan6d760662016-02-20 16:05:43 +05306685 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006686 goto skip_multicast_logging;
6687
6688 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6689
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006690 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6691 if (ret)
6692 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05306693
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006694 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6695 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306696 goto err_free_histogram;
6697
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006698
6699 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306700 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006701 * levels of the code need not be set when the logger thread
6702 * is not enabled.
6703 */
6704 if (cds_is_multicast_logging())
6705 wlan_logging_set_log_level();
6706
6707skip_multicast_logging:
6708 hdd_set_trace_level_for_each(hdd_ctx);
6709
6710 return hdd_ctx;
6711
Nirav Shahed34b212016-04-25 10:59:16 +05306712err_free_histogram:
6713 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6714
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006715err_deinit_hdd_context:
6716 hdd_context_deinit(hdd_ctx);
6717
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006718err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306719 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006720
6721err_free_hdd_context:
6722 wiphy_free(hdd_ctx->wiphy);
6723
6724err_out:
6725 return ERR_PTR(ret);
6726}
6727
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006728#ifdef WLAN_OPEN_P2P_INTERFACE
6729/**
6730 * hdd_open_p2p_interface - Open P2P interface
6731 * @hdd_ctx: HDD context
6732 * @rtnl_held: True if RTNL lock held
6733 *
6734 * Open P2P interface during probe. This function called to open the P2P
6735 * interface at probe along with STA interface.
6736 *
6737 * Return: 0 on success and errno on failure
6738 */
6739static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6740{
6741 hdd_adapter_t *adapter;
6742 uint8_t *p2p_dev_addr;
6743
6744 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6745 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306746 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006747 hdd_ctx->config->intfMacAddr[0].bytes,
6748 sizeof(tSirMacAddr));
6749
6750 /*
6751 * Generate the P2P Device Address. This consists of
6752 * the device's primary MAC address with the locally
6753 * administered bit set.
6754 */
6755 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6756 } else {
6757 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6758 if (p2p_dev_addr == NULL) {
6759 hdd_alert("Failed to allocate mac_address for p2p_device");
6760 return -ENOSPC;
6761 }
6762
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306763 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306764 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006765 }
6766
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006767 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006768 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006769 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006770
6771 if (NULL == adapter) {
6772 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6773 return -ENOSPC;
6774 }
6775
6776 return 0;
6777}
6778#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306779static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006780 bool rtnl_held)
6781{
6782 return 0;
6783}
6784#endif
6785
6786/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306787 * hdd_start_station_adapter()- Start the Station Adapter
6788 * @adapter: HDD adapter
6789 *
6790 * This function initializes the adapter for the station mode.
6791 *
6792 * Return: 0 on success or errno on failure.
6793 */
6794int hdd_start_station_adapter(hdd_adapter_t *adapter)
6795{
6796 QDF_STATUS status;
6797
6798 ENTER_DEV(adapter->dev);
6799
6800 status = hdd_init_station_mode(adapter);
6801
6802 if (QDF_STATUS_SUCCESS != status) {
6803 hdd_err("Error Initializing station mode: %d", status);
6804 return qdf_status_to_os_return(status);
6805 }
6806
Arun Khandavallifae92942016-08-01 13:31:08 +05306807 hdd_register_tx_flow_control(adapter,
6808 hdd_tx_resume_timer_expired_handler,
6809 hdd_tx_resume_cb);
6810
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306811 EXIT();
6812 return 0;
6813}
6814
6815/**
6816 * hdd_start_ap_adapter()- Start AP Adapter
6817 * @adapter: HDD adapter
6818 *
6819 * This function initializes the adapter for the AP mode.
6820 *
6821 * Return: 0 on success errno on failure.
6822 */
6823int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6824{
6825 QDF_STATUS status;
6826
6827 ENTER();
6828
6829 status = hdd_init_ap_mode(adapter);
6830
6831 if (QDF_STATUS_SUCCESS != status) {
6832 hdd_err("Error Initializing the AP mode: %d", status);
6833 return qdf_status_to_os_return(status);
6834 }
6835
Arun Khandavallifae92942016-08-01 13:31:08 +05306836 hdd_register_tx_flow_control(adapter,
6837 hdd_softap_tx_resume_timer_expired_handler,
6838 hdd_softap_tx_resume_cb);
6839
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306840 EXIT();
6841 return 0;
6842}
6843
6844/**
6845 * hdd_start_ftm_adapter()- Start FTM adapter
6846 * @adapter: HDD adapter
6847 *
6848 * This function initializes the adapter for the FTM mode.
6849 *
6850 * Return: 0 on success or errno on failure.
6851 */
6852int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6853{
6854 QDF_STATUS qdf_status;
6855
6856 ENTER_DEV(adapter->dev);
6857
6858 qdf_status = hdd_init_tx_rx(adapter);
6859
6860 if (QDF_STATUS_SUCCESS != qdf_status) {
6861 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6862 return qdf_status_to_os_return(qdf_status);
6863 }
6864
6865 return 0;
6866 EXIT();
6867}
6868
6869/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006870 * hdd_open_interfaces - Open all required interfaces
6871 * hdd_ctx: HDD context
6872 * rtnl_held: True if RTNL lock is held
6873 *
6874 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6875 *
6876 * Return: Primary adapter on success and PTR_ERR on failure
6877 */
6878static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6879 bool rtnl_held)
6880{
6881 hdd_adapter_t *adapter = NULL;
6882 hdd_adapter_t *adapter_11p = NULL;
6883 int ret;
6884
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006885 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306886 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006887 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006888 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006889 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006890
6891 if (adapter == NULL)
6892 return ERR_PTR(-ENOSPC);
6893
6894 return adapter;
6895 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006896 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006897 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006898 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006899
6900 if (adapter == NULL)
6901 return ERR_PTR(-ENOSPC);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08006902 /* fast roaming is allowed only on first STA, i.e. wlan adapter */
6903 adapter->fast_roaming_allowed = true;
6904
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006905 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6906 if (ret)
6907 goto err_close_adapter;
6908
6909 /* Open 802.11p Interface */
6910 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006911 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006912 "wlanocb%d",
6913 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006914 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006915 if (adapter_11p == NULL) {
6916 hdd_err("Failed to open 802.11p interface");
6917 goto err_close_adapter;
6918 }
6919 }
6920
6921 return adapter;
6922
6923err_close_adapter:
6924 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6925 return ERR_PTR(ret);
6926}
6927
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006928/**
6929 * hdd_update_country_code - Update country code
6930 * @hdd_ctx: HDD context
6931 * @adapter: Primary adapter context
6932 *
6933 * Update country code based on module parameter country_code at SME and wait
6934 * for the settings to take effect.
6935 *
6936 * Return: 0 on success and errno on failure
6937 */
6938static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6939 hdd_adapter_t *adapter)
6940{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306941 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006942 int ret = 0;
6943 unsigned long rc;
6944
6945 if (country_code == NULL)
6946 return 0;
6947
6948 INIT_COMPLETION(adapter->change_country_code);
6949
6950 status = sme_change_country_code(hdd_ctx->hHal,
6951 wlan_hdd_change_country_code_callback,
6952 country_code, adapter,
6953 hdd_ctx->pcds_context, eSIR_TRUE,
6954 eSIR_TRUE);
6955
6956
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306957 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006958 hdd_err("SME Change Country code from module param fail ret=%d",
6959 ret);
6960 return -EINVAL;
6961 }
6962
6963 rc = wait_for_completion_timeout(&adapter->change_country_code,
6964 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6965 if (!rc) {
6966 hdd_err("SME while setting country code timed out");
6967 ret = -ETIMEDOUT;
6968 }
6969
6970 return ret;
6971}
6972
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306973#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6974/**
6975 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6976 * @cds_cfg: CDS Configuration
6977 * @hdd_ctx: Pointer to hdd context
6978 *
6979 * Return: none
6980 */
6981static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6982 *cds_cfg,
6983 hdd_context_t *hdd_ctx)
6984{
6985 cds_cfg->tx_flow_stop_queue_th =
6986 hdd_ctx->config->TxFlowStopQueueThreshold;
6987 cds_cfg->tx_flow_start_queue_offset =
6988 hdd_ctx->config->TxFlowStartQueueOffset;
6989}
6990#else
6991static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6992 *cds_cfg,
6993 hdd_context_t *hdd_ctx)
6994{
6995}
6996#endif
6997
6998#ifdef FEATURE_WLAN_RA_FILTERING
6999/**
7000 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
7001 * @cds_cfg: CDS Configuration
7002 * @hdd_ctx: Pointer to hdd context
7003 *
7004 * Return: none
7005 */
Anand Kumar3b92a912016-12-05 12:01:26 +05307006static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307007 hdd_context_t *hdd_ctx)
7008{
7009 cds_cfg->ra_ratelimit_interval =
7010 hdd_ctx->config->RArateLimitInterval;
7011 cds_cfg->is_ra_ratelimit_enabled =
7012 hdd_ctx->config->IsRArateLimitEnabled;
7013}
7014#else
Anand Kumar3b92a912016-12-05 12:01:26 +05307015static inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307016 hdd_context_t *hdd_ctx)
7017{
7018}
7019#endif
7020
7021/**
7022 * hdd_update_cds_config() - API to update cds configuration parameters
7023 * @hdd_ctx: HDD Context
7024 *
7025 * Return: 0 for Success, errno on failure
7026 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007027static int hdd_update_cds_config(hdd_context_t *hdd_ctx)
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307028{
7029 struct cds_config_info *cds_cfg;
7030
7031 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
7032 if (!cds_cfg) {
7033 hdd_err("failed to allocate cds config");
7034 return -ENOMEM;
7035 }
7036
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307037 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
7038 cds_cfg->powersave_offload_enabled =
7039 hdd_ctx->config->enablePowersaveOffload;
7040 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
7041 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
7042 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
7043 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
7044 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
7045
7046 /* Here ol_ini_info is used to store ini status of arp offload
7047 * ns offload and others. Currently 1st bit is used for arp
7048 * off load and 2nd bit for ns offload currently, rest bits are unused
7049 */
7050 if (hdd_ctx->config->fhostArpOffload)
7051 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
7052 if (hdd_ctx->config->fhostNSOffload)
7053 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
7054
7055 /*
7056 * Copy the DFS Phyerr Filtering Offload status.
7057 * This parameter reflects the value of the
7058 * dfs_phyerr_filter_offload flag as set in the ini.
7059 */
7060 cds_cfg->dfs_phyerr_filter_offload =
7061 hdd_ctx->config->fDfsPhyerrFilterOffload;
7062 if (hdd_ctx->config->ssdp)
7063 cds_cfg->ssdp = hdd_ctx->config->ssdp;
7064
7065 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
7066 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
7067
7068 cds_cfg->ap_maxoffload_reorderbuffs =
7069 hdd_ctx->config->apMaxOffloadReorderBuffs;
7070
7071 cds_cfg->ap_disable_intrabss_fwd =
7072 hdd_ctx->config->apDisableIntraBssFwd;
7073
7074 cds_cfg->dfs_pri_multiplier =
7075 hdd_ctx->config->dfsRadarPriMultiplier;
7076 cds_cfg->reorder_offload =
7077 hdd_ctx->config->reorderOffloadSupport;
7078
7079 /* IPA micro controller data path offload resource config item */
7080 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
Yun Parkde380782016-08-17 16:26:54 -07007081 if (!is_power_of_2(hdd_ctx->config->IpaUcTxBufCount)) {
7082 /* IpaUcTxBufCount should be power of 2 */
7083 hdd_err("Round down IpaUcTxBufCount %d to nearest power of 2",
7084 hdd_ctx->config->IpaUcTxBufCount);
7085 hdd_ctx->config->IpaUcTxBufCount =
7086 rounddown_pow_of_two(
7087 hdd_ctx->config->IpaUcTxBufCount);
7088 if (!hdd_ctx->config->IpaUcTxBufCount) {
7089 hdd_err("Failed to round down IpaUcTxBufCount");
7090 return -EINVAL;
7091 }
7092 hdd_err("IpaUcTxBufCount rounded down to %d",
7093 hdd_ctx->config->IpaUcTxBufCount);
7094 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307095 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
7096 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
Yun Parkde380782016-08-17 16:26:54 -07007097 if (!is_power_of_2(hdd_ctx->config->IpaUcRxIndRingCount)) {
7098 /* IpaUcRxIndRingCount should be power of 2 */
7099 hdd_err("Round down IpaUcRxIndRingCount %d to nearest power of 2",
7100 hdd_ctx->config->IpaUcRxIndRingCount);
7101 hdd_ctx->config->IpaUcRxIndRingCount =
7102 rounddown_pow_of_two(
7103 hdd_ctx->config->IpaUcRxIndRingCount);
7104 if (!hdd_ctx->config->IpaUcRxIndRingCount) {
7105 hdd_err("Failed to round down IpaUcRxIndRingCount");
7106 return -EINVAL;
7107 }
7108 hdd_err("IpaUcRxIndRingCount rounded down to %d",
7109 hdd_ctx->config->IpaUcRxIndRingCount);
7110 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307111 cds_cfg->uc_rxind_ringcount =
Yun Parkde380782016-08-17 16:26:54 -07007112 hdd_ctx->config->IpaUcRxIndRingCount;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307113 cds_cfg->uc_tx_partition_base =
7114 hdd_ctx->config->IpaUcTxPartitionBase;
7115 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
7116
7117 cds_cfg->ip_tcp_udp_checksum_offload =
7118 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05307119 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307120 cds_cfg->ce_classify_enabled =
7121 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07007122 cds_cfg->bpf_packet_filter_enable =
7123 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307124 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
7125 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
7126 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07007127 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07007128 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Naveen Rawat91df30a2016-10-12 21:26:18 -07007129 cds_cfg->self_recovery_enabled = hdd_ctx->config->enableSelfRecovery;
Sandeep Puligillaafa52892016-10-26 19:03:16 -07007130 cds_cfg->fw_timeout_crash = hdd_ctx->config->fw_timeout_crash;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307131
7132 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
7133 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
7134 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07007135 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307136 cds_init_ini_config(cds_cfg);
7137 return 0;
7138}
7139
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007140/**
7141 * hdd_init_thermal_info - Initialize thermal level
7142 * @hdd_ctx: HDD context
7143 *
7144 * Initialize thermal level at SME layer and set the thermal level callback
7145 * which would be called when a configured thermal threshold is hit.
7146 *
7147 * Return: 0 on success and errno on failure
7148 */
7149static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
7150{
7151 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307152 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007153
7154 thermal_param.smeThermalMgmtEnabled =
7155 hdd_ctx->config->thermalMitigationEnable;
7156 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
7157
Poddar, Siddarth83905022016-04-16 17:56:08 -07007158 thermal_param.sme_throttle_duty_cycle_tbl[0] =
7159 hdd_ctx->config->throttle_dutycycle_level0;
7160 thermal_param.sme_throttle_duty_cycle_tbl[1] =
7161 hdd_ctx->config->throttle_dutycycle_level1;
7162 thermal_param.sme_throttle_duty_cycle_tbl[2] =
7163 hdd_ctx->config->throttle_dutycycle_level2;
7164 thermal_param.sme_throttle_duty_cycle_tbl[3] =
7165 hdd_ctx->config->throttle_dutycycle_level3;
7166
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007167 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
7168 hdd_ctx->config->thermalTempMinLevel0;
7169 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
7170 hdd_ctx->config->thermalTempMaxLevel0;
7171 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
7172 hdd_ctx->config->thermalTempMinLevel1;
7173 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
7174 hdd_ctx->config->thermalTempMaxLevel1;
7175 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
7176 hdd_ctx->config->thermalTempMinLevel2;
7177 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
7178 hdd_ctx->config->thermalTempMaxLevel2;
7179 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
7180 hdd_ctx->config->thermalTempMinLevel3;
7181 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
7182 hdd_ctx->config->thermalTempMaxLevel3;
7183
7184 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
7185
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307186 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05307187 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08007188
7189 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
7190 hdd_set_thermal_level_cb);
7191
7192 return 0;
7193
7194}
7195
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007196#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
7197/**
7198 * hdd_hold_rtnl_lock - Hold RTNL lock
7199 *
7200 * Hold RTNL lock
7201 *
7202 * Return: True if held and false otherwise
7203 */
7204static inline bool hdd_hold_rtnl_lock(void)
7205{
7206 rtnl_lock();
7207 return true;
7208}
7209
7210/**
7211 * hdd_release_rtnl_lock - Release RTNL lock
7212 *
7213 * Release RTNL lock
7214 *
7215 * Return: None
7216 */
7217static inline void hdd_release_rtnl_lock(void)
7218{
7219 rtnl_unlock();
7220}
7221#else
7222static inline bool hdd_hold_rtnl_lock(void) { return false; }
7223static inline void hdd_release_rtnl_lock(void) { }
7224#endif
7225
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007226#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007227
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307228/* MAX iwpriv command support */
7229#define PKTLOG_SET_BUFF_SIZE 3
7230#define MAX_PKTLOG_SIZE 16
7231
7232/**
7233 * hdd_pktlog_set_buff_size() - set pktlog buffer size
7234 * @hdd_ctx: hdd context
7235 * @set_value2: pktlog buffer size value
7236 *
7237 *
7238 * Return: 0 for success or error.
7239 */
7240static int hdd_pktlog_set_buff_size(hdd_context_t *hdd_ctx, int set_value2)
7241{
7242 struct sir_wifi_start_log start_log = { 0 };
7243 QDF_STATUS status;
7244
7245 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7246 start_log.verbose_level = WLAN_LOG_LEVEL_OFF;
7247 start_log.ini_triggered = cds_is_packet_log_enabled();
7248 start_log.user_triggered = 1;
7249 start_log.size = set_value2;
7250
7251 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7252 if (!QDF_IS_STATUS_SUCCESS(status)) {
7253 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7254 EXIT();
7255 return -EINVAL;
7256 }
7257
7258 return 0;
7259}
7260
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007261/**
7262 * hdd_process_pktlog_command() - process pktlog command
7263 * @hdd_ctx: hdd context
7264 * @set_value: value set by user
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307265 * @set_value2: pktlog buffer size value
7266 *
7267 * This function process pktlog command.
7268 * set_value2 only matters when set_value is 3 (set buff size)
7269 * otherwise we ignore it.
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007270 *
7271 * Return: 0 for success or error.
7272 */
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307273int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value,
7274 int set_value2)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007275{
7276 int ret;
7277 bool enable;
7278 uint8_t user_triggered = 0;
7279
7280 ret = wlan_hdd_validate_context(hdd_ctx);
7281 if (0 != ret)
7282 return ret;
7283
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307284 hdd_info("set pktlog %d, set size %d", set_value, set_value2);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007285
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307286 if (set_value > PKTLOG_SET_BUFF_SIZE) {
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007287 hdd_err("invalid pktlog value %d", set_value);
7288 return -EINVAL;
7289 }
7290
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307291 if (set_value == PKTLOG_SET_BUFF_SIZE) {
7292 if (set_value2 <= 0) {
7293 hdd_err("invalid pktlog size %d", set_value2);
7294 return -EINVAL;
7295 } else if (set_value2 > MAX_PKTLOG_SIZE) {
7296 hdd_err("Pktlog buff size is too large. max value is 16MB.\n");
7297 return -EINVAL;
7298 }
7299 return hdd_pktlog_set_buff_size(hdd_ctx, set_value2);
7300 }
7301
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007302 /*
7303 * set_value = 0 then disable packetlog
7304 * set_value = 1 enable packetlog forcefully
7305 * set_vlaue = 2 then disable packetlog if disabled through ini or
7306 * enable packetlog with AUTO type.
7307 */
7308 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
7309 true : false;
7310
7311 if (1 == set_value) {
7312 enable = true;
7313 user_triggered = 1;
7314 }
7315
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307316 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered, 0);
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007317}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007318/**
7319 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
7320 * @hdd_ctx: HDD context
7321 * @enable: Flag to enable/disable
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307322 * @user_triggered: triggered through iwpriv
7323 * @size: buffer size to be used for packetlog
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007324 *
7325 * Return: 0 on success; error number otherwise
7326 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007327int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307328 uint8_t user_triggered, int size)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007329{
7330 struct sir_wifi_start_log start_log;
7331 QDF_STATUS status;
7332
7333 start_log.ring_id = RING_ID_PER_PACKET_STATS;
7334 start_log.verbose_level =
7335 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007336 start_log.ini_triggered = cds_is_packet_log_enabled();
7337 start_log.user_triggered = user_triggered;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307338 start_log.size = size;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307339 /*
7340 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
7341 * commands. Host uses this flag to decide whether to send pktlog
7342 * disable command to fw without sending pktlog enable command
7343 * previously. For eg, If vendor sends pktlog disable command without
7344 * sending pktlog enable command, then host discards the packet
7345 * but for iwpriv command, host will send it to fw.
7346 */
7347 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007348 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
7349 if (!QDF_IS_STATUS_SUCCESS(status)) {
7350 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
7351 EXIT();
7352 return -EINVAL;
7353 }
7354
7355 return 0;
7356}
7357#endif /* REMOVE_PKT_LOG */
7358
7359
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05307360#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
7361/**
7362 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
7363 * switch without restart
7364 *
7365 * Registers callback function to change the operating channel of SAP by using
7366 * channel switch announcements instead of restarting SAP.
7367 *
7368 * Return: QDF_STATUS
7369 */
7370QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
7371{
7372 QDF_STATUS status;
7373
7374 status = cds_register_sap_restart_channel_switch_cb(
7375 (void *)hdd_sap_restart_with_channel_switch);
7376 if (!QDF_IS_STATUS_SUCCESS(status))
7377 hdd_err("restart cb registration failed");
7378
7379 return status;
7380}
7381#endif
7382
Komal Seelam92fff912016-03-24 11:51:41 +05307383/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007384 * hdd_get_platform_wlan_mac_buff() - API to query platform driver
7385 * for MAC address
Komal Seelam92fff912016-03-24 11:51:41 +05307386 * @dev: Device Pointer
7387 * @num: Number of Valid Mac address
7388 *
7389 * Return: Pointer to MAC address buffer
7390 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007391static uint8_t *hdd_get_platform_wlan_mac_buff(struct device *dev,
7392 uint32_t *num)
Komal Seelam92fff912016-03-24 11:51:41 +05307393{
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007394 return pld_get_wlan_mac_address(dev, num);
Komal Seelam92fff912016-03-24 11:51:41 +05307395}
Komal Seelam92fff912016-03-24 11:51:41 +05307396
7397/**
7398 * hdd_populate_random_mac_addr() - API to populate random mac addresses
7399 * @hdd_ctx: HDD Context
7400 * @num: Number of random mac addresses needed
7401 *
7402 * Generate random addresses using bit manipulation on the base mac address
7403 *
7404 * Return: None
7405 */
7406static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
7407{
7408 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
7409 uint32_t iter;
7410 struct hdd_config *ini = hdd_ctx->config;
7411 uint8_t *buf = NULL;
7412 uint8_t macaddr_b3, tmp_br3;
7413 uint8_t *src = ini->intfMacAddr[0].bytes;
7414
7415 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
7416 buf = ini->intfMacAddr[iter].bytes;
7417 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7418 macaddr_b3 = buf[3];
7419 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7420 INTF_MACADDR_MASK;
7421 macaddr_b3 += tmp_br3;
7422 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7423 buf[0] |= 0x02;
7424 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007425 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307426 }
7427}
7428
7429/**
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007430 * hdd_platform_wlan_mac() - API to get mac addresses from platform driver
Komal Seelam92fff912016-03-24 11:51:41 +05307431 * @hdd_ctx: HDD Context
7432 *
7433 * API to get mac addresses from platform driver and update the driver
7434 * structures and configure FW with the base mac address.
7435 * Return: int
7436 */
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007437static int hdd_platform_wlan_mac(hdd_context_t *hdd_ctx)
Komal Seelam92fff912016-03-24 11:51:41 +05307438{
7439 uint32_t no_of_mac_addr, iter;
7440 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7441 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7442 uint8_t *addr, *buf;
7443 struct device *dev = hdd_ctx->parent_dev;
7444 struct hdd_config *ini = hdd_ctx->config;
7445 tSirMacAddr mac_addr;
7446 QDF_STATUS status;
7447
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007448 addr = hdd_get_platform_wlan_mac_buff(dev, &no_of_mac_addr);
Komal Seelam92fff912016-03-24 11:51:41 +05307449
7450 if (no_of_mac_addr == 0 || !addr) {
7451 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7452 return -EINVAL;
7453 }
7454
7455 if (no_of_mac_addr > max_mac_addr)
7456 no_of_mac_addr = max_mac_addr;
7457
7458 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7459
7460 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7461 buf = ini->intfMacAddr[iter].bytes;
7462 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007463 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307464 }
7465
7466 status = sme_set_custom_mac_addr(mac_addr);
7467
7468 if (!QDF_IS_STATUS_SUCCESS(status))
7469 return -EAGAIN;
7470 if (no_of_mac_addr < max_mac_addr)
7471 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7472 no_of_mac_addr);
7473 return 0;
7474}
7475
7476/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007477 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7478 * @hdd_ctx: HDD Context
7479 *
7480 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7481 * will generate its own MAC and update it to FW.
7482 *
7483 * Return: 0 for success
7484 * Non-zero error code for failure
7485 */
7486static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7487{
7488 tSirMacAddr customMacAddr;
7489 QDF_STATUS status;
7490
7491 qdf_mem_copy(&customMacAddr,
7492 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7493 sizeof(tSirMacAddr));
7494 status = sme_set_custom_mac_addr(customMacAddr);
7495 if (!QDF_IS_STATUS_SUCCESS(status))
7496 return -EAGAIN;
7497 return 0;
7498}
7499
7500/**
Komal Seelam92fff912016-03-24 11:51:41 +05307501 * hdd_initialize_mac_address() - API to get wlan mac addresses
7502 * @hdd_ctx: HDD Context
7503 *
7504 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
7505 * is provisioned with mac addresses, driver uses it, else it will use
7506 * wlan_mac.bin to update HW MAC addresses.
7507 *
7508 * Return: None
7509 */
7510static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
7511{
7512 QDF_STATUS status;
7513 int ret;
7514
Yuanyuan Liu7145eb22016-12-01 10:59:29 -08007515 ret = hdd_platform_wlan_mac(hdd_ctx);
Komal Seelam92fff912016-03-24 11:51:41 +05307516 if (ret == 0)
7517 return;
7518
7519 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7520
7521 status = hdd_update_mac_config(hdd_ctx);
7522
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007523 if (QDF_IS_STATUS_SUCCESS(status))
7524 return;
7525
7526 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
7527
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007528 if (hdd_ctx->update_mac_addr_to_fw) {
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007529 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
Yuanyuan Liu1c2caa32016-11-07 17:13:48 -08007530 if (ret != 0) {
7531 hdd_err("MAC address out-of-sync, ret:%d", ret);
7532 QDF_ASSERT(ret);
7533 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007534 }
Komal Seelam92fff912016-03-24 11:51:41 +05307535}
7536
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007537/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007538 * hdd_tsf_init() - Initialize the TSF synchronization interface
7539 * @hdd_ctx: HDD global context
7540 *
7541 * When TSF synchronization via GPIO is supported by the driver and
7542 * has been enabled in the configuration file, this function plumbs
7543 * the GPIO value down to firmware via SME.
7544 *
7545 * Return: None
7546 */
7547#ifdef WLAN_FEATURE_TSF
7548static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7549{
7550 QDF_STATUS status;
7551
7552 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7553 return;
7554
7555 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7556 hdd_ctx->config->tsf_gpio_pin);
7557 if (!QDF_IS_STATUS_SUCCESS(status))
7558 hdd_err("Set tsf GPIO failed, status: %d", status);
7559}
7560#else
7561static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7562{
7563}
7564#endif
7565
7566/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007567 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7568 * @hdd_ctx: HDD context
7569 *
7570 * Pre configurations to be done at lower layer before calling cds enable.
7571 *
7572 * Return: 0 on success and errno on failure.
7573 */
7574static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7575{
7576 int ret;
7577 QDF_STATUS status;
7578 tSirRetStatus hal_status;
Leo Changfdb45c32016-10-28 11:09:23 -07007579 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007580
Leo Changfdb45c32016-10-28 11:09:23 -07007581 cdp_register_pause_cb(soc, wlan_hdd_txrx_pause_cb);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007582 /*
7583 * Set 802.11p config
7584 * TODO-OCB: This has been temporarily added here to ensure this
7585 * parameter is set in CSR when we init the channel list. This should
7586 * be removed once the 5.9 GHz channels are added to the regulatory
7587 * domain.
7588 */
7589 hdd_set_dot11p_config(hdd_ctx);
7590
7591 /*
7592 * Note that the cds_pre_enable() sequence triggers the cfg download.
7593 * The cfg download must occur before we update the SME config
7594 * since the SME config operation must access the cfg database
7595 */
7596 status = hdd_set_sme_config(hdd_ctx);
7597
7598 if (QDF_STATUS_SUCCESS != status) {
7599 hdd_alert("Failed hdd_set_sme_config: %d", status);
7600 ret = qdf_status_to_os_return(status);
7601 goto out;
7602 }
7603
7604 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7605 hdd_ctx->config->tx_chain_mask_1ss,
7606 PDEV_CMD);
7607 if (0 != ret) {
7608 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7609 goto out;
7610 }
7611
7612 hdd_program_country_code(hdd_ctx);
7613
7614 status = hdd_set_sme_chan_list(hdd_ctx);
7615 if (status != QDF_STATUS_SUCCESS) {
7616 hdd_alert("Failed to init channel list: %d", status);
7617 ret = qdf_status_to_os_return(status);
7618 goto out;
7619 }
7620
7621 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07007622 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07007623 hdd_alert("config update failed");
7624 ret = -EINVAL;
7625 goto out;
7626 }
7627
Prashanth Bhatta07998752016-04-28 12:35:33 -07007628 /*
7629 * Set the MAC Address Currently this is used by HAL to add self sta.
7630 * Remove this once self sta is added as part of session open.
7631 */
7632 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7633 hdd_ctx->config->intfMacAddr[0].bytes,
7634 sizeof(hdd_ctx->config->intfMacAddr[0]));
7635
7636 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7637 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7638 hal_status, hal_status);
7639 ret = -EINVAL;
7640 goto out;
7641 }
7642
7643 hdd_init_channel_avoidance(hdd_ctx);
7644
7645out:
7646 return ret;
7647}
7648
7649/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007650 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7651 * @context_ptr - hdd context pointer
7652 * @event_ptr - event structure pointer
7653 *
7654 * This is the p2p listen offload stop event handler, it sends vendor
7655 * event back to supplicant to notify the stop reason.
7656 *
7657 * Return: None
7658 */
7659static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7660 void *event_ptr)
7661{
7662 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7663 struct sir_p2p_lo_event *evt = event_ptr;
7664 struct sk_buff *vendor_event;
7665
7666 ENTER();
7667
7668 if (hdd_ctx == NULL) {
7669 hdd_err("Invalid HDD context pointer");
7670 return;
7671 }
7672
7673 vendor_event =
7674 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7675 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7676 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7677 GFP_KERNEL);
7678
7679 if (!vendor_event) {
7680 hdd_err("cfg80211_vendor_event_alloc failed");
7681 return;
7682 }
7683
7684 if (nla_put_u32(vendor_event,
7685 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7686 evt->reason_code)) {
7687 hdd_err("nla put failed");
7688 kfree_skb(vendor_event);
7689 return;
7690 }
7691
7692 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7693}
7694
7695/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307696 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7697 * @hdd_ctx: HDD context
7698 *
7699 * This function sends the adaptive dwell time config configuration to the
7700 * firmware via WMA
7701 *
7702 * Return: 0 - success, < 0 - failure
7703 */
7704static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7705{
7706 QDF_STATUS status;
7707 struct adaptive_dwelltime_params dwelltime_params;
7708
7709 dwelltime_params.is_enabled =
7710 hdd_ctx->config->adaptive_dwell_mode_enabled;
7711 dwelltime_params.dwelltime_mode =
7712 hdd_ctx->config->global_adapt_dwelltime_mode;
7713 dwelltime_params.lpf_weight =
7714 hdd_ctx->config->adapt_dwell_lpf_weight;
7715 dwelltime_params.passive_mon_intval =
7716 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7717 dwelltime_params.wifi_act_threshold =
7718 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7719
7720 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7721 &dwelltime_params);
7722
7723 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7724 if (!QDF_IS_STATUS_SUCCESS(status)) {
7725 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7726 return -EAGAIN;
7727 }
7728 return 0;
7729}
7730
Arun Khandavallid4349a92016-07-25 11:10:43 +05307731#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7732/**
7733 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7734 * @hdd_ctx: HDD context
7735 *
7736 * Set auto shutdown callback to get indications from firmware to indicate
7737 * userspace to shutdown WLAN after a configured amount of inactivity.
7738 *
7739 * Return: 0 on success and errno on failure.
7740 */
7741static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7742{
7743 QDF_STATUS status;
7744
7745 if (!hdd_ctx->config->WlanAutoShutdown)
7746 return 0;
7747
7748 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7749 wlan_hdd_auto_shutdown_cb);
7750 if (status != QDF_STATUS_SUCCESS)
7751 hdd_err("Auto shutdown feature could not be enabled: %d",
7752 status);
7753
7754 return qdf_status_to_os_return(status);
7755}
7756#else
7757static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7758{
7759 return 0;
7760}
7761#endif
7762
7763/**
7764 * hdd_features_init() - Init features
7765 * @hdd_ctx: HDD context
7766 * @adapter: Primary adapter context
7767 *
7768 * Initialize features and their feature context after WLAN firmware is up.
7769 *
7770 * Return: 0 on success and errno on failure.
7771 */
7772static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7773{
7774 tSirTxPowerLimit hddtxlimit;
7775 QDF_STATUS status;
7776 int ret;
7777
7778 ENTER();
7779
7780 ret = hdd_update_country_code(hdd_ctx, adapter);
7781 if (ret) {
7782 hdd_err("Failed to update country code: %d", ret);
7783 goto out;
7784 }
7785
7786 /* FW capabilities received, Set the Dot11 mode */
7787 sme_setdef_dot11mode(hdd_ctx->hHal);
Kiran Kumar Lokere1aa9c9a2016-10-05 18:50:59 -07007788 sme_set_prefer_80MHz_over_160MHz(hdd_ctx->hHal,
7789 hdd_ctx->config->sta_prefer_80MHz_over_160MHz);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307790
Arun Khandavallid4349a92016-07-25 11:10:43 +05307791
7792 if (hdd_ctx->config->fIsImpsEnabled)
7793 hdd_set_idle_ps_config(hdd_ctx, true);
7794 else
7795 hdd_set_idle_ps_config(hdd_ctx, false);
7796
7797 if (hdd_lro_init(hdd_ctx))
7798 hdd_err("Unable to initialize LRO in fw");
7799
7800 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7801 hdd_err("Unable to send adaptive dwelltime setting to FW");
7802
7803 ret = hdd_init_thermal_info(hdd_ctx);
7804 if (ret) {
7805 hdd_err("Error while initializing thermal information");
7806 goto deregister_frames;
7807 }
7808
7809 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7810 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7811 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7812 if (!QDF_IS_STATUS_SUCCESS(status))
7813 hdd_err("Error setting txlimit in sme: %d", status);
7814
7815 hdd_tsf_init(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307816 hdd_encrypt_decrypt_init(hdd_ctx);
Arun Khandavallid4349a92016-07-25 11:10:43 +05307817
Arun Khandavallid4349a92016-07-25 11:10:43 +05307818 ret = hdd_register_cb(hdd_ctx);
7819 if (ret) {
7820 hdd_err("Failed to register HDD callbacks!");
7821 goto deregister_frames;
7822 }
7823
7824 if (hdd_ctx->config->dual_mac_feature_disable) {
7825 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7826 if (status != QDF_STATUS_SUCCESS) {
7827 hdd_err("Failed to disable dual mac features");
7828 goto deregister_cb;
7829 }
7830 }
7831
7832 /* register P2P Listen Offload event callback */
7833 if (wma_is_p2p_lo_capable())
7834 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7835 wlan_hdd_p2p_lo_event_callback);
7836
7837 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7838
7839 if (ret)
7840 goto deregister_cb;
7841
7842 EXIT();
7843 return 0;
7844
7845deregister_cb:
7846 hdd_deregister_cb(hdd_ctx);
7847deregister_frames:
7848 wlan_hdd_cfg80211_deregister_frames(adapter);
7849out:
7850 return -EINVAL;
7851
7852}
7853
7854
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307855/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307856 * hdd_configure_cds() - Configure cds modules
7857 * @hdd_ctx: HDD context
7858 * @adapter: Primary adapter context
7859 *
7860 * Enable Cds modules after WLAN firmware is up.
7861 *
7862 * Return: 0 on success and errno on failure.
7863 */
7864int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7865{
7866 int ret;
7867 QDF_STATUS status;
7868 /* structure of function pointers to be used by CDS */
7869 struct cds_sme_cbacks sme_cbacks;
7870
7871 ret = hdd_pre_enable_configure(hdd_ctx);
7872 if (ret) {
7873 hdd_err("Failed to pre-configure cds");
7874 goto out;
7875 }
7876
7877 /*
7878 * Start CDS which starts up the SME/MAC/HAL modules and everything
7879 * else
7880 */
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307881 status = cds_enable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307882
7883 if (!QDF_IS_STATUS_SUCCESS(status)) {
7884 hdd_alert("cds_enable failed");
7885 goto out;
7886 }
7887
7888 status = hdd_post_cds_enable_config(hdd_ctx);
7889 if (!QDF_IS_STATUS_SUCCESS(status)) {
7890 hdd_alert("hdd_post_cds_enable_config failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007891 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307892 }
7893
7894 ret = hdd_features_init(hdd_ctx, adapter);
7895 if (ret)
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007896 goto cds_disable;
Arun Khandavallifae92942016-08-01 13:31:08 +05307897
7898 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7899 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7900 status = cds_init_policy_mgr(&sme_cbacks);
7901 if (!QDF_IS_STATUS_SUCCESS(status)) {
7902 hdd_err("Policy manager initialization failed");
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007903 goto hdd_features_deinit;
Arun Khandavallifae92942016-08-01 13:31:08 +05307904 }
7905
7906 return 0;
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007907
7908hdd_features_deinit:
7909 hdd_deregister_cb(hdd_ctx);
7910 wlan_hdd_cfg80211_deregister_frames(adapter);
7911cds_disable:
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307912 cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Houston Hoffman8d1a6f02016-10-10 17:48:58 -07007913
Arun Khandavallifae92942016-08-01 13:31:08 +05307914out:
7915 return -EINVAL;
7916}
7917
7918/**
7919 * hdd_deconfigure_cds() -De-Configure cds
7920 * @hdd_ctx: HDD context
7921 *
7922 * Deconfigure Cds modules before WLAN firmware is down.
7923 *
7924 * Return: 0 on success and errno on failure.
7925 */
Jeff Johnson590e2012016-10-05 16:16:24 -07007926static int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307927{
7928 QDF_STATUS qdf_status;
Houston Hoffman6640cf32016-10-10 16:44:29 -07007929 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307930
7931 ENTER();
7932 /* De-register the SME callbacks */
7933 hdd_deregister_cb(hdd_ctx);
Padma, Santhosh Kumar1472fab2016-10-07 13:29:27 +05307934 hdd_encrypt_decrypt_deinit(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307935
7936 /* De-init Policy Manager */
7937 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7938 hdd_err("Failed to deinit policy manager");
7939 /* Proceed and complete the clean up */
Houston Hoffman6640cf32016-10-10 16:44:29 -07007940 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307941 }
7942
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05307943 qdf_status = cds_disable(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05307944 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7945 hdd_err("Failed to Disable the CDS Modules! :%d",
7946 qdf_status);
Houston Hoffman6640cf32016-10-10 16:44:29 -07007947 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05307948 }
7949
7950 EXIT();
Houston Hoffman6640cf32016-10-10 16:44:29 -07007951 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307952}
7953
7954
7955/**
7956 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7957 * @hdd_ctx: HDD context
Arun Khandavallifae92942016-08-01 13:31:08 +05307958 *
7959 * This function maintains the driver state machine it will be invoked from
7960 * exit, shutdown and con_mode change handler. Depending on the driver state
7961 * shall perform the stopping/closing of the modules.
7962 *
7963 * Return: 0 for success; non-zero for failure
7964 */
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07007965int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx)
Arun Khandavallifae92942016-08-01 13:31:08 +05307966{
7967 void *hif_ctx;
7968 qdf_device_t qdf_ctx;
7969 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307970 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307971 p_cds_sched_context cds_sched_context = NULL;
7972
7973 ENTER();
7974
7975 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7976 if (!qdf_ctx) {
7977 hdd_err("QDF device context NULL");
7978 return -EINVAL;
7979 }
7980
7981 cds_sched_context = get_cds_sched_ctxt();
7982 if (!cds_sched_context) {
7983 hdd_err("cds scheduler context NULL");
7984 return -EINVAL;
7985 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307986 mutex_lock(&hdd_ctx->iface_change_lock);
7987 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307988
7989 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7990
7991 switch (hdd_ctx->driver_status) {
7992 case DRIVER_MODULES_UNINITIALIZED:
7993 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307994 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307995 case DRIVER_MODULES_CLOSED:
7996 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307997 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307998 case DRIVER_MODULES_ENABLED:
Komal Seelamf2136bb2016-09-28 18:30:44 +05307999 hdd_disable_power_management();
Arun Khandavallifae92942016-08-01 13:31:08 +05308000 if (hdd_deconfigure_cds(hdd_ctx)) {
8001 hdd_alert("Failed to de-configure CDS");
8002 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308003 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308004 }
8005 hdd_info("successfully Disabled the CDS modules!");
8006 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
8007 break;
8008 case DRIVER_MODULES_OPENED:
8009 hdd_info("Closing CDS modules!");
8010 break;
8011 default:
8012 hdd_err("Trying to stop wlan in a wrong state: %d",
8013 hdd_ctx->driver_status);
8014 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308015 ret = -EINVAL;
8016 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05308017 }
8018
Govind Singhb048e872016-09-27 22:07:43 +05308019 qdf_status = cds_post_disable(hdd_ctx->pcds_context);
8020 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8021 hdd_err("Failed to process post CDS disable Modules! :%d",
8022 qdf_status);
8023 ret = -EINVAL;
8024 QDF_ASSERT(0);
8025 }
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308026 qdf_status = cds_close(hdd_ctx->hdd_psoc, hdd_ctx->pcds_context);
Arun Khandavallifae92942016-08-01 13:31:08 +05308027 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
8028 hdd_warn("Failed to stop CDS:%d", qdf_status);
Govind Singhb048e872016-09-27 22:07:43 +05308029 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308030 QDF_ASSERT(0);
8031 }
Krunal Sonid32c6bc2016-10-18 18:00:21 -07008032
Rajeev Kumar3a6c13c2017-01-06 13:01:08 -08008033 qdf_status = hdd_release_and_destroy_pdev(hdd_ctx);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308034 if (QDF_IS_STATUS_ERROR(qdf_status))
8035 hdd_err("Pdev delete failed");
8036
Rajeev Kumar1cba9d02017-01-06 11:36:14 -08008037 qdf_status = hdd_release_and_destroy_psoc(hdd_ctx);
Selvaraj, Sridhar0672a122016-12-29 16:11:48 +05308038 if (QDF_IS_STATUS_ERROR(qdf_status))
8039 hdd_err("Psoc delete failed");
8040
Arun Khandavallifae92942016-08-01 13:31:08 +05308041 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
8042 if (!hif_ctx) {
8043 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308044 ret = -EINVAL;
Arun Khandavallifae92942016-08-01 13:31:08 +05308045 }
8046
8047 hdd_hif_close(hif_ctx);
8048
8049 ol_cds_free();
8050
Arunk Khandavalli649c0092016-11-22 21:20:43 +05308051 if (!cds_is_driver_recovering() && !cds_is_driver_unloading()) {
Arun Khandavallifae92942016-08-01 13:31:08 +05308052 ret = pld_power_off(qdf_ctx->dev);
8053 if (ret)
8054 hdd_err("CNSS power down failed put device into Low power mode:%d",
8055 ret);
8056 }
8057 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
8058
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308059done:
8060 hdd_ctx->stop_modules_in_progress = false;
8061 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05308062 EXIT();
8063
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308064 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308065
8066}
8067
8068/**
8069 * hdd_iface_change_callback() - Function invoked when stop modules expires
8070 * @priv: pointer to hdd context
8071 *
8072 * This function is invoked when the timer waiting for the interface change
8073 * expires, it shall cut-down the power to wlan and stop all the modules.
8074 *
8075 * Return: void
8076 */
8077static void hdd_iface_change_callback(void *priv)
8078{
8079 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
8080 int ret;
8081 int status = wlan_hdd_validate_context(hdd_ctx);
8082
8083 if (status)
8084 return;
8085
8086 ENTER();
8087 hdd_info("Interface change timer expired close the modules!");
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008088 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308089 if (ret)
8090 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05308091 EXIT();
8092}
8093
8094/**
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308095 * hdd_state_info_dump() - prints state information of hdd layer
8096 * @buf: buffer pointer
8097 * @size: size of buffer to be filled
8098 *
8099 * This function is used to dump state information of hdd layer
8100 *
8101 * Return: None
8102 */
8103static void hdd_state_info_dump(char **buf_ptr, uint16_t *size)
8104{
8105 hdd_context_t *hdd_ctx;
8106 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8107 QDF_STATUS status;
8108 hdd_station_ctx_t *hdd_sta_ctx;
8109 hdd_adapter_t *adapter;
8110 uint16_t len = 0;
8111 char *buf = *buf_ptr;
8112
8113 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8114 if (!hdd_ctx) {
8115 hdd_err("Failed to get hdd context ");
8116 return;
8117 }
8118
8119 hdd_notice("size of buffer: %d", *size);
8120
8121 len += scnprintf(buf + len, *size - len,
8122 "\n isWiphySuspended %d", hdd_ctx->isWiphySuspended);
8123 len += scnprintf(buf + len, *size - len,
Rajeev Kumareada0d02016-12-08 17:44:17 -08008124 "\n is_scheduler_suspended %d",
8125 hdd_ctx->is_scheduler_suspended);
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308126
8127 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8128
8129 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8130 adapter = adapter_node->pAdapter;
8131 if (adapter->dev)
8132 len += scnprintf(buf + len, *size - len,
8133 "\n device name: %s", adapter->dev->name);
8134 len += scnprintf(buf + len, *size - len,
8135 "\n device_mode: %d", adapter->device_mode);
8136 switch (adapter->device_mode) {
8137 case QDF_STA_MODE:
8138 case QDF_P2P_CLIENT_MODE:
8139 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8140 len += scnprintf(buf + len, *size - len,
8141 "\n connState: %d",
8142 hdd_sta_ctx->conn_info.connState);
8143 break;
8144
8145 default:
8146 break;
8147 }
8148 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
8149 adapter_node = next;
8150 }
8151
8152 *size -= len;
8153 *buf_ptr += len;
8154}
8155
8156/**
8157 * hdd_register_debug_callback() - registration function for hdd layer
8158 * to print hdd state information
8159 *
8160 * Return: None
8161 */
8162static void hdd_register_debug_callback(void)
8163{
8164 qdf_register_debug_callback(QDF_MODULE_ID_HDD, &hdd_state_info_dump);
8165}
8166
8167/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008168 * hdd_wlan_startup() - HDD init function
8169 * @dev: Pointer to the underlying device
8170 *
8171 * This is the driver startup code executed once a WLAN device has been detected
8172 *
8173 * Return: 0 for success, < 0 for failure
8174 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308175int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008176{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308177 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008178 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008179 hdd_context_t *hdd_ctx = NULL;
8180 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308181 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008182 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308183 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008184
8185 ENTER();
8186
Arun Khandavallifae92942016-08-01 13:31:08 +05308187 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008188
8189 if (IS_ERR(hdd_ctx))
8190 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008191
Arun Khandavallifae92942016-08-01 13:31:08 +05308192 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
8193 hdd_iface_change_callback, (void *)hdd_ctx);
8194
8195 mutex_init(&hdd_ctx->iface_change_lock);
8196
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008197 ret = hdd_init_netlink_services(hdd_ctx);
8198 if (ret)
8199 goto err_hdd_free_context;
8200
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07008201 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308202
Arun Khandavallifae92942016-08-01 13:31:08 +05308203 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
8204 if (ret) {
8205 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008206 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008207 }
8208
Yingying Tang80e15f32016-09-27 18:23:01 +08008209 wlan_hdd_update_wiphy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008210
Yingying Tang95409972016-10-20 15:16:15 +08008211 if (0 != wlan_hdd_set_wow_pulse(hdd_ctx, true))
8212 hdd_notice("Failed to set wow pulse");
8213
Anurag Chouhan6d760662016-02-20 16:05:43 +05308214 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008215
8216 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008217 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05308218 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008219 }
8220
Prashanth Bhatta07998752016-04-28 12:35:33 -07008221 ret = hdd_wiphy_init(hdd_ctx);
8222 if (ret) {
8223 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05308224 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008225 }
8226
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05308227 if (hdd_ctx->config->enable_dp_trace)
8228 qdf_dp_trace_init();
8229
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308230 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008231 goto err_wiphy_unregister;
8232
Yuanyuan Liuc98370e2016-10-13 11:22:13 -07008233 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08008234
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008235 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008236
Arun Khandavallifae92942016-08-01 13:31:08 +05308237 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008238
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008239 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008240 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008241 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05308242 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008243 }
8244
Arun Khandavallifae92942016-08-01 13:31:08 +05308245 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308246 if (!hif_sc) {
8247 hdd_err("HIF context is NULL");
8248 goto err_close_adapter;
8249 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008250 /*
8251 * target hw version/revision would only be retrieved after firmware
8252 * donwload
8253 */
8254 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
8255 &hdd_ctx->target_hw_revision,
8256 &hdd_ctx->target_hw_name);
8257
8258 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05308259 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008260
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008261 hdd_release_rtnl_lock();
8262 rtnl_held = false;
8263
Agrawal Ashishb2d1a452016-05-05 12:23:58 +05308264 if (hdd_ctx->config->enable_go_cts2self_for_sta)
8265 sme_set_cts2self_for_p2p_go(hdd_ctx->hHal);
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08008266
8267 wlan_hdd_update_11n_mode(hdd_ctx->config);
8268
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008269#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05308270 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308271 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008272 hdd_skip_acs_scan_timer_handler,
8273 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308274 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07008275 hdd_err("Failed to init ACS Skip timer");
Liangwei Dongaef84342016-10-21 05:28:00 -04008276 qdf_spinlock_create(&hdd_ctx->acs_skip_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008277#endif
8278
Nitesh Shah61c10d92016-10-19 19:29:15 +05308279 qdf_mc_timer_init(&hdd_ctx->tdls_source_timer,
8280 QDF_TIMER_TYPE_SW,
8281 wlan_hdd_change_tdls_mode,
8282 hdd_ctx);
8283
Prashanth Bhattaab004382016-10-11 16:08:11 -07008284 hdd_bus_bandwidth_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008285
Jeff Johnson9afc5012016-09-23 13:56:27 -07008286 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008287
Nirav Shahbd36b062016-07-18 11:12:59 +05308288 if (hdd_ctx->rps)
8289 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07008290
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008291
8292 if (cds_is_packet_log_enabled())
Poddar, Siddarth176c4362016-10-03 12:25:00 +05308293 hdd_pktlog_enable_disable(hdd_ctx, true, 0, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08008294
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008295 ret = hdd_register_notifiers(hdd_ctx);
8296 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05308297 goto err_debugfs_exit;
8298
8299 status = wlansap_global_init();
8300 if (QDF_IS_STATUS_ERROR(status))
8301 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07008302
Komal Seelam8634b772016-09-29 12:12:24 +05308303 hdd_runtime_suspend_context_init(hdd_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008304 memdump_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05308305 hdd_driver_memdump_init();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008306
bings612b9c42016-11-07 10:52:03 +08008307 if (hdd_enable_egap(hdd_ctx))
8308 hdd_err("enhance green ap is not enabled");
8309
Arun Khandavallifae92942016-08-01 13:31:08 +05308310 if (hdd_ctx->config->fIsImpsEnabled)
8311 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308312
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05308313 if (hdd_ctx->config->sifs_burst_duration) {
8314 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
8315 hdd_ctx->config->sifs_burst_duration;
8316
8317 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
8318 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
8319 set_value, PDEV_CMD);
8320 }
8321
Arun Khandavallifae92942016-08-01 13:31:08 +05308322 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
8323 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05308324
8325 if (hdd_ctx->config->goptimize_chan_avoid_event) {
8326 status = sme_enable_disable_chanavoidind_event(
8327 hdd_ctx->hHal, 0);
8328 if (!QDF_IS_STATUS_SUCCESS(status))
8329 hdd_err("Failed to disable Chan Avoidance Indication");
8330 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008331 goto success;
8332
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008333err_debugfs_exit:
8334 hdd_debugfs_exit(adapter);
Anurag Chouhance6a4052016-09-14 18:20:42 +05308335
8336err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08008337 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008338
Arun Khandavallid4349a92016-07-25 11:10:43 +05308339 if (rtnl_held)
8340 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008341
Anurag Chouhance6a4052016-09-14 18:20:42 +05308342err_ipa_cleanup:
8343 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08008344
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008345err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008346 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008347
Arun Khandavallifae92942016-08-01 13:31:08 +05308348err_stop_modules:
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07008349 hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05308350
8351
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008352 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308353 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008354 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308355 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008356 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008357
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008358err_exit_nl_srv:
Houston Hoffman47a4a052016-11-14 23:22:44 -08008359 hdd_green_ap_deinit(hdd_ctx);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07008360 hdd_exit_netlink_services(hdd_ctx);
8361
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308362 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008363err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05308364 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
8365 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07008366 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308367 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008369 return -EIO;
8370
8371success:
8372 EXIT();
8373 return 0;
8374}
8375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008376/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308377 * hdd_wlan_update_target_info() - update target type info
8378 * @hdd_ctx: HDD context
8379 * @context: hif context
8380 *
8381 * Update target info received from firmware in hdd context
8382 * Return:None
8383 */
8384
8385void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
8386{
8387 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
8388
8389 if (!tgt_info) {
8390 hdd_err("Target info is Null");
8391 return;
8392 }
8393
8394 hdd_ctx->target_type = tgt_info->target_type;
8395}
8396
8397/**
8398 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308399 * @hdd_ctx: HDD context
8400 *
8401 * Register the HDD callbacks to CDS/SME.
8402 *
8403 * Return: 0 for success or Error code for failure
8404 */
8405int hdd_register_cb(hdd_context_t *hdd_ctx)
8406{
8407 QDF_STATUS status;
8408 int ret = 0;
8409
8410 ENTER();
8411
8412 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
8413
8414 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
8415 hdd_send_oem_data_rsp_msg);
8416
8417 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
8418 wlan_hdd_cfg80211_fw_mem_dump_cb);
8419 if (!QDF_IS_STATUS_SUCCESS(status)) {
8420 hdd_err("Failed to register memdump callback");
8421 ret = -EINVAL;
8422 return ret;
8423 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05308424 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
8425 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308426 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
8427 sme_nan_register_callback(hdd_ctx->hHal,
8428 wlan_hdd_cfg80211_nan_callback);
8429 sme_stats_ext_register_callback(hdd_ctx->hHal,
8430 wlan_hdd_cfg80211_stats_ext_callback);
8431
8432 sme_ext_scan_register_callback(hdd_ctx->hHal,
8433 wlan_hdd_cfg80211_extscan_callback);
8434
8435 status = cds_register_sap_restart_channel_switch_cb(
8436 (void *)hdd_sap_restart_with_channel_switch);
8437 if (!QDF_IS_STATUS_SUCCESS(status)) {
8438 hdd_err("restart cb registration failed");
8439 ret = -EINVAL;
8440 return ret;
8441 }
8442
8443 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
8444 hdd_rssi_threshold_breached);
8445
8446 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
8447 hdd_get_bpf_offload_cb);
8448 if (!QDF_IS_STATUS_SUCCESS(status)) {
8449 hdd_err("set bpf offload callback failed");
8450 ret = -EINVAL;
8451 return ret;
8452 }
8453
8454 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
8455 wlan_hdd_cfg80211_link_layer_stats_callback);
8456
Sreelakshmi Konamki58c72432016-11-09 17:06:44 +05308457 status = sme_set_lost_link_info_cb(hdd_ctx->hHal,
8458 hdd_lost_link_info_cb);
8459 /* print error and not block the startup process */
8460 if (!QDF_IS_STATUS_SUCCESS(status))
8461 hdd_err("set lost link info callback failed");
8462
Arun Khandavalli4b55da72016-07-19 19:55:01 +05308463 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
8464
8465 EXIT();
8466
8467 return ret;
8468}
8469
8470/**
8471 * hdd_deregister_cb() - De-Register HDD callbacks.
8472 * @hdd_ctx: HDD context
8473 *
8474 * De-Register the HDD callbacks to CDS/SME.
8475 *
8476 * Return: void
8477 */
8478void hdd_deregister_cb(hdd_context_t *hdd_ctx)
8479{
8480 QDF_STATUS status;
8481
8482 ENTER();
8483
8484 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
8485 if (!QDF_IS_STATUS_SUCCESS(status))
8486 hdd_err("De-register of dcc stats callback failed: %d",
8487 status);
8488
8489 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
8490 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
8491 if (!QDF_IS_STATUS_SUCCESS(status))
8492 hdd_err("De-register bpf offload callback failed: %d",
8493 status);
8494 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
8495
8496 status = cds_deregister_sap_restart_channel_switch_cb();
8497 if (!QDF_IS_STATUS_SUCCESS(status))
8498 hdd_err("De-register restart cb registration failed: %d",
8499 status);
8500
8501 sme_stats_ext_register_callback(hdd_ctx->hHal,
8502 wlan_hdd_cfg80211_stats_ext_callback);
8503
8504 sme_nan_deregister_callback(hdd_ctx->hHal);
8505 status = sme_reset_tsfcb(hdd_ctx->hHal);
8506 if (!QDF_IS_STATUS_SUCCESS(status))
8507 hdd_err("Failed to de-register tsfcb the callback:%d",
8508 status);
8509 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
8510 if (!QDF_IS_STATUS_SUCCESS(status))
8511 hdd_err("Failed to de-register the fw mem dump callback: %d",
8512 status);
8513
8514 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
8515 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
8516
8517 EXIT();
8518}
8519
8520/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008521 * hdd_softap_sta_deauth() - handle deauth req from HDD
8522 * @adapter: Pointer to the HDD
8523 * @enable: bool value
8524 *
8525 * This to take counter measure to handle deauth req from HDD
8526 *
8527 * Return: None
8528 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308529QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008530 struct tagCsrDelStaParams *pDelStaParams)
8531{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308532 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008533
8534 ENTER();
8535
Jeff Johnson34c88b72016-08-15 14:27:11 -07008536 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008537 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8538
8539 /* Ignore request to deauth bcmc station */
8540 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308541 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008542
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308543 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008544 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8545 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008546
8547 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308548 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008549}
8550
8551/**
8552 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
8553 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308554 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008555 *
8556 * This to take counter measure to handle deauth req from HDD
8557 *
8558 * Return: None
8559 */
8560void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308561 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008562{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563 ENTER();
8564
Jeff Johnson34c88b72016-08-15 14:27:11 -07008565 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008566 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8567
8568 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308569 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008570 return;
8571
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008572 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308573 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008574}
8575
8576void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
8577 bool enable)
8578{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008579 ENTER();
8580
Jeff Johnson34c88b72016-08-15 14:27:11 -07008581 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008582 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008584 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8585 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008586}
8587
8588/**
8589 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
8590 * @hdd_ctx: HDD Context
8591 *
8592 * API to find if there is any STA or P2P-Client is connected
8593 *
8594 * Return: true if connected; false otherwise
8595 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308596QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008597{
8598 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
8599}
8600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008601/**
8602 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
8603 * @adapter: HDD adapter pointer
8604 *
8605 * This function loop through each adapter and disable roaming on each STA
8606 * device mode except the input adapter.
8607 *
8608 * Note: On the input adapter roaming is not enabled yet hence no need to
8609 * disable.
8610 *
8611 * Return: None
8612 */
8613void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8614{
8615 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8616 hdd_adapter_t *adapterIdx = NULL;
8617 hdd_adapter_list_node_t *adapterNode = NULL;
8618 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308619 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008620
8621 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8622 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008623 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008624 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008625 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008626 adapter->sessionId);
8627 /*
8628 * Loop through adapter and disable roaming for each STA device
8629 * mode except the input adapter.
8630 */
8631 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8632
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308633 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008634 adapterIdx = adapterNode->pAdapter;
8635
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008636 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008637 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008638 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008639 adapterIdx->sessionId);
8640 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8641 (adapterIdx),
8642 adapterIdx->sessionId, 0);
8643 }
8644
8645 status = hdd_get_next_adapter(hdd_ctx,
8646 adapterNode,
8647 &pNext);
8648 adapterNode = pNext;
8649 }
8650 }
8651}
8652
8653/**
8654 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8655 * @adapter: HDD adapter pointer
8656 *
8657 * This function loop through each adapter and enable roaming on each STA
8658 * device mode except the input adapter.
8659 * Note: On the input adapter no need to enable roaming because link got
8660 * disconnected on this.
8661 *
8662 * Return: None
8663 */
8664void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8665{
8666 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8667 hdd_adapter_t *adapterIdx = NULL;
8668 hdd_adapter_list_node_t *adapterNode = NULL;
8669 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308670 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008671
8672 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8673 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008674 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008675 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008676 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008677 adapter->sessionId);
8678 /*
8679 * Loop through adapter and enable roaming for each STA device
8680 * mode except the input adapter.
8681 */
8682 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8683
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308684 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008685 adapterIdx = adapterNode->pAdapter;
8686
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008687 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008688 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008689 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008690 adapterIdx->sessionId);
8691 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8692 (adapterIdx),
8693 adapterIdx->sessionId,
8694 REASON_CONNECT);
8695 }
8696
8697 status = hdd_get_next_adapter(hdd_ctx,
8698 adapterNode,
8699 &pNext);
8700 adapterNode = pNext;
8701 }
8702 }
8703}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008704
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308705void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008706{
8707 struct sk_buff *skb;
8708 struct nlmsghdr *nlh;
8709 tAniMsgHdr *ani_hdr;
8710 void *nl_data = NULL;
8711 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308712 struct radio_index_tlv *radio_info;
8713 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008714
8715 if (in_interrupt() || irqs_disabled() || in_atomic())
8716 flags = GFP_ATOMIC;
8717
8718 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8719
8720 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008721 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008722 return;
8723 }
8724
8725 nlh = (struct nlmsghdr *)skb->data;
8726 nlh->nlmsg_pid = 0; /* from kernel */
8727 nlh->nlmsg_flags = 0;
8728 nlh->nlmsg_seq = 0;
8729 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8730
8731 ani_hdr = NLMSG_DATA(nlh);
8732 ani_hdr->type = type;
8733
8734 switch (type) {
8735 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05308736 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008737 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008738 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008739 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008740 ani_hdr->length = 0;
8741 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8742 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8743 break;
8744 case WLAN_SVC_WLAN_STATUS_IND:
8745 case WLAN_SVC_WLAN_VERSION_IND:
8746 case WLAN_SVC_DFS_CAC_START_IND:
8747 case WLAN_SVC_DFS_CAC_END_IND:
8748 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8749 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8750 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008751 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308752 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008753 ani_hdr->length = len;
8754 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8755 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8756 memcpy(nl_data, data, len);
8757 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
8758 break;
8759
8760 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008761 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008762 type);
8763 kfree_skb(skb);
8764 return;
8765 }
8766
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308767 /*
Jeff Johnson0d52c7a2017-01-12 08:46:55 -08008768 * Add radio index at the end of the svc event in TLV format
8769 * to maintain the backward compatibility with userspace
8770 * applications.
8771 */
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308772
8773 tlv_len = 0;
8774
8775 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8776 < WLAN_NL_MAX_PAYLOAD) {
8777 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8778 sizeof(*ani_hdr) + len);
8779 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8780 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8781 radio_info->radio = radio;
8782 tlv_len = sizeof(*radio_info);
8783 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8784 "Added radio index tlv - radio index %d",
8785 radio_info->radio);
8786 }
8787
8788 nlh->nlmsg_len += tlv_len;
8789 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008791 nl_srv_bcast(skb);
8792
8793 return;
8794}
8795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008796#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8797void wlan_hdd_auto_shutdown_cb(void)
8798{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008799 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308800
8801 if (!hdd_ctx)
8802 return;
8803
Jeff Johnson28f8a772016-08-15 15:30:36 -07008804 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308805 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8806 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008807}
8808
8809void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8810{
8811 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308812 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008813 hdd_adapter_t *adapter;
8814 bool ap_connected = false, sta_connected = false;
8815 tHalHandle hal_handle;
8816
8817 hal_handle = hdd_ctx->hHal;
8818 if (hal_handle == NULL)
8819 return;
8820
8821 if (hdd_ctx->config->WlanAutoShutdown == 0)
8822 return;
8823
8824 if (enable == false) {
8825 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308826 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008827 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008828 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308829 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008830 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008831 return;
8832 }
8833
8834 /* To enable shutdown timer check conncurrency */
8835 if (cds_concurrent_open_sessions_running()) {
8836 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8837
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308838 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008839 adapter = adapterNode->pAdapter;
8840 if (adapter
8841 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008842 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008843 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8844 conn_info.connState ==
8845 eConnectionState_Associated) {
8846 sta_connected = true;
8847 break;
8848 }
8849 }
8850 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008851 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008852 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8853 bApActive == true) {
8854 ap_connected = true;
8855 break;
8856 }
8857 }
8858 status = hdd_get_next_adapter(hdd_ctx,
8859 adapterNode,
8860 &pNext);
8861 adapterNode = pNext;
8862 }
8863 }
8864
8865 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008866 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008867 return;
8868 } else {
8869 if (sme_set_auto_shutdown_timer(hal_handle,
8870 hdd_ctx->config->
8871 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308872 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008873 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008874 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008875 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008876 hdd_ctx->config->WlanAutoShutdown);
8877
8878 }
8879}
8880#endif
8881
8882hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8883 bool check_start_bss)
8884{
8885 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8886 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308887 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008888 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8889
8890 con_sap_adapter = NULL;
8891
8892 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308893 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008894 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008895 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8896 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008897 adapter != this_sap_adapter) {
8898 if (check_start_bss) {
8899 if (test_bit(SOFTAP_BSS_STARTED,
8900 &adapter->event_flags)) {
8901 con_sap_adapter = adapter;
8902 break;
8903 }
8904 } else {
8905 con_sap_adapter = adapter;
8906 break;
8907 }
8908 }
8909 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8910 adapterNode = pNext;
8911 }
8912
8913 return con_sap_adapter;
8914}
8915
8916#ifdef MSM_PLATFORM
8917void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8918{
8919 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8920
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05308921 if (hdd_ctx->bus_bw_timer_started)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008922 return;
8923
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05308924 hdd_ctx->bus_bw_timer_started = true;
8925 qdf_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008926 hdd_ctx->config->busBandwidthComputeInterval);
8927}
8928
8929void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8930{
8931 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308932 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008933 bool can_stop = true;
8934 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8935
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05308936 if (!hdd_ctx->bus_bw_timer_started) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008937 /* trying to stop timer, when not running is not good */
Srinivas Girigowda0ee96442016-08-17 19:10:56 -07008938 hdd_info("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008939 return;
8940 }
8941
8942 if (cds_concurrent_open_sessions_running()) {
8943 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8944
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308945 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008946 adapter = adapterNode->pAdapter;
8947 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008948 && (adapter->device_mode == QDF_STA_MODE
8949 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008950 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8951 conn_info.connState ==
8952 eConnectionState_Associated) {
8953 can_stop = false;
8954 break;
8955 }
8956 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008957 && (adapter->device_mode == QDF_SAP_MODE
8958 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008959 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8960 true) {
8961 can_stop = false;
8962 break;
8963 }
8964 status = hdd_get_next_adapter(hdd_ctx,
8965 adapterNode,
8966 &pNext);
8967 adapterNode = pNext;
8968 }
8969 }
8970
Ravi Joshib89e7f72016-09-07 13:43:15 -07008971 if (can_stop == true) {
Chris Guoc0c95bf2016-11-10 14:28:25 +08008972 /* reset the ipa perf level */
8973 hdd_ipa_set_perf_level(hdd_ctx, 0, 0);
Poddar, Siddarth2333acb2017-01-09 16:45:39 +05308974 qdf_timer_stop(&hdd_ctx->bus_bw_timer);
8975 hdd_ctx->bus_bw_timer_started = false;
Ravi Joshib89e7f72016-09-07 13:43:15 -07008976 hdd_reset_tcp_delack(hdd_ctx);
8977 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008978}
8979#endif
8980
8981/**
8982 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8983 * and sta's operating channel.
8984 * @sta_adapter: Describe the first argument to foobar.
8985 * @ap_adapter: Describe the second argument to foobar.
8986 * @roam_profile: Roam profile of AP to which STA wants to connect.
8987 * @concurrent_chnl_same: If both SAP and STA channels are same then
8988 * set this flag to true else false.
8989 *
8990 * This function checks the sap's operating channel and sta's operating channel.
8991 * if both are same then it will return false else it will restart the sap in
8992 * sta's channel and return true.
8993 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308994 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008995 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308996QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008997 hdd_adapter_t *ap_adapter,
8998 tCsrRoamProfile *roam_profile,
8999 tScanResultHandle *scan_cache,
9000 bool *concurrent_chnl_same)
9001{
9002 hdd_ap_ctx_t *hdd_ap_ctx;
9003 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309004 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009005 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009006 *concurrent_chnl_same = true;
9007
9008 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9009 status =
9010 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
9011 roam_profile,
9012 scan_cache,
9013 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309014 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009015 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009016 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
9017 if (hdd_ap_ctx->operatingChannel != channel_id) {
9018 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009019 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009020 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009021 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009022 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
9023 if (hdd_ap_ctx->operatingChannel != channel_id) {
9024 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07009025 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009026 }
9027 }
9028 } else {
9029 /*
9030 * Lets handle worst case scenario here, Scan cache lookup is
9031 * failed so we have to stop the SAP to avoid any channel
9032 * discrepancy between SAP's channel and STA's channel.
9033 * Return the status as failure so caller function could know
9034 * that scan look up is failed.
9035 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07009036 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309037 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009038 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309039 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009040}
9041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009042/**
9043 * wlan_hdd_stop_sap() - This function stops bss of SAP.
9044 * @ap_adapter: SAP adapter
9045 *
9046 * This function will process the stopping of sap adapter.
9047 *
9048 * Return: None
9049 */
9050void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
9051{
9052 hdd_ap_ctx_t *hdd_ap_ctx;
9053 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309054 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009055 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009056
9057 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009058 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009059 return;
9060 }
9061
9062 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9063 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309064 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009065 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309066
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009067 mutex_lock(&hdd_ctx->sap_lock);
9068 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08009069 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009070 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
9071 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009072 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309073 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309074 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009075 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309076 qdf_status = qdf_wait_single_event(&hostapd_state->
Naveen Rawatb56880c2016-12-13 17:56:03 -08009077 qdf_stop_bss_event,
9078 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309079 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009080 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009081 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009082 return;
9083 }
9084 }
9085 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08009086 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009087 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07009088 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009089 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009090 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009091 }
9092 mutex_unlock(&hdd_ctx->sap_lock);
9093 return;
9094}
9095
9096/**
9097 * wlan_hdd_start_sap() - this function starts bss of SAP.
9098 * @ap_adapter: SAP adapter
9099 *
9100 * This function will process the starting of sap adapter.
9101 *
9102 * Return: None
9103 */
9104void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
9105{
9106 hdd_ap_ctx_t *hdd_ap_ctx;
9107 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309108 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009109 hdd_context_t *hdd_ctx;
9110 tsap_Config_t *sap_config;
9111
9112 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009113 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009114 return;
9115 }
9116
Krunal Soni9b04c9b2016-03-10 13:08:05 -08009117 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07009118 hdd_err("SoftAp role has not been enabled");
9119 return;
9120 }
9121
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009122 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
9123 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9124 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9125 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
9126
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309127 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009128 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05309129
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009130 mutex_lock(&hdd_ctx->sap_lock);
9131 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
9132 goto end;
9133
9134 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009135 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009136 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
9137 goto end;
9138 }
9139
Wei Song2f76f642016-11-18 16:32:53 +08009140 qdf_event_reset(&hostapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009141 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
9142 &hdd_ap_ctx->sapConfig,
9143 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309144 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009145 goto end;
9146
Jeff Johnson28f8a772016-08-15 15:30:36 -07009147 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309148 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Naveen Rawatb56880c2016-12-13 17:56:03 -08009149 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309150 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07009151 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152 goto end;
9153 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07009154 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009155 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Krunal Sonib37bb352016-12-20 14:12:21 -08009156 if (hostapd_state->bssState == BSS_START)
9157 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009158 ap_adapter->sessionId);
9159 hostapd_state->bCommit = true;
9160
9161end:
9162 mutex_unlock(&hdd_ctx->sap_lock);
9163 return;
9164}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009165
9166/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08009167 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
9168 * mac scan config
9169 * @status: Status of set antenna mode
9170 *
9171 * Callback on setting the dual mac configuration
9172 *
9173 * Return: None
9174 */
9175void wlan_hdd_soc_set_antenna_mode_cb(
9176 enum set_antenna_mode_status status)
9177{
9178 hdd_context_t *hdd_ctx;
9179
9180 hdd_info("Status: %d", status);
9181
9182 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9183 if (0 != wlan_hdd_validate_context(hdd_ctx))
9184 return;
9185
9186 /* Signal the completion of set dual mac config */
9187 complete(&hdd_ctx->set_antenna_mode_cmpl);
9188}
9189
9190/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009191 * hdd_get_fw_version() - Get FW version
9192 * @hdd_ctx: pointer to HDD context.
9193 * @major_spid: FW version - major spid.
9194 * @minor_spid: FW version - minor spid
9195 * @ssid: FW version - ssid
9196 * @crmid: FW version - crmid
9197 *
9198 * This function is called to get the firmware build version stored
9199 * as part of the HDD context
9200 *
9201 * Return: None
9202 */
9203void hdd_get_fw_version(hdd_context_t *hdd_ctx,
9204 uint32_t *major_spid, uint32_t *minor_spid,
9205 uint32_t *siid, uint32_t *crmid)
9206{
9207 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
9208 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
9209 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
9210 *crmid = hdd_ctx->target_fw_version & 0x7fff;
9211}
9212
9213#ifdef QCA_CONFIG_SMP
9214/**
9215 * wlan_hdd_get_cpu() - get cpu_index
9216 *
9217 * Return: cpu_index
9218 */
9219int wlan_hdd_get_cpu(void)
9220{
9221 int cpu_index = get_cpu();
9222 put_cpu();
9223 return cpu_index;
9224}
9225#endif
9226
9227/**
9228 * hdd_get_fwpath() - get framework path
9229 *
9230 * This function is used to get the string written by
9231 * userspace to start the wlan driver
9232 *
9233 * Return: string
9234 */
9235const char *hdd_get_fwpath(void)
9236{
9237 return fwpath.string;
9238}
9239
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009240/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009241 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009242 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009243 * This function initilizes CDS global context with the help of cds_init. This
9244 * has to be the first function called after probe to get a valid global
9245 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009246 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009247 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009248 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009249int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009250{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009251 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009252 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009253
9254#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9255 wlan_logging_sock_init_svc();
9256#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009257 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009258
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009259 if (p_cds_context == NULL) {
9260 hdd_alert("Failed to allocate CDS context");
9261 ret = -ENOMEM;
9262 goto err_out;
9263 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009264
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009265 hdd_trace_init();
Padma, Santhosh Kumar9aba02f2016-08-11 16:30:25 +05309266 hdd_register_debug_callback();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009267
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009268err_out:
9269 return ret;
9270}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009271
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009272/**
9273 * hdd_deinit() - Deinitialize Driver
9274 *
9275 * This function frees CDS global context with the help of cds_deinit. This
9276 * has to be the last function call in remove callback to free the global
9277 * context.
9278 */
9279void hdd_deinit(void)
9280{
9281 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009282
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009283#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9284 wlan_logging_sock_deinit_svc();
9285#endif
9286}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009287
9288#ifdef QCA_WIFI_3_0_ADRASTEA
9289#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
9290#else
9291#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
9292#endif
9293
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009294/**
9295 * __hdd_module_init - Module init helper
9296 *
9297 * Module init helper function used by both module and static driver.
9298 *
9299 * Return: 0 for success, errno on failure
9300 */
9301static int __hdd_module_init(void)
9302{
9303 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009304
Arun Khandavallifae92942016-08-01 13:31:08 +05309305 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009306 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009307
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009308 pld_init();
9309
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309310 ret = hdd_init();
9311 if (ret) {
9312 pr_err("hdd_init failed %x\n", ret);
9313 goto err_hdd_init;
9314 }
9315
Rajeev Kumar97767a02016-11-30 11:20:40 -08009316 dispatcher_init();
9317
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309318 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009319
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009320 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009321
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009322 ret = wlan_hdd_register_driver();
9323 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07009324 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
9325 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009326 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009327 }
9328
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309329 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009330
9331 return 0;
9332out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309333 qdf_wake_lock_destroy(&wlan_wake_lock);
Rajeev Kumar97767a02016-11-30 11:20:40 -08009334 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309335 hdd_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009336
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309337err_hdd_init:
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009338 pld_deinit();
Rajeev Kumar97767a02016-11-30 11:20:40 -08009339
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009340 return ret;
9341}
9342
9343/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309344 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
9345 *
9346 * Block the unloading of the driver until the cds recovery is completed
9347 *
9348 * Return: None
9349 */
9350static void hdd_wait_for_recovery_completion(void)
9351{
9352 int retry = 0;
9353
9354 /* Wait for recovery to complete */
9355 while (cds_is_driver_recovering()) {
9356 hdd_alert("Recovery in progress; wait here!!!");
9357 msleep(1000);
9358 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
9359 hdd_alert("SSR never completed, fatal error");
9360 QDF_BUG(0);
9361 }
9362 }
9363}
9364
9365/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009366 * __hdd_module_exit - Module exit helper
9367 *
9368 * Module exit helper function used by both module and static driver.
9369 */
9370static void __hdd_module_exit(void)
9371{
9372 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
9373 QWLAN_VERSIONSTR);
9374
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05309375 hdd_wait_for_recovery_completion();
9376
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009377 wlan_hdd_unregister_driver();
9378
Anurag Chouhana37b5b72016-02-21 14:53:42 +05309379 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009380
Rajeev Kumar97767a02016-11-30 11:20:40 -08009381 dispatcher_deinit();
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309382 hdd_deinit();
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07009383 pld_deinit();
9384
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009385 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009386}
9387
Arun Khandavallifae92942016-08-01 13:31:08 +05309388#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009389/**
Arun Khandavallifae92942016-08-01 13:31:08 +05309390 * wlan_boot_cb() - Wlan boot callback
9391 * @kobj: object whose directory we're creating the link in.
9392 * @attr: attribute the user is interacting with
9393 * @buff: the buffer containing the user data
9394 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009395 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309396 * This callback is invoked when the fs is ready to start the
9397 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009398 *
Arun Khandavallifae92942016-08-01 13:31:08 +05309399 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009400 */
Arun Khandavallifae92942016-08-01 13:31:08 +05309401static ssize_t wlan_boot_cb(struct kobject *kobj,
9402 struct kobj_attribute *attr,
9403 const char *buf,
9404 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009405{
Arun Khandavallifae92942016-08-01 13:31:08 +05309406
9407 int ret = 0;
9408
9409 if (wlan_loader->loaded_state) {
9410 pr_info("Wlan driver already initialized");
9411 return 0;
9412 }
9413
9414
9415 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9416 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9417
9418 if (__hdd_module_init()) {
9419 pr_err("%s: Failed to register handler\n", __func__);
9420 ret = -EINVAL;
9421 } else
9422 wlan_loader->loaded_state = MODULE_INITIALIZED;
9423
9424 return count;
9425
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009426}
Arun Khandavallifae92942016-08-01 13:31:08 +05309427
9428/**
9429 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
9430 * ready
9431 *
9432 * This is creates the syfs entry boot_wlan. Which shall be invoked
9433 * when the filesystem is ready.
9434 *
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009435 * Return: 0 for success, errno on failure
Arun Khandavallifae92942016-08-01 13:31:08 +05309436 */
9437static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009438{
Arun Khandavallifae92942016-08-01 13:31:08 +05309439 int ret = -EINVAL;
9440
9441 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
9442 if (!wlan_loader) {
9443 pr_err("%s: memory alloc failed\n", __func__);
9444 ret = -ENOMEM;
9445 return ret;
9446 }
9447
9448 wlan_loader->boot_wlan_obj = NULL;
9449 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
9450 GFP_KERNEL);
9451 if (!wlan_loader->attr_group) {
9452 pr_err("%s: malloc attr_group failed\n", __func__);
9453 ret = -ENOMEM;
9454 goto error_return;
9455 }
9456
9457 wlan_loader->loaded_state = 0;
9458 wlan_loader->attr_group->attrs = attrs;
9459
9460 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
9461 kernel_kobj);
9462 if (!wlan_loader->boot_wlan_obj) {
9463 pr_err("%s: sysfs create and add failed\n", __func__);
9464 ret = -ENOMEM;
9465 goto error_return;
9466 }
9467
9468 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
9469 wlan_loader->attr_group);
9470 if (ret) {
9471 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
9472 goto error_return;
9473 }
9474
9475 return 0;
9476
9477error_return:
9478
9479 if (wlan_loader->boot_wlan_obj) {
9480 kobject_del(wlan_loader->boot_wlan_obj);
9481 wlan_loader->boot_wlan_obj = NULL;
9482 }
9483
9484 return ret;
9485}
9486
9487/**
9488 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
9489 *
9490 * Return: 0 on success or errno on failure
9491 */
9492static int wlan_deinit_sysfs(void)
9493{
9494
9495 if (!wlan_loader) {
9496 hdd_alert("wlan loader context is Null!");
9497 return -EINVAL;
9498 }
9499
9500 if (wlan_loader->boot_wlan_obj) {
9501 sysfs_remove_group(wlan_loader->boot_wlan_obj,
9502 wlan_loader->attr_group);
9503 kobject_del(wlan_loader->boot_wlan_obj);
9504 wlan_loader->boot_wlan_obj = NULL;
9505 }
9506
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009507 return 0;
9508}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009509
Arun Khandavallifae92942016-08-01 13:31:08 +05309510#endif
9511
9512#ifdef MODULE
9513/**
9514 * __hdd_module_init - Module init helper
9515 *
9516 * Module init helper function used by both module and static driver.
9517 *
9518 * Return: 0 for success, errno on failure
9519 */
9520static int hdd_module_init(void)
9521{
9522 int ret = 0;
9523
9524 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
9525 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9526
9527 if (__hdd_module_init()) {
9528 pr_err("%s: Failed to register handler\n", __func__);
9529 ret = -EINVAL;
9530 }
9531
9532 return ret;
9533}
9534#else
9535static int __init hdd_module_init(void)
9536{
9537 int ret = -EINVAL;
9538
9539 ret = wlan_init_sysfs();
Srinivas Girigowda5e7dafe2016-11-02 14:09:13 -07009540 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +05309541 pr_err("Failed to create sysfs entry for loading wlan");
9542
9543 return ret;
9544}
9545#endif
9546
9547
9548#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009549/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009550 * hdd_module_exit() - Exit function
9551 *
9552 * This is the driver exit point (invoked when module is unloaded using rmmod)
9553 *
9554 * Return: None
9555 */
9556static void __exit hdd_module_exit(void)
9557{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009558 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009559}
Arun Khandavallifae92942016-08-01 13:31:08 +05309560#else
9561static void __exit hdd_module_exit(void)
9562{
9563 __hdd_module_exit();
9564 wlan_deinit_sysfs();
9565}
9566#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009567
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009568static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
9569{
9570 return param_set_copystring(kmessage, kp);
9571}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009572
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309573/**
9574 * is_con_mode_valid() check con mode is valid or not
9575 * @mode: global con mode
9576 *
9577 * Return: TRUE on success FALSE on failure
9578 */
9579static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
9580{
9581 switch (mode) {
9582 case QDF_GLOBAL_MONITOR_MODE:
9583 case QDF_GLOBAL_FTM_MODE:
9584 case QDF_GLOBAL_EPPING_MODE:
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309585 case QDF_GLOBAL_MISSION_MODE:
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309586 return true;
9587 default:
9588 return false;
9589 }
9590}
9591
9592/**
9593 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
9594 * @mode: global con mode
9595 *
9596 * Return: adapter mode
9597 */
9598static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
9599 enum tQDF_GLOBAL_CON_MODE mode)
9600{
9601
9602 switch (mode) {
9603 case QDF_GLOBAL_MISSION_MODE:
9604 return QDF_STA_MODE;
9605 case QDF_GLOBAL_MONITOR_MODE:
9606 return QDF_MONITOR_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309607 case QDF_GLOBAL_EPPING_MODE:
9608 return QDF_EPPING_MODE;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309609 case QDF_GLOBAL_FTM_MODE:
9610 return QDF_FTM_MODE;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309611 case QDF_GLOBAL_QVIT_MODE:
9612 return QDF_QVIT_MODE;
9613 default:
9614 return QDF_MAX_NO_OF_MODE;
9615 }
9616}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009617
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309618static void hdd_cleanup_present_mode(hdd_context_t *hdd_ctx,
9619 enum tQDF_GLOBAL_CON_MODE curr_mode)
9620{
9621 switch (curr_mode) {
9622 case QDF_GLOBAL_MISSION_MODE:
9623 case QDF_GLOBAL_MONITOR_MODE:
9624 case QDF_GLOBAL_FTM_MODE:
9625 hdd_abort_mac_scan_all_adapters(hdd_ctx);
9626 hdd_stop_all_adapters(hdd_ctx);
9627 hdd_deinit_all_adapters(hdd_ctx, false);
9628 hdd_close_all_adapters(hdd_ctx, false);
9629 break;
9630 case QDF_GLOBAL_EPPING_MODE:
9631 epping_disable();
9632 epping_close();
9633 break;
9634 default:
9635 return;
9636 }
9637}
9638
9639static int hdd_register_req_mode(hdd_context_t *hdd_ctx,
9640 enum tQDF_GLOBAL_CON_MODE mode)
9641{
9642 hdd_adapter_t *adapter;
9643 int ret = 0;
9644 bool rtnl_held;
9645 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
9646 QDF_STATUS status;
9647
9648 if (!qdf_dev) {
9649 hdd_err("qdf device context is Null return!");
9650 return -EINVAL;
9651 }
9652
9653 rtnl_held = hdd_hold_rtnl_lock();
9654 switch (mode) {
9655 case QDF_GLOBAL_MISSION_MODE:
9656 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
9657 if (IS_ERR(adapter)) {
9658 hdd_alert("Failed to open interface, adapter is NULL");
9659 ret = -EINVAL;
9660 }
9661 break;
9662 case QDF_GLOBAL_FTM_MODE:
9663 adapter = hdd_open_adapter(hdd_ctx, QDF_FTM_MODE, "wlan%d",
9664 wlan_hdd_get_intf_addr(hdd_ctx),
9665 NET_NAME_UNKNOWN, rtnl_held);
9666 if (adapter == NULL)
9667 ret = -EINVAL;
9668 break;
9669 case QDF_GLOBAL_MONITOR_MODE:
9670 adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
9671 wlan_hdd_get_intf_addr(hdd_ctx),
9672 NET_NAME_UNKNOWN, rtnl_held);
9673 if (adapter == NULL)
9674 ret = -EINVAL;
9675 break;
9676 case QDF_GLOBAL_EPPING_MODE:
9677 status = epping_open();
9678 if (status != QDF_STATUS_SUCCESS) {
9679 hdd_err("Failed to open in eeping mode: %d", status);
9680 ret = -EINVAL;
9681 break;
9682 }
9683 ret = epping_enable(qdf_dev->dev);
9684 if (ret) {
9685 hdd_err("Failed to enable in epping mode : %d", ret);
9686 epping_close();
9687 }
9688 break;
9689 default:
9690 hdd_info("Mode not supported");
9691 ret = -ENOTSUPP;
9692 break;
9693 }
9694 hdd_release_rtnl_lock();
9695 rtnl_held = false;
9696 return ret;
9697}
9698
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009699/**
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309700 * __con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309701 * @kmessage: con mode name on which driver to be bring up
9702 * @kp: The associated kernel parameter
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309703 * @hdd_ctx: Pointer to the global HDD context
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009704 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309705 * This function is invoked when user updates con mode using sys entry,
9706 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009707 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309708 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009709 */
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309710static int __con_mode_handler(const char *kmessage, struct kernel_param *kp,
9711 hdd_context_t *hdd_ctx)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009712{
9713 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309714 hdd_adapter_t *adapter;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309715 enum tQDF_GLOBAL_CON_MODE curr_mode;
9716 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309717
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +05309718 ret = wlan_hdd_validate_context(hdd_ctx);
9719 if (ret)
9720 return ret;
9721
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309722 cds_set_load_in_progress(true);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009723
Arun Khandavallifae92942016-08-01 13:31:08 +05309724 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009725 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05309726
Arun Khandavallifae92942016-08-01 13:31:08 +05309727
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309728
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309729 if (!(is_con_mode_valid(con_mode))) {
9730 hdd_err("invlaid con_mode %d", con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309731 ret = -EINVAL;
9732 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309733 }
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309734
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309735 curr_mode = hdd_get_conparam();
9736 if (curr_mode == con_mode) {
9737 hdd_err("curr mode: %d is same as user triggered mode %d",
9738 curr_mode, con_mode);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309739 ret = 0;
9740 goto reset_flags;
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309741 }
9742
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309743 /* Cleanup present mode before switching to new mode */
9744 hdd_cleanup_present_mode(hdd_ctx, curr_mode);
Hanumanth Reddy Pothula9f4048f2016-09-30 15:06:57 +05309745
Prashanth Bhatta2ac92bd2016-10-11 16:08:00 -07009746 ret = hdd_wlan_stop_modules(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05309747 if (ret) {
9748 hdd_err("Stop wlan modules failed");
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309749 goto reset_flags;
9750 }
9751
9752 hdd_set_conparam(con_mode);
9753
9754 /* Register for new con_mode & then kick_start modules again */
9755 ret = hdd_register_req_mode(hdd_ctx, con_mode);
9756 if (ret) {
9757 hdd_err("Failed to register for new mode");
9758 goto reset_flags;
9759 }
9760
9761 adapter_mode = hdd_get_adpter_mode(con_mode);
9762 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
9763 hdd_err("invalid adapter");
9764 ret = -EINVAL;
9765 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309766 }
9767
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309768 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309769 if (!adapter) {
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309770 hdd_err("Failed to get adapter:%d", adapter_mode);
9771 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309772 }
9773
9774 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
9775 if (ret) {
9776 hdd_err("Start wlan modules failed: %d", ret);
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309777 goto reset_flags;
Arun Khandavallifae92942016-08-01 13:31:08 +05309778 }
9779
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309780 if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
9781 con_mode == QDF_GLOBAL_FTM_MODE) {
9782 if (hdd_start_adapter(adapter)) {
9783 hdd_err("Failed to start %s adapter", kmessage);
9784 ret = -EINVAL;
9785 goto reset_flags;
9786 }
Arun Khandavallifae92942016-08-01 13:31:08 +05309787 }
9788
Arun Khandavalli16fd1ee2016-10-08 17:47:07 +05309789 hdd_info("Mode successfully changed to %s", kmessage);
9790 ret = 0;
9791
9792reset_flags:
9793 cds_set_load_in_progress(false);
9794 return ret;
9795}
9796
9797
9798static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
9799{
9800 int ret;
9801 hdd_context_t *hdd_ctx;
9802
9803 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9804 ret = wlan_hdd_validate_context(hdd_ctx);
9805 if (ret)
9806 return ret;
9807
9808 cds_ssr_protect(__func__);
9809 ret = __con_mode_handler(kmessage, kp, hdd_ctx);
9810 cds_ssr_unprotect(__func__);
9811
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009812 return ret;
9813}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009814
9815/**
9816 * hdd_get_conparam() - driver exit point
9817 *
9818 * This is the driver exit point (invoked when module is unloaded using rmmod)
9819 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309820 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009821 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309822enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009823{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309824 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009825}
9826
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009827void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009828{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009829 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009830}
9831
Komal Seelamc11bb222016-01-27 18:57:10 +05309832/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309833 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9834 * @hdd_ctx: HDD context
9835 *
9836 * Cleans up the pre cac interface, if it exists
9837 *
9838 * Return: None
9839 */
9840void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9841{
9842 uint8_t session_id;
9843 QDF_STATUS status;
9844 struct hdd_adapter_s *precac_adapter;
9845
9846 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9847 if (QDF_IS_STATUS_ERROR(status)) {
9848 hdd_err("failed to get pre cac vdev id");
9849 return;
9850 }
9851
9852 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9853 if (!precac_adapter) {
9854 hdd_err("invalid pre cac adapater");
9855 return;
9856 }
9857
9858 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9859 wlan_hdd_sap_pre_cac_failure,
9860 (void *)precac_adapter);
9861 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9862
9863}
9864
9865/**
Komal Seelamec702b02016-02-24 18:42:16 +05309866 * hdd_update_ol_config - API to update ol configuration parameters
9867 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309868 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309869 * Return: void
9870 */
Komal Seelamec702b02016-02-24 18:42:16 +05309871static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309872{
Komal Seelamec702b02016-02-24 18:42:16 +05309873 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309874 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309875
Komal Seelamec702b02016-02-24 18:42:16 +05309876 if (!ol_ctx)
9877 return;
9878
9879 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9880 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9881 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9882 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -07009883 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +05309884
9885 ol_init_ini_config(ol_ctx, &cfg);
9886}
9887
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009888#ifdef FEATURE_RUNTIME_PM
9889/**
9890 * hdd_populate_runtime_cfg() - populate runtime configuration
9891 * @hdd_ctx: hdd context
9892 * @cfg: pointer to the configuration memory being populated
9893 *
9894 * Return: void
9895 */
9896static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9897 struct hif_config_info *cfg)
9898{
9899 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9900 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9901}
9902#else
9903static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9904 struct hif_config_info *cfg)
9905{
9906}
9907#endif
9908
Komal Seelamec702b02016-02-24 18:42:16 +05309909/**
9910 * hdd_update_hif_config - API to update HIF configuration parameters
9911 * @hdd_ctx: HDD Context
9912 *
9913 * Return: void
9914 */
9915static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9916{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309917 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309918 struct hif_config_info cfg;
9919
9920 if (!scn)
9921 return;
9922
9923 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009924 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05309925 hif_init_ini_config(scn, &cfg);
9926}
9927
9928/**
9929 * hdd_update_config() - Initialize driver per module ini parameters
9930 * @hdd_ctx: HDD Context
9931 *
9932 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309933 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05309934 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309935int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05309936{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309937 int ret;
9938
Komal Seelamec702b02016-02-24 18:42:16 +05309939 hdd_update_ol_config(hdd_ctx);
9940 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309941 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
9942 ret = hdd_update_cds_config_ftm(hdd_ctx);
9943 else
9944 ret = hdd_update_cds_config(hdd_ctx);
9945
9946 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05309947}
9948
Agrawal Ashish65634612016-08-18 13:24:32 +05309949/**
9950 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
9951 * @mode : cfg80211 DFS mode
9952 *
9953 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
9954 */
9955enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
9956{
9957 switch (mode) {
9958 case DFS_MODE_ENABLE:
9959 return ACS_DFS_MODE_ENABLE;
9960 break;
9961 case DFS_MODE_DISABLE:
9962 return ACS_DFS_MODE_DISABLE;
9963 break;
9964 case DFS_MODE_DEPRIORITIZE:
9965 return ACS_DFS_MODE_DEPRIORITIZE;
9966 break;
9967 default:
9968 hdd_err("ACS dfs mode is NONE");
9969 return ACS_DFS_MODE_NONE;
9970 }
9971}
9972
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309973/**
9974 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
9975 * @hddctx: pointer to hdd context
9976 * @set_value: enable/disable
9977 *
9978 * When Host sends vendor command enable, FW will send *ONE* CA ind to
9979 * Host(even though it is duplicate). When Host send vendor command
9980 * disable,FW doesn't perform any action. Whenever any change in
9981 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
9982 *
9983 * return - 0 on success, appropriate error values on failure.
9984 */
9985int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
9986{
9987 QDF_STATUS status;
9988
9989 if (0 != wlan_hdd_validate_context(hddctx)) {
9990 return -EAGAIN;
9991 }
9992
9993 if (!hddctx->config->goptimize_chan_avoid_event) {
9994 hdd_warn("goptimize_chan_avoid_event ini param disabled");
9995 return -EINVAL;
9996 }
9997
9998 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
9999 if (!QDF_IS_STATUS_SUCCESS(status)) {
10000 hdd_err("Failed to send chan avoid command to SME");
10001 return -EINVAL;
10002 }
10003 return 0;
10004}
Agrawal Ashish65634612016-08-18 13:24:32 +053010005
Varun Reddy Yeturudce1c562016-11-18 10:00:45 -080010006/**
10007 * hdd_set_roaming_in_progress() - to set the roaming in progress flag
10008 * @value: value to set
10009 *
10010 * This function will set the passed value to roaming in progress flag.
10011 *
10012 * Return: None
10013 */
10014void hdd_set_roaming_in_progress(bool value)
10015{
10016 hdd_context_t *hdd_ctx;
10017
10018 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10019 if (!hdd_ctx) {
10020 hdd_err("HDD context is NULL");
10021 return;
10022 }
10023
10024 hdd_ctx->roaming_in_progress = value;
10025 hdd_info("Roaming in Progress set to %d", value);
10026}
10027
10028/**
10029 * hdd_is_roaming_in_progress() - check if roaming is in progress
10030 * @hdd_ctx - HDD context
10031 *
10032 * Return: true if roaming is in progress else false
10033 */
10034bool hdd_is_roaming_in_progress(void)
10035{
10036 hdd_context_t *hdd_ctx;
10037
10038 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10039 if (!hdd_ctx) {
10040 hdd_err("HDD context is NULL");
10041 return false;
10042 }
10043 return hdd_ctx->roaming_in_progress;
10044}
10045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010046/* Register the module init/exit functions */
10047module_init(hdd_module_init);
10048module_exit(hdd_module_exit);
10049
10050MODULE_LICENSE("Dual BSD/GPL");
10051MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10052MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10053
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010054module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10055 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056
10057module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
10058 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
10059
10060module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
10061
10062module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
10063
10064module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);