blob: 7f6aac2791da87e88d936615745d97d04bc14b04 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
Jeff Johnson94be11c2016-08-15 15:39:25 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038/* Include Files */
39#include <wlan_hdd_includes.h>
40#include <cds_api.h>
41#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053042#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#ifdef WLAN_FEATURE_LPSS
44#include <cds_utils.h>
45#endif
46#include <linux/etherdevice.h>
47#include <linux/firmware.h>
48#include <wlan_hdd_tx_rx.h>
49#include <wni_api.h>
50#include <wlan_hdd_cfg.h>
51#include <wlan_ptt_sock_svc.h>
52#include <dbglog_host.h>
53#include <wlan_logging_sock_svc.h>
54#include <wlan_hdd_wowl.h>
55#include <wlan_hdd_misc.h>
56#include <wlan_hdd_wext.h>
57#include "wlan_hdd_trace.h"
58#include "wlan_hdd_ioctl.h"
59#include "wlan_hdd_ftm.h"
60#include "wlan_hdd_power.h"
61#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070062#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070065#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080066
67#include <net/addrconf.h>
68#include <linux/wireless.h>
69#include <net/cfg80211.h>
70#include <linux/inetdevice.h>
71#include <net/addrconf.h>
72#include "wlan_hdd_cfg80211.h"
73#include "wlan_hdd_ext_scan.h"
74#include "wlan_hdd_p2p.h"
75#include <linux/rtnetlink.h>
76#include "sap_api.h"
77#include <linux/semaphore.h>
78#include <linux/ctype.h>
79#include <linux/compat.h>
80#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081#include <soc/qcom/subsystem_restart.h>
82#endif
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -070083#include <soc/qcom/socinfo.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084#include <wlan_hdd_hostapd.h>
85#include <wlan_hdd_softap_tx_rx.h>
86#include "cfg_api.h"
87#include "qwlan_version.h"
88#include "wma_types.h"
89#include "wlan_hdd_tdls.h"
90#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053091#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080092#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070094#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080095#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096#include "wlan_hdd_nan.h"
97#include "wlan_hdd_debugfs.h"
98#include "wlan_hdd_driver_ops.h"
99#include "epping_main.h"
100#include "wlan_hdd_memdump.h"
101
102#include <wlan_hdd_ipa.h>
103#include "hif.h"
104#include "wma.h"
105#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700106#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530108#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700109#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530110#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700111#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530112#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700113#include <wlan_hdd_napi.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114
115#ifdef MODULE
116#define WLAN_MODULE_NAME module_name(THIS_MODULE)
117#else
118#define WLAN_MODULE_NAME "wlan"
119#endif
120
121#ifdef TIMER_MANAGER
122#define TIMER_MANAGER_STR " +TIMER_MANAGER"
123#else
124#define TIMER_MANAGER_STR ""
125#endif
126
127#ifdef MEMORY_DEBUG
128#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
129#else
130#define MEMORY_DEBUG_STR ""
131#endif
132
Arun Khandavallifae92942016-08-01 13:31:08 +0530133#ifndef MODULE
134static struct gwlan_loader *wlan_loader;
135static ssize_t wlan_boot_cb(struct kobject *kobj,
136 struct kobj_attribute *attr,
137 const char *buf, size_t count);
138struct gwlan_loader {
139 bool loaded_state;
140 struct kobject *boot_wlan_obj;
141 struct attribute_group *attr_group;
142};
143
144static struct kobj_attribute wlan_boot_attribute =
145 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
146
147static struct attribute *attrs[] = {
148 &wlan_boot_attribute.attr,
149 NULL,
150};
151
152#define MODULE_INITIALIZED 1
153#endif
154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155/* the Android framework expects this param even though we don't use it */
156#define BUF_LEN 20
157static char fwpath_buffer[BUF_LEN];
158static struct kparam_string fwpath = {
159 .string = fwpath_buffer,
160 .maxlen = BUF_LEN,
161};
162
163static char *country_code;
164static int enable_11d = -1;
165static int enable_dfs_chan_scan = -1;
166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167/*
168 * spinlock for synchronizing asynchronous request/response
169 * (full description of use in wlan_hdd_main.h)
170 */
171DEFINE_SPINLOCK(hdd_context_lock);
172
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800173#define WLAN_NLINK_CESIUM 30
174
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530175static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176
177#define WOW_MAX_FILTER_LISTS 1
178#define WOW_MAX_FILTERS_PER_LIST 4
179#define WOW_MIN_PATTERN_SIZE 6
180#define WOW_MAX_PATTERN_SIZE 64
181
182#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
183static const struct wiphy_wowlan_support wowlan_support_reg_init = {
184 .flags = WIPHY_WOWLAN_ANY |
185 WIPHY_WOWLAN_MAGIC_PKT |
186 WIPHY_WOWLAN_DISCONNECT |
187 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
188 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
189 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
190 WIPHY_WOWLAN_4WAY_HANDSHAKE |
191 WIPHY_WOWLAN_RFKILL_RELEASE,
192 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
193 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
194 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
195};
196#endif
197
198/* internal function declaration */
199
200struct sock *cesium_nl_srv_sock;
201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800202#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
203void wlan_hdd_auto_shutdown_cb(void);
204#endif
205
206/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530207 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
208 * @hdd_ctx: pointer to hdd_context_t
209 *
210 * Return: none
211 */
212void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
213{
214 hdd_adapter_t *adapter;
215 hdd_adapter_list_node_t *adapter_node, *next;
216 QDF_STATUS status = QDF_STATUS_SUCCESS;
217
218 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
219 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
220 adapter = adapter_node->pAdapter;
221 if (NULL != adapter)
222 hdd_send_rps_ind(adapter);
223 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
224 adapter_node = next;
225 }
226}
227
228/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
230 * @vdev_id: vdev_id
231 * @action: action type
232 * @reason: reason type
233 *
234 * Return: none
235 */
236void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
237 enum netif_action_type action, enum netif_reason_type reason)
238{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530239 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800240 hdd_adapter_t *adapter;
241
242 if (!hdd_ctx) {
243 hdd_err("hdd ctx is NULL");
244 return;
245 }
246 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
247
248 wlan_hdd_netif_queue_control(adapter, action, reason);
249 return;
250}
251
252/*
253 * Store WLAN driver version info in a global variable such that crash debugger
254 * can extract it from driver debug symbol and crashdump for post processing
255 */
256uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
257
258/**
259 * hdd_device_mode_to_string() - return string conversion of device mode
260 * @device_mode: device mode
261 *
262 * This utility function helps log string conversion of device mode.
263 *
264 * Return: string conversion of device mode, if match found;
265 * "Unknown" otherwise.
266 */
267const char *hdd_device_mode_to_string(uint8_t device_mode)
268{
269 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800270 CASE_RETURN_STRING(QDF_STA_MODE);
271 CASE_RETURN_STRING(QDF_SAP_MODE);
272 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
273 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
274 CASE_RETURN_STRING(QDF_FTM_MODE);
275 CASE_RETURN_STRING(QDF_IBSS_MODE);
276 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
277 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700278 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 default:
280 return "Unknown";
281 }
282}
283
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530284/**
285 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
286 * @adapter: HDD adapter
287 * @chan_number: Channel number
288 * @chan_bw: Bandwidth
289 *
290 * Checks if the given bandwidth is valid for the given channel number.
291 *
292 * Return: 0 for success, non-zero for failure
293 */
294int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
295 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800296 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530297{
298 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
299 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
300 bool found = false;
301 tHalHandle hal;
302
303 hal = WLAN_HDD_GET_HAL_CTX(adapter);
304 if (!hal) {
305 hdd_err("Invalid HAL context");
306 return -EINVAL;
307 }
308
309 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
310 hdd_err("No valid channel list");
311 return -EOPNOTSUPP;
312 }
313
314 for (i = 0; i < len; i++) {
315 if (chan[i] == chan_number) {
316 found = true;
317 break;
318 }
319 }
320
321 if (found == false) {
322 hdd_err("Channel not in driver's valid channel list");
323 return -EOPNOTSUPP;
324 }
325
326 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
327 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
328 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
329 return -EINVAL;
330 }
331
332 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
333 if (chan_bw == CH_WIDTH_80MHZ) {
334 hdd_err("BW80 not possible in 2.4GHz band");
335 return -EINVAL;
336 }
337 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
338 (chan_bw != CH_WIDTH_MAX)) {
339 hdd_err("Only BW20 possible on channel 14");
340 return -EINVAL;
341 }
342 }
343
344 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
345 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
346 (chan_bw != CH_WIDTH_MAX)) {
347 hdd_err("Only BW20 possible on channel 165");
348 return -EINVAL;
349 }
350 }
351
352 return 0;
353}
354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355static int __hdd_netdev_notifier_call(struct notifier_block *nb,
356 unsigned long state, void *data)
357{
358#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
359 struct netdev_notifier_info *dev_notif_info = data;
360 struct net_device *dev = dev_notif_info->dev;
361#else
362 struct net_device *dev = data;
363#endif
364 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
365 hdd_context_t *hdd_ctx;
366
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800367 ENTER_DEV(dev);
368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369 /* Make sure that this callback corresponds to our device. */
370 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
371 return NOTIFY_DONE;
372
373 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
374 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700375 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 return NOTIFY_DONE;
377 }
378
379 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700380 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800381 return NOTIFY_DONE;
382 }
383
384 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
385 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700386 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530387 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 return NOTIFY_DONE;
389 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800390 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 return NOTIFY_DONE;
392
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700393 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394 dev->name, state);
395
396 switch (state) {
397 case NETDEV_REGISTER:
398 break;
399
400 case NETDEV_UNREGISTER:
401 break;
402
403 case NETDEV_UP:
404 sme_ch_avoid_update_req(hdd_ctx->hHal);
405 break;
406
407 case NETDEV_DOWN:
408 break;
409
410 case NETDEV_CHANGE:
411 if (true == adapter->isLinkUpSvcNeeded)
412 complete(&adapter->linkup_event_var);
413 break;
414
415 case NETDEV_GOING_DOWN:
416 if (adapter->scan_info.mScanPending != false) {
417 unsigned long rc;
418 INIT_COMPLETION(adapter->scan_info.
419 abortscan_event_var);
420 hdd_abort_mac_scan(adapter->pHddCtx,
421 adapter->sessionId,
422 eCSR_SCAN_ABORT_DEFAULT);
423 rc = wait_for_completion_timeout(
424 &adapter->scan_info.abortscan_event_var,
425 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
426 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700427 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 }
429 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700430 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431 }
432 break;
433
434 default:
435 break;
436 }
437
438 return NOTIFY_DONE;
439}
440
441/**
442 * hdd_netdev_notifier_call() - netdev notifier callback function
443 * @nb: pointer to notifier block
444 * @state: state
445 * @ndev: ndev pointer
446 *
447 * Return: 0 on success, error number otherwise.
448 */
449static int hdd_netdev_notifier_call(struct notifier_block *nb,
450 unsigned long state,
451 void *ndev)
452{
453 int ret;
454
455 cds_ssr_protect(__func__);
456 ret = __hdd_netdev_notifier_call(nb, state, ndev);
457 cds_ssr_unprotect(__func__);
458
459 return ret;
460}
461
462struct notifier_block hdd_netdev_notifier = {
463 .notifier_call = hdd_netdev_notifier_call,
464};
465
466/* variable to hold the insmod parameters */
467static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800468
469/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800470static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530472/**
473 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
474 * @ch_width: NL channel width
475 *
476 * Converts the NL channel width to the driver's internal representation
477 *
478 * Return: Converted channel width. In case of non matching NL channel width,
479 * CH_WIDTH_MAX will be returned.
480 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800481enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530482{
483 switch (ch_width) {
484 case NL80211_CHAN_WIDTH_20_NOHT:
485 case NL80211_CHAN_WIDTH_20:
486 return CH_WIDTH_20MHZ;
487 case NL80211_CHAN_WIDTH_40:
488 return CH_WIDTH_40MHZ;
489 break;
490 case NL80211_CHAN_WIDTH_80:
491 return CH_WIDTH_80MHZ;
492 case NL80211_CHAN_WIDTH_80P80:
493 return CH_WIDTH_80P80MHZ;
494 case NL80211_CHAN_WIDTH_160:
495 return CH_WIDTH_160MHZ;
496 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800497 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530498 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800499 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530500 default:
501 hdd_err("Invalid channel width %d, setting to default",
502 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800503 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530504 }
505}
506
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530507/* wlan_hdd_find_opclass() - Find operating class for a channel
508 * @hal: handler to HAL
509 * @channel: channel id
510 * @bw_offset: bandwidth offset
511 *
512 * Function invokes sme api to find the operating class
513 *
514 * Return: operating class
515 */
516uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
517 uint8_t bw_offset)
518{
519 uint8_t opclass = 0;
520
521 sme_get_opclass(hal, channel, bw_offset, &opclass);
522 return opclass;
523}
524
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530526 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800527 * @moduleId: Module whose trace level is being configured
528 * @bitmask: Bitmask of log levels to be enabled
529 *
530 * Called immediately after the cfg.ini is read in order to configure
531 * the desired trace levels.
532 *
533 * Return: None
534 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530535static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530537 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538
539 /*
540 * if the bitmask is the default value, then a bitmask was not
541 * specified in cfg.ini, so leave the logging level alone (it
542 * will remain at the "compiled in" default value)
543 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530544 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545 return;
546 }
547
548 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530549 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550
551 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530552 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 while (0 != bitmask) {
554 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530555 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 }
557 level++;
558 bitmask >>= 1;
559 }
560}
561
562/**
563 * wlan_hdd_validate_context() - check the HDD context
564 * @hdd_ctx: HDD context pointer
565 *
566 * Return: 0 if the context is valid. Error code otherwise
567 */
568int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
569{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800570 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530571 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 return -ENODEV;
573 }
574
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800575 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530576 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
577 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 return -EAGAIN;
579 }
580
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800581 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530582 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
583 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584 return -EAGAIN;
585 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530586
587 if (hdd_ctx->start_modules_in_progress ||
588 hdd_ctx->stop_modules_in_progress) {
589 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
590 (void *)_RET_IP_);
591 return -EAGAIN;
592 }
593
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594 return 0;
595}
596
597void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
598{
599 hdd_adapter_t *adapter = NULL;
600 hdd_station_ctx_t *pHddStaCtx = NULL;
601 eCsrPhyMode phyMode;
602 struct hdd_config *cfg_param = NULL;
603
604 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700605 hdd_alert("HDD Context is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606 return;
607 }
608
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800609 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 if (NULL == adapter) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700611 hdd_alert("adapter is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612 return;
613 }
614
615 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
616
617 cfg_param = hdd_ctx->config;
618 if (NULL == cfg_param) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700619 hdd_alert("cfg_params not available !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 return;
621 }
622
623 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
624
625 if (!hdd_ctx->isVHT80Allowed) {
626 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
627 (eCSR_DOT11_MODE_11ac == phyMode) ||
628 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700629 hdd_notice("Setting phymode to 11n!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
631 eCSR_DOT11_MODE_11n);
632 }
633 } else {
634 /*
635 * New country Supports 11ac as well resetting value back from
636 * .ini
637 */
638 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
639 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
640 dot11Mode));
641 return;
642 }
643
644 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
645 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
646 || (eCSR_CFG_DOT11_MODE_11AC ==
647 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530648 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649
650 /* need to issue a disconnect to CSR. */
651 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530652 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 adapter->sessionId,
654 eCSR_DISCONNECT_REASON_UNSPECIFIED);
655
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530656 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 unsigned long rc;
658
659 rc = wait_for_completion_timeout(
660 &adapter->disconnect_comp_var,
661 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
662 if (!rc)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700663 hdd_err("failure waiting for disconnect_comp_var");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 }
665 }
666}
667
668/**
669 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
670 * @hdd_adapter_t Hdd adapter.
671 *
672 * This function sets the IBSS power save config parameters to WMA
673 * which will send it to firmware if FW supports IBSS power save
674 * before vdev start.
675 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 * on failure.
678 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530679QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680{
681 int ret;
682 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
683
684 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700685 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530686 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 }
688
689 ret = wma_cli_set_command(adapter->sessionId,
690 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
691 hdd_ctx->config->ibssATIMWinSize,
692 VDEV_CMD);
693 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700694 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530695 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 }
697
698 ret = wma_cli_set_command(adapter->sessionId,
699 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
700 hdd_ctx->config->isIbssPowerSaveAllowed,
701 VDEV_CMD);
702 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700703 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
704 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530705 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 }
707
708 ret = wma_cli_set_command(adapter->sessionId,
709 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
710 hdd_ctx->config->
711 isIbssPowerCollapseAllowed, VDEV_CMD);
712 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700713 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
714 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530715 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 }
717
718 ret = wma_cli_set_command(adapter->sessionId,
719 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
720 hdd_ctx->config->isIbssAwakeOnTxRx,
721 VDEV_CMD);
722 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700723 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530724 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725 }
726
727 ret = wma_cli_set_command(adapter->sessionId,
728 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
729 hdd_ctx->config->ibssInactivityCount,
730 VDEV_CMD);
731 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700732 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530733 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800734 }
735
736 ret = wma_cli_set_command(adapter->sessionId,
737 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
738 hdd_ctx->config->ibssTxSpEndInactivityTime,
739 VDEV_CMD);
740 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700741 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
742 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530743 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744 }
745
746 ret = wma_cli_set_command(adapter->sessionId,
747 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
748 hdd_ctx->config->ibssPsWarmupTime,
749 VDEV_CMD);
750 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700751 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
752 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530753 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754 }
755
756 ret = wma_cli_set_command(adapter->sessionId,
757 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
758 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
759 VDEV_CMD);
760 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700761 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
762 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530763 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 }
765
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767}
768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769#define INTF_MACADDR_MASK 0x7
770
771/**
772 * hdd_update_macaddr() - update mac address
773 * @config: hdd configuration
774 * @hw_macaddr: mac address
775 *
776 * Mac address for multiple virtual interface is found as following
777 * i) The mac address of the first interface is just the actual hw mac address.
778 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
779 * define the mac address for the remaining interfaces and locally
780 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
781 * supported virtual interfaces, right now this is 0x07 (meaning 8
782 * interface).
783 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
784 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
785 *
786 * Return: None
787 */
788void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530789 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790{
791 int8_t i;
792 uint8_t macaddr_b3, tmp_br3;
793
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530794 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530795 QDF_MAC_ADDR_SIZE);
796 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530797 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530798 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 macaddr_b3 = config->intfMacAddr[i].bytes[3];
800 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
801 INTF_MACADDR_MASK;
802 macaddr_b3 += tmp_br3;
803
804 /* XOR-ing bit-24 of the mac address. This will give enough
805 * mac address range before collision
806 */
807 macaddr_b3 ^= (1 << 7);
808
809 /* Set locally administered bit */
810 config->intfMacAddr[i].bytes[0] |= 0x02;
811 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700812 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 MAC_ADDRESS_STR, i,
814 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
815 }
816}
817
818static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
819 struct wma_tgt_services *cfg)
820{
821 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822
823 /* Set up UAPSD */
824 config->apUapsdEnabled &= cfg->uapsd;
825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 /* 11AC mode support */
827 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
828 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
829 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830
831 /* ARP offload: override user setting if invalid */
832 config->fhostArpOffload &= cfg->arp_offload;
833
834#ifdef FEATURE_WLAN_SCAN_PNO
835 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700836 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837 if (cfg->pno_offload)
838 config->PnoOffload = true;
839#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840#ifdef FEATURE_WLAN_TDLS
841 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530842 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
843 cfg->en_tdls_offchan;
844 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
845 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
847 config->fEnableTDLSSleepSta = true;
848 } else {
849 config->fEnableTDLSSleepSta = false;
850 }
851#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852#ifdef WLAN_FEATURE_ROAM_OFFLOAD
853 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
854#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700855 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800856
857}
858
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700859/**
860 * hdd_update_vdev_nss() - sets the vdev nss
861 * @hdd_ctx: HDD context
862 *
863 * Sets the Nss per vdev type based on INI
864 *
865 * Return: None
866 */
867static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
868{
869 struct hdd_config *cfg_ini = hdd_ctx->config;
870 uint8_t max_supp_nss = 1;
871
872 if (cfg_ini->enable2x2)
873 max_supp_nss = 2;
874
875 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
876 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
877
878 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
879 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
880}
881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
883 struct wma_tgt_ht_cap *cfg)
884{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530885 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 uint32_t value, val32;
887 uint16_t val16;
888 struct hdd_config *pconfig = hdd_ctx->config;
889 tSirMacHTCapabilityInfo *phtCapInfo;
890 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
891 uint8_t enable_tx_stbc;
892
893 /* check and update RX STBC */
894 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
895 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
896
897 /* get the MPDU density */
898 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
899
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530900 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700901 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 value = 0;
903 }
904
905 /*
906 * MPDU density:
907 * override user's setting if value is larger
908 * than the one supported by target
909 */
910 if (value > cfg->mpdu_density) {
911 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
912 cfg->mpdu_density);
913
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 MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 }
917
918 /* get the HT capability info */
919 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530920 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700921 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 return;
923 }
924 val16 = (uint16_t) val32;
925 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
926
927 /* Set the LDPC capability */
928 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
929
930 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
931 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
932
933 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
934 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
935
936 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
937 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
938
939 enable_tx_stbc = pconfig->enableTxSTBC;
940
941 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
942 pconfig->enable2x2 = 1;
943 } else {
944 pconfig->enable2x2 = 0;
945 enable_tx_stbc = 0;
946
947 /* 1x1 */
948 /* Update Rx Highest Long GI data Rate */
949 if (sme_cfg_set_int(hdd_ctx->hHal,
950 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700951 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530952 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700953 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954 }
955
956 /* Update Tx Highest Long GI data Rate */
957 if (sme_cfg_set_int
958 (hdd_ctx->hHal,
959 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700960 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700962 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 }
964 }
965 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
966 enable_tx_stbc = 0;
967 phtCapInfo->txSTBC = enable_tx_stbc;
968
969 val32 = val16;
970 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530971 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700972 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800973#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
974 value = SIZE_OF_SUPPORTED_MCS_SET;
975 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530976 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700977 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978
979 if (pconfig->enable2x2) {
980 for (value = 0; value < cfg->num_rf_chains; value++)
981 mcs_set[value] =
982 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
983
984 status =
985 sme_cfg_set_str(hdd_ctx->hHal,
986 WNI_CFG_SUPPORTED_MCS_SET,
987 mcs_set,
988 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530989 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700990 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 }
992 }
993#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
994}
995
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
997 struct wma_tgt_vht_cap *cfg)
998{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530999 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 uint32_t value = 0;
1001 struct hdd_config *pconfig = hdd_ctx->config;
1002 struct wiphy *wiphy = hdd_ctx->wiphy;
1003 struct ieee80211_supported_band *band_5g =
1004 wiphy->bands[IEEE80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001005 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006
1007 /* Get the current MPDU length */
1008 status =
1009 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1010 &value);
1011
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301012 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001013 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001014 value = 0;
1015 }
1016
1017 /*
1018 * VHT max MPDU length:
1019 * override if user configured value is too high
1020 * that the target cannot support
1021 */
1022 if (value > cfg->vht_max_mpdu) {
1023 status = sme_cfg_set_int(hdd_ctx->hHal,
1024 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1025 cfg->vht_max_mpdu);
1026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301027 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001028 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001029 }
1030 }
1031
1032 /* Get the current supported chan width */
1033 status = sme_cfg_get_int(hdd_ctx->hHal,
1034 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1035 &value);
1036
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301037 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001038 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039 value = 0;
1040 }
1041
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001042 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1043 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1044
1045 if (pconfig->enable2x2)
1046 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1047
1048 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1049 QDF_STATUS_E_FAILURE) {
1050 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1051 }
1052
1053 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1054 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1055 if (pconfig->enable2x2)
1056 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1057
1058 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1059 QDF_STATUS_E_FAILURE) {
1060 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1061 }
1062
1063 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1064 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1065 if (pconfig->enable2x2)
1066 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1067
1068 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1069 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1070
1071 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1072 QDF_STATUS_E_FAILURE) {
1073 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1074 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001076 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001077 &value);
1078
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301079 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001080 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001081 value = 0;
1082 }
1083
1084 /* Set the LDPC capability */
1085 if (value && !cfg->vht_rx_ldpc) {
1086 status = sme_cfg_set_int(hdd_ctx->hHal,
1087 WNI_CFG_VHT_LDPC_CODING_CAP,
1088 cfg->vht_rx_ldpc);
1089
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301090 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001091 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092 }
1093 }
1094
1095 /* Get current GI 80 value */
1096 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1097 &value);
1098
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301099 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001100 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101 value = 0;
1102 }
1103
1104 /* set the Guard interval 80MHz */
1105 if (value && !cfg->vht_short_gi_80) {
1106 status = sme_cfg_set_int(hdd_ctx->hHal,
1107 WNI_CFG_VHT_SHORT_GI_80MHZ,
1108 cfg->vht_short_gi_80);
1109
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301110 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001111 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001112 }
1113 }
1114
1115 /* Get current GI 160 value */
1116 status = sme_cfg_get_int(hdd_ctx->hHal,
1117 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1118 &value);
1119
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301120 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001121 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001122 value = 0;
1123 }
1124
1125 /* Get VHT TX STBC cap */
1126 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1127
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301128 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001129 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130 value = 0;
1131 }
1132
1133 /* VHT TX STBC cap */
1134 if (value && !cfg->vht_tx_stbc) {
1135 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1136 cfg->vht_tx_stbc);
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 TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 }
1141 }
1142
1143 /* Get VHT RX STBC cap */
1144 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1145
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301146 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001147 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 value = 0;
1149 }
1150
1151 /* VHT RX STBC cap */
1152 if (value && !cfg->vht_rx_stbc) {
1153 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1154 cfg->vht_rx_stbc);
1155
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301156 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001157 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158 }
1159 }
1160
1161 /* Get VHT SU Beamformer cap */
1162 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1163 &value);
1164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301165 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001166 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001167 value = 0;
1168 }
1169
1170 /* set VHT SU Beamformer cap */
1171 if (value && !cfg->vht_su_bformer) {
1172 status = sme_cfg_set_int(hdd_ctx->hHal,
1173 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1174 cfg->vht_su_bformer);
1175
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301176 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001177 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001178 }
1179 }
1180
1181 /* check and update SU BEAMFORMEE capabality */
1182 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1183 pconfig->enableTxBF = cfg->vht_su_bformee;
1184
1185 status = sme_cfg_set_int(hdd_ctx->hHal,
1186 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1187 pconfig->enableTxBF);
1188
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301189 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001190 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001191 }
1192
1193 /* Get VHT MU Beamformer cap */
1194 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1195 &value);
1196
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301197 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001198 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 value = 0;
1200 }
1201
1202 /* set VHT MU Beamformer cap */
1203 if (value && !cfg->vht_mu_bformer) {
1204 status = sme_cfg_set_int(hdd_ctx->hHal,
1205 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1206 cfg->vht_mu_bformer);
1207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301208 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001209 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210 }
1211 }
1212
1213 /* Get VHT MU Beamformee cap */
1214 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1215 &value);
1216
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301217 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001218 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 value = 0;
1220 }
1221
1222 /* set VHT MU Beamformee cap */
1223 if (value && !cfg->vht_mu_bformee) {
1224 status = sme_cfg_set_int(hdd_ctx->hHal,
1225 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1226 cfg->vht_mu_bformee);
1227
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301228 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001229 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 }
1231 }
1232
1233 /* Get VHT MAX AMPDU Len exp */
1234 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1235 &value);
1236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301237 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001238 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 value = 0;
1240 }
1241
1242 /*
1243 * VHT max AMPDU len exp:
1244 * override if user configured value is too high
1245 * that the target cannot support.
1246 * Even though Rome publish ampdu_len=7, it can
1247 * only support 4 because of some h/w bug.
1248 */
1249
1250 if (value > cfg->vht_max_ampdu_len_exp) {
1251 status = sme_cfg_set_int(hdd_ctx->hHal,
1252 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1253 cfg->vht_max_ampdu_len_exp);
1254
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301255 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001256 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 }
1258 }
1259
1260 /* Get VHT TXOP PS CAP */
1261 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1262
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301263 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001264 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 value = 0;
1266 }
1267
1268 /* set VHT TXOP PS cap */
1269 if (value && !cfg->vht_txop_ps) {
1270 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1271 cfg->vht_txop_ps);
1272
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301273 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001274 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001275 }
1276 }
1277
1278 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1279 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1280 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1281 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1282 else
1283 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1284
1285
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001286 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 band_5g->vht_cap.cap |=
1288 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001289 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001290 band_5g->vht_cap.cap |=
1291 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001292
1293 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1294 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1295
1296 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1297 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1298 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1299 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1300
1301 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1302 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1303
1304 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1305 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1306 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1307 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1308 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1309 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1310
1311 band_5g->vht_cap.cap |=
1312 (cfg->vht_max_ampdu_len_exp <<
1313 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1314
1315 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1316 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1317 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1318 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1319 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1320 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1321 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1322 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1323
1324 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1325 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1326
1327}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001328
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001329/**
1330 * hdd_generate_macaddr_auto() - Auto-generate mac address
1331 * @hdd_ctx: Pointer to the HDD context
1332 *
1333 * Auto-generate mac address using device serial number.
1334 * Keep the first 3 bytes of OUI as before and replace
1335 * the last 3 bytes with the lower 3 bytes of serial number.
1336 *
1337 * Return: 0 for success
1338 * Non zero failure code for errors
1339 */
1340static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1341{
1342 unsigned int serialno = 0;
1343 struct qdf_mac_addr mac_addr = {
1344 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1345 };
1346
1347 serialno = socinfo_get_serial_number();
1348 if (serialno == 0)
1349 return -EINVAL;
1350
1351 serialno &= 0x00ffffff;
1352
1353 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1354 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1355 mac_addr.bytes[5] = serialno & 0xff;
1356
1357 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1358 return 0;
1359}
1360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361void hdd_update_tgt_cfg(void *context, void *param)
1362{
1363 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1364 struct wma_tgt_cfg *cfg = param;
1365 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001366 struct cds_config_info *cds_cfg = cds_get_ini_config();
1367
1368 if (cds_cfg) {
1369 if (hdd_ctx->config->enable_sub_20_channel_width !=
1370 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1371 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1372 cds_cfg->sub_20_channel_width =
1373 WLAN_SUB_20_CH_WIDTH_NONE;
1374 } else {
1375 cds_cfg->sub_20_channel_width =
1376 hdd_ctx->config->enable_sub_20_channel_width;
1377 }
1378 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379
1380 /* first store the INI band capability */
1381 temp_band_cap = hdd_ctx->config->nBandCapability;
1382
1383 hdd_ctx->config->nBandCapability = cfg->band_cap;
1384
1385 /* now overwrite the target band capability with INI
1386 setting if INI setting is a subset */
1387
1388 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1389 (temp_band_cap != eCSR_BAND_ALL))
1390 hdd_ctx->config->nBandCapability = temp_band_cap;
1391 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1392 (temp_band_cap != eCSR_BAND_ALL) &&
1393 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001394 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395 }
1396
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001397 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1399 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1400 }
1401
1402 /* This can be extended to other configurations like ht, vht cap... */
1403
Anurag Chouhanc5548422016-02-24 18:33:27 +05301404 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1406 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001407 static struct qdf_mac_addr default_mac_addr = {
1408 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1409 };
1410 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1411 &default_mac_addr)) {
1412 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1413 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1414 MAC_ADDRESS_STR,
1415 MAC_ADDR_ARRAY(hdd_ctx->config->
1416 intfMacAddr[0].bytes));
1417 } else {
1418 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1419 MAC_ADDRESS_STR,
1420 MAC_ADDR_ARRAY(hdd_ctx->config->
1421 intfMacAddr[0].bytes));
1422 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001423 }
1424
1425 hdd_ctx->target_fw_version = cfg->target_fw_version;
1426
1427 hdd_ctx->max_intf_count = cfg->max_intf_count;
1428
1429#ifdef WLAN_FEATURE_LPSS
1430 hdd_ctx->lpss_support = cfg->lpss_support;
1431#endif
1432
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001433 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1436 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1437
1438 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1439
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001441
1442 hdd_update_vdev_nss(hdd_ctx);
1443
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001444 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001445 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001446 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001447 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001448
1449 hdd_ctx->current_antenna_mode =
1450 (hdd_ctx->config->enable2x2 == 0x01) ?
1451 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1452 hdd_info("Init current antenna mode: %d",
1453 hdd_ctx->current_antenna_mode);
1454
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001455 hdd_info("Target BPF %d Host BPF %d",
1456 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1457 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1458 hdd_ctx->config->bpf_packet_filter_enable);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301459
Arun Khandavallid454d422016-08-17 12:47:05 +05301460 /*
1461 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1462 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1463 * configure the STA mode wow pattern.
1464 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301465 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301466 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301467
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001468 /* Configure NAN datapath features */
1469 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470}
1471
1472/**
1473 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1474 * @context: HDD context pointer
1475 * @param: HDD radar indication pointer
1476 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001477 * This function is invoked in atomic context when a radar
1478 * is found on the SAP current operating channel and Data Tx
1479 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001480 * Actions: Stop the netif Tx queues,Indicate Radar present
1481 * in HDD context for future usage.
1482 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301483 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001484 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301485bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001486{
1487 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1488 struct wma_dfs_radar_ind *hdd_radar_event =
1489 (struct wma_dfs_radar_ind *)param;
1490 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1491 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301492 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301493 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301495 if (!hdd_ctx || !hdd_radar_event ||
1496 hdd_ctx->config->disableDFSChSwitch)
1497 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498
1499 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001500 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301501 /*
1502 * Application already triggered channel switch
1503 * on current channel, so return here.
1504 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301505 return false;
1506 }
1507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301509 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001510 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301511 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1512 if ((QDF_SAP_MODE == adapter->device_mode ||
1513 QDF_P2P_GO_MODE == adapter->device_mode) &&
1514 (CHANNEL_STATE_DFS ==
1515 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1517 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301518 hdd_info("tx blocked for session:%d",
1519 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520 }
1521
1522 status = hdd_get_next_adapter(hdd_ctx,
1523 adapterNode,
1524 &pNext);
1525 adapterNode = pNext;
1526 }
1527 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301528
1529 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001530}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001531
1532/**
1533 * hdd_is_valid_mac_address() - validate MAC address
1534 * @pMacAddr: Pointer to the input MAC address
1535 *
1536 * This function validates whether the given MAC address is valid or not
1537 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1538 * where X is the hexa decimal digit character and separated by ':'
1539 * This algorithm works even if MAC address is not separated by ':'
1540 *
1541 * This code checks given input string mac contains exactly 12 hexadecimal
1542 * digits and a separator colon : appears in the input string only after
1543 * an even number of hex digits.
1544 *
1545 * Return: 1 for valid and 0 for invalid
1546 */
1547bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1548{
1549 int xdigit = 0;
1550 int separator = 0;
1551 while (*pMacAddr) {
1552 if (isxdigit(*pMacAddr)) {
1553 xdigit++;
1554 } else if (':' == *pMacAddr) {
1555 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1556 break;
1557
1558 ++separator;
1559 } else {
1560 /* Invalid MAC found */
1561 return 0;
1562 }
1563 ++pMacAddr;
1564 }
1565 return xdigit == 12 && (separator == 5 || separator == 0);
1566}
1567
1568/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301569 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1570 * @dev: Handle to struct net_device to be updated.
1571 *
1572 * Return: None
1573 */
1574static void hdd_mon_mode_ether_setup(struct net_device *dev)
1575{
1576 dev->header_ops = NULL;
1577 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1578 dev->hard_header_len = ETH_HLEN;
1579 dev->mtu = ETH_DATA_LEN;
1580 dev->addr_len = ETH_ALEN;
1581 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1582 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1583 dev->priv_flags |= IFF_TX_SKB_SHARING;
1584
1585 memset(dev->broadcast, 0xFF, ETH_ALEN);
1586}
1587
1588/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001589 * __hdd__mon_open() - HDD Open function
1590 * @dev: Pointer to net_device structure
1591 *
1592 * This is called in response to ifconfig up
1593 *
1594 * Return: 0 for success; non-zero for failure
1595 */
1596static int __hdd_mon_open(struct net_device *dev)
1597{
1598 int ret;
1599
1600 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301601 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001602 ret = hdd_set_mon_rx_cb(dev);
1603 return ret;
1604}
1605
1606/**
1607 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1608 * @dev: Pointer to net_device structure
1609 *
1610 * This is called in response to ifconfig up
1611 *
1612 * Return: 0 for success; non-zero for failure
1613 */
1614int hdd_mon_open(struct net_device *dev)
1615{
1616 int ret;
1617
1618 cds_ssr_protect(__func__);
1619 ret = __hdd_mon_open(dev);
1620 cds_ssr_unprotect(__func__);
1621
1622 return ret;
1623}
1624
1625/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301626 * hdd_start_adapter() - Wrapper function for device specific adapter
1627 * @adapter: pointer to HDD adapter
1628 *
1629 * This function is called to start the device specific adapter for
1630 * the mode passed in the adapter's device_mode.
1631 *
1632 * Return: 0 for success; non-zero for failure
1633 */
1634int hdd_start_adapter(hdd_adapter_t *adapter)
1635{
1636
1637 int ret;
1638 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1639
1640 ENTER_DEV(adapter->dev);
1641 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1642
1643 switch (device_mode) {
1644 case QDF_P2P_CLIENT_MODE:
1645 case QDF_P2P_DEVICE_MODE:
1646 case QDF_OCB_MODE:
1647 case QDF_STA_MODE:
1648 case QDF_MONITOR_MODE:
1649 ret = hdd_start_station_adapter(adapter);
1650 if (ret)
1651 goto err_start_adapter;
1652 break;
1653 case QDF_P2P_GO_MODE:
1654 case QDF_SAP_MODE:
1655 ret = hdd_start_ap_adapter(adapter);
1656 if (ret)
1657 goto err_start_adapter;
1658 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301659 case QDF_IBSS_MODE:
1660 /*
1661 * For IBSS interface is initialized as part of
1662 * hdd_init_station_mode()
1663 */
1664 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301665 case QDF_FTM_MODE:
1666 ret = hdd_start_ftm_adapter(adapter);
1667 if (ret)
1668 goto err_start_adapter;
1669 break;
1670 default:
1671 hdd_err("Invalid session type %d", device_mode);
1672 QDF_ASSERT(0);
1673 goto err_start_adapter;
1674 }
1675 if (hdd_set_fw_params(adapter))
1676 hdd_err("Failed to set the FW params for the adapter!");
1677
1678 /*
1679 * Action frame registered in one adapter which will
1680 * applicable to all interfaces
1681 */
1682 wlan_hdd_cfg80211_register_frames(adapter);
1683 EXIT();
1684 return 0;
1685err_start_adapter:
1686 return -EINVAL;
1687}
1688
1689/**
1690 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1691 * @hdd_ctx: HDD context
1692 * @adapter: HDD adapter
1693 * @reinit: flag to indicate from SSR or normal path
1694 *
1695 * This function maintains the driver state machine it will be invoked from
1696 * startup, reinit and change interface. Depending on the driver state shall
1697 * perform the opening of the modules.
1698 *
1699 * Return: 0 for success; non-zero for failure
1700 */
1701int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1702 bool reinit)
1703{
1704 int ret;
1705 qdf_device_t qdf_dev;
1706 QDF_STATUS status;
1707 p_cds_contextType p_cds_context;
1708 bool unint = false;
1709 void *hif_ctx;
1710
1711 ENTER();
1712
1713 p_cds_context = cds_get_global_context();
1714 if (!p_cds_context) {
1715 hdd_err("Global Context is NULL");
1716 QDF_ASSERT(0);
1717 return -EINVAL;
1718 }
1719
1720 hdd_info("start modules called in state! :%d reinit: %d",
1721 hdd_ctx->driver_status, reinit);
1722
1723 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1724 if (!qdf_dev) {
1725 hdd_err("QDF Device Context is Invalid return");
1726 return -EINVAL;
1727 }
1728
1729 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301730 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301731
1732 if (QDF_TIMER_STATE_RUNNING ==
1733 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1734
1735 hdd_set_idle_ps_config(hdd_ctx, false);
1736 hdd_info("Interface change Timer running Stop timer");
1737 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1738 }
1739
1740 switch (hdd_ctx->driver_status) {
1741 case DRIVER_MODULES_UNINITIALIZED:
1742 unint = true;
1743 /* Fall through dont add break here */
1744 case DRIVER_MODULES_CLOSED:
1745 if (!reinit && !unint) {
1746 ret = pld_power_on(qdf_dev->dev);
1747 if (ret) {
1748 hdd_err("Failed to Powerup the device: %d", ret);
1749 goto release_lock;
1750 }
1751 }
1752 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1753 qdf_dev->bus_type,
1754 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1755 HIF_ENABLE_TYPE_PROBE);
1756 if (ret) {
1757 hdd_err("Failed to open hif: %d", ret);
1758 goto power_down;
1759 }
1760
1761 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301762 if (!hif_ctx) {
1763 hdd_err("hif context is null!!");
1764 goto power_down;
1765 }
1766
Arun Khandavallifae92942016-08-01 13:31:08 +05301767 status = ol_cds_init(qdf_dev, hif_ctx);
1768 if (status != QDF_STATUS_SUCCESS) {
1769 hdd_err("No Memory to Create BMI Context :%d", status);
1770 goto hif_close;
1771 }
1772
Arun Khandavallif6246632016-08-17 17:43:06 +05301773 ret = hdd_update_config(hdd_ctx);
1774 if (ret) {
1775 hdd_err("Failed to update configuration :%d", ret);
1776 goto ol_cds_free;
1777 }
1778
Arun Khandavallifae92942016-08-01 13:31:08 +05301779 status = cds_open();
1780 if (!QDF_IS_STATUS_SUCCESS(status)) {
1781 hdd_err("Failed to Open CDS: %d", status);
1782 goto ol_cds_free;
1783 }
1784
1785 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1786
1787 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1788
1789 status = cds_pre_enable(hdd_ctx->pcds_context);
1790 if (!QDF_IS_STATUS_SUCCESS(status)) {
1791 hdd_err("Failed to pre-enable CDS: %d", status);
1792 goto close;
1793 }
1794
1795 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1796 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1797 hdd_ftm_mc_process_msg);
1798 break;
1799 }
1800 if (unint) {
1801 hdd_info("In phase-1 initialization don't enable modules");
1802 break;
1803 }
1804 /* Fall through dont add break here */
1805 case DRIVER_MODULES_OPENED:
1806 if (!adapter) {
1807 hdd_alert("adapter is Null");
1808 goto close;
1809 }
1810 if (hdd_configure_cds(hdd_ctx, adapter)) {
1811 hdd_err("Failed to Enable cds modules");
1812 goto close;
1813 }
1814 hdd_info("Driver Modules Successfully Enabled");
1815 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1816 break;
1817 case DRIVER_MODULES_ENABLED:
1818 hdd_info("Driver modules already Enabled");
1819 break;
1820 default:
1821 hdd_err("WLAN start invoked in wrong state! :%d\n",
1822 hdd_ctx->driver_status);
1823 goto release_lock;
1824 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301825 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301826 mutex_unlock(&hdd_ctx->iface_change_lock);
1827 EXIT();
1828 return 0;
1829
1830close:
1831 cds_close(p_cds_context);
1832
1833ol_cds_free:
1834 ol_cds_free();
1835
1836hif_close:
1837 hdd_hif_close(p_cds_context->pHIFContext);
1838power_down:
1839 if (!reinit && !unint)
1840 pld_power_off(qdf_dev->dev);
1841release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301842 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301843 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301844 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301845 return -EINVAL;
1846}
1847
1848/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001849 * __hdd_open() - HDD Open function
1850 * @dev: Pointer to net_device structure
1851 *
1852 * This is called in response to ifconfig up
1853 *
1854 * Return: 0 for success; non-zero for failure
1855 */
1856static int __hdd_open(struct net_device *dev)
1857{
1858 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1859 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1860 int ret;
1861
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001862 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301863 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301864 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865
1866 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301867 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301869
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870
Arun Khandavallifae92942016-08-01 13:31:08 +05301871 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1872 if (ret) {
1873 hdd_err("Failed to start WLAN modules return");
1874 return -ret;
1875 }
1876
1877
1878 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1879 ret = hdd_start_adapter(adapter);
1880 if (ret) {
1881 hdd_err("Failed to start adapter :%d",
1882 adapter->device_mode);
1883 return ret;
1884 }
1885 }
1886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1888 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301889 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 /* Enable TX queues only when we are connected */
1891 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301892 WLAN_START_ALL_NETIF_QUEUE,
1893 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 }
1895
1896 return ret;
1897}
1898
Arun Khandavallifae92942016-08-01 13:31:08 +05301899
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900/**
1901 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1902 * @dev: Pointer to net_device structure
1903 *
1904 * This is called in response to ifconfig up
1905 *
1906 * Return: 0 for success; non-zero for failure
1907 */
1908int hdd_open(struct net_device *dev)
1909{
1910 int ret;
1911
1912 cds_ssr_protect(__func__);
1913 ret = __hdd_open(dev);
1914 cds_ssr_unprotect(__func__);
1915
1916 return ret;
1917}
1918
1919/**
1920 * __hdd_stop() - HDD stop function
1921 * @dev: Pointer to net_device structure
1922 *
1923 * This is called in response to ifconfig down
1924 *
1925 * Return: 0 for success; non-zero for failure
1926 */
1927static int __hdd_stop(struct net_device *dev)
1928{
1929 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1930 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301931 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301933 bool close_modules = true;
1934 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001936 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301938 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001939 adapter->sessionId, adapter->device_mode));
1940
1941 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301942 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001944
1945 /* Nothing to be done if the interface is not opened */
1946 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001947 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 return -ENODEV;
1949 }
1950
1951 /* Make sure the interface is marked as closed */
1952 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001953 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954
1955 /*
1956 * Disable TX on the interface, after this hard_start_xmit() will not
1957 * be called on that interface
1958 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001959 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1961 WLAN_CONTROL_PATH);
1962
1963 /*
1964 * The interface is marked as down for outside world (aka kernel)
1965 * But the driver is pretty much alive inside. The driver needs to
1966 * tear down the existing connection on the netdev (session)
1967 * cleanup the data pipes and wait until the control plane is stabilized
1968 * for this interface. The call also needs to wait until the above
1969 * mentioned actions are completed before returning to the caller.
1970 * Notice that the hdd_stop_adapter is requested not to close the session
1971 * That is intentional to be able to scan if it is a STA/P2P interface
1972 */
Arun Khandavallifae92942016-08-01 13:31:08 +05301973 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974
1975 /* DeInit the adapter. This ensures datapath cleanup as well */
1976 hdd_deinit_adapter(hdd_ctx, adapter, true);
1977
Arun Khandavallifae92942016-08-01 13:31:08 +05301978
1979 /*
1980 * Find if any iface is up. If any iface is up then can't put device to
1981 * sleep/power save mode
1982 */
1983 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
1984 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
1985 if (test_bit(DEVICE_IFACE_OPENED,
1986 &adapternode->pAdapter->event_flags)) {
1987 hdd_info("Still other ifaces are up cannot close modules");
1988 close_modules = false;
1989 break;
1990 }
1991 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
1992 adapternode = next;
1993
1994 }
1995
1996 if (close_modules) {
1997 hdd_info("Closing all modules from the hdd_stop");
1998 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
1999 hdd_ctx->config->iface_change_wait_time
2000 * 50000);
2001 }
2002
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003 EXIT();
2004 return 0;
2005}
2006
2007/**
2008 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2009 * @dev: pointer to net_device structure
2010 *
2011 * This is called in response to ifconfig down
2012 *
2013 * Return: 0 for success and error number for failure
2014 */
2015int hdd_stop(struct net_device *dev)
2016{
2017 int ret;
2018
2019 cds_ssr_protect(__func__);
2020 ret = __hdd_stop(dev);
2021 cds_ssr_unprotect(__func__);
2022
2023 return ret;
2024}
2025
2026/**
2027 * __hdd_uninit() - HDD uninit function
2028 * @dev: Pointer to net_device structure
2029 *
2030 * This is called during the netdev unregister to uninitialize all data
2031 * associated with the device
2032 *
2033 * Return: None
2034 */
2035static void __hdd_uninit(struct net_device *dev)
2036{
2037 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2038
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002039 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040
2041 do {
2042 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002043 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044 break;
2045 }
2046
2047 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002048 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049 break;
2050 }
2051
2052 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002053 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054 /*
2055 * we haven't validated all cases so let this go for
2056 * now
2057 */
2058 }
2059
2060 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2061
2062 /* after uninit our adapter structure will no longer be valid */
2063 adapter->dev = NULL;
2064 adapter->magic = 0;
2065 } while (0);
2066
2067 EXIT();
2068}
2069
2070/**
2071 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2072 * @dev: pointer to net_device structure
2073 *
2074 * This is called during the netdev unregister to uninitialize all data
2075 * associated with the device
2076 *
2077 * Return: none
2078 */
2079static void hdd_uninit(struct net_device *dev)
2080{
2081 cds_ssr_protect(__func__);
2082 __hdd_uninit(dev);
2083 cds_ssr_unprotect(__func__);
2084}
2085
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002086static int hdd_open_cesium_nl_sock(void)
2087{
2088#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2089 struct netlink_kernel_cfg cfg = {
2090 .groups = WLAN_NLINK_MCAST_GRP_ID,
2091 .input = NULL
2092 };
2093#endif
2094 int ret = 0;
2095
2096#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2097 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2098#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2099 THIS_MODULE,
2100#endif
2101 &cfg);
2102#else
2103 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2104 WLAN_NLINK_MCAST_GRP_ID,
2105 NULL, NULL, THIS_MODULE);
2106#endif
2107
2108 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002109 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002110 ret = -ECONNREFUSED;
2111 }
2112
2113 return ret;
2114}
2115
2116static void hdd_close_cesium_nl_sock(void)
2117{
2118 if (NULL != cesium_nl_srv_sock) {
2119 netlink_kernel_release(cesium_nl_srv_sock);
2120 cesium_nl_srv_sock = NULL;
2121 }
2122}
2123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002124/**
2125 * __hdd_set_mac_address() - set the user specified mac address
2126 * @dev: Pointer to the net device.
2127 * @addr: Pointer to the sockaddr.
2128 *
2129 * This function sets the user specified mac address using
2130 * the command ifconfig wlanX hw ether <mac adress>.
2131 *
2132 * Return: 0 for success, non zero for failure
2133 */
2134static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2135{
2136 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2137 hdd_context_t *hdd_ctx;
2138 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302139 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140 int ret;
2141
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002142 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143
2144 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2145 ret = wlan_hdd_validate_context(hdd_ctx);
2146 if (0 != ret)
2147 return ret;
2148
2149 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2150 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2151
2152 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302153 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002154}
2155
2156/**
2157 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2158 * function from SSR
2159 * @dev: pointer to net_device structure
2160 * @addr: Pointer to the sockaddr
2161 *
2162 * This function sets the user specified mac address using
2163 * the command ifconfig wlanX hw ether <mac adress>.
2164 *
2165 * Return: 0 for success.
2166 */
2167static int hdd_set_mac_address(struct net_device *dev, void *addr)
2168{
2169 int ret;
2170
2171 cds_ssr_protect(__func__);
2172 ret = __hdd_set_mac_address(dev, addr);
2173 cds_ssr_unprotect(__func__);
2174
2175 return ret;
2176}
2177
2178uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2179{
2180 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302181 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2183 break;
2184 }
2185
Anurag Chouhan6d760662016-02-20 16:05:43 +05302186 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 return NULL;
2188
2189 hdd_ctx->config->intfAddrMask |= (1 << i);
2190 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2191}
2192
2193void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2194{
2195 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302196 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197 if (!memcmp(releaseAddr,
2198 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2199 6)) {
2200 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2201 break;
2202 }
2203 }
2204 return;
2205}
2206
2207#ifdef WLAN_FEATURE_PACKET_FILTERING
2208/**
2209 * __hdd_set_multicast_list() - set the multicast address list
2210 * @dev: Pointer to the WLAN device.
2211 * @skb: Pointer to OS packet (sk_buff).
2212 *
2213 * This funciton sets the multicast address list.
2214 *
2215 * Return: None
2216 */
2217static void __hdd_set_multicast_list(struct net_device *dev)
2218{
2219 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2220 int mc_count;
2221 int i = 0, status;
2222 struct netdev_hw_addr *ha;
2223 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2224 static const uint8_t ipv6_router_solicitation[]
2225 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2226
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002227 ENTER_DEV(dev);
2228
Anurag Chouhan6d760662016-02-20 16:05:43 +05302229 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302230 return;
2231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302233 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235
2236 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002237 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238 adapter->mc_addr_list.mc_cnt = 0;
2239 } else {
2240 mc_count = netdev_mc_count(dev);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002241 hdd_notice("mc_count = %u", mc_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002242 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002243 hdd_notice("No free filter available; allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002244 adapter->mc_addr_list.mc_cnt = 0;
2245 return;
2246 }
2247
2248 adapter->mc_addr_list.mc_cnt = mc_count;
2249
2250 netdev_for_each_mc_addr(ha, dev) {
2251 if (i == mc_count)
2252 break;
2253 /*
2254 * Skip following addresses:
2255 * 1)IPv6 router solicitation address
2256 * 2)Any other address pattern if its set during
2257 * RXFILTER REMOVE driver command based on
2258 * addr_filter_pattern
2259 */
2260 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2261 ETH_ALEN)) ||
2262 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2263 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002264 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002265 MAC_ADDR_ARRAY(ha->addr));
2266 adapter->mc_addr_list.mc_cnt--;
2267 continue;
2268 }
2269
2270 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2271 ETH_ALEN);
2272 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2273 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002274 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2276 i++;
2277 }
2278 }
2279 if (hdd_ctx->config->active_mode_offload) {
2280 hdd_info("enable mc filtering");
2281 wlan_hdd_set_mc_addr_list(adapter, true);
2282 } else {
2283 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2284 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302285 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 return;
2287}
2288
2289/**
2290 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2291 * @dev: pointer to net_device
2292 *
2293 * Return: none
2294 */
2295static void hdd_set_multicast_list(struct net_device *dev)
2296{
2297 cds_ssr_protect(__func__);
2298 __hdd_set_multicast_list(dev);
2299 cds_ssr_unprotect(__func__);
2300}
2301#endif
2302
2303/**
2304 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2305 * @dev: Pointer to the WLAN device.
2306 * @skb: Pointer to OS packet (sk_buff).
2307 *
2308 * This function is registered with the Linux OS for network
2309 * core to decide which queue to use first.
2310 *
2311 * Return: ac, Queue Index/access category corresponding to UP in IP header
2312 */
2313static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2314#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2315 , void *accel_priv
2316#endif
2317#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2318 , select_queue_fallback_t fallback
2319#endif
2320)
2321{
2322 return hdd_wmm_select_queue(dev, skb);
2323}
2324
2325static struct net_device_ops wlan_drv_ops = {
2326 .ndo_open = hdd_open,
2327 .ndo_stop = hdd_stop,
2328 .ndo_uninit = hdd_uninit,
2329 .ndo_start_xmit = hdd_hard_start_xmit,
2330 .ndo_tx_timeout = hdd_tx_timeout,
2331 .ndo_get_stats = hdd_get_stats,
2332 .ndo_do_ioctl = hdd_ioctl,
2333 .ndo_set_mac_address = hdd_set_mac_address,
2334 .ndo_select_queue = hdd_select_queue,
2335#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337#endif
2338};
2339
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002340/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2341static struct net_device_ops wlan_mon_drv_ops = {
2342 .ndo_open = hdd_mon_open,
2343 .ndo_stop = hdd_stop,
2344 .ndo_get_stats = hdd_get_stats,
2345};
2346
2347/**
2348 * hdd_set_station_ops() - update net_device ops for monitor mode
2349 * @pWlanDev: Handle to struct net_device to be updated.
2350 * Return: None
2351 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002352void hdd_set_station_ops(struct net_device *pWlanDev)
2353{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002354 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2355 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2356 else
2357 pWlanDev->netdev_ops = &wlan_drv_ops;
2358}
2359
2360/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002361 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2362 * @hdd_ctx: global hdd context
2363 * @macAddr: mac address to assign to the interface
2364 * @name: User-visible name of the interface
2365 *
2366 * hdd adapter pointer would point to the netdev->priv space, this function
2367 * would retrive the pointer, and setup the hdd adapter configuration.
2368 *
2369 * Return: the pointer to hdd adapter, otherwise NULL
2370 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2372 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002373 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 const char *name)
2375{
2376 struct net_device *pWlanDev = NULL;
2377 hdd_adapter_t *adapter = NULL;
2378 /*
2379 * cfg80211 initialization and registration....
2380 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002381 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2382#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2383 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002385 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2386 hdd_mon_mode_ether_setup : ether_setup),
2387 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388
2389 if (pWlanDev != NULL) {
2390
2391 /* Save the pointer to the net_device in the HDD adapter */
2392 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2393
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302394 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395
2396 adapter->dev = pWlanDev;
2397 adapter->pHddCtx = hdd_ctx;
2398 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302399 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400
2401 init_completion(&adapter->session_open_comp_var);
2402 init_completion(&adapter->session_close_comp_var);
2403 init_completion(&adapter->disconnect_comp_var);
2404 init_completion(&adapter->linkup_event_var);
2405 init_completion(&adapter->cancel_rem_on_chan_var);
2406 init_completion(&adapter->rem_on_chan_ready_event);
2407 init_completion(&adapter->sta_authorized_event);
2408 init_completion(&adapter->offchannel_tx_event);
2409 init_completion(&adapter->tx_action_cnf_event);
2410#ifdef FEATURE_WLAN_TDLS
2411 init_completion(&adapter->tdls_add_station_comp);
2412 init_completion(&adapter->tdls_del_station_comp);
2413 init_completion(&adapter->tdls_mgmt_comp);
2414 init_completion(&adapter->tdls_link_establish_req_comp);
2415#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002416 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002417 init_completion(&adapter->change_country_code);
2418
2419
2420 init_completion(&adapter->scan_info.abortscan_event_var);
2421
2422 adapter->offloads_configured = false;
2423 adapter->isLinkUpSvcNeeded = false;
2424 adapter->higherDtimTransition = true;
2425 /* Init the net_device structure */
2426 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2427
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302428 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302430 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 sizeof(tSirMacAddr));
2432 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433
2434 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2435 pWlanDev->features |=
2436 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2437 pWlanDev->features |= NETIF_F_RXCSUM;
2438
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002439 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 hdd_set_station_ops(adapter->dev);
2442
2443 pWlanDev->destructor = free_netdev;
2444 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002445 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 adapter->wdev.wiphy = hdd_ctx->wiphy;
2447 adapter->wdev.netdev = pWlanDev;
2448 /* set pWlanDev's parent to underlying device */
2449 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2450 hdd_wmm_init(adapter);
2451 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302452 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 }
2454
2455 return adapter;
2456}
2457
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302458QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002459 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460{
2461 struct net_device *pWlanDev = adapter->dev;
2462 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
2463 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302464 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002466 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2468 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002469 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302470 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471 }
2472 }
2473 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002474 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302475 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 }
2477 } else {
2478 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002479 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302480 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 }
2482 }
2483 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2484
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302485 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486}
2487
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002488QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489{
2490 hdd_adapter_t *adapter = pContext;
2491
2492 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002493 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302494 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 }
2496
2497 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002498 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302499 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002500 }
2501
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002502 /*
2503 * For NAN Data interface, the close session results in the final
2504 * indication to the userspace
2505 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002506 if (adapter->device_mode == QDF_NDI_MODE)
2507 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511 /*
2512 * We can be blocked while waiting for scheduled work to be
2513 * flushed, and the adapter structure can potentially be freed, in
2514 * which case the magic will have been reset. So make sure the
2515 * magic is still good, and hence the adapter structure is still
2516 * valid, before signaling completion
2517 */
2518 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2519 complete(&adapter->session_close_comp_var);
2520
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302521 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522}
2523
Krunal Soni8c37e322016-02-03 16:08:37 -08002524/**
2525 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2526 * @adapter: pointer to device adapter
2527 * @type: type of interface
2528 *
2529 * This routine will check the mode of adapter and if it is required then it
2530 * will initialize the TDLS operations
2531 *
2532 * Return: QDF_STATUS
2533 */
2534#ifdef FEATURE_WLAN_TDLS
2535static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2536{
2537 if (QDF_IBSS_MODE != type) {
2538 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002539 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002540 return QDF_STATUS_E_FAILURE;
2541 }
2542 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2543 }
2544 return QDF_STATUS_SUCCESS;
2545}
2546#else
2547static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2548{
2549 return QDF_STATUS_SUCCESS;
2550}
2551#endif
2552
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302553QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554{
2555 struct net_device *pWlanDev = adapter->dev;
2556 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2557 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302558 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302559 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 uint32_t type, subType;
2561 unsigned long rc;
2562 int ret_val;
2563
2564 INIT_COMPLETION(adapter->session_open_comp_var);
2565 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002566 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302568 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002569 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 goto error_sme_open;
2571 }
2572 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302573 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2575 (uint8_t *) &adapter->macAddressCurrent,
2576 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302577 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002578 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302579 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302580 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 goto error_sme_open;
2582 }
2583 /* Block on a completion variable. Can't wait forever though. */
2584 rc = wait_for_completion_timeout(
2585 &adapter->session_open_comp_var,
2586 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2587 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002588 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302590 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591 goto error_sme_open;
2592 }
2593
2594 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302595 qdf_ret_status = hdd_register_wext(pWlanDev);
2596 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002597 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302598 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302599 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 goto error_register_wext;
2601 }
2602 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002603 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2605
2606 /* Set the default operation channel */
2607 pHddStaCtx->conn_info.operationChannel =
2608 hdd_ctx->config->OperatingChannel;
2609
2610 /* Make the default Auth Type as OPEN */
2611 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2612
2613 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302614 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002615 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002616 status, status);
2617 goto error_init_txrx;
2618 }
2619
2620 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2621
2622 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302623 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002624 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 status, status);
2626 goto error_wmm_init;
2627 }
2628
2629 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2630
2631 ret_val = wma_cli_set_command(adapter->sessionId,
2632 WMI_PDEV_PARAM_BURST_ENABLE,
2633 hdd_ctx->config->enableSifsBurst,
2634 PDEV_CMD);
2635
2636 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002637 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638 ret_val);
2639 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002640 status = hdd_check_and_init_tdls(adapter, type);
2641 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002642 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002643
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302644 status = hdd_lro_enable(hdd_ctx, adapter);
2645 if (status != QDF_STATUS_SUCCESS)
2646 goto error_lro_enable;
2647
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302648 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302650error_lro_enable:
2651 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002652error_tdls_init:
2653 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2654 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655error_wmm_init:
2656 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2657 hdd_deinit_tx_rx(adapter);
2658error_init_txrx:
2659 hdd_unregister_wext(pWlanDev);
2660error_register_wext:
2661 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2662 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302663 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 adapter->sessionId,
2665 hdd_sme_close_session_callback,
2666 adapter)) {
2667 unsigned long rc;
2668
2669 /*
2670 * Block on a completion variable.
2671 * Can't wait forever though.
2672 */
2673 rc = wait_for_completion_timeout(
2674 &adapter->session_close_comp_var,
2675 msecs_to_jiffies
2676 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2677 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002678 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002679 rc);
2680 }
2681 }
2682error_sme_open:
2683 return status;
2684}
2685
2686void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2687{
2688 hdd_cfg80211_state_t *cfgState;
2689
2690 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2691
2692 if (NULL != cfgState->buf) {
2693 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002694 rc = wait_for_completion_timeout(
2695 &adapter->tx_action_cnf_event,
2696 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2697 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002698 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302699 /*
2700 * Inform tx status as FAILURE to upper layer and free
2701 * cfgState->buf
2702 */
2703 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 }
2705 }
2706 return;
2707}
2708
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302709/**
2710 * hdd_station_adapter_deinit() - De-initialize the station adapter
2711 * @hdd_ctx: global hdd context
2712 * @adapter: HDD adapter
2713 *
2714 * This function De-initializes the STA/P2P/OCB adapter.
2715 *
2716 * Return: None.
2717 */
2718void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2719 hdd_adapter_t *adapter)
2720{
2721 ENTER_DEV(adapter->dev);
2722
2723 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2724 hdd_deinit_tx_rx(adapter);
2725 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2726 }
2727
2728 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2729 hdd_wmm_adapter_close(adapter);
2730 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2731 }
2732
2733 hdd_cleanup_actionframe(hdd_ctx, adapter);
2734 wlan_hdd_tdls_exit(adapter);
2735
2736 EXIT();
2737}
2738
2739/**
2740 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2741 * @hdd_ctx: global hdd context
2742 * @adapter: HDD adapter
2743 * @rtnl_held: the rtnl lock hold flag
2744 * This function De-initializes the AP/P2PGo adapter.
2745 *
2746 * Return: None.
2747 */
2748void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2749 bool rtnl_held)
2750{
2751 ENTER_DEV(adapter->dev);
2752
2753 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2754 hdd_wmm_adapter_close(adapter);
2755 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2756 }
2757
2758 hdd_cleanup_actionframe(hdd_ctx, adapter);
2759
2760 hdd_unregister_hostapd(adapter, rtnl_held);
2761
2762 EXIT();
2763}
2764
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002765void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2766 bool rtnl_held)
2767{
2768 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302769
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002770 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002771 case QDF_STA_MODE:
2772 case QDF_P2P_CLIENT_MODE:
2773 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002774 {
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302775 hdd_station_adapter_deinit(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 break;
2777 }
2778
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002779 case QDF_SAP_MODE:
2780 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 {
2782
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302783 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 break;
2785 }
2786
2787 default:
2788 break;
2789 }
2790
2791 EXIT();
2792}
2793
2794void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002795 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796{
2797 struct net_device *pWlanDev = NULL;
2798
2799 if (adapter)
2800 pWlanDev = adapter->dev;
2801 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002802 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002803 return;
2804 }
2805
Rajeev Kumardca5f812016-02-04 17:28:06 -08002806 hdd_debugfs_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 /*
2808 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2809 * the driver is almost closed and cannot handle either control
2810 * messages or data. However, unregister_netdevice() call above will
2811 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2812 * to close the active connections (basically excites control path) which
2813 * is not right. Setting this flag helps hdd_stop() to recognize that
2814 * the interface is closed and restricts any operations on that
2815 */
2816 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2817
2818 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2819 if (rtnl_held) {
2820 unregister_netdevice(pWlanDev);
2821 } else {
2822 unregister_netdev(pWlanDev);
2823 }
2824 /*
2825 * Note that the adapter is no longer valid at this point
2826 * since the memory has been reclaimed
2827 */
2828 }
2829}
2830
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302831QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 tSirMacAddr macAddr)
2833{
2834 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2835 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302836 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302838 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 adapter = adapterNode->pAdapter;
2840 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302841 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002842 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302843 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002844 }
2845 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2846 adapterNode = pNext;
2847 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302848 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002849}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002850
Arun Khandavalli2358d522016-05-16 18:05:37 +05302851#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2852/**
2853 * hdd_set_fw_log_params() - Set log parameters to FW
2854 * @hdd_ctx: HDD Context
2855 * @adapter: HDD Adapter
2856 *
2857 * This function set the FW Debug log level based on the INI.
2858 *
2859 * Return: None
2860 */
2861static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2862 hdd_adapter_t *adapter)
2863{
2864 uint8_t count = 0, numentries = 0,
2865 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2866 uint32_t value = 0;
2867 int ret;
2868
Arun Khandavallifae92942016-08-01 13:31:08 +05302869 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
2870 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302871 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
2872 return;
2873 }
2874
Arun Khandavallifae92942016-08-01 13:31:08 +05302875 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05302876 hdd_ctx->fw_log_settings.dl_type =
2877 hdd_ctx->config->enableFwLogType;
2878 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302879 WMI_DBGLOG_TYPE,
2880 hdd_ctx->config->enableFwLogType,
2881 DBG_CMD);
2882 if (ret != 0)
2883 hdd_err("Failed to enable FW log type ret %d",
2884 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302885
2886 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05302887 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05302888 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302889 WMI_DBGLOG_LOG_LEVEL,
2890 hdd_ctx->config->enableFwLogLevel,
2891 DBG_CMD);
2892 if (ret != 0)
2893 hdd_err("Failed to enable FW log level ret %d",
2894 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302895
2896 hdd_string_to_u8_array(
2897 hdd_ctx->config->enableFwModuleLogLevel,
2898 moduleloglevel,
2899 &numentries,
2900 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2901
2902 while (count < numentries) {
2903 /*
2904 * FW module log level input string looks like
2905 * below:
2906 * gFwDebugModuleLoglevel=<FW Module ID>,
2907 * <Log Level>,...
2908 * For example:
2909 * gFwDebugModuleLoglevel=
2910 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
2911 * Above input string means :
2912 * For FW module ID 1 enable log level 0
2913 * For FW module ID 2 enable log level 1
2914 * For FW module ID 3 enable log level 2
2915 * For FW module ID 4 enable log level 3
2916 * For FW module ID 5 enable log level 4
2917 * For FW module ID 6 enable log level 5
2918 * For FW module ID 7 enable log level 6
2919 */
2920
Arun Khandavallifae92942016-08-01 13:31:08 +05302921 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05302922 * Module ID * 10 + Module Log level
2923 */
2924 value = ((moduleloglevel[count] * 10) +
2925 moduleloglevel[count + 1]);
2926 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302927 WMI_DBGLOG_MOD_LOG_LEVEL,
2928 value, DBG_CMD);
2929 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05302930 hdd_err("Failed to enable FW module log level %d ret %d",
2931 value, ret);
2932
2933 count += 2;
2934 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302935
Arun Khandavalli2358d522016-05-16 18:05:37 +05302936}
2937#else
2938static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2939 hdd_adapter_t *adapter)
2940{
2941}
2942
2943#endif
2944
2945/**
2946 * hdd_set_fw_params() - Set parameters to firmware
2947 * @adapter: HDD adapter
2948 *
2949 * This function Sets various parameters to fw once the
2950 * adapter is started.
2951 *
2952 * Return: 0 on success or errno on failure
2953 */
2954int hdd_set_fw_params(hdd_adapter_t *adapter)
2955{
2956 int ret;
2957 hdd_context_t *hdd_ctx;
2958
2959 ENTER_DEV(adapter->dev);
2960
2961 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2962 if (!hdd_ctx)
2963 return -EINVAL;
2964
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07002965 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05302966 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302967#define HDD_DTIM_1CHAIN_RX_ID 0x5
2968#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07002969 /*
2970 * Disable DTIM 1 chain Rx when in 1x1,
2971 * we are passing two value
2972 * as param_id << 29 | param_value.
2973 * Below param_value = 0(disable)
2974 */
2975 ret = wma_cli_set_command(adapter->sessionId,
2976 WMI_STA_SMPS_PARAM_CMDID,
2977 HDD_DTIM_1CHAIN_RX_ID <<
2978 HDD_SMPS_PARAM_VALUE_S,
2979 VDEV_CMD);
2980 if (ret) {
2981 hdd_err("DTIM 1 chain set failed %d", ret);
2982 goto error;
2983 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05302984
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07002985 ret = wma_cli_set_command(adapter->sessionId,
2986 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2987 hdd_ctx->config->txchainmask1x1,
2988 PDEV_CMD);
2989 if (ret) {
2990 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
2991 ret);
2992 goto error;
2993 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05302994
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07002995 ret = wma_cli_set_command(adapter->sessionId,
2996 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2997 hdd_ctx->config->rxchainmask1x1,
2998 PDEV_CMD);
2999 if (ret) {
3000 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3001 ret);
3002 goto error;
3003 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303004#undef HDD_DTIM_1CHAIN_RX_ID
3005#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003006 } else {
3007 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3008 }
3009
Arun Khandavallifae92942016-08-01 13:31:08 +05303010 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3011 ret = wma_cli_set_command(adapter->sessionId,
3012 WMI_PDEV_PARAM_HYST_EN,
3013 hdd_ctx->config->enableMemDeepSleep,
3014 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303015
Arun Khandavallifae92942016-08-01 13:31:08 +05303016 if (ret) {
3017 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3018 ret);
3019 goto error;
3020 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303021 }
3022
3023 hdd_set_fw_log_params(hdd_ctx, adapter);
3024
3025 EXIT();
3026 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303027
Arun Khandavalli2358d522016-05-16 18:05:37 +05303028error:
3029 return -EINVAL;
3030}
3031
Ryan Hsu07495ea2016-01-21 15:25:39 -08003032/**
3033 * hdd_open_adapter() - open and setup the hdd adatper
3034 * @hdd_ctx: global hdd context
3035 * @session_type: type of the interface to be created
3036 * @iface_name: User-visible name of the interface
3037 * @macAddr: MAC address to assign to the interface
3038 * @name_assign_type: the name of assign type of the netdev
3039 * @rtnl_held: the rtnl lock hold flag
3040 *
3041 * This function open and setup the hdd adpater according to the device
3042 * type request, assign the name, the mac address assigned, and then prepared
3043 * the hdd related parameters, queue, lock and ready to start.
3044 *
3045 * Return: the pointer of hdd adapter, otherwise NULL.
3046 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3048 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003049 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003050 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051{
3052 hdd_adapter_t *adapter = NULL;
3053 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303054 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056
Arun Khandavallifae92942016-08-01 13:31:08 +05303057 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003058
3059 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3060 /*
3061 * Max limit reached on the number of vdevs configured by the
3062 * host. Return error
3063 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303064 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3065 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 return NULL;
3067 }
3068
3069 if (macAddr == NULL) {
3070 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303071 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 return NULL;
3073 }
3074 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303075 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303076 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3077 " already exists",
3078 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003079 return NULL;
3080 }
3081
3082 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003083 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 /* Reset locally administered bit if the device mode is STA */
3085 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3086 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003087 case QDF_P2P_CLIENT_MODE:
3088 case QDF_P2P_DEVICE_MODE:
3089 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003090 case QDF_NDI_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003091 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3092 name_assign_type,
3093 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003094
3095 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303096 hdd_err("failed to allocate adapter for session %d",
3097 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 return NULL;
3099 }
3100
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003101 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003102 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003103 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 else
3106 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3107
3108 adapter->device_mode = session_type;
3109
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303110 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003111 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303112 if (QDF_STATUS_SUCCESS != status)
3113 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303114 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116 /*
3117 * Workqueue which gets scheduled in IPv4 notification
3118 * callback
3119 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3121 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122
3123#ifdef WLAN_NS_OFFLOAD
3124 /*
3125 * Workqueue which gets scheduled in IPv6
3126 * notification callback.
3127 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3129 hdd_ipv6_notifier_work_queue);
3130#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303132 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003133 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3134 goto err_lro_cleanup;
3135 }
3136
3137 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303138 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003139 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303140 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3141 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003142 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003145 case QDF_P2P_GO_MODE:
3146 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003147 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3148 name_assign_type,
3149 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303151 hdd_alert("failed to allocate adapter for session %d",
3152 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003153 return NULL;
3154 }
3155
3156 adapter->wdev.iftype =
3157 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003158 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 NL80211_IFTYPE_P2P_GO;
3160 adapter->device_mode = session_type;
3161
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303163 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3165 goto err_free_netdev;
3166 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303167 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303169 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3170 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303173 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303174 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 return NULL;
3176 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177
3178 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3179 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3180
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303181 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 /* Add it to the hdd's session list. */
3183 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303184 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303186 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187 } else {
3188 pHddAdapterNode->pAdapter = adapter;
3189 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3190 }
3191 }
3192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303193 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 if (NULL != adapter) {
3195 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3196 adapter = NULL;
3197 }
3198 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303199 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200 }
3201 return NULL;
3202 }
3203
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303204 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003205 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206
3207 /* Initialize the WoWL service */
3208 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003209 hdd_alert("hdd_init_wowl failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 goto err_lro_cleanup;
3211 }
3212
3213 /* Adapter successfully added. Increment the vdev count */
3214 hdd_ctx->current_intf_count++;
3215
Jeff Johnson5880d792016-08-15 13:32:30 -07003216 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217 hdd_ctx->current_intf_count);
3218
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003219 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 }
3221
Rajeev Kumardca5f812016-02-04 17:28:06 -08003222 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3223 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224
3225 return adapter;
3226
3227err_lro_cleanup:
3228 hdd_lro_disable(hdd_ctx, adapter);
3229err_free_netdev:
3230 free_netdev(adapter->dev);
3231 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
3232
3233 return NULL;
3234}
3235
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303236QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003237 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238{
3239 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303240 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241
3242 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303243 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003244 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003245 status);
3246 return status;
3247 }
3248
3249 while (pCurrent->pAdapter != adapter) {
3250 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303251 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 break;
3253
3254 pCurrent = pNext;
3255 }
3256 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303257 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003258 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003259 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3260
3261 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303262 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 adapterNode = NULL;
3264
3265 /* Adapter removed. Decrement vdev count */
3266 if (hdd_ctx->current_intf_count != 0)
3267 hdd_ctx->current_intf_count--;
3268
3269 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303270 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303272 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273}
3274
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003275/**
3276 * hdd_close_all_adapters - Close all open adapters
3277 * @hdd_ctx: Hdd context
3278 * rtnl_held: True if RTNL lock held
3279 *
3280 * Close all open adapters.
3281 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303282 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003283 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303284QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285{
3286 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303287 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288
3289 ENTER();
3290
3291 do {
3292 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303293 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003295 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303296 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003297 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303298 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299
3300 EXIT();
3301
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303302 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003303}
3304
3305void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3306{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303307 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308 tSirUpdateIE updateIE;
3309 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003310 case QDF_STA_MODE:
3311 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 {
3313 hdd_station_ctx_t *pHddStaCtx =
3314 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003315 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 break;
3317 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003318 case QDF_SAP_MODE:
3319 case QDF_P2P_GO_MODE:
3320 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003322 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003323 break;
3324 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003325 case QDF_FTM_MODE:
3326 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327 default:
3328 /*
3329 * wlan_hdd_reset_prob_rspies should not have been called
3330 * for these kind of devices
3331 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003332 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333 pHostapdAdapter->device_mode);
3334 return;
3335 }
3336
Anurag Chouhanc5548422016-02-24 18:33:27 +05303337 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3339 updateIE.ieBufferlength = 0;
3340 updateIE.pAdditionIEBuffer = NULL;
3341 updateIE.append = true;
3342 updateIE.notify = false;
3343 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3344 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303345 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003346 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 }
3348}
3349
Peng Xu66162de2016-02-11 17:01:20 -08003350/**
3351 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3352 * @hdd_ctx: HDD context which is already NULL validated
3353 * @adapter: HDD adapter which is already NULL validated
3354 *
3355 * Close the SME session and wait for its completion, if needed.
3356 *
3357 * Return: None
3358 */
3359static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3360 hdd_adapter_t *adapter)
3361{
3362 unsigned long rc;
3363
3364 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3365 hdd_err("session is not opened:%d", adapter->sessionId);
3366 return;
3367 }
3368
3369 INIT_COMPLETION(adapter->session_close_comp_var);
3370 if (QDF_STATUS_SUCCESS ==
3371 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3372 hdd_sme_close_session_callback,
3373 adapter)) {
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05303374 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003375 /*
3376 * Block on a completion variable. Can't wait
3377 * forever though.
3378 */
3379 rc = wait_for_completion_timeout(
3380 &adapter->session_close_comp_var,
3381 msecs_to_jiffies
3382 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3383 if (!rc)
3384 hdd_err("failure waiting for session_close_comp_var");
3385 }
3386}
3387
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303388QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 const bool bCloseSession)
3390{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303391 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003392 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3393 union iwreq_data wrqu;
3394 tSirUpdateIE updateIE;
3395 unsigned long rc;
3396
3397 ENTER();
3398
Jeff Johnson5880d792016-08-15 13:32:30 -07003399 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3401 WLAN_CONTROL_PATH);
3402 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003403 case QDF_STA_MODE:
3404 case QDF_P2P_CLIENT_MODE:
3405 case QDF_IBSS_MODE:
3406 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003407 case QDF_NDI_MODE:
3408 if ((QDF_NDI_MODE == adapter->device_mode) ||
3409 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003410 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3411 hdd_is_connecting(
3412 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003413 INIT_COMPLETION(adapter->disconnect_comp_var);
3414 /*
3415 * For NDI do not use pWextState from sta_ctx, if needed
3416 * extract from ndi_ctx.
3417 */
3418 if (QDF_NDI_MODE == adapter->device_mode)
3419 qdf_ret_status = sme_roam_disconnect(
3420 hdd_ctx->hHal,
3421 adapter->sessionId,
3422 eCSR_DISCONNECT_REASON_NDI_DELETE);
3423 else if (pWextState->roamProfile.BSSType ==
3424 eCSR_BSS_TYPE_START_IBSS)
3425 qdf_ret_status = sme_roam_disconnect(
3426 hdd_ctx->hHal,
3427 adapter->sessionId,
3428 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003430 qdf_ret_status = sme_roam_disconnect(
3431 hdd_ctx->hHal,
3432 adapter->sessionId,
3433 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003434 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303435 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 rc = wait_for_completion_timeout(
3437 &adapter->disconnect_comp_var,
3438 msecs_to_jiffies
3439 (WLAN_WAIT_TIME_DISCONNECT));
3440 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003441 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 }
3443 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003444 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003445 }
3446 memset(&wrqu, '\0', sizeof(wrqu));
3447 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3448 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3449 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3450 NULL);
3451 } else {
3452 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3453 eCSR_SCAN_ABORT_DEFAULT);
3454 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303455 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303456 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003457
3458#ifdef WLAN_OPEN_SOURCE
3459 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3460#endif
3461
3462 hdd_deregister_tx_flow_control(adapter);
3463
3464#ifdef WLAN_NS_OFFLOAD
3465#ifdef WLAN_OPEN_SOURCE
3466 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3467#endif
3468#endif
3469
3470 /*
3471 * It is possible that the caller of this function does not
3472 * wish to close the session
3473 */
Peng Xu66162de2016-02-11 17:01:20 -08003474 if (true == bCloseSession)
3475 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 break;
3477
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003478 case QDF_SAP_MODE:
3479 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003481 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482 /*
3483 * Before stopping the sap adapter, lets make sure there
3484 * is no sap restart work pending.
3485 */
3486 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003487 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003488 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 }
3490 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003491 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3493
3494 hdd_deregister_tx_flow_control(adapter);
3495
3496 mutex_lock(&hdd_ctx->sap_lock);
3497 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303498 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303499 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500
3501 /* Stop Bss. */
3502#ifdef WLAN_FEATURE_MBSSID
3503 status = wlansap_stop_bss(
3504 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3505#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003506 status = wlansap_stop_bss(
3507 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508#endif
3509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303510 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511 hdd_hostapd_state_t *hostapd_state =
3512 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303513 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303514 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303515 qdf_status =
3516 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303517 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 BSS_WAIT_TIMEOUT);
3519
Anurag Chouhance0dc992016-02-16 18:18:03 +05303520 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003521 hdd_err("failure waiting for wlansap_stop_bss %d",
3522 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523 }
3524 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003525 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526 }
3527 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003528 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 adapter->device_mode,
3530 adapter->sessionId);
3531
Anurag Chouhanc5548422016-02-24 18:33:27 +05303532 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003533 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534 updateIE.smeSessionId = adapter->sessionId;
3535 updateIE.ieBufferlength = 0;
3536 updateIE.pAdditionIEBuffer = NULL;
3537 updateIE.append = false;
3538 updateIE.notify = false;
3539 /* Probe bcn reset */
3540 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3541 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303542 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003543 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003544 }
3545 /* Assoc resp reset */
3546 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3547 &updateIE,
3548 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303549 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003550 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 }
3552 /* Reset WNI_CFG_PROBE_RSP Flags */
3553 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303554 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555 adapter->sessionCtx.ap.beacon = NULL;
3556 }
3557 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003558 if (true == bCloseSession)
3559 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003560 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003561 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3563 conn_info.staId[0]);
3564 break;
3565 default:
3566 break;
3567 }
3568
3569 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303570 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003571}
3572
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303573QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574{
3575 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303576 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577 hdd_adapter_t *adapter;
3578
3579 ENTER();
3580
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303581 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003583 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3584
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303585 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586 adapter = adapterNode->pAdapter;
3587 hdd_stop_adapter(hdd_ctx, adapter, true);
3588 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3589 adapterNode = pNext;
3590 }
3591
3592 EXIT();
3593
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303594 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595}
3596
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303597QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598{
3599 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303600 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003601 hdd_adapter_t *adapter;
3602
3603 ENTER();
3604
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303605 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3608
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303609 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003611 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003612 wlan_hdd_netif_queue_control(adapter,
3613 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3614 WLAN_CONTROL_PATH);
3615
3616 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3617
3618 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003619 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620 adapter->sessionId);
3621 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3622 hdd_wmm_adapter_close(adapter);
3623 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3624 }
3625
3626 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3627 adapterNode = pNext;
3628 }
3629
3630 EXIT();
3631
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303632 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633}
3634
Arun Khandavallifae92942016-08-01 13:31:08 +05303635/**
3636 * hdd_is_interface_up()- Checkfor interface up before ssr
3637 * @hdd_ctx: HDD context
3638 *
3639 * check if there are any wlan interfaces before SSR accordingly start
3640 * the interface.
3641 *
3642 * Return: 0 if interface was opened else false
3643 */
3644static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3645{
3646 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3647 return true;
3648 else
3649 return false;
3650}
3651
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303652QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003653{
3654 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303655 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 hdd_adapter_t *adapter;
3657#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303658 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659#endif
3660 eConnectionState connState;
3661
3662 ENTER();
3663
3664 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303665 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 adapter = adapterNode->pAdapter;
3667
Arun Khandavallifae92942016-08-01 13:31:08 +05303668 if (!hdd_is_interface_up(adapter))
3669 continue;
3670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003671 hdd_wmm_init(adapter);
3672
3673 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003674 case QDF_STA_MODE:
3675 case QDF_P2P_CLIENT_MODE:
3676 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003677
3678 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3679 ->conn_info.connState;
3680
3681 hdd_init_station_mode(adapter);
3682 /* Open the gates for HDD to receive Wext commands */
3683 adapter->isLinkUpSvcNeeded = false;
3684 adapter->scan_info.mScanPending = false;
3685
3686 /* Indicate disconnect event to supplicant if associated previously */
3687 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003688 eConnectionState_IbssConnected == connState ||
3689 eConnectionState_NotConnected == connState ||
3690 eConnectionState_IbssDisconnected == connState ||
3691 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 union iwreq_data wrqu;
3693 memset(&wrqu, '\0', sizeof(wrqu));
3694 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3695 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3696 wireless_send_event(adapter->dev, SIOCGIWAP,
3697 &wrqu, NULL);
3698 adapter->sessionCtx.station.
3699 hdd_ReassocScenario = false;
3700
3701 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05303702 wlan_hdd_cfg80211_indicate_disconnect(
3703 adapter->dev, false,
3704 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705 } else if (eConnectionState_Connecting == connState) {
3706 /*
3707 * Indicate connect failure to supplicant if we were in the
3708 * process of connecting
3709 */
3710 cfg80211_connect_result(adapter->dev, NULL,
3711 NULL, 0, NULL, 0,
3712 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3713 GFP_KERNEL);
3714 }
3715
3716 hdd_register_tx_flow_control(adapter,
3717 hdd_tx_resume_timer_expired_handler,
3718 hdd_tx_resume_cb);
3719
3720 break;
3721
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003722 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723 /* softAP can handle SSR */
3724 break;
3725
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003726 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003727#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07003728 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3730#else
Jeff Johnson5880d792016-08-15 13:32:30 -07003731 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 /* event supplicant to restart */
3733 cfg80211_del_sta(adapter->dev,
3734 (const u8 *)&bcastMac.bytes[0],
3735 GFP_KERNEL);
3736#endif
3737 break;
3738
3739 default:
3740 break;
3741 }
3742
3743 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3744 adapterNode = pNext;
3745 }
3746
3747 EXIT();
3748
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303749 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750}
3751
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303752QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003753 hdd_adapter_list_node_t **padapterNode)
3754{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303755 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003756 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303757 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3758 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003759 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003760 return status;
3761}
3762
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303763QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003764 hdd_adapter_list_node_t *adapterNode,
3765 hdd_adapter_list_node_t **pNextAdapterNode)
3766{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303767 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003768 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303769 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3770 (qdf_list_node_t *) adapterNode,
3771 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003773 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774 return status;
3775}
3776
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303777QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 hdd_adapter_list_node_t *adapterNode)
3779{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303780 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003781 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303782 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003784 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 return status;
3786}
3787
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303788QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003789 hdd_adapter_list_node_t **padapterNode)
3790{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303791 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003792 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303793 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3794 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003795 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796 return status;
3797}
3798
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303799QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800 hdd_adapter_list_node_t *adapterNode)
3801{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303802 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003803 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303804 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3805 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003806 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 return status;
3808}
3809
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303810QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 hdd_adapter_list_node_t *adapterNode)
3812{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303813 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003814 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303815 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3816 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003817 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818 return status;
3819}
3820
3821hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3822 tSirMacAddr macAddr)
3823{
3824 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3825 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303826 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827
3828 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3829
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303830 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 adapter = adapterNode->pAdapter;
3832
3833 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303834 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003835 macAddr, sizeof(tSirMacAddr))) {
3836 return adapter;
3837 }
3838 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3839 adapterNode = pNext;
3840 }
3841
3842 return NULL;
3843
3844}
3845
3846hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3847 uint32_t vdev_id)
3848{
3849 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3850 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303851 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303853 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003854
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303855 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856 adapter = adapterNode->pAdapter;
3857
3858 if (adapter->sessionId == vdev_id)
3859 return adapter;
3860
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303861 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003862 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3863 adapterNode = pNext;
3864 }
3865
Jeff Johnson5880d792016-08-15 13:32:30 -07003866 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003867
3868 return NULL;
3869}
3870
Abhishek Singh7996eb72015-12-30 17:24:02 +05303871/**
3872 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3873 * the sessionid
3874 * @hdd_ctx: hdd context.
3875 * @sme_session_id: sme session is for the adapter to get.
3876 *
3877 * This function is used to get the adapter with provided session id
3878 *
3879 * Return: adapter pointer if found
3880 *
3881 */
3882hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3883 uint32_t sme_session_id)
3884{
3885 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3886 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303887 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303888
3889
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303890 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303891
3892 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303893 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303894 adapter = adapter_node->pAdapter;
3895
3896 if (adapter &&
3897 adapter->sessionId == sme_session_id)
3898 return adapter;
3899
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303900 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303901 hdd_get_next_adapter(hdd_ctx,
3902 adapter_node, &next);
3903 adapter_node = next;
3904 }
3905 return NULL;
3906}
3907
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003908/**
3909 * hdd_get_adapter() - to get adapter matching the mode
3910 * @hdd_ctx: hdd context
3911 * @mode: adapter mode
3912 *
3913 * This routine will return the pointer to adapter matching
3914 * with the passed mode.
3915 *
3916 * Return: pointer to adapter or null
3917 */
3918hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
3919 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920{
3921 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3922 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303923 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924
3925 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3926
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303927 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003928 adapter = adapterNode->pAdapter;
3929
3930 if (adapter && (mode == adapter->device_mode))
3931 return adapter;
3932
3933 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3934 adapterNode = pNext;
3935 }
3936
3937 return NULL;
3938
3939}
3940
3941/**
3942 * hdd_get_operating_channel() - return operating channel of the device mode
3943 * @hdd_ctx: Pointer to the HDD context.
3944 * @mode: Device mode for which operating channel is required.
3945 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003946 * QDF_STA_MODE,
3947 * QDF_P2P_CLIENT_MODE,
3948 * QDF_SAP_MODE,
3949 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950 *
3951 * This API returns the operating channel of the requested device mode
3952 *
3953 * Return: channel number. "0" id the requested device is not found OR it is
3954 * not connected.
3955 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003956uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
3957 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958{
3959 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303960 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003961 hdd_adapter_t *adapter;
3962 uint8_t operatingChannel = 0;
3963
3964 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3965
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303966 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003967 adapter = adapterNode->pAdapter;
3968
3969 if (mode == adapter->device_mode) {
3970 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003971 case QDF_STA_MODE:
3972 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 if (hdd_conn_is_connected
3974 (WLAN_HDD_GET_STATION_CTX_PTR
3975 (adapter))) {
3976 operatingChannel =
3977 (WLAN_HDD_GET_STATION_CTX_PTR
3978 (adapter))->conn_info.
3979 operationChannel;
3980 }
3981 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003982 case QDF_SAP_MODE:
3983 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003984 /* softap connection info */
3985 if (test_bit
3986 (SOFTAP_BSS_STARTED,
3987 &adapter->event_flags))
3988 operatingChannel =
3989 (WLAN_HDD_GET_AP_CTX_PTR
3990 (adapter))->operatingChannel;
3991 break;
3992 default:
3993 break;
3994 }
3995
3996 break; /* Found the device of interest. break the loop */
3997 }
3998
3999 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4000 adapterNode = pNext;
4001 }
4002 return operatingChannel;
4003}
4004
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304005static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 hdd_ctx)
4007{
4008 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304009 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010 hdd_adapter_t *adapter;
4011
4012 ENTER();
4013
4014 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4015
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;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004018 if ((adapter->device_mode == QDF_STA_MODE) ||
4019 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4020 (adapter->device_mode == QDF_IBSS_MODE) ||
4021 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4022 (adapter->device_mode == QDF_SAP_MODE) ||
4023 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 wlan_hdd_cfg80211_deregister_frames(adapter);
4025 hdd_unregister_wext(adapter->dev);
4026 }
4027 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4028 adapterNode = pNext;
4029 }
4030
4031 EXIT();
4032
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304033 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004034}
4035
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304036QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037{
4038 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304039 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 hdd_adapter_t *adapter;
4041
4042 ENTER();
4043
4044 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4045
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304046 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004047 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004048 if ((adapter->device_mode == QDF_STA_MODE) ||
4049 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4050 (adapter->device_mode == QDF_IBSS_MODE) ||
4051 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4052 (adapter->device_mode == QDF_SAP_MODE) ||
4053 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004054 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4055 eCSR_SCAN_ABORT_DEFAULT);
4056 }
4057 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4058 adapterNode = pNext;
4059 }
4060
4061 EXIT();
4062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304063 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064}
4065
4066#ifdef WLAN_NS_OFFLOAD
4067/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004068 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069 * @hdd_ctx: Pointer to hdd context
4070 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004071 * Unregister for IPv6 address change notifications.
4072 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 * Return: None
4074 */
4075static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4076{
4077 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4078
4079 return;
4080}
4081
4082/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004083 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 * @hdd_ctx: Pointer to hdd context
4085 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004086 * Register for IPv6 address change notifications.
4087 *
4088 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004089 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004090static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091{
4092 int ret;
4093
4094 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4095 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004096 if (ret) {
4097 hdd_err("Failed to register IPv6 notifier: %d", ret);
4098 goto out;
4099 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004101 hdd_info("Registered IPv6 notifier");
4102out:
4103 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104}
4105#else
4106/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004107 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 * @hdd_ctx: Pointer to hdd context
4109 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004110 * Unregister for IPv6 address change notifications.
4111 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004112 * Return: None
4113 */
4114static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4115{
4116}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004118/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004119 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120 * @hdd_ctx: Pointer to hdd context
4121 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004122 * Register for IPv6 address change notifications.
4123 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 * Return: None
4125 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004126static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004128 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129}
4130#endif
4131
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304132#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4133/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004134 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304135 * @hdd_ctx: HDD context
4136 *
4137 * Activates the logging service
4138 *
4139 * Return: Zero in case of success, negative value otherwise
4140 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004141static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304142{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004143 int ret;
4144 struct hdd_config *config = hdd_ctx->config;
4145
4146 if (!config->wlanLoggingEnable)
4147 return 0;
4148
4149 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4150 config->wlanLoggingNumBuf);
4151 if (ret)
4152 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4153 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304154}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004155
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304156/**
4157 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4158 * @hdd_ctx: HDD context
4159 *
4160 * Deactivates the logging service
4161 *
4162 * Return: 0 on deactivating the logging service
4163 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004164static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304165{
4166 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4167 return wlan_logging_sock_deactivate_svc();
4168
4169 return 0;
4170}
4171#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004172static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304173{
4174 return 0;
4175}
4176
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004177static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304178{
4179 return 0;
4180}
4181#endif
4182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004184 * hdd_register_notifiers - Register netdev notifiers.
4185 * @hdd_ctx: HDD context
4186 *
4187 * Register netdev notifiers like IPv4 and IPv6.
4188 *
4189 * Return: 0 on success and errno on failure
4190 */
4191static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4192{
4193 int ret;
4194
4195 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4196 if (ret) {
4197 hdd_err("register_netdevice_notifier failed: %d", ret);
4198 goto out;
4199 }
4200
4201 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4202 if (ret)
4203 goto unregister_notifier;
4204
4205 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4206 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4207 if (ret) {
4208 hdd_err("Failed to register IPv4 notifier: %d", ret);
4209 goto unregister_ip6_notifier;
4210 }
4211
4212 return 0;
4213
4214unregister_ip6_notifier:
4215 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4216unregister_notifier:
4217 unregister_netdevice_notifier(&hdd_netdev_notifier);
4218out:
4219 return ret;
4220
4221}
4222
4223/**
4224 * hdd_unregister_notifiers - Unregister netdev notifiers.
4225 * @hdd_ctx: HDD context
4226 *
4227 * Unregister netdev notifiers like IPv4 and IPv6.
4228 *
4229 * Return: None.
4230 */
4231static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4232{
4233 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4234
4235 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4236
4237 unregister_netdevice_notifier(&hdd_netdev_notifier);
4238}
4239
4240/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004241 * hdd_exit_netlink_services - Exit netlink services
4242 * @hdd_ctx: HDD context
4243 *
4244 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4245 * nl service.
4246 *
4247 * Return: None.
4248 */
4249static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4250{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004251 hdd_close_cesium_nl_sock();
4252
4253 ptt_sock_deactivate_svc();
4254
4255 nl_srv_exit();
4256}
4257
4258/**
4259 * hdd_init_netlink_services- Init netlink services
4260 * @hdd_ctx: HDD context
4261 *
4262 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4263 * nl service.
4264 *
4265 * Return: 0 on success and errno on failure.
4266 */
4267static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4268{
4269 int ret;
4270
Ryan Hsuceddceb2016-04-28 10:20:14 -07004271 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004272 if (ret) {
4273 hdd_alert("nl_srv_init failed: %d", ret);
4274 goto out;
4275 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004276 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004277
4278 ret = oem_activate_service(hdd_ctx);
4279 if (ret) {
4280 hdd_alert("oem_activate_service failed: %d", ret);
4281 goto err_nl_srv;
4282 }
4283
4284 ret = ptt_sock_activate_svc();
4285 if (ret) {
4286 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4287 goto err_nl_srv;
4288 }
4289
4290 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004291 if (ret)
4292 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004293
4294 ret = cnss_diag_activate_service();
4295 if (ret) {
4296 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4297 goto err_close_cesium;
4298 }
4299
4300 return 0;
4301
4302err_close_cesium:
4303 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004304 ptt_sock_deactivate_svc();
4305err_nl_srv:
4306 nl_srv_exit();
4307out:
4308 return ret;
4309}
4310
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004311#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4312/**
4313 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4314 * @hdd_ctx: HDD context.
4315 *
4316 * Destroy RX wakelock.
4317 *
4318 * Return: None.
4319 */
4320static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4321{
4322 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4323}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004324
4325/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004326 * hdd_rx_wake_lock_create() - Create RX wakelock
4327 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004328 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004329 * Create RX wakelock.
4330 *
4331 * Return: None.
4332 */
4333static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4334{
4335 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4336}
4337#else
4338static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { }
4339static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { }
4340#endif
4341
4342/**
4343 * hdd_roc_context_init() - Init ROC context
4344 * @hdd_ctx: HDD context.
4345 *
4346 * Initialize ROC context.
4347 *
4348 * Return: 0 on success and errno on failure.
4349 */
4350static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4351{
4352 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4353 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4354
4355 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4356
4357 return 0;
4358}
4359
4360/**
4361 * hdd_roc_context_destroy() - Destroy ROC context
4362 * @hdd_ctx: HDD context.
4363 *
4364 * Destroy roc list and flush the pending roc work.
4365 *
4366 * Return: None.
4367 */
4368static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4369{
4370 flush_delayed_work(&hdd_ctx->roc_req_work);
4371 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4372}
4373
4374/**
4375 * hdd_context_destroy() - Destroy HDD context
4376 * @hdd_ctx: HDD context to be destroyed.
4377 *
4378 * Free config and HDD context as well as destroy all the resources.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004379 *
4380 * Return: None
4381 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004382static void hdd_context_destroy(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004383{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304384 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004385 hdd_logging_sock_deactivate_svc(hdd_ctx);
4386
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004387 hdd_roc_context_destroy(hdd_ctx);
4388
4389 hdd_sap_context_destroy(hdd_ctx);
4390
4391 hdd_rx_wake_lock_destroy(hdd_ctx);
4392
4393 hdd_tdls_context_destroy(hdd_ctx);
4394
4395 hdd_scan_context_destroy(hdd_ctx);
4396
4397 qdf_list_destroy(&hdd_ctx->hddAdapters);
4398
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304399 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004400 hdd_ctx->config = NULL;
4401
4402 wiphy_free(hdd_ctx->wiphy);
4403}
4404
4405/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406 * hdd_wlan_exit() - HDD WLAN exit function
4407 * @hdd_ctx: Pointer to the HDD Context
4408 *
4409 * This is the driver exit point (invoked during rmmod)
4410 *
4411 * Return: None
4412 */
4413void hdd_wlan_exit(hdd_context_t *hdd_ctx)
4414{
4415 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304416 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304418 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419
4420 ENTER();
4421
Arun Khandavallifae92942016-08-01 13:31:08 +05304422 if (QDF_TIMER_STATE_RUNNING ==
4423 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4424 hdd_info("Stpp interface change timer");
4425 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 }
4427
Arun Khandavallifae92942016-08-01 13:31:08 +05304428 if (!QDF_IS_STATUS_SUCCESS
4429 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4430 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004431
Arun Khandavallifae92942016-08-01 13:31:08 +05304432
4433 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434
4435#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05304436 if (QDF_TIMER_STATE_RUNNING ==
4437 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
4438 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 }
4440
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304441 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304442 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004443 hdd_err("Cannot deallocate Bus bandwidth timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444 }
4445#endif
4446
4447#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304448 if (QDF_TIMER_STATE_RUNNING ==
4449 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4450 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451 }
4452
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304453 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304454 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004455 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004456 }
4457#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004458
Arun Khandavallifae92942016-08-01 13:31:08 +05304459 mutex_lock(&hdd_ctx->iface_change_lock);
4460 driver_status = hdd_ctx->driver_status;
4461 mutex_unlock(&hdd_ctx->iface_change_lock);
4462
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 /*
4464 * Powersave Offload Case
4465 * Disable Idle Power Save Mode
4466 */
4467 hdd_set_idle_ps_config(hdd_ctx, false);
4468
Arun Khandavallifae92942016-08-01 13:31:08 +05304469 if (driver_status != DRIVER_MODULES_CLOSED) {
4470 hdd_unregister_wext_all_adapters(hdd_ctx);
4471 /*
4472 * Cancel any outstanding scan requests. We are about to close
4473 * all of our adapters, but an adapter structure is what SME
4474 * passes back to our callback function. Hence if there
4475 * are any outstanding scan requests then there is a
4476 * race condition between when the adapter is closed and
4477 * when the callback is invoked. We try to resolve that
4478 * race condition here by canceling any outstanding scans
4479 * before we close the adapters.
4480 * Note that the scans may be cancelled in an asynchronous
4481 * manner, so ideally there needs to be some kind of
4482 * synchronization. Rather than introduce a new
4483 * synchronization here, we will utilize the fact that we are
4484 * about to Request Full Power, and since that is synchronized,
4485 * the expectation is that by the time Request Full Power has
4486 * completed, all scans will be cancelled
4487 */
4488 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4489 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 }
4491
Arun Khandavallifae92942016-08-01 13:31:08 +05304492 hdd_wlan_stop_modules(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 /*
4494 * Close the scheduler before calling cds_close to make sure no thread
4495 * is scheduled after the each module close is called i.e after all the
4496 * data structures are freed.
4497 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304498 qdf_status = cds_sched_close(p_cds_context);
4499 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004500 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304501 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304504 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4505 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4506 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508 /*
4509 * Close CDS
4510 * This frees pMac(HAL) context. There should not be any call
4511 * that requires pMac access after this.
4512 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513
4514 hdd_wlan_green_ap_deinit(hdd_ctx);
4515
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004516 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004517
4518 hdd_ipa_cleanup(hdd_ctx);
4519
4520 /* Free up RoC request queue and flush workqueue */
4521 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522
Arun Khandavallifae92942016-08-01 13:31:08 +05304523
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004524
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304525 wlansap_global_deinit();
Nirav Shahed34b212016-04-25 10:59:16 +05304526 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304528 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004529
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004530 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
4531
Arun Khandavallifae92942016-08-01 13:31:08 +05304532 hdd_exit_netlink_services(hdd_ctx);
4533 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004534 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535}
4536
4537void __hdd_wlan_exit(void)
4538{
4539 hdd_context_t *hdd_ctx;
4540
4541 ENTER();
4542
Anurag Chouhan6d760662016-02-20 16:05:43 +05304543 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004544 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004545 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 EXIT();
4547 return;
4548 }
4549
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004550 /* Check IPA HW Pipe shutdown */
4551 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4552
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004553 memdump_deinit();
4554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 /* Do all the cleanup before deregistering the driver */
4556 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 EXIT();
4559}
4560
4561#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4562void hdd_skip_acs_scan_timer_handler(void *data)
4563{
4564 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4565
Jeff Johnson760350b2016-08-15 14:01:52 -07004566 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004567 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4568
4569 if (!hdd_ctx->hHal)
4570 return;
4571 sme_scan_flush_result(hdd_ctx->hHal);
4572}
4573#endif
4574
4575#ifdef QCA_HT_2040_COEX
4576/**
4577 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4578 * @adapter: pointer to adapter
4579 * @staId: station id
4580 * @macAddrSTA: station MAC address
4581 * @channel_type: channel type
4582 *
4583 * This function notifies FW with HT20/HT40 mode
4584 *
4585 * Return: 0 if successful, error number otherwise
4586 */
4587int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304588 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589{
4590 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304591 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592 hdd_context_t *hdd_ctx = NULL;
4593
4594 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4595
4596 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304597 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004598 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304599
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004600 if (!hdd_ctx->hHal)
4601 return -EINVAL;
4602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304603 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004604 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304605 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004606 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607 return -EINVAL;
4608 }
4609
4610 return 0;
4611}
4612#endif
4613
4614/**
4615 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4616 * @state: state
4617 *
4618 * This function notifies FW with modem power status
4619 *
4620 * Return: 0 if successful, error number otherwise
4621 */
4622int hdd_wlan_notify_modem_power_state(int state)
4623{
4624 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304625 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626 hdd_context_t *hdd_ctx;
4627
Anurag Chouhan6d760662016-02-20 16:05:43 +05304628 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004629 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304630 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004631 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633 if (!hdd_ctx->hHal)
4634 return -EINVAL;
4635
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304636 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4637 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004638 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 state);
4640 return -EINVAL;
4641 }
4642 return 0;
4643}
4644
4645/**
4646 *
4647 * hdd_post_cds_enable_config() - HDD post cds start config helper
4648 * @adapter - Pointer to the HDD
4649 *
4650 * Return: None
4651 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304652QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304654 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655
4656 /*
4657 * Send ready indication to the HDD. This will kick off the MAC
4658 * into a 'running' state and should kick off an initial scan.
4659 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304660 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4661 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004662 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
4663 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304664 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 }
4666
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304667 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668}
4669
4670/* wake lock APIs for HDD */
4671void hdd_prevent_suspend(uint32_t reason)
4672{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304673 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674}
4675
4676void hdd_allow_suspend(uint32_t reason)
4677{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304678 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679}
4680
4681void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
4682{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05304683 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
4684 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685}
4686
4687/**
4688 * hdd_exchange_version_and_caps() - exchange version and capability with target
4689 * @hdd_ctx: Pointer to HDD context
4690 *
4691 * This is the HDD function to exchange version and capability information
4692 * between Host and Target
4693 *
4694 * This function gets reported version of FW.
4695 * It also finds the version of target headers used to compile the host;
4696 * It compares the above two and prints a warning if they are different;
4697 * It gets the SW and HW version string;
4698 * Finally, it exchanges capabilities between host and target i.e. host
4699 * and target exchange a msg indicating the features they support through a
4700 * bitmap
4701 *
4702 * Return: None
4703 */
4704void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4705{
4706
4707 tSirVersionType versionCompiled;
4708 tSirVersionType versionReported;
4709 tSirVersionString versionString;
4710 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304711 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712
4713 memset(&versionCompiled, 0, sizeof(versionCompiled));
4714 memset(&versionReported, 0, sizeof(versionReported));
4715
4716 /* retrieve and display WCNSS version information */
4717 do {
4718
4719 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4720 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304721 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004722 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723 break;
4724 }
4725
4726 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4727 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304728 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004729 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730 break;
4731 }
4732
4733 if ((versionCompiled.major != versionReported.major) ||
4734 (versionCompiled.minor != versionReported.minor) ||
4735 (versionCompiled.version != versionReported.version) ||
4736 (versionCompiled.revision != versionReported.revision)) {
4737 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4738 "Host expected %u.%u.%u.%u\n",
4739 WLAN_MODULE_NAME,
4740 (int)versionReported.major,
4741 (int)versionReported.minor,
4742 (int)versionReported.version,
4743 (int)versionReported.revision,
4744 (int)versionCompiled.major,
4745 (int)versionCompiled.minor,
4746 (int)versionCompiled.version,
4747 (int)versionCompiled.revision);
4748 } else {
4749 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4750 WLAN_MODULE_NAME,
4751 (int)versionReported.major,
4752 (int)versionReported.minor,
4753 (int)versionReported.version,
4754 (int)versionReported.revision);
4755 }
4756
4757 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4758 versionString,
4759 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304760 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004761 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 break;
4763 }
4764
4765 pr_info("%s: WCNSS software version %s\n",
4766 WLAN_MODULE_NAME, versionString);
4767
4768 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4769 versionString,
4770 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304771 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07004772 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004773 break;
4774 }
4775
4776 pr_info("%s: WCNSS hardware version %s\n",
4777 WLAN_MODULE_NAME, versionString);
4778
4779 /*
4780 * 1.Check if FW version is greater than 0.1.1.0. Only then
4781 * send host-FW capability exchange message
4782 * 2.Host-FW capability exchange message is only present on
4783 * target 1.1 so send the message only if it the target is 1.1
4784 * minor numbers for different target branches:
4785 * 0 -> (1.0)Mainline Build
4786 * 1 -> (1.1)Mainline Build
4787 * 2->(1.04) Stability Build
4788 */
4789 if (((versionReported.major > 0) || (versionReported.minor > 1)
4790 || ((versionReported.minor >= 1)
4791 && (versionReported.version >= 1)))
4792 && ((versionReported.major == 1)
4793 && (versionReported.minor >= 1)))
4794 fwFeatCapsMsgSupported = 1;
4795
4796 if (fwFeatCapsMsgSupported) {
4797 /*
4798 * Indicate if IBSS heartbeat monitoring needs to be
4799 * offloaded
4800 */
4801 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4802 sme_disable_feature_capablity
4803 (IBSS_HEARTBEAT_OFFLOAD);
4804 }
4805
4806 sme_feature_caps_exchange(hdd_ctx->hHal);
4807 }
4808
4809 } while (0);
4810
4811}
4812
4813/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304814QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815{
4816 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4817 hdd_ctx->reg.cc_src);
4818}
4819
4820/**
4821 * hdd_is_5g_supported() - check if hardware supports 5GHz
4822 * @hdd_ctx: Pointer to the hdd context
4823 *
4824 * HDD function to know if hardware supports 5GHz
4825 *
4826 * Return: true if hardware supports 5GHz
4827 */
4828bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4829{
4830 /*
4831 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4832 * then hardware support 5Ghz.
4833 */
4834 return true;
4835}
4836
Amar Singhale4f28ee2015-10-21 14:36:56 -07004837static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838{
4839 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07004840 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004841
4842 wiphy = hdd_ctx->wiphy;
4843
4844 /*
4845 * The channel information in
4846 * wiphy needs to be initialized before wiphy registration
4847 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004848 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
4849 if (ret_val) {
4850 hdd_alert("regulatory init failed");
4851 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004852 }
4853
4854#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4855 wiphy->wowlan = &wowlan_support_reg_init;
4856#else
4857 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4858 WIPHY_WOWLAN_MAGIC_PKT |
4859 WIPHY_WOWLAN_DISCONNECT |
4860 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4861 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4862 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4863 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4864 WIPHY_WOWLAN_RFKILL_RELEASE;
4865
4866 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4867 WOW_MAX_FILTERS_PER_LIST);
4868 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4869 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4870#endif
4871
4872 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004873 ret_val = wlan_hdd_cfg80211_register(wiphy);
4874 if (0 > ret_val)
4875 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004876
Amar Singhale4f28ee2015-10-21 14:36:56 -07004877 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878}
4879
Ravi Joshie2331e82015-07-01 18:18:54 -07004880/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07004881 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07004882 * @hdd_ctx - handle to hdd context
4883 * @tx_packets - transmit packet count
4884 * @rx_packets - receive packet count
4885 *
4886 * The function controls the bus bandwidth and dynamic control of
4887 * tcp delayed ack configuration
4888 *
4889 * Returns: None
4890 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891#ifdef MSM_PLATFORM
Yuanyuan Liu13738502016-04-06 17:41:37 -07004892void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004893 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004894{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004896 uint64_t temp_rx = 0;
4897 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07004898 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004899 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4900 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004902 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004903 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004905 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004906 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004907 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004908 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07004909 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004910
Mohit Khannae71e2262015-11-10 09:37:24 -08004911 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4912 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913
4914 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004915 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
4916 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07004918 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05304919 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05304920 if (hdd_ctx->hbw_requested) {
4921 pld_remove_pm_qos(hdd_ctx->parent_dev);
4922 hdd_ctx->hbw_requested = false;
4923 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05304924 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07004925 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05304926 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05304927 if (!hdd_ctx->hbw_requested) {
4928 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
4929 hdd_ctx->hbw_requested = true;
4930 }
4931
Nirav Shah3bbfa512016-05-12 16:43:49 +05304932 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07004933 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05304934 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07004935 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004936 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004937
4938 /* fine-tuning parameters for RX Flows */
4939 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941 hdd_ctx->prev_rx = rx_packets;
4942 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004943 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004944 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004945 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004946
Mohit Khannae71e2262015-11-10 09:37:24 -08004947 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4948 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949
4950 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004951 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 next_rx_level, temp_rx);
4953 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07004954 /* Send throughput indication only if it is enabled.
4955 * Disabling tcp_del_ack will revert the tcp stack behavior
4956 * to default delayed ack. Note that this will disable the
4957 * dynamic delayed ack mechanism across the system
4958 */
4959 if (hdd_ctx->config->enable_tcp_delack)
4960 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004961 &next_rx_level,
4962 sizeof(next_rx_level));
4963 }
4964
Mohit Khannae71e2262015-11-10 09:37:24 -08004965 /* fine-tuning parameters for TX Flows */
4966 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4967 hdd_ctx->prev_tx = tx_packets;
4968 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4969 next_tx_level = WLAN_SVC_TP_HIGH;
4970 else
4971 next_tx_level = WLAN_SVC_TP_LOW;
4972
4973 if (hdd_ctx->cur_tx_level != next_tx_level) {
4974 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4975 next_tx_level, temp_tx);
4976 hdd_ctx->cur_tx_level = next_tx_level;
4977 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4978 &next_tx_level,
4979 sizeof(next_tx_level));
4980 }
4981
4982 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4983 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984 hdd_ctx->hdd_txrx_hist_idx++;
4985 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004986}
4987
4988#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4989static void hdd_bus_bw_compute_cbk(void *priv)
4990{
4991 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4992 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304993 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05304994 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
4995 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004996 uint64_t total_tx = 0, total_rx = 0;
4997 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304998 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304999 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005000 bool connected = false;
5001 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5002
5003 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305004 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 status =
5006 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5007
5008 if (adapterNode->pAdapter == NULL)
5009 continue;
5010 adapter = adapterNode->pAdapter;
5011
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005012 if ((adapter->device_mode == QDF_STA_MODE ||
5013 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5015 != eConnectionState_Associated) {
5016
5017 continue;
5018 }
5019
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005020 if ((adapter->device_mode == QDF_SAP_MODE ||
5021 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005022 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5023
5024 continue;
5025 }
5026
5027 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5028 adapter->prev_tx_packets);
5029 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5030 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305031
5032 if (adapter->device_mode == QDF_SAP_MODE ||
5033 adapter->device_mode == QDF_P2P_GO_MODE ||
5034 adapter->device_mode == QDF_IBSS_MODE) {
5035
5036 ret = ol_get_intra_bss_fwd_pkts_count(
5037 adapter->sessionId,
5038 &fwd_tx_packets, &fwd_rx_packets);
5039 if (ret == A_OK) {
5040 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5041 fwd_tx_packets,
5042 adapter->prev_fwd_tx_packets);
5043 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5044 fwd_tx_packets,
5045 adapter->prev_fwd_rx_packets);
5046 }
5047 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048
5049 total_rx += adapter->stats.rx_packets;
5050 total_tx += adapter->stats.tx_packets;
5051
5052 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5053 adapter->prev_tx_packets = adapter->stats.tx_packets;
5054 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305055 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5056 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5058 connected = true;
5059 }
5060
5061 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5062 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5063 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5064 rx_packets;
5065 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5066 tx_packets;
5067
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305068 /* add intra bss forwarded tx and rx packets */
5069 tx_packets += fwd_tx_packets_diff;
5070 rx_packets += fwd_rx_packets_diff;
5071
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5073 tx_packets += (uint64_t)ipa_tx_packets;
5074 rx_packets += (uint64_t)ipa_rx_packets;
5075
5076 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005077 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005078 return;
5079 }
5080
Yuanyuan Liu13738502016-04-06 17:41:37 -07005081 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005082
5083 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5084 hdd_ipa_uc_stat_request(adapter, 2);
5085
Anurag Chouhan210db072016-02-22 18:42:15 +05305086 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087 hdd_ctx->config->busBandwidthComputeInterval);
5088}
5089#endif
5090
5091/**
Nirav Shahed34b212016-04-25 10:59:16 +05305092 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5093 * @hdd_ctx: hdd context
5094 *
5095 * Return: 0 for success or error code
5096 */
5097int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
5098{
5099 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5100 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5101 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005102 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305103 return -ENOMEM;
5104 }
5105 return 0;
5106}
5107
5108/**
5109 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5110 * @hdd_ctx: hdd context
5111 *
5112 * Return: none
5113 */
5114void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5115{
5116 if (hdd_ctx->hdd_txrx_hist) {
5117 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5118 hdd_ctx->hdd_txrx_hist = NULL;
5119 }
5120}
5121
Nirav Shahda008342016-05-17 18:50:40 +05305122static uint8_t *convert_level_to_string(uint32_t level)
5123{
5124 switch (level) {
5125 /* initialize the wlan sub system */
5126 case WLAN_SVC_TP_NONE:
5127 return "NONE";
5128 case WLAN_SVC_TP_LOW:
5129 return "LOW";
5130 case WLAN_SVC_TP_MEDIUM:
5131 return "MED";
5132 case WLAN_SVC_TP_HIGH:
5133 return "HIGH";
5134 default:
5135 return "INVAL";
5136 }
5137}
5138
Nirav Shahed34b212016-04-25 10:59:16 +05305139
5140/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005141 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5142 * @hdd_ctx: hdd context
5143 *
5144 * Return: none
5145 */
5146void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5147{
5148 int i;
5149
5150#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005151 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305152 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005153 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005154 hdd_ctx->config->busBandwidthHighThreshold,
5155 hdd_ctx->config->busBandwidthMediumThreshold,
5156 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005157 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305158 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005159 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160 hdd_ctx->config->tcpDelackThresholdHigh,
5161 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005162 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305163 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005164#endif
5165
Jeff Johnson760350b2016-08-15 14:01:52 -07005166 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305167 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5168
Jeff Johnson760350b2016-08-15 14:01:52 -07005169 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 -08005170
5171 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005172 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5174 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5175 hdd_ctx->hdd_txrx_hist[i].total_tx,
5176 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305177 convert_level_to_string(
5178 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5179 convert_level_to_string(
5180 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5181 convert_level_to_string(
5182 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005183 }
5184 return;
5185}
5186
5187/**
5188 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5189 * @hdd_ctx: hdd context
5190 *
5191 * Return: none
5192 */
5193void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5194{
5195 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305196 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5197 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005198}
5199
5200/**
5201 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5202 * @pHddCtx: hdd context
5203 *
5204 * Return: none
5205 */
5206void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5207{
5208
5209 hdd_adapter_t *adapter = NULL;
5210 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305211 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305213 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214
5215 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305216 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 adapter = adapter_node->pAdapter;
5218
Jeff Johnson760350b2016-08-15 14:01:52 -07005219 hdd_err("\nNetif queue operation statistics:");
5220 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305221 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005222 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305223 curr_time = qdf_system_ticks();
5224 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305225 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305226 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305227 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305228 unpause = adapter->total_unpause_time;
5229 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305230 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305231 pause = adapter->total_pause_time;
5232 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005233 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305234 qdf_system_ticks_to_msecs(total),
5235 qdf_system_ticks_to_msecs(pause),
5236 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005237 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238
Nirav Shahda008342016-05-17 18:50:40 +05305239 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5240 qdf_time_t pause_delta = 0;
5241
5242 if (adapter->pause_map & (1 << i))
5243 pause_delta = delta;
5244
Jeff Johnson760350b2016-08-15 14:01:52 -07005245 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246 hdd_reason_type_to_string(i),
5247 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305248 adapter->queue_oper_stats[i].unpause_count,
5249 qdf_system_ticks_to_msecs(
5250 adapter->queue_oper_stats[i].total_pause_time +
5251 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 }
5253
Jeff Johnson760350b2016-08-15 14:01:52 -07005254 hdd_err("\nNetif queue operation history:");
5255 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305256 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5257
Jeff Johnson760350b2016-08-15 14:01:52 -07005258 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259
5260 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005261 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305262 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005263 adapter->queue_oper_history[i].time),
5264 hdd_action_type_to_string(
5265 adapter->queue_oper_history[i].netif_action),
5266 hdd_reason_type_to_string(
5267 adapter->queue_oper_history[i].netif_reason),
5268 adapter->queue_oper_history[i].pause_map);
5269 }
5270
5271 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5272 adapter_node = next;
5273 }
5274
5275
5276}
5277
5278/**
5279 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5280 * @hdd_ctx: hdd context
5281 *
5282 * Return: none
5283 */
5284void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5285{
5286 hdd_adapter_t *adapter = NULL;
5287 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305288 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005289
5290 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305291 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 adapter = adapter_node->pAdapter;
5293
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305294 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305296 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305298 adapter->history_index = 0;
5299 adapter->start_time = adapter->last_time = qdf_system_ticks();
5300 adapter->total_pause_time = 0;
5301 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005302 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5303 adapter_node = next;
5304 }
5305}
5306
5307/**
5308 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5309 * @halHandle: Hal handle
5310 * @pContext: Pointer to the context
5311 * @sessionId: Session ID
5312 * @scanId: Scan ID
5313 * @status: Status
5314 *
5315 * This is the callback to be executed when 11d scan is completed to flush out
5316 * the scan results
5317 *
5318 * 11d scan is done during driver load and is a passive scan on all
5319 * channels supported by the device, 11d scans may find some APs on
5320 * frequencies which are forbidden to be used in the regulatory domain
5321 * the device is operating in. If these APs are notified to the supplicant
5322 * it may try to connect to these APs, thus flush out all the scan results
5323 * which are present in SME after 11d scan is done.
5324 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305325 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005326 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305327static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 uint8_t sessionId, uint32_t scanId,
5329 eCsrScanStatus status)
5330{
5331 ENTER();
5332
5333 sme_scan_flush_result(halHandle);
5334
5335 EXIT();
5336
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305337 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338}
5339
5340#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5341/**
5342 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5343 * @hdd_ctx: hdd global context
5344 *
5345 * Return: none
5346 */
5347static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5348{
5349 uint8_t i;
5350
5351 mutex_init(&hdd_ctx->op_ctx.op_lock);
5352 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5353 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5354 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5355 }
5356}
5357#else
5358static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5359{
5360}
5361#endif
5362
5363#ifdef WLAN_FEATURE_FASTPATH
5364/**
5365 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5366 * @hdd_cfg: hdd config
5367 * @context: lower layer context
5368 *
5369 * Return: none
5370 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305371void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 void *context)
5373{
5374 if (hdd_cfg->fastpath_enable)
5375 hif_enable_fastpath(context);
5376}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377#endif
5378
Yuanyuan Liu13738502016-04-06 17:41:37 -07005379#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380/**
5381 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005382 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 * @level: thermal level
5384 *
5385 * Change IPA data path to SW path when the thermal throttle level greater
5386 * than 0, and restore the original data path when throttle level is 0
5387 *
5388 * Return: none
5389 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005390static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005391{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005392 hdd_context_t *hdd_ctx = context;
5393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005394 /* Change IPA to SW path when throttle level greater than 0 */
5395 if (level > THROTTLE_LEVEL_0)
5396 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5397 else
5398 /* restore original concurrency mode */
5399 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5400}
5401
5402/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305403 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5404 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305405 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005406 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305407 * Get a safe channel to restart SAP. PCL already takes into account the
5408 * unsafe channels. So, the PCL is validated with the ACS range to provide
5409 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305411 * Return: Channel number to restart SAP in case of success. In case of any
5412 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305414static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5415 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305417 struct sir_pcl_list pcl;
5418 QDF_STATUS status;
5419 uint32_t i, j;
5420 tHalHandle *hal_handle;
5421 hdd_context_t *hdd_ctx;
5422 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305424 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5425 if (!hdd_ctx) {
5426 hdd_err("invalid HDD context");
5427 return INVALID_CHANNEL_ID;
5428 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305430 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5431 if (!hal_handle) {
5432 hdd_err("invalid HAL handle");
5433 return INVALID_CHANNEL_ID;
5434 }
5435
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305436 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5437 pcl.pcl_list, &pcl.pcl_len,
5438 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5439 if (QDF_IS_STATUS_ERROR(status)) {
5440 hdd_err("Get PCL failed");
5441 return INVALID_CHANNEL_ID;
5442 }
5443
5444 if (!pcl.pcl_len) {
5445 hdd_alert("pcl length is zero. this is not expected");
5446 return INVALID_CHANNEL_ID;
5447 }
5448
5449 hdd_info("start:%d end:%d",
5450 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5451 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5452
5453 /* PCL already takes unsafe channel into account */
5454 for (i = 0; i < pcl.pcl_len; i++) {
5455 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5456 if ((pcl.pcl_list[i] >=
5457 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5458 (pcl.pcl_list[i] <=
5459 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5460 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5461 return pcl.pcl_list[i];
5462 }
5463 }
5464
5465 hdd_info("no safe channel from PCL found in ACS range");
5466
5467 /* Try for safe channel from all valid channel */
5468 pcl.pcl_len = MAX_NUM_CHAN;
5469 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5470 &pcl.pcl_len);
5471 if (QDF_IS_STATUS_ERROR(status)) {
5472 hdd_err("error in getting valid channel list");
5473 return INVALID_CHANNEL_ID;
5474 }
5475
5476 for (i = 0; i < pcl.pcl_len; i++) {
5477 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5478 found = false;
5479 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
5480 if (cds_chan_to_freq(pcl.pcl_list[i]) ==
5481 hdd_ctx->unsafe_channel_list[j]) {
5482 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5483 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005484 break;
5485 }
5486 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305487
5488 if (found)
5489 continue;
5490
5491 if ((pcl.pcl_list[i] >=
5492 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5493 (pcl.pcl_list[i] <=
5494 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5495 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5496 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497 }
5498 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305499
5500 return INVALID_CHANNEL_ID;
5501}
5502
5503/**
5504 * hdd_restart_sap() - Restarts SAP on the given channel
5505 * @adapter: AP adapter
5506 * @channel: Channel
5507 *
5508 * Restarts the SAP interface by invoking the function which executes the
5509 * callback to perform channel switch using (E)CSA.
5510 *
5511 * Return: None
5512 */
5513void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
5514{
5515 hdd_ap_ctx_t *hdd_ap_ctx;
5516 tHalHandle *hal_handle;
5517
5518 if (!adapter) {
5519 hdd_err("invalid adapter");
5520 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305522
5523 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5524
5525 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5526 if (!hal_handle) {
5527 hdd_err("invalid HAL handle");
5528 return;
5529 }
5530
5531 hdd_ap_ctx->sapConfig.channel = channel;
5532 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5533 hdd_ap_ctx->sapConfig.ch_width_orig;
5534
5535 hdd_info("chan:%d width:%d",
5536 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5537
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005538 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305539 hdd_ap_ctx->sapConfig.sec_ch,
5540 &hdd_ap_ctx->sapConfig.ch_params);
5541
5542 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005543}
5544
5545/**
5546 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
5547 * @adapter: HDD adapter pointer
5548 * @indParam: Channel avoid notification parameter
5549 *
5550 * Avoid channel notification from FW handler.
5551 * FW will send un-safe channel list to avoid over wrapping.
5552 * hostapd should not use notified channel
5553 *
5554 * Return: None
5555 */
5556static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
5557{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558 hdd_context_t *hdd_ctxt;
5559 tSirChAvoidIndType *ch_avoid_indi;
5560 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08005561 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
5562 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005563 uint16_t start_channel;
5564 uint16_t end_channel;
5565 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 tHddAvoidFreqList hdd_avoid_freq_list;
5567 uint32_t i;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305568 QDF_STATUS status;
5569 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
5570 hdd_adapter_t *adapter_temp;
5571 uint8_t restart_chan;
5572 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573
5574 /* Basic sanity */
5575 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005576 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577 return;
5578 }
5579
5580 hdd_ctxt = (hdd_context_t *) hdd_context;
5581 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
5582 cds_context = hdd_ctxt->pcds_context;
5583
5584 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07005585 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586 ch_avoid_indi->avoid_range_count);
5587
5588 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305589 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
5591 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
5592 ch_avoid_indi->avoid_freq_range[i].start_freq;
5593 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
5594 ch_avoid_indi->avoid_freq_range[i].end_freq;
5595 }
5596 hdd_avoid_freq_list.avoidFreqRangeCount =
5597 ch_avoid_indi->avoid_range_count;
5598
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005599 /* clear existing unsafe channel cache */
5600 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305601 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 sizeof(hdd_ctxt->unsafe_channel_list));
5603
5604 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
5605 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08005606 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005607 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005608 break;
5609 }
5610
5611 start_channel = ieee80211_frequency_to_channel(
5612 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
5613 end_channel = ieee80211_frequency_to_channel(
5614 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07005615 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
5617 start_channel,
5618 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
5619 end_channel);
5620
5621 /* do not process frequency bands that are not mapped to
5622 * predefined channels
5623 */
5624 if (start_channel == 0 || end_channel == 0)
5625 continue;
5626
Amar Singhalb8d4f152016-02-10 10:21:43 -08005627 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5628 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005629 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630 ch_avoid_indi->avoid_freq_range[
5631 range_loop].start_freq) {
5632 start_channel_idx = channel_loop;
5633 break;
5634 }
5635 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08005636 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5637 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005638 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005639 ch_avoid_indi->avoid_freq_range[
5640 range_loop].end_freq) {
5641 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07005642 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005643 ch_avoid_indi->avoid_freq_range[
5644 range_loop].end_freq)
5645 end_channel_idx--;
5646 break;
5647 }
5648 }
5649
Amar Singhalb8d4f152016-02-10 10:21:43 -08005650 if (start_channel_idx == INVALID_CHANNEL ||
5651 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 continue;
5653
5654 for (channel_loop = start_channel_idx; channel_loop <=
5655 end_channel_idx; channel_loop++) {
5656 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07005657 hdd_ctxt->unsafe_channel_count++] =
5658 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005659 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08005660 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005661 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005662 break;
5663 }
5664 }
5665 }
5666
Jeff Johnson34c88b72016-08-15 14:27:11 -07005667 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 hdd_ctxt->unsafe_channel_count);
5669
Yuanyuan Liu13738502016-04-06 17:41:37 -07005670 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
5671 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 hdd_ctxt->unsafe_channel_count)) {
5673 hdd_err("Failed to set unsafe channel");
5674
5675 /* clear existing unsafe channel cache */
5676 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305677 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 sizeof(hdd_ctxt->unsafe_channel_list));
5679
5680 return;
5681 }
5682
5683 for (channel_loop = 0;
5684 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005685 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 hdd_ctxt->unsafe_channel_list[channel_loop]);
5687 }
5688
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05305689 /*
5690 * first update the unsafe channel list to the platform driver and
5691 * send the avoid freq event to the application
5692 */
5693 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
5694
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305695 if (!hdd_ctxt->unsafe_channel_count) {
5696 hdd_info("no unsafe channels - not restarting SAP");
5697 return;
5698 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305700 /* No channel change is done for fixed channel SAP.
5701 * Loop through all ACS SAP interfaces and change the channels for
5702 * the ones operating on unsafe channels.
5703 */
5704 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
5705 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5706 adapter_temp = adapter_node->pAdapter;
5707
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305708 if (!adapter_temp) {
5709 hdd_err("adapter is NULL, moving to next one");
5710 goto next_adapater;
5711 }
5712
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305713 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
5714 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
5715 hdd_info("skip device mode:%d acs:%d",
5716 adapter_temp->device_mode,
5717 adapter_temp->sessionCtx.ap.sapConfig.
5718 acs_cfg.acs_mode);
5719 goto next_adapater;
5720 }
5721
5722 found = false;
5723 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
5724 if (cds_chan_to_freq(
5725 adapter_temp->sessionCtx.ap.operatingChannel) ==
5726 hdd_ctxt->unsafe_channel_list[i]) {
5727 found = true;
5728 hdd_info("operating ch:%d is unsafe",
5729 adapter_temp->sessionCtx.ap.operatingChannel);
5730 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005731 }
5732 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305733
5734 if (!found) {
5735 hdd_info("ch:%d is safe. no need to change channel",
5736 adapter_temp->sessionCtx.ap.operatingChannel);
5737 goto next_adapater;
5738 }
5739
5740 restart_chan =
5741 hdd_get_safe_channel_from_pcl_and_acs_range(
5742 adapter_temp);
5743 if (!restart_chan) {
5744 hdd_alert("fail to restart SAP");
5745 } else {
5746 hdd_info("sending coex indication");
5747 wlan_hdd_send_svc_nlink_msg
5748 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
5749 hdd_restart_sap(adapter_temp, restart_chan);
5750 }
5751
5752next_adapater:
5753 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
5754 adapter_node = next;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005755 }
5756 return;
5757}
5758
5759/**
5760 * hdd_init_channel_avoidance() - Initialize channel avoidance
5761 * @hdd_ctx: HDD global context
5762 *
5763 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07005764 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005765 * down to the lower layers. Then subscribe to subsequent channel
5766 * avoidance events.
5767 *
5768 * Return: None
5769 */
5770static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5771{
5772 uint16_t unsafe_channel_count;
5773 int index;
5774
Yuanyuan Liu13738502016-04-06 17:41:37 -07005775 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
5776 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005777 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08005778 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779
Jeff Johnson34c88b72016-08-15 14:27:11 -07005780 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005781 hdd_ctx->unsafe_channel_count);
5782
Anurag Chouhan6d760662016-02-20 16:05:43 +05305783 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08005784 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005785
5786 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005787 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005788 hdd_ctx->unsafe_channel_list[index]);
5789
5790 }
5791
5792 /* Plug in avoid channel notification callback */
5793 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
5794}
5795#else
5796static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5797{
5798}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005799static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800{
5801}
Yuanyuan Liu13738502016-04-06 17:41:37 -07005802#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803
5804/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08005805 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
5806 * user space
5807 * @frame_ind: Management frame data to be informed.
5808 *
5809 * This function is used to indicate management frame to
5810 * user space
5811 *
5812 * Return: None
5813 *
5814 */
5815void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
5816{
5817 hdd_context_t *hdd_ctx = NULL;
5818 hdd_adapter_t *adapter = NULL;
5819 void *cds_context = NULL;
5820 int i;
5821
5822 /* Get the global VOSS context.*/
5823 cds_context = cds_get_global_context();
5824 if (!cds_context) {
5825 hdd_err("Global CDS context is Null");
5826 return;
5827 }
5828 /* Get the HDD context.*/
5829 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
5830
5831 if (0 != wlan_hdd_validate_context(hdd_ctx))
5832 return;
5833
5834 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
5835 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
5836 adapter =
5837 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
5838 if (adapter)
5839 break;
5840 }
5841 } else {
5842 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
5843 frame_ind->sessionId);
5844 }
5845
5846 if ((NULL != adapter) &&
5847 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
5848 __hdd_indicate_mgmt_frame(adapter,
5849 frame_ind->frame_len,
5850 frame_ind->frameBuf,
5851 frame_ind->frameType,
5852 frame_ind->rxChan,
5853 frame_ind->rxRssi);
5854 return;
5855}
5856
5857/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005858 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
5859 * @hdd_ctx: HDD context
5860 *
5861 * Disables all the dual mac features like DBS, Agile DFS etc.
5862 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305863 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305865static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005866{
5867 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305868 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869
5870 if (!hdd_ctx) {
5871 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305872 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005873 }
5874
Arun Khandavallid4349a92016-07-25 11:10:43 +05305875 if (hdd_ctx->config->dual_mac_feature_disable)
5876 return QDF_STATUS_SUCCESS;
5877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005878 cfg.scan_config = 0;
5879 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05305880 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005881
5882 hdd_debug("Disabling all dual mac features...");
5883
5884 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305885 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005886 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
5887 return status;
5888 }
5889
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305890 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005891}
5892
5893/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005894 * hdd_override_ini_config - Override INI config
5895 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005896 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005897 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005899 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005901static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005902{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005903
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005904 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
5905 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5906 hdd_notice("Module enable_dfs_chan_scan set to %d",
5907 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005908 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005909 if (0 == enable_11d || 1 == enable_11d) {
5910 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5911 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005912 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005913}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005914
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005915/**
5916 * hdd_set_trace_level_for_each - Set trace level for each INI config
5917 * @hdd_ctx - HDD context
5918 *
5919 * Set trace level for each module based on INI config.
5920 *
5921 * Return: None
5922 */
5923static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5924{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305925 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
5926 hdd_ctx->config->qdf_trace_enable_wdi);
5927 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
5928 hdd_ctx->config->qdf_trace_enable_hdd);
5929 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
5930 hdd_ctx->config->qdf_trace_enable_sme);
5931 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
5932 hdd_ctx->config->qdf_trace_enable_pe);
5933 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
5934 hdd_ctx->config->qdf_trace_enable_wma);
5935 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
5936 hdd_ctx->config->qdf_trace_enable_sys);
5937 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
5938 hdd_ctx->config->qdf_trace_enable_qdf);
5939 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
5940 hdd_ctx->config->qdf_trace_enable_sap);
5941 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
5942 hdd_ctx->config->qdf_trace_enable_hdd_sap);
5943 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
5944 hdd_ctx->config->qdf_trace_enable_bmi);
5945 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
5946 hdd_ctx->config->qdf_trace_enable_cfg);
5947 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
5948 hdd_ctx->config->qdf_trace_enable_epping);
5949 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
5950 hdd_ctx->config->qdf_trace_enable_qdf_devices);
5951 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05305952 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305953 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
5954 hdd_ctx->config->qdf_trace_enable_htc);
5955 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
5956 hdd_ctx->config->qdf_trace_enable_hif);
5957 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
5958 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
5959 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
5960 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005963}
5964
5965/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005966 * hdd_context_init() - Initialize HDD context
5967 * @hdd_ctx: HDD context.
5968 *
5969 * Initialize HDD context along with all the feature specific contexts.
5970 *
5971 * return: 0 on success and errno on failure.
5972 */
5973static int hdd_context_init(hdd_context_t *hdd_ctx)
5974{
5975 int ret;
5976
5977 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5978 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5979
5980 hdd_init_ll_stats_ctx();
5981
5982 init_completion(&hdd_ctx->mc_sus_event_var);
5983 init_completion(&hdd_ctx->ready_to_suspend);
5984
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305985 hdd_init_bpf_completion();
5986
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005987 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305988 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005989 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305990
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005991 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
5992
5993 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
5994
5995 ret = hdd_scan_context_init(hdd_ctx);
5996 if (ret)
5997 goto list_destroy;
5998
5999 hdd_tdls_context_init(hdd_ctx);
6000
6001 hdd_rx_wake_lock_create(hdd_ctx);
6002
6003 ret = hdd_sap_context_init(hdd_ctx);
6004 if (ret)
6005 goto scan_destroy;
6006
6007 ret = hdd_roc_context_init(hdd_ctx);
6008 if (ret)
6009 goto sap_destroy;
6010
6011 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6012
6013 hdd_init_offloaded_packets_ctx(hdd_ctx);
6014
6015 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6016 hdd_ctx->config);
6017 if (ret)
6018 goto roc_destroy;
6019
6020 return 0;
6021
6022roc_destroy:
6023 hdd_roc_context_destroy(hdd_ctx);
6024
6025sap_destroy:
6026 hdd_sap_context_destroy(hdd_ctx);
6027
6028scan_destroy:
6029 hdd_scan_context_destroy(hdd_ctx);
6030 hdd_rx_wake_lock_destroy(hdd_ctx);
6031 hdd_tdls_context_destroy(hdd_ctx);
6032
6033list_destroy:
6034 qdf_list_destroy(&hdd_ctx->hddAdapters);
6035 return ret;
6036}
6037
6038/**
6039 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306040 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006041 *
6042 * Allocate and initialize HDD context. HDD context is allocated as part of
6043 * wiphy allocation and then context is initialized.
6044 *
6045 * Return: HDD context on success and ERR_PTR on failure
6046 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306047hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006048{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306049 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006050 int ret = 0;
6051 hdd_context_t *hdd_ctx;
6052 v_CONTEXT_t p_cds_context;
6053
6054 ENTER();
6055
6056 p_cds_context = cds_get_global_context();
6057 if (p_cds_context == NULL) {
6058 hdd_alert("Failed to get CDS global context");
6059 ret = -EINVAL;
6060 goto err_out;
6061 }
6062
6063 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6064
6065 if (hdd_ctx == NULL) {
6066 ret = -ENOMEM;
6067 goto err_out;
6068 }
6069
6070 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006071 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006072
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306073 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006074 if (hdd_ctx->config == NULL) {
6075 hdd_alert("Failed to alloc memory for HDD config!");
6076 ret = -ENOMEM;
6077 goto err_free_hdd_context;
6078 }
6079
6080 /* Read and parse the qcom_cfg.ini file */
6081 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306082 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306083 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006084 WLAN_INI_FILE);
6085 ret = -EINVAL;
6086 goto err_free_config;
6087 }
6088
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006089 hdd_ctx->configuredMcastBcastFilter =
6090 hdd_ctx->config->mcastBcastFilterSetting;
6091
6092 hdd_notice("Setting configuredMcastBcastFilter: %d",
6093 hdd_ctx->config->mcastBcastFilterSetting);
6094
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306095 if (hdd_ctx->config->fhostNSOffload)
6096 hdd_ctx->ns_offload_enable = true;
6097
Abhishek Singh5ea86532016-04-27 14:10:53 +05306098 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6099
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006100 hdd_override_ini_config(hdd_ctx);
6101
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006102 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006103
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006104 ret = hdd_context_init(hdd_ctx);
6105
6106 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006107 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006108
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006109
Yuanyuan Liu13738502016-04-06 17:41:37 -07006110 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6111 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006112
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006113
6114 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306115 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006116
Anurag Chouhan6d760662016-02-20 16:05:43 +05306117 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006118 goto skip_multicast_logging;
6119
6120 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6121
Nirav Shahed34b212016-04-25 10:59:16 +05306122 status = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6123 if (status)
6124 goto err_free_config;
6125
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006126 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6127 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306128 goto err_free_histogram;
6129
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006130
6131 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306132 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006133 * levels of the code need not be set when the logger thread
6134 * is not enabled.
6135 */
6136 if (cds_is_multicast_logging())
6137 wlan_logging_set_log_level();
6138
6139skip_multicast_logging:
6140 hdd_set_trace_level_for_each(hdd_ctx);
6141
6142 return hdd_ctx;
6143
Nirav Shahed34b212016-04-25 10:59:16 +05306144err_free_histogram:
6145 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6146
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006147err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306148 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006149
6150err_free_hdd_context:
6151 wiphy_free(hdd_ctx->wiphy);
6152
6153err_out:
6154 return ERR_PTR(ret);
6155}
6156
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006157#ifdef WLAN_OPEN_P2P_INTERFACE
6158/**
6159 * hdd_open_p2p_interface - Open P2P interface
6160 * @hdd_ctx: HDD context
6161 * @rtnl_held: True if RTNL lock held
6162 *
6163 * Open P2P interface during probe. This function called to open the P2P
6164 * interface at probe along with STA interface.
6165 *
6166 * Return: 0 on success and errno on failure
6167 */
6168static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6169{
6170 hdd_adapter_t *adapter;
6171 uint8_t *p2p_dev_addr;
6172
6173 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6174 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306175 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006176 hdd_ctx->config->intfMacAddr[0].bytes,
6177 sizeof(tSirMacAddr));
6178
6179 /*
6180 * Generate the P2P Device Address. This consists of
6181 * the device's primary MAC address with the locally
6182 * administered bit set.
6183 */
6184 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6185 } else {
6186 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6187 if (p2p_dev_addr == NULL) {
6188 hdd_alert("Failed to allocate mac_address for p2p_device");
6189 return -ENOSPC;
6190 }
6191
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306192 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306193 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006194 }
6195
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006196 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006197 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006198 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006199
6200 if (NULL == adapter) {
6201 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6202 return -ENOSPC;
6203 }
6204
6205 return 0;
6206}
6207#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306208static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006209 bool rtnl_held)
6210{
6211 return 0;
6212}
6213#endif
6214
6215/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306216 * hdd_start_station_adapter()- Start the Station Adapter
6217 * @adapter: HDD adapter
6218 *
6219 * This function initializes the adapter for the station mode.
6220 *
6221 * Return: 0 on success or errno on failure.
6222 */
6223int hdd_start_station_adapter(hdd_adapter_t *adapter)
6224{
6225 QDF_STATUS status;
6226
6227 ENTER_DEV(adapter->dev);
6228
6229 status = hdd_init_station_mode(adapter);
6230
6231 if (QDF_STATUS_SUCCESS != status) {
6232 hdd_err("Error Initializing station mode: %d", status);
6233 return qdf_status_to_os_return(status);
6234 }
6235
Arun Khandavallifae92942016-08-01 13:31:08 +05306236 hdd_register_tx_flow_control(adapter,
6237 hdd_tx_resume_timer_expired_handler,
6238 hdd_tx_resume_cb);
6239
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306240 EXIT();
6241 return 0;
6242}
6243
6244/**
6245 * hdd_start_ap_adapter()- Start AP Adapter
6246 * @adapter: HDD adapter
6247 *
6248 * This function initializes the adapter for the AP mode.
6249 *
6250 * Return: 0 on success errno on failure.
6251 */
6252int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6253{
6254 QDF_STATUS status;
6255
6256 ENTER();
6257
6258 status = hdd_init_ap_mode(adapter);
6259
6260 if (QDF_STATUS_SUCCESS != status) {
6261 hdd_err("Error Initializing the AP mode: %d", status);
6262 return qdf_status_to_os_return(status);
6263 }
6264
Arun Khandavallifae92942016-08-01 13:31:08 +05306265 hdd_register_tx_flow_control(adapter,
6266 hdd_softap_tx_resume_timer_expired_handler,
6267 hdd_softap_tx_resume_cb);
6268
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306269 EXIT();
6270 return 0;
6271}
6272
6273/**
6274 * hdd_start_ftm_adapter()- Start FTM adapter
6275 * @adapter: HDD adapter
6276 *
6277 * This function initializes the adapter for the FTM mode.
6278 *
6279 * Return: 0 on success or errno on failure.
6280 */
6281int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6282{
6283 QDF_STATUS qdf_status;
6284
6285 ENTER_DEV(adapter->dev);
6286
6287 qdf_status = hdd_init_tx_rx(adapter);
6288
6289 if (QDF_STATUS_SUCCESS != qdf_status) {
6290 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6291 return qdf_status_to_os_return(qdf_status);
6292 }
6293
6294 return 0;
6295 EXIT();
6296}
6297
6298/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006299 * hdd_open_interfaces - Open all required interfaces
6300 * hdd_ctx: HDD context
6301 * rtnl_held: True if RTNL lock is held
6302 *
6303 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6304 *
6305 * Return: Primary adapter on success and PTR_ERR on failure
6306 */
6307static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6308 bool rtnl_held)
6309{
6310 hdd_adapter_t *adapter = NULL;
6311 hdd_adapter_t *adapter_11p = NULL;
6312 int ret;
6313
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006314 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306315 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006316 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006317 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006318 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006319
6320 if (adapter == NULL)
6321 return ERR_PTR(-ENOSPC);
6322
6323 return adapter;
6324 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006325 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006326 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006327 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006328
6329 if (adapter == NULL)
6330 return ERR_PTR(-ENOSPC);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006331 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6332 if (ret)
6333 goto err_close_adapter;
6334
6335 /* Open 802.11p Interface */
6336 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006337 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006338 "wlanocb%d",
6339 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006340 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006341 if (adapter_11p == NULL) {
6342 hdd_err("Failed to open 802.11p interface");
6343 goto err_close_adapter;
6344 }
6345 }
6346
6347 return adapter;
6348
6349err_close_adapter:
6350 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6351 return ERR_PTR(ret);
6352}
6353
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006354/**
6355 * hdd_update_country_code - Update country code
6356 * @hdd_ctx: HDD context
6357 * @adapter: Primary adapter context
6358 *
6359 * Update country code based on module parameter country_code at SME and wait
6360 * for the settings to take effect.
6361 *
6362 * Return: 0 on success and errno on failure
6363 */
6364static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6365 hdd_adapter_t *adapter)
6366{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306367 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006368 int ret = 0;
6369 unsigned long rc;
6370
6371 if (country_code == NULL)
6372 return 0;
6373
6374 INIT_COMPLETION(adapter->change_country_code);
6375
6376 status = sme_change_country_code(hdd_ctx->hHal,
6377 wlan_hdd_change_country_code_callback,
6378 country_code, adapter,
6379 hdd_ctx->pcds_context, eSIR_TRUE,
6380 eSIR_TRUE);
6381
6382
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306383 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006384 hdd_err("SME Change Country code from module param fail ret=%d",
6385 ret);
6386 return -EINVAL;
6387 }
6388
6389 rc = wait_for_completion_timeout(&adapter->change_country_code,
6390 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6391 if (!rc) {
6392 hdd_err("SME while setting country code timed out");
6393 ret = -ETIMEDOUT;
6394 }
6395
6396 return ret;
6397}
6398
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306399#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6400/**
6401 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6402 * @cds_cfg: CDS Configuration
6403 * @hdd_ctx: Pointer to hdd context
6404 *
6405 * Return: none
6406 */
6407static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6408 *cds_cfg,
6409 hdd_context_t *hdd_ctx)
6410{
6411 cds_cfg->tx_flow_stop_queue_th =
6412 hdd_ctx->config->TxFlowStopQueueThreshold;
6413 cds_cfg->tx_flow_start_queue_offset =
6414 hdd_ctx->config->TxFlowStartQueueOffset;
6415}
6416#else
6417static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6418 *cds_cfg,
6419 hdd_context_t *hdd_ctx)
6420{
6421}
6422#endif
6423
6424#ifdef FEATURE_WLAN_RA_FILTERING
6425/**
6426 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6427 * @cds_cfg: CDS Configuration
6428 * @hdd_ctx: Pointer to hdd context
6429 *
6430 * Return: none
6431 */
6432inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6433 hdd_context_t *hdd_ctx)
6434{
6435 cds_cfg->ra_ratelimit_interval =
6436 hdd_ctx->config->RArateLimitInterval;
6437 cds_cfg->is_ra_ratelimit_enabled =
6438 hdd_ctx->config->IsRArateLimitEnabled;
6439}
6440#else
6441inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6442 hdd_context_t *hdd_ctx)
6443{
6444}
6445#endif
6446
6447/**
6448 * hdd_update_cds_config() - API to update cds configuration parameters
6449 * @hdd_ctx: HDD Context
6450 *
6451 * Return: 0 for Success, errno on failure
6452 */
6453int hdd_update_cds_config(hdd_context_t *hdd_ctx)
6454{
6455 struct cds_config_info *cds_cfg;
6456
6457 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6458 if (!cds_cfg) {
6459 hdd_err("failed to allocate cds config");
6460 return -ENOMEM;
6461 }
6462
6463 qdf_mem_zero(cds_cfg, sizeof(*cds_cfg));
6464
6465 /* UMA is supported in hardware for performing the
6466 * frame translation 802.11 <-> 802.3
6467 */
6468 cds_cfg->frame_xln_reqd = 1;
6469 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
6470 cds_cfg->powersave_offload_enabled =
6471 hdd_ctx->config->enablePowersaveOffload;
6472 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
6473 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
6474 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
6475 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
6476 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
6477
6478 /* Here ol_ini_info is used to store ini status of arp offload
6479 * ns offload and others. Currently 1st bit is used for arp
6480 * off load and 2nd bit for ns offload currently, rest bits are unused
6481 */
6482 if (hdd_ctx->config->fhostArpOffload)
6483 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
6484 if (hdd_ctx->config->fhostNSOffload)
6485 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
6486
6487 /*
6488 * Copy the DFS Phyerr Filtering Offload status.
6489 * This parameter reflects the value of the
6490 * dfs_phyerr_filter_offload flag as set in the ini.
6491 */
6492 cds_cfg->dfs_phyerr_filter_offload =
6493 hdd_ctx->config->fDfsPhyerrFilterOffload;
6494 if (hdd_ctx->config->ssdp)
6495 cds_cfg->ssdp = hdd_ctx->config->ssdp;
6496
6497 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
6498 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
6499
6500 cds_cfg->ap_maxoffload_reorderbuffs =
6501 hdd_ctx->config->apMaxOffloadReorderBuffs;
6502
6503 cds_cfg->ap_disable_intrabss_fwd =
6504 hdd_ctx->config->apDisableIntraBssFwd;
6505
6506 cds_cfg->dfs_pri_multiplier =
6507 hdd_ctx->config->dfsRadarPriMultiplier;
6508 cds_cfg->reorder_offload =
6509 hdd_ctx->config->reorderOffloadSupport;
6510
6511 /* IPA micro controller data path offload resource config item */
6512 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
6513 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
6514 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
6515 cds_cfg->uc_rxind_ringcount =
6516 hdd_ctx->config->IpaUcRxIndRingCount;
6517 cds_cfg->uc_tx_partition_base =
6518 hdd_ctx->config->IpaUcTxPartitionBase;
6519 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
6520
6521 cds_cfg->ip_tcp_udp_checksum_offload =
6522 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05306523 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306524 cds_cfg->ce_classify_enabled =
6525 hdd_ctx->config->ce_classify_enabled;
6526 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
6527 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
6528 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07006529 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306530
6531 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
6532 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
6533 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
6534
6535 cds_init_ini_config(cds_cfg);
6536 return 0;
6537}
6538
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006539/**
6540 * hdd_init_thermal_info - Initialize thermal level
6541 * @hdd_ctx: HDD context
6542 *
6543 * Initialize thermal level at SME layer and set the thermal level callback
6544 * which would be called when a configured thermal threshold is hit.
6545 *
6546 * Return: 0 on success and errno on failure
6547 */
6548static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
6549{
6550 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306551 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006552
6553 thermal_param.smeThermalMgmtEnabled =
6554 hdd_ctx->config->thermalMitigationEnable;
6555 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
6556
Poddar, Siddarth83905022016-04-16 17:56:08 -07006557 thermal_param.sme_throttle_duty_cycle_tbl[0] =
6558 hdd_ctx->config->throttle_dutycycle_level0;
6559 thermal_param.sme_throttle_duty_cycle_tbl[1] =
6560 hdd_ctx->config->throttle_dutycycle_level1;
6561 thermal_param.sme_throttle_duty_cycle_tbl[2] =
6562 hdd_ctx->config->throttle_dutycycle_level2;
6563 thermal_param.sme_throttle_duty_cycle_tbl[3] =
6564 hdd_ctx->config->throttle_dutycycle_level3;
6565
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006566 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
6567 hdd_ctx->config->thermalTempMinLevel0;
6568 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
6569 hdd_ctx->config->thermalTempMaxLevel0;
6570 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
6571 hdd_ctx->config->thermalTempMinLevel1;
6572 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
6573 hdd_ctx->config->thermalTempMaxLevel1;
6574 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
6575 hdd_ctx->config->thermalTempMinLevel2;
6576 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
6577 hdd_ctx->config->thermalTempMaxLevel2;
6578 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
6579 hdd_ctx->config->thermalTempMinLevel3;
6580 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
6581 hdd_ctx->config->thermalTempMaxLevel3;
6582
6583 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
6584
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306585 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05306586 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006587
6588 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
6589 hdd_set_thermal_level_cb);
6590
6591 return 0;
6592
6593}
6594
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006595#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
6596/**
6597 * hdd_hold_rtnl_lock - Hold RTNL lock
6598 *
6599 * Hold RTNL lock
6600 *
6601 * Return: True if held and false otherwise
6602 */
6603static inline bool hdd_hold_rtnl_lock(void)
6604{
6605 rtnl_lock();
6606 return true;
6607}
6608
6609/**
6610 * hdd_release_rtnl_lock - Release RTNL lock
6611 *
6612 * Release RTNL lock
6613 *
6614 * Return: None
6615 */
6616static inline void hdd_release_rtnl_lock(void)
6617{
6618 rtnl_unlock();
6619}
6620#else
6621static inline bool hdd_hold_rtnl_lock(void) { return false; }
6622static inline void hdd_release_rtnl_lock(void) { }
6623#endif
6624
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006625#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006626
6627/**
6628 * hdd_process_pktlog_command() - process pktlog command
6629 * @hdd_ctx: hdd context
6630 * @set_value: value set by user
6631 *
6632 * Return: 0 for success or error.
6633 */
6634int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value)
6635{
6636 int ret;
6637 bool enable;
6638 uint8_t user_triggered = 0;
6639
6640 ret = wlan_hdd_validate_context(hdd_ctx);
6641 if (0 != ret)
6642 return ret;
6643
6644 hdd_info("set pktlog %d", set_value);
6645
6646 if (set_value > 2) {
6647 hdd_err("invalid pktlog value %d", set_value);
6648 return -EINVAL;
6649 }
6650
6651 /*
6652 * set_value = 0 then disable packetlog
6653 * set_value = 1 enable packetlog forcefully
6654 * set_vlaue = 2 then disable packetlog if disabled through ini or
6655 * enable packetlog with AUTO type.
6656 */
6657 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
6658 true : false;
6659
6660 if (1 == set_value) {
6661 enable = true;
6662 user_triggered = 1;
6663 }
6664
6665 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered);
6666}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006667/**
6668 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
6669 * @hdd_ctx: HDD context
6670 * @enable: Flag to enable/disable
6671 *
6672 * Return: 0 on success; error number otherwise
6673 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006674int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
6675 uint8_t user_triggered)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006676{
6677 struct sir_wifi_start_log start_log;
6678 QDF_STATUS status;
6679
6680 start_log.ring_id = RING_ID_PER_PACKET_STATS;
6681 start_log.verbose_level =
6682 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006683 start_log.ini_triggered = cds_is_packet_log_enabled();
6684 start_log.user_triggered = user_triggered;
6685
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006686 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
6687 if (!QDF_IS_STATUS_SUCCESS(status)) {
6688 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
6689 EXIT();
6690 return -EINVAL;
6691 }
6692
6693 return 0;
6694}
6695#endif /* REMOVE_PKT_LOG */
6696
6697
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05306698#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
6699/**
6700 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
6701 * switch without restart
6702 *
6703 * Registers callback function to change the operating channel of SAP by using
6704 * channel switch announcements instead of restarting SAP.
6705 *
6706 * Return: QDF_STATUS
6707 */
6708QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
6709{
6710 QDF_STATUS status;
6711
6712 status = cds_register_sap_restart_channel_switch_cb(
6713 (void *)hdd_sap_restart_with_channel_switch);
6714 if (!QDF_IS_STATUS_SUCCESS(status))
6715 hdd_err("restart cb registration failed");
6716
6717 return status;
6718}
6719#endif
6720
Komal Seelam92fff912016-03-24 11:51:41 +05306721#ifdef CONFIG_CNSS
6722/**
6723 * hdd_get_cnss_wlan_mac_buff() - API to query platform driver for MAC address
6724 * @dev: Device Pointer
6725 * @num: Number of Valid Mac address
6726 *
6727 * Return: Pointer to MAC address buffer
6728 */
6729static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6730{
6731 return cnss_common_get_wlan_mac_address(dev, num);
6732}
6733#else
6734static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6735{
6736 *num = 0;
6737 return NULL;
6738}
6739#endif
6740
6741/**
6742 * hdd_populate_random_mac_addr() - API to populate random mac addresses
6743 * @hdd_ctx: HDD Context
6744 * @num: Number of random mac addresses needed
6745 *
6746 * Generate random addresses using bit manipulation on the base mac address
6747 *
6748 * Return: None
6749 */
6750static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
6751{
6752 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
6753 uint32_t iter;
6754 struct hdd_config *ini = hdd_ctx->config;
6755 uint8_t *buf = NULL;
6756 uint8_t macaddr_b3, tmp_br3;
6757 uint8_t *src = ini->intfMacAddr[0].bytes;
6758
6759 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
6760 buf = ini->intfMacAddr[iter].bytes;
6761 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
6762 macaddr_b3 = buf[3];
6763 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
6764 INTF_MACADDR_MASK;
6765 macaddr_b3 += tmp_br3;
6766 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
6767 buf[0] |= 0x02;
6768 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07006769 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05306770 }
6771}
6772
6773/**
6774 * hdd_cnss_wlan_mac() - API to get mac addresses from cnss platform driver
6775 * @hdd_ctx: HDD Context
6776 *
6777 * API to get mac addresses from platform driver and update the driver
6778 * structures and configure FW with the base mac address.
6779 * Return: int
6780 */
6781static int hdd_cnss_wlan_mac(hdd_context_t *hdd_ctx)
6782{
6783 uint32_t no_of_mac_addr, iter;
6784 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
6785 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
6786 uint8_t *addr, *buf;
6787 struct device *dev = hdd_ctx->parent_dev;
6788 struct hdd_config *ini = hdd_ctx->config;
6789 tSirMacAddr mac_addr;
6790 QDF_STATUS status;
6791
6792 addr = hdd_get_cnss_wlan_mac_buff(dev, &no_of_mac_addr);
6793
6794 if (no_of_mac_addr == 0 || !addr) {
6795 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
6796 return -EINVAL;
6797 }
6798
6799 if (no_of_mac_addr > max_mac_addr)
6800 no_of_mac_addr = max_mac_addr;
6801
6802 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
6803
6804 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
6805 buf = ini->intfMacAddr[iter].bytes;
6806 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006807 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05306808 }
6809
6810 status = sme_set_custom_mac_addr(mac_addr);
6811
6812 if (!QDF_IS_STATUS_SUCCESS(status))
6813 return -EAGAIN;
6814 if (no_of_mac_addr < max_mac_addr)
6815 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
6816 no_of_mac_addr);
6817 return 0;
6818}
6819
6820/**
6821 * hdd_initialize_mac_address() - API to get wlan mac addresses
6822 * @hdd_ctx: HDD Context
6823 *
6824 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
6825 * is provisioned with mac addresses, driver uses it, else it will use
6826 * wlan_mac.bin to update HW MAC addresses.
6827 *
6828 * Return: None
6829 */
6830static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
6831{
6832 QDF_STATUS status;
6833 int ret;
6834
6835 ret = hdd_cnss_wlan_mac(hdd_ctx);
6836 if (ret == 0)
6837 return;
6838
6839 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
6840
6841 status = hdd_update_mac_config(hdd_ctx);
6842
6843 if (!QDF_IS_STATUS_SUCCESS(status))
6844 hdd_warn("can't update mac config, using MAC from ini file");
6845}
6846
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006847/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07006848 * hdd_tsf_init() - Initialize the TSF synchronization interface
6849 * @hdd_ctx: HDD global context
6850 *
6851 * When TSF synchronization via GPIO is supported by the driver and
6852 * has been enabled in the configuration file, this function plumbs
6853 * the GPIO value down to firmware via SME.
6854 *
6855 * Return: None
6856 */
6857#ifdef WLAN_FEATURE_TSF
6858static void hdd_tsf_init(hdd_context_t *hdd_ctx)
6859{
6860 QDF_STATUS status;
6861
6862 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
6863 return;
6864
6865 status = sme_set_tsf_gpio(hdd_ctx->hHal,
6866 hdd_ctx->config->tsf_gpio_pin);
6867 if (!QDF_IS_STATUS_SUCCESS(status))
6868 hdd_err("Set tsf GPIO failed, status: %d", status);
6869}
6870#else
6871static void hdd_tsf_init(hdd_context_t *hdd_ctx)
6872{
6873}
6874#endif
6875
6876/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07006877 * hdd_pre_enable_configure() - Configurations prior to cds_enable
6878 * @hdd_ctx: HDD context
6879 *
6880 * Pre configurations to be done at lower layer before calling cds enable.
6881 *
6882 * Return: 0 on success and errno on failure.
6883 */
6884static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
6885{
6886 int ret;
6887 QDF_STATUS status;
6888 tSirRetStatus hal_status;
6889
6890 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
6891
6892 /*
6893 * Set 802.11p config
6894 * TODO-OCB: This has been temporarily added here to ensure this
6895 * parameter is set in CSR when we init the channel list. This should
6896 * be removed once the 5.9 GHz channels are added to the regulatory
6897 * domain.
6898 */
6899 hdd_set_dot11p_config(hdd_ctx);
6900
6901 /*
6902 * Note that the cds_pre_enable() sequence triggers the cfg download.
6903 * The cfg download must occur before we update the SME config
6904 * since the SME config operation must access the cfg database
6905 */
6906 status = hdd_set_sme_config(hdd_ctx);
6907
6908 if (QDF_STATUS_SUCCESS != status) {
6909 hdd_alert("Failed hdd_set_sme_config: %d", status);
6910 ret = qdf_status_to_os_return(status);
6911 goto out;
6912 }
6913
6914 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
6915 hdd_ctx->config->tx_chain_mask_1ss,
6916 PDEV_CMD);
6917 if (0 != ret) {
6918 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
6919 goto out;
6920 }
6921
6922 hdd_program_country_code(hdd_ctx);
6923
6924 status = hdd_set_sme_chan_list(hdd_ctx);
6925 if (status != QDF_STATUS_SUCCESS) {
6926 hdd_alert("Failed to init channel list: %d", status);
6927 ret = qdf_status_to_os_return(status);
6928 goto out;
6929 }
6930
6931 /* Apply the cfg.ini to cfg.dat */
6932 if (!hdd_update_config_dat(hdd_ctx)) {
6933 hdd_alert("config update failed");
6934 ret = -EINVAL;
6935 goto out;
6936 }
6937
Komal Seelam92fff912016-03-24 11:51:41 +05306938 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta07998752016-04-28 12:35:33 -07006939
6940 /*
6941 * Set the MAC Address Currently this is used by HAL to add self sta.
6942 * Remove this once self sta is added as part of session open.
6943 */
6944 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
6945 hdd_ctx->config->intfMacAddr[0].bytes,
6946 sizeof(hdd_ctx->config->intfMacAddr[0]));
6947
6948 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
6949 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
6950 hal_status, hal_status);
6951 ret = -EINVAL;
6952 goto out;
6953 }
6954
6955 hdd_init_channel_avoidance(hdd_ctx);
6956
6957out:
6958 return ret;
6959}
6960
6961/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006962 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
6963 * @context_ptr - hdd context pointer
6964 * @event_ptr - event structure pointer
6965 *
6966 * This is the p2p listen offload stop event handler, it sends vendor
6967 * event back to supplicant to notify the stop reason.
6968 *
6969 * Return: None
6970 */
6971static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
6972 void *event_ptr)
6973{
6974 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
6975 struct sir_p2p_lo_event *evt = event_ptr;
6976 struct sk_buff *vendor_event;
6977
6978 ENTER();
6979
6980 if (hdd_ctx == NULL) {
6981 hdd_err("Invalid HDD context pointer");
6982 return;
6983 }
6984
6985 vendor_event =
6986 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
6987 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
6988 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
6989 GFP_KERNEL);
6990
6991 if (!vendor_event) {
6992 hdd_err("cfg80211_vendor_event_alloc failed");
6993 return;
6994 }
6995
6996 if (nla_put_u32(vendor_event,
6997 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
6998 evt->reason_code)) {
6999 hdd_err("nla put failed");
7000 kfree_skb(vendor_event);
7001 return;
7002 }
7003
7004 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7005}
7006
7007/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307008 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7009 * @hdd_ctx: HDD context
7010 *
7011 * This function sends the adaptive dwell time config configuration to the
7012 * firmware via WMA
7013 *
7014 * Return: 0 - success, < 0 - failure
7015 */
7016static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7017{
7018 QDF_STATUS status;
7019 struct adaptive_dwelltime_params dwelltime_params;
7020
7021 dwelltime_params.is_enabled =
7022 hdd_ctx->config->adaptive_dwell_mode_enabled;
7023 dwelltime_params.dwelltime_mode =
7024 hdd_ctx->config->global_adapt_dwelltime_mode;
7025 dwelltime_params.lpf_weight =
7026 hdd_ctx->config->adapt_dwell_lpf_weight;
7027 dwelltime_params.passive_mon_intval =
7028 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7029 dwelltime_params.wifi_act_threshold =
7030 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7031
7032 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7033 &dwelltime_params);
7034
7035 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7036 if (!QDF_IS_STATUS_SUCCESS(status)) {
7037 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7038 return -EAGAIN;
7039 }
7040 return 0;
7041}
7042
Arun Khandavallid4349a92016-07-25 11:10:43 +05307043#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7044/**
7045 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7046 * @hdd_ctx: HDD context
7047 *
7048 * Set auto shutdown callback to get indications from firmware to indicate
7049 * userspace to shutdown WLAN after a configured amount of inactivity.
7050 *
7051 * Return: 0 on success and errno on failure.
7052 */
7053static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7054{
7055 QDF_STATUS status;
7056
7057 if (!hdd_ctx->config->WlanAutoShutdown)
7058 return 0;
7059
7060 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7061 wlan_hdd_auto_shutdown_cb);
7062 if (status != QDF_STATUS_SUCCESS)
7063 hdd_err("Auto shutdown feature could not be enabled: %d",
7064 status);
7065
7066 return qdf_status_to_os_return(status);
7067}
7068#else
7069static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7070{
7071 return 0;
7072}
7073#endif
7074
7075/**
7076 * hdd_features_init() - Init features
7077 * @hdd_ctx: HDD context
7078 * @adapter: Primary adapter context
7079 *
7080 * Initialize features and their feature context after WLAN firmware is up.
7081 *
7082 * Return: 0 on success and errno on failure.
7083 */
7084static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7085{
7086 tSirTxPowerLimit hddtxlimit;
7087 QDF_STATUS status;
7088 int ret;
7089
7090 ENTER();
7091
7092 ret = hdd_update_country_code(hdd_ctx, adapter);
7093 if (ret) {
7094 hdd_err("Failed to update country code: %d", ret);
7095 goto out;
7096 }
7097
7098 /* FW capabilities received, Set the Dot11 mode */
7099 sme_setdef_dot11mode(hdd_ctx->hHal);
7100
Arun Khandavallid4349a92016-07-25 11:10:43 +05307101
7102 if (hdd_ctx->config->fIsImpsEnabled)
7103 hdd_set_idle_ps_config(hdd_ctx, true);
7104 else
7105 hdd_set_idle_ps_config(hdd_ctx, false);
7106
7107 if (hdd_lro_init(hdd_ctx))
7108 hdd_err("Unable to initialize LRO in fw");
7109
7110 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7111 hdd_err("Unable to send adaptive dwelltime setting to FW");
7112
7113 ret = hdd_init_thermal_info(hdd_ctx);
7114 if (ret) {
7115 hdd_err("Error while initializing thermal information");
7116 goto deregister_frames;
7117 }
7118
7119 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7120 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7121 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7122 if (!QDF_IS_STATUS_SUCCESS(status))
7123 hdd_err("Error setting txlimit in sme: %d", status);
7124
7125 hdd_tsf_init(hdd_ctx);
7126
7127 if (hdd_ctx->config->dual_mac_feature_disable) {
7128 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7129 if (status != QDF_STATUS_SUCCESS) {
7130 hdd_err("Failed to disable dual mac features");
7131 goto deregister_frames;
7132 }
7133 }
7134
7135 ret = hdd_register_cb(hdd_ctx);
7136 if (ret) {
7137 hdd_err("Failed to register HDD callbacks!");
7138 goto deregister_frames;
7139 }
7140
7141 if (hdd_ctx->config->dual_mac_feature_disable) {
7142 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7143 if (status != QDF_STATUS_SUCCESS) {
7144 hdd_err("Failed to disable dual mac features");
7145 goto deregister_cb;
7146 }
7147 }
7148
7149 /* register P2P Listen Offload event callback */
7150 if (wma_is_p2p_lo_capable())
7151 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7152 wlan_hdd_p2p_lo_event_callback);
7153
7154 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7155
7156 if (ret)
7157 goto deregister_cb;
7158
7159 EXIT();
7160 return 0;
7161
7162deregister_cb:
7163 hdd_deregister_cb(hdd_ctx);
7164deregister_frames:
7165 wlan_hdd_cfg80211_deregister_frames(adapter);
7166out:
7167 return -EINVAL;
7168
7169}
7170
7171
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307172/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307173 * hdd_configure_cds() - Configure cds modules
7174 * @hdd_ctx: HDD context
7175 * @adapter: Primary adapter context
7176 *
7177 * Enable Cds modules after WLAN firmware is up.
7178 *
7179 * Return: 0 on success and errno on failure.
7180 */
7181int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7182{
7183 int ret;
7184 QDF_STATUS status;
7185 /* structure of function pointers to be used by CDS */
7186 struct cds_sme_cbacks sme_cbacks;
7187
7188 ret = hdd_pre_enable_configure(hdd_ctx);
7189 if (ret) {
7190 hdd_err("Failed to pre-configure cds");
7191 goto out;
7192 }
7193
7194 /*
7195 * Start CDS which starts up the SME/MAC/HAL modules and everything
7196 * else
7197 */
7198 status = cds_enable(hdd_ctx->pcds_context);
7199
7200 if (!QDF_IS_STATUS_SUCCESS(status)) {
7201 hdd_alert("cds_enable failed");
7202 goto out;
7203 }
7204
7205 status = hdd_post_cds_enable_config(hdd_ctx);
7206 if (!QDF_IS_STATUS_SUCCESS(status)) {
7207 hdd_alert("hdd_post_cds_enable_config failed");
7208 goto out;
7209 }
7210
7211 ret = hdd_features_init(hdd_ctx, adapter);
7212 if (ret)
7213 goto out;
7214
7215 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7216 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7217 status = cds_init_policy_mgr(&sme_cbacks);
7218 if (!QDF_IS_STATUS_SUCCESS(status)) {
7219 hdd_err("Policy manager initialization failed");
7220 goto out;
7221 }
7222
7223 return 0;
7224out:
7225 return -EINVAL;
7226}
7227
7228/**
7229 * hdd_deconfigure_cds() -De-Configure cds
7230 * @hdd_ctx: HDD context
7231 *
7232 * Deconfigure Cds modules before WLAN firmware is down.
7233 *
7234 * Return: 0 on success and errno on failure.
7235 */
7236int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
7237{
7238 QDF_STATUS qdf_status;
7239
7240 ENTER();
7241 /* De-register the SME callbacks */
7242 hdd_deregister_cb(hdd_ctx);
7243
7244 /* De-init Policy Manager */
7245 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7246 hdd_err("Failed to deinit policy manager");
7247 /* Proceed and complete the clean up */
7248 return -EINVAL;
7249 }
7250
7251 qdf_status = cds_disable(hdd_ctx->pcds_context);
7252 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7253 hdd_err("Failed to Disable the CDS Modules! :%d",
7254 qdf_status);
7255 return -EINVAL;
7256 }
7257
7258 EXIT();
7259 return 0;
7260}
7261
7262
7263/**
7264 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7265 * @hdd_ctx: HDD context
7266 * @shutdown: flag to indicate from SSR or normal path
7267 *
7268 * This function maintains the driver state machine it will be invoked from
7269 * exit, shutdown and con_mode change handler. Depending on the driver state
7270 * shall perform the stopping/closing of the modules.
7271 *
7272 * Return: 0 for success; non-zero for failure
7273 */
7274int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
7275{
7276 void *hif_ctx;
7277 qdf_device_t qdf_ctx;
7278 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307279 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307280 p_cds_sched_context cds_sched_context = NULL;
7281
7282 ENTER();
7283
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307284
Arun Khandavallifae92942016-08-01 13:31:08 +05307285 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7286 if (!qdf_ctx) {
7287 hdd_err("QDF device context NULL");
7288 return -EINVAL;
7289 }
7290
7291 cds_sched_context = get_cds_sched_ctxt();
7292 if (!cds_sched_context) {
7293 hdd_err("cds scheduler context NULL");
7294 return -EINVAL;
7295 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307296 mutex_lock(&hdd_ctx->iface_change_lock);
7297 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307298
7299 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7300
7301 switch (hdd_ctx->driver_status) {
7302 case DRIVER_MODULES_UNINITIALIZED:
7303 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307304 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307305 case DRIVER_MODULES_CLOSED:
7306 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307307 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307308 case DRIVER_MODULES_ENABLED:
7309 if (hdd_deconfigure_cds(hdd_ctx)) {
7310 hdd_alert("Failed to de-configure CDS");
7311 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307312 ret = -EINVAL;
7313 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307314 }
7315 hdd_info("successfully Disabled the CDS modules!");
7316 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7317 break;
7318 case DRIVER_MODULES_OPENED:
7319 hdd_info("Closing CDS modules!");
7320 break;
7321 default:
7322 hdd_err("Trying to stop wlan in a wrong state: %d",
7323 hdd_ctx->driver_status);
7324 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307325 ret = -EINVAL;
7326 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307327 }
7328
7329 qdf_status = cds_close(hdd_ctx->pcds_context);
7330 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7331 hdd_warn("Failed to stop CDS:%d", qdf_status);
7332 QDF_ASSERT(0);
7333 }
7334 /* Clean up message queues of TX, RX and MC thread */
7335 cds_sched_flush_mc_mqs(cds_sched_context);
7336
7337 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
7338 if (!hif_ctx) {
7339 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307340 ret = -EINVAL;
7341 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307342 }
7343
7344 hdd_hif_close(hif_ctx);
7345
7346 ol_cds_free();
7347
7348 if (!shutdown) {
7349 ret = pld_power_off(qdf_ctx->dev);
7350 if (ret)
7351 hdd_err("CNSS power down failed put device into Low power mode:%d",
7352 ret);
7353 }
7354 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
7355
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307356done:
7357 hdd_ctx->stop_modules_in_progress = false;
7358 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05307359 EXIT();
7360
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307361 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307362
7363}
7364
7365/**
7366 * hdd_iface_change_callback() - Function invoked when stop modules expires
7367 * @priv: pointer to hdd context
7368 *
7369 * This function is invoked when the timer waiting for the interface change
7370 * expires, it shall cut-down the power to wlan and stop all the modules.
7371 *
7372 * Return: void
7373 */
7374static void hdd_iface_change_callback(void *priv)
7375{
7376 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
7377 int ret;
7378 int status = wlan_hdd_validate_context(hdd_ctx);
7379
7380 if (status)
7381 return;
7382
7383 ENTER();
7384 hdd_info("Interface change timer expired close the modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05307385 ret = hdd_wlan_stop_modules(hdd_ctx, false);
7386 if (ret)
7387 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05307388 EXIT();
7389}
7390
7391/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007392 * hdd_wlan_startup() - HDD init function
7393 * @dev: Pointer to the underlying device
7394 *
7395 * This is the driver startup code executed once a WLAN device has been detected
7396 *
7397 * Return: 0 for success, < 0 for failure
7398 */
Arun Khandavallifae92942016-08-01 13:31:08 +05307399int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007400{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307401 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007402 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007403 hdd_context_t *hdd_ctx = NULL;
7404 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307405 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007406 bool rtnl_held;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007407
7408 ENTER();
7409
Arun Khandavallifae92942016-08-01 13:31:08 +05307410 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007411
7412 if (IS_ERR(hdd_ctx))
7413 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007414
Arun Khandavallifae92942016-08-01 13:31:08 +05307415 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
7416 hdd_iface_change_callback, (void *)hdd_ctx);
7417
7418 mutex_init(&hdd_ctx->iface_change_lock);
7419
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007420 ret = hdd_init_netlink_services(hdd_ctx);
7421 if (ret)
7422 goto err_hdd_free_context;
7423
Arun Khandavallifae92942016-08-01 13:31:08 +05307424 hdd_wlan_green_ap_init(hdd_ctx);
7425
Arun Khandavallifae92942016-08-01 13:31:08 +05307426 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
7427 if (ret) {
7428 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007429 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007430 }
7431
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007432 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007433
Anurag Chouhan6d760662016-02-20 16:05:43 +05307434 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007435
7436 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007437 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05307438 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007439 }
7440
Prashanth Bhatta07998752016-04-28 12:35:33 -07007441 ret = hdd_wiphy_init(hdd_ctx);
7442 if (ret) {
7443 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05307444 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007445 }
7446
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05307447 if (hdd_ctx->config->enable_dp_trace)
7448 qdf_dp_trace_init();
7449
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307450 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007451 goto err_wiphy_unregister;
7452
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08007453
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007454 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007455
Arun Khandavallifae92942016-08-01 13:31:08 +05307456
7457 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007458
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007459 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007460 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007461 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05307462 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007463 }
7464
Arun Khandavallifae92942016-08-01 13:31:08 +05307465 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007466 /*
7467 * target hw version/revision would only be retrieved after firmware
7468 * donwload
7469 */
7470 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
7471 &hdd_ctx->target_hw_revision,
7472 &hdd_ctx->target_hw_name);
7473
7474 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05307475 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007476
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007477 hdd_release_rtnl_lock();
7478 rtnl_held = false;
7479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007480#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05307481 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307482 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007483 hdd_skip_acs_scan_timer_handler,
7484 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307485 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07007486 hdd_err("Failed to init ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007487#endif
7488
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007489#ifdef MSM_PLATFORM
7490 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05307491 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307492 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007493 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
7494#endif
7495
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007496 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
7497 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
7498 hdd_ctx->target_hw_version,
7499 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007500
Nirav Shahbd36b062016-07-18 11:12:59 +05307501 if (hdd_ctx->rps)
7502 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07007503
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007504
7505 if (cds_is_packet_log_enabled())
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007506 hdd_pktlog_enable_disable(hdd_ctx, true, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007507
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007508 ret = hdd_register_notifiers(hdd_ctx);
7509 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05307510 goto err_debugfs_exit;
7511
7512 status = wlansap_global_init();
7513 if (QDF_IS_STATUS_ERROR(status))
7514 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007515
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007516 memdump_init();
7517
Arun Khandavallifae92942016-08-01 13:31:08 +05307518 if (hdd_ctx->config->fIsImpsEnabled)
7519 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307520
Arun Khandavallifae92942016-08-01 13:31:08 +05307521 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
7522 hdd_ctx->config->iface_change_wait_time * 5000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007523 goto success;
7524
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007525err_debugfs_exit:
7526 hdd_debugfs_exit(adapter);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007527 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007528
Arun Khandavallid4349a92016-07-25 11:10:43 +05307529 if (rtnl_held)
7530 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007531
Yun Park6a46ad82016-01-04 16:48:19 -08007532
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007533err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007534 wiphy_unregister(hdd_ctx->wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05307535 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007536
Arun Khandavallifae92942016-08-01 13:31:08 +05307537err_ipa_cleanup:
7538 hdd_ipa_cleanup(hdd_ctx);
7539
7540err_stop_modules:
7541 hdd_wlan_stop_modules(hdd_ctx, false);
7542
7543
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007544 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307545 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007546 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307547 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007548 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007549
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007550err_exit_nl_srv:
7551 hdd_exit_netlink_services(hdd_ctx);
7552
7553 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7554 hdd_err("Failed to deinit policy manager");
7555 /* Proceed and complete the clean up */
7556 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307557 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007558err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05307559 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
7560 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007561 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307562 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007563
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007564 return -EIO;
7565
7566success:
7567 EXIT();
7568 return 0;
7569}
7570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007571/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307572 * hdd_wlan_update_target_info() - update target type info
7573 * @hdd_ctx: HDD context
7574 * @context: hif context
7575 *
7576 * Update target info received from firmware in hdd context
7577 * Return:None
7578 */
7579
7580void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
7581{
7582 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
7583
7584 if (!tgt_info) {
7585 hdd_err("Target info is Null");
7586 return;
7587 }
7588
7589 hdd_ctx->target_type = tgt_info->target_type;
7590}
7591
7592/**
7593 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307594 * @hdd_ctx: HDD context
7595 *
7596 * Register the HDD callbacks to CDS/SME.
7597 *
7598 * Return: 0 for success or Error code for failure
7599 */
7600int hdd_register_cb(hdd_context_t *hdd_ctx)
7601{
7602 QDF_STATUS status;
7603 int ret = 0;
7604
7605 ENTER();
7606
7607 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
7608
7609 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
7610 hdd_send_oem_data_rsp_msg);
7611
7612 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
7613 wlan_hdd_cfg80211_fw_mem_dump_cb);
7614 if (!QDF_IS_STATUS_SUCCESS(status)) {
7615 hdd_err("Failed to register memdump callback");
7616 ret = -EINVAL;
7617 return ret;
7618 }
7619
7620 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
7621 sme_nan_register_callback(hdd_ctx->hHal,
7622 wlan_hdd_cfg80211_nan_callback);
7623 sme_stats_ext_register_callback(hdd_ctx->hHal,
7624 wlan_hdd_cfg80211_stats_ext_callback);
7625
7626 sme_ext_scan_register_callback(hdd_ctx->hHal,
7627 wlan_hdd_cfg80211_extscan_callback);
7628
7629 status = cds_register_sap_restart_channel_switch_cb(
7630 (void *)hdd_sap_restart_with_channel_switch);
7631 if (!QDF_IS_STATUS_SUCCESS(status)) {
7632 hdd_err("restart cb registration failed");
7633 ret = -EINVAL;
7634 return ret;
7635 }
7636
7637 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
7638 hdd_rssi_threshold_breached);
7639
7640 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
7641 hdd_get_bpf_offload_cb);
7642 if (!QDF_IS_STATUS_SUCCESS(status)) {
7643 hdd_err("set bpf offload callback failed");
7644 ret = -EINVAL;
7645 return ret;
7646 }
7647
7648 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
7649 wlan_hdd_cfg80211_link_layer_stats_callback);
7650
7651 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
7652
7653 EXIT();
7654
7655 return ret;
7656}
7657
7658/**
7659 * hdd_deregister_cb() - De-Register HDD callbacks.
7660 * @hdd_ctx: HDD context
7661 *
7662 * De-Register the HDD callbacks to CDS/SME.
7663 *
7664 * Return: void
7665 */
7666void hdd_deregister_cb(hdd_context_t *hdd_ctx)
7667{
7668 QDF_STATUS status;
7669
7670 ENTER();
7671
7672 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
7673 if (!QDF_IS_STATUS_SUCCESS(status))
7674 hdd_err("De-register of dcc stats callback failed: %d",
7675 status);
7676
7677 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
7678 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
7679 if (!QDF_IS_STATUS_SUCCESS(status))
7680 hdd_err("De-register bpf offload callback failed: %d",
7681 status);
7682 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
7683
7684 status = cds_deregister_sap_restart_channel_switch_cb();
7685 if (!QDF_IS_STATUS_SUCCESS(status))
7686 hdd_err("De-register restart cb registration failed: %d",
7687 status);
7688
7689 sme_stats_ext_register_callback(hdd_ctx->hHal,
7690 wlan_hdd_cfg80211_stats_ext_callback);
7691
7692 sme_nan_deregister_callback(hdd_ctx->hHal);
7693 status = sme_reset_tsfcb(hdd_ctx->hHal);
7694 if (!QDF_IS_STATUS_SUCCESS(status))
7695 hdd_err("Failed to de-register tsfcb the callback:%d",
7696 status);
7697 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
7698 if (!QDF_IS_STATUS_SUCCESS(status))
7699 hdd_err("Failed to de-register the fw mem dump callback: %d",
7700 status);
7701
7702 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
7703 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
7704
7705 EXIT();
7706}
7707
7708/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007709 * hdd_softap_sta_deauth() - handle deauth req from HDD
7710 * @adapter: Pointer to the HDD
7711 * @enable: bool value
7712 *
7713 * This to take counter measure to handle deauth req from HDD
7714 *
7715 * Return: None
7716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307717QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007718 struct tagCsrDelStaParams *pDelStaParams)
7719{
7720#ifndef WLAN_FEATURE_MBSSID
7721 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7722#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307723 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007724
7725 ENTER();
7726
Jeff Johnson34c88b72016-08-15 14:27:11 -07007727 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007728 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7729
7730 /* Ignore request to deauth bcmc station */
7731 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307732 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007733
7734#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307735 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007736 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7737 pDelStaParams);
7738#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307739 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007740#endif
7741
7742 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307743 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007744}
7745
7746/**
7747 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
7748 * @adapter: Pointer to the HDD
7749 *
7750 * This to take counter measure to handle deauth req from HDD
7751 *
7752 * Return: None
7753 */
7754void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
7755 uint8_t *pDestMacAddress)
7756{
7757#ifndef WLAN_FEATURE_MBSSID
7758 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7759#endif
7760
7761 ENTER();
7762
Jeff Johnson34c88b72016-08-15 14:27:11 -07007763 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007764 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7765
7766 /* Ignore request to disassoc bcmc station */
7767 if (pDestMacAddress[0] & 0x1)
7768 return;
7769
7770#ifdef WLAN_FEATURE_MBSSID
7771 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7772 pDestMacAddress);
7773#else
7774 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
7775#endif
7776}
7777
7778void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
7779 bool enable)
7780{
7781#ifndef WLAN_FEATURE_MBSSID
7782 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7783#endif
7784
7785 ENTER();
7786
Jeff Johnson34c88b72016-08-15 14:27:11 -07007787 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007788 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7789
7790#ifdef WLAN_FEATURE_MBSSID
7791 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7792 (bool) enable);
7793#else
7794 wlansap_set_counter_measure(p_cds_context, (bool) enable);
7795#endif
7796}
7797
7798/**
7799 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
7800 * @hdd_ctx: HDD Context
7801 *
7802 * API to find if there is any STA or P2P-Client is connected
7803 *
7804 * Return: true if connected; false otherwise
7805 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307806QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007807{
7808 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
7809}
7810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007811/**
7812 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
7813 * @adapter: HDD adapter pointer
7814 *
7815 * This function loop through each adapter and disable roaming on each STA
7816 * device mode except the input adapter.
7817 *
7818 * Note: On the input adapter roaming is not enabled yet hence no need to
7819 * disable.
7820 *
7821 * Return: None
7822 */
7823void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
7824{
7825 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7826 hdd_adapter_t *adapterIdx = NULL;
7827 hdd_adapter_list_node_t *adapterNode = NULL;
7828 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307829 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007830
7831 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
7832 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007833 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007834 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007835 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007836 adapter->sessionId);
7837 /*
7838 * Loop through adapter and disable roaming for each STA device
7839 * mode except the input adapter.
7840 */
7841 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
7842
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307843 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007844 adapterIdx = adapterNode->pAdapter;
7845
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007846 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007847 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007848 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007849 adapterIdx->sessionId);
7850 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
7851 (adapterIdx),
7852 adapterIdx->sessionId, 0);
7853 }
7854
7855 status = hdd_get_next_adapter(hdd_ctx,
7856 adapterNode,
7857 &pNext);
7858 adapterNode = pNext;
7859 }
7860 }
7861}
7862
7863/**
7864 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
7865 * @adapter: HDD adapter pointer
7866 *
7867 * This function loop through each adapter and enable roaming on each STA
7868 * device mode except the input adapter.
7869 * Note: On the input adapter no need to enable roaming because link got
7870 * disconnected on this.
7871 *
7872 * Return: None
7873 */
7874void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
7875{
7876 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7877 hdd_adapter_t *adapterIdx = NULL;
7878 hdd_adapter_list_node_t *adapterNode = NULL;
7879 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307880 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007881
7882 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
7883 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007884 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007885 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007886 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007887 adapter->sessionId);
7888 /*
7889 * Loop through adapter and enable roaming for each STA device
7890 * mode except the input adapter.
7891 */
7892 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
7893
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307894 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007895 adapterIdx = adapterNode->pAdapter;
7896
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007897 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007898 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007899 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007900 adapterIdx->sessionId);
7901 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
7902 (adapterIdx),
7903 adapterIdx->sessionId,
7904 REASON_CONNECT);
7905 }
7906
7907 status = hdd_get_next_adapter(hdd_ctx,
7908 adapterNode,
7909 &pNext);
7910 adapterNode = pNext;
7911 }
7912 }
7913}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007914
7915void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
7916{
7917 struct sk_buff *skb;
7918 struct nlmsghdr *nlh;
7919 tAniMsgHdr *ani_hdr;
7920 void *nl_data = NULL;
7921 int flags = GFP_KERNEL;
7922
7923 if (in_interrupt() || irqs_disabled() || in_atomic())
7924 flags = GFP_ATOMIC;
7925
7926 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
7927
7928 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007929 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007930 return;
7931 }
7932
7933 nlh = (struct nlmsghdr *)skb->data;
7934 nlh->nlmsg_pid = 0; /* from kernel */
7935 nlh->nlmsg_flags = 0;
7936 nlh->nlmsg_seq = 0;
7937 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
7938
7939 ani_hdr = NLMSG_DATA(nlh);
7940 ani_hdr->type = type;
7941
7942 switch (type) {
7943 case WLAN_SVC_FW_CRASHED_IND:
7944 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007945 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07007946 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007947 ani_hdr->length = 0;
7948 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
7949 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
7950 break;
7951 case WLAN_SVC_WLAN_STATUS_IND:
7952 case WLAN_SVC_WLAN_VERSION_IND:
7953 case WLAN_SVC_DFS_CAC_START_IND:
7954 case WLAN_SVC_DFS_CAC_END_IND:
7955 case WLAN_SVC_DFS_RADAR_DETECT_IND:
7956 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
7957 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08007958 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05307959 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007960 ani_hdr->length = len;
7961 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
7962 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
7963 memcpy(nl_data, data, len);
7964 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
7965 break;
7966
7967 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07007968 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007969 type);
7970 kfree_skb(skb);
7971 return;
7972 }
7973
7974 nl_srv_bcast(skb);
7975
7976 return;
7977}
7978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007979#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7980void wlan_hdd_auto_shutdown_cb(void)
7981{
Jeff Johnson28f8a772016-08-15 15:30:36 -07007982 hdd_err("Wlan Idle. Sending Shutdown event..");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007983 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
7984}
7985
7986void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
7987{
7988 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307989 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007990 hdd_adapter_t *adapter;
7991 bool ap_connected = false, sta_connected = false;
7992 tHalHandle hal_handle;
7993
7994 hal_handle = hdd_ctx->hHal;
7995 if (hal_handle == NULL)
7996 return;
7997
7998 if (hdd_ctx->config->WlanAutoShutdown == 0)
7999 return;
8000
8001 if (enable == false) {
8002 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308003 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008004 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008005 }
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008006 wlan_hdd_send_svc_nlink_msg(
8007 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008008 return;
8009 }
8010
8011 /* To enable shutdown timer check conncurrency */
8012 if (cds_concurrent_open_sessions_running()) {
8013 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8014
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308015 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008016 adapter = adapterNode->pAdapter;
8017 if (adapter
8018 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008019 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008020 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8021 conn_info.connState ==
8022 eConnectionState_Associated) {
8023 sta_connected = true;
8024 break;
8025 }
8026 }
8027 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008028 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008029 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8030 bApActive == true) {
8031 ap_connected = true;
8032 break;
8033 }
8034 }
8035 status = hdd_get_next_adapter(hdd_ctx,
8036 adapterNode,
8037 &pNext);
8038 adapterNode = pNext;
8039 }
8040 }
8041
8042 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008043 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008044 return;
8045 } else {
8046 if (sme_set_auto_shutdown_timer(hal_handle,
8047 hdd_ctx->config->
8048 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308049 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008050 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008051 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008052 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008053 hdd_ctx->config->WlanAutoShutdown);
8054
8055 }
8056}
8057#endif
8058
8059hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8060 bool check_start_bss)
8061{
8062 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8063 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308064 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008065 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8066
8067 con_sap_adapter = NULL;
8068
8069 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308070 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008071 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008072 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8073 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008074 adapter != this_sap_adapter) {
8075 if (check_start_bss) {
8076 if (test_bit(SOFTAP_BSS_STARTED,
8077 &adapter->event_flags)) {
8078 con_sap_adapter = adapter;
8079 break;
8080 }
8081 } else {
8082 con_sap_adapter = adapter;
8083 break;
8084 }
8085 }
8086 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8087 adapterNode = pNext;
8088 }
8089
8090 return con_sap_adapter;
8091}
8092
8093#ifdef MSM_PLATFORM
8094void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8095{
8096 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8097
Anurag Chouhan210db072016-02-22 18:42:15 +05308098 if (QDF_TIMER_STATE_RUNNING ==
8099 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008100 return;
8101
Anurag Chouhan210db072016-02-22 18:42:15 +05308102 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008103 hdd_ctx->config->busBandwidthComputeInterval);
8104}
8105
8106void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8107{
8108 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308109 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008110 bool can_stop = true;
8111 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8112
Anurag Chouhan210db072016-02-22 18:42:15 +05308113 if (QDF_TIMER_STATE_RUNNING !=
8114 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008115 /* trying to stop timer, when not running is not good */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008116 hdd_err("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008117 return;
8118 }
8119
8120 if (cds_concurrent_open_sessions_running()) {
8121 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8122
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308123 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008124 adapter = adapterNode->pAdapter;
8125 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008126 && (adapter->device_mode == QDF_STA_MODE
8127 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008128 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8129 conn_info.connState ==
8130 eConnectionState_Associated) {
8131 can_stop = false;
8132 break;
8133 }
8134 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008135 && (adapter->device_mode == QDF_SAP_MODE
8136 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008137 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8138 true) {
8139 can_stop = false;
8140 break;
8141 }
8142 status = hdd_get_next_adapter(hdd_ctx,
8143 adapterNode,
8144 &pNext);
8145 adapterNode = pNext;
8146 }
8147 }
8148
8149 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05308150 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008151}
8152#endif
8153
8154/**
8155 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8156 * and sta's operating channel.
8157 * @sta_adapter: Describe the first argument to foobar.
8158 * @ap_adapter: Describe the second argument to foobar.
8159 * @roam_profile: Roam profile of AP to which STA wants to connect.
8160 * @concurrent_chnl_same: If both SAP and STA channels are same then
8161 * set this flag to true else false.
8162 *
8163 * This function checks the sap's operating channel and sta's operating channel.
8164 * if both are same then it will return false else it will restart the sap in
8165 * sta's channel and return true.
8166 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308167 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008168 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308169QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008170 hdd_adapter_t *ap_adapter,
8171 tCsrRoamProfile *roam_profile,
8172 tScanResultHandle *scan_cache,
8173 bool *concurrent_chnl_same)
8174{
8175 hdd_ap_ctx_t *hdd_ap_ctx;
8176 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308177 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008178 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008179 *concurrent_chnl_same = true;
8180
8181 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8182 status =
8183 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8184 roam_profile,
8185 scan_cache,
8186 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308187 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008188 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008189 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8190 if (hdd_ap_ctx->operatingChannel != channel_id) {
8191 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008192 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008193 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008194 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008195 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8196 if (hdd_ap_ctx->operatingChannel != channel_id) {
8197 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008198 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008199 }
8200 }
8201 } else {
8202 /*
8203 * Lets handle worst case scenario here, Scan cache lookup is
8204 * failed so we have to stop the SAP to avoid any channel
8205 * discrepancy between SAP's channel and STA's channel.
8206 * Return the status as failure so caller function could know
8207 * that scan look up is failed.
8208 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008209 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308210 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008211 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308212 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008213}
8214
8215#ifdef WLAN_FEATURE_MBSSID
8216/**
8217 * wlan_hdd_stop_sap() - This function stops bss of SAP.
8218 * @ap_adapter: SAP adapter
8219 *
8220 * This function will process the stopping of sap adapter.
8221 *
8222 * Return: None
8223 */
8224void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
8225{
8226 hdd_ap_ctx_t *hdd_ap_ctx;
8227 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308228 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008229 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008230
8231 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008232 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008233 return;
8234 }
8235
8236 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8237 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308238 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008239 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308240
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008241 mutex_lock(&hdd_ctx->sap_lock);
8242 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08008243 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008244 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
8245 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008246 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308247 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308248 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008249 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05308250 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308251 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008252 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308253 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008254 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008255 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008256 return;
8257 }
8258 }
8259 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008260 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008261 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008262 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008263 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008264 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008265 }
8266 mutex_unlock(&hdd_ctx->sap_lock);
8267 return;
8268}
8269
8270/**
8271 * wlan_hdd_start_sap() - this function starts bss of SAP.
8272 * @ap_adapter: SAP adapter
8273 *
8274 * This function will process the starting of sap adapter.
8275 *
8276 * Return: None
8277 */
8278void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
8279{
8280 hdd_ap_ctx_t *hdd_ap_ctx;
8281 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308282 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008283 hdd_context_t *hdd_ctx;
8284 tsap_Config_t *sap_config;
8285
8286 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008287 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008288 return;
8289 }
8290
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008291 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07008292 hdd_err("SoftAp role has not been enabled");
8293 return;
8294 }
8295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008296 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
8297 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8298 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8299 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
8300
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308301 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008302 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008304 mutex_lock(&hdd_ctx->sap_lock);
8305 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
8306 goto end;
8307
8308 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008309 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008310 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
8311 goto end;
8312 }
8313
8314 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
8315 &hdd_ap_ctx->sapConfig,
8316 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308317 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008318 goto end;
8319
Jeff Johnson28f8a772016-08-15 15:30:36 -07008320 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308321 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008322 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308323 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008324 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008325 goto end;
8326 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07008327 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008328 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008329 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008330 ap_adapter->sessionId);
8331 hostapd_state->bCommit = true;
8332
8333end:
8334 mutex_unlock(&hdd_ctx->sap_lock);
8335 return;
8336}
8337#endif
8338
8339/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08008340 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
8341 * mac scan config
8342 * @status: Status of set antenna mode
8343 *
8344 * Callback on setting the dual mac configuration
8345 *
8346 * Return: None
8347 */
8348void wlan_hdd_soc_set_antenna_mode_cb(
8349 enum set_antenna_mode_status status)
8350{
8351 hdd_context_t *hdd_ctx;
8352
8353 hdd_info("Status: %d", status);
8354
8355 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8356 if (0 != wlan_hdd_validate_context(hdd_ctx))
8357 return;
8358
8359 /* Signal the completion of set dual mac config */
8360 complete(&hdd_ctx->set_antenna_mode_cmpl);
8361}
8362
8363/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008364 * hdd_get_fw_version() - Get FW version
8365 * @hdd_ctx: pointer to HDD context.
8366 * @major_spid: FW version - major spid.
8367 * @minor_spid: FW version - minor spid
8368 * @ssid: FW version - ssid
8369 * @crmid: FW version - crmid
8370 *
8371 * This function is called to get the firmware build version stored
8372 * as part of the HDD context
8373 *
8374 * Return: None
8375 */
8376void hdd_get_fw_version(hdd_context_t *hdd_ctx,
8377 uint32_t *major_spid, uint32_t *minor_spid,
8378 uint32_t *siid, uint32_t *crmid)
8379{
8380 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
8381 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
8382 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
8383 *crmid = hdd_ctx->target_fw_version & 0x7fff;
8384}
8385
8386#ifdef QCA_CONFIG_SMP
8387/**
8388 * wlan_hdd_get_cpu() - get cpu_index
8389 *
8390 * Return: cpu_index
8391 */
8392int wlan_hdd_get_cpu(void)
8393{
8394 int cpu_index = get_cpu();
8395 put_cpu();
8396 return cpu_index;
8397}
8398#endif
8399
8400/**
8401 * hdd_get_fwpath() - get framework path
8402 *
8403 * This function is used to get the string written by
8404 * userspace to start the wlan driver
8405 *
8406 * Return: string
8407 */
8408const char *hdd_get_fwpath(void)
8409{
8410 return fwpath.string;
8411}
8412
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008413/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008414 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008415 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008416 * This function initilizes CDS global context with the help of cds_init. This
8417 * has to be the first function called after probe to get a valid global
8418 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008419 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008420 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008421 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008422int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008423{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008424 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008425 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008426
8427#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8428 wlan_logging_sock_init_svc();
8429#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008430 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008431
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008432 if (p_cds_context == NULL) {
8433 hdd_alert("Failed to allocate CDS context");
8434 ret = -ENOMEM;
8435 goto err_out;
8436 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008437
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008438 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008439
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008440err_out:
8441 return ret;
8442}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008443
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008444/**
8445 * hdd_deinit() - Deinitialize Driver
8446 *
8447 * This function frees CDS global context with the help of cds_deinit. This
8448 * has to be the last function call in remove callback to free the global
8449 * context.
8450 */
8451void hdd_deinit(void)
8452{
8453 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008454
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008455#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8456 wlan_logging_sock_deinit_svc();
8457#endif
8458}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008459
8460#ifdef QCA_WIFI_3_0_ADRASTEA
8461#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
8462#else
8463#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
8464#endif
8465
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008466/**
8467 * __hdd_module_init - Module init helper
8468 *
8469 * Module init helper function used by both module and static driver.
8470 *
8471 * Return: 0 for success, errno on failure
8472 */
8473static int __hdd_module_init(void)
8474{
8475 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008476
Arun Khandavallifae92942016-08-01 13:31:08 +05308477 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008478 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008479
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008480 pld_init();
8481
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308482 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008483
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008484 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008485
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008486 ret = wlan_hdd_register_driver();
8487 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07008488 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
8489 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008490 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008491 }
8492
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308493 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008494
8495 return 0;
8496out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308497 qdf_wake_lock_destroy(&wlan_wake_lock);
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008498 pld_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008499 return ret;
8500}
8501
8502/**
8503 * __hdd_module_exit - Module exit helper
8504 *
8505 * Module exit helper function used by both module and static driver.
8506 */
8507static void __hdd_module_exit(void)
8508{
8509 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
8510 QWLAN_VERSIONSTR);
8511
8512 wlan_hdd_unregister_driver();
8513
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308514 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008515
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008516 pld_deinit();
8517
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008518 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008519}
8520
Arun Khandavallifae92942016-08-01 13:31:08 +05308521#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008522/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308523 * wlan_boot_cb() - Wlan boot callback
8524 * @kobj: object whose directory we're creating the link in.
8525 * @attr: attribute the user is interacting with
8526 * @buff: the buffer containing the user data
8527 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008528 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308529 * This callback is invoked when the fs is ready to start the
8530 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008531 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308532 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008533 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308534static ssize_t wlan_boot_cb(struct kobject *kobj,
8535 struct kobj_attribute *attr,
8536 const char *buf,
8537 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008538{
Arun Khandavallifae92942016-08-01 13:31:08 +05308539
8540 int ret = 0;
8541
8542 if (wlan_loader->loaded_state) {
8543 pr_info("Wlan driver already initialized");
8544 return 0;
8545 }
8546
8547
8548 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8549 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8550
8551 if (__hdd_module_init()) {
8552 pr_err("%s: Failed to register handler\n", __func__);
8553 ret = -EINVAL;
8554 } else
8555 wlan_loader->loaded_state = MODULE_INITIALIZED;
8556
8557 return count;
8558
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008559}
Arun Khandavallifae92942016-08-01 13:31:08 +05308560
8561/**
8562 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
8563 * ready
8564 *
8565 * This is creates the syfs entry boot_wlan. Which shall be invoked
8566 * when the filesystem is ready.
8567 *
8568 * Return: None
8569 */
8570static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008571{
Arun Khandavallifae92942016-08-01 13:31:08 +05308572 int ret = -EINVAL;
8573
8574 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
8575 if (!wlan_loader) {
8576 pr_err("%s: memory alloc failed\n", __func__);
8577 ret = -ENOMEM;
8578 return ret;
8579 }
8580
8581 wlan_loader->boot_wlan_obj = NULL;
8582 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
8583 GFP_KERNEL);
8584 if (!wlan_loader->attr_group) {
8585 pr_err("%s: malloc attr_group failed\n", __func__);
8586 ret = -ENOMEM;
8587 goto error_return;
8588 }
8589
8590 wlan_loader->loaded_state = 0;
8591 wlan_loader->attr_group->attrs = attrs;
8592
8593 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
8594 kernel_kobj);
8595 if (!wlan_loader->boot_wlan_obj) {
8596 pr_err("%s: sysfs create and add failed\n", __func__);
8597 ret = -ENOMEM;
8598 goto error_return;
8599 }
8600
8601 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
8602 wlan_loader->attr_group);
8603 if (ret) {
8604 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
8605 goto error_return;
8606 }
8607
8608 return 0;
8609
8610error_return:
8611
8612 if (wlan_loader->boot_wlan_obj) {
8613 kobject_del(wlan_loader->boot_wlan_obj);
8614 wlan_loader->boot_wlan_obj = NULL;
8615 }
8616
8617 return ret;
8618}
8619
8620/**
8621 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
8622 *
8623 * Return: 0 on success or errno on failure
8624 */
8625static int wlan_deinit_sysfs(void)
8626{
8627
8628 if (!wlan_loader) {
8629 hdd_alert("wlan loader context is Null!");
8630 return -EINVAL;
8631 }
8632
8633 if (wlan_loader->boot_wlan_obj) {
8634 sysfs_remove_group(wlan_loader->boot_wlan_obj,
8635 wlan_loader->attr_group);
8636 kobject_del(wlan_loader->boot_wlan_obj);
8637 wlan_loader->boot_wlan_obj = NULL;
8638 }
8639
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008640 return 0;
8641}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008642
Arun Khandavallifae92942016-08-01 13:31:08 +05308643#endif
8644
8645#ifdef MODULE
8646/**
8647 * __hdd_module_init - Module init helper
8648 *
8649 * Module init helper function used by both module and static driver.
8650 *
8651 * Return: 0 for success, errno on failure
8652 */
8653static int hdd_module_init(void)
8654{
8655 int ret = 0;
8656
8657 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8658 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8659
8660 if (__hdd_module_init()) {
8661 pr_err("%s: Failed to register handler\n", __func__);
8662 ret = -EINVAL;
8663 }
8664
8665 return ret;
8666}
8667#else
8668static int __init hdd_module_init(void)
8669{
8670 int ret = -EINVAL;
8671
8672 ret = wlan_init_sysfs();
8673 if (!ret)
8674 pr_err("Failed to create sysfs entry for loading wlan");
8675
8676 return ret;
8677}
8678#endif
8679
8680
8681#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008682/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008683 * hdd_module_exit() - Exit function
8684 *
8685 * This is the driver exit point (invoked when module is unloaded using rmmod)
8686 *
8687 * Return: None
8688 */
8689static void __exit hdd_module_exit(void)
8690{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008691 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008692}
Arun Khandavallifae92942016-08-01 13:31:08 +05308693#else
8694static void __exit hdd_module_exit(void)
8695{
8696 __hdd_module_exit();
8697 wlan_deinit_sysfs();
8698}
8699#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008700
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008701static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
8702{
8703 return param_set_copystring(kmessage, kp);
8704}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008705
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008706
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008707/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08008708 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008709 *
8710 * Handler function for module param con_mode when it is changed by userspace
8711 * Dynamically linked - do nothing
8712 * Statically linked - exit and init driver, as in rmmod and insmod
8713 *
8714 * Return -
8715 */
8716static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
8717{
8718 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308719 hdd_context_t *hdd_ctx;
8720 hdd_adapter_t *adapter;
8721 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8722 QDF_STATUS status;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008723
Arun Khandavallifae92942016-08-01 13:31:08 +05308724 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008725 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05308726
8727 if (!qdf_dev) {
8728 hdd_err("qdf device context is Null return!");
8729 return -EINVAL;
8730 }
8731
8732 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8733 if (!hdd_ctx) {
8734 hdd_err("Hdd context Null return!");
8735 return -EINVAL;
8736 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308737
Arun Khandavallifae92942016-08-01 13:31:08 +05308738 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05308739 if (ret) {
8740 hdd_err("Stop wlan modules failed");
8741 return -EINVAL;
8742 }
8743
8744 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
8745 if (!adapter) {
8746 hdd_err("Failed to get station adapter");
8747 return -EINVAL;
8748 }
8749
8750 if (con_mode == QDF_GLOBAL_FTM_MODE) {
8751 adapter->device_mode = QDF_FTM_MODE;
8752 hdd_set_conparam(QDF_GLOBAL_FTM_MODE);
8753 } else if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
8754 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
8755 adapter->device_mode = QDF_MONITOR_MODE;
8756 hdd_set_conparam(QDF_GLOBAL_MONITOR_MODE);
8757 hdd_set_station_ops(adapter->dev);
8758 } else if (con_mode == QDF_GLOBAL_EPPING_MODE) {
8759 hdd_set_conparam(QDF_GLOBAL_EPPING_MODE);
8760 status = epping_open();
8761 if (status != QDF_STATUS_SUCCESS) {
8762 hdd_err("Failed to open in eeping mode: %d", status);
8763 return -EINVAL;
8764 }
8765 ret = epping_enable(qdf_dev->dev);
8766 if (ret) {
8767 hdd_err("Failed to enable in epping mode : %d", ret);
8768 epping_close();
8769 return -EINVAL;
8770 }
8771 hdd_info("epping mode successfully enabled");
8772 return 0;
8773 } else {
8774 hdd_info("Con mode not supported");
8775 return -EINVAL;
8776 }
8777
8778 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
8779 if (ret) {
8780 hdd_err("Start wlan modules failed: %d", ret);
8781 return -EINVAL;
8782 }
8783
8784 if (hdd_start_adapter(adapter)) {
8785 hdd_err("Failed to start %s adapter", kmessage);
8786 return -EINVAL;
8787 } else {
8788 hdd_info("Mode successfully changed to %s", kmessage);
8789 ret = 0;
8790 }
8791
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008792 return ret;
8793}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008794
8795/**
8796 * hdd_get_conparam() - driver exit point
8797 *
8798 * This is the driver exit point (invoked when module is unloaded using rmmod)
8799 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05308800 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008801 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05308802enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008803{
Anurag Chouhan6d760662016-02-20 16:05:43 +05308804 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008805}
8806
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08008807void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008808{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08008809 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008810}
8811
Komal Seelamc11bb222016-01-27 18:57:10 +05308812#ifdef WLAN_FEATURE_LPSS
8813static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
8814{
8815 return hdd_ctx->config->enable_lpass_support;
8816}
8817#else
8818static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
8819{
8820 return false;
8821}
8822#endif
8823
8824/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308825 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
8826 * @hdd_ctx: HDD context
8827 *
8828 * Cleans up the pre cac interface, if it exists
8829 *
8830 * Return: None
8831 */
8832void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
8833{
8834 uint8_t session_id;
8835 QDF_STATUS status;
8836 struct hdd_adapter_s *precac_adapter;
8837
8838 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
8839 if (QDF_IS_STATUS_ERROR(status)) {
8840 hdd_err("failed to get pre cac vdev id");
8841 return;
8842 }
8843
8844 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
8845 if (!precac_adapter) {
8846 hdd_err("invalid pre cac adapater");
8847 return;
8848 }
8849
8850 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
8851 wlan_hdd_sap_pre_cac_failure,
8852 (void *)precac_adapter);
8853 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
8854
8855}
8856
8857/**
Komal Seelamec702b02016-02-24 18:42:16 +05308858 * hdd_update_ol_config - API to update ol configuration parameters
8859 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05308860 *
Komal Seelamc11bb222016-01-27 18:57:10 +05308861 * Return: void
8862 */
Komal Seelamec702b02016-02-24 18:42:16 +05308863static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05308864{
Komal Seelamec702b02016-02-24 18:42:16 +05308865 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05308866 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05308867
Komal Seelamec702b02016-02-24 18:42:16 +05308868 if (!ol_ctx)
8869 return;
8870
8871 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
8872 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
8873 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
8874 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
8875 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
8876
8877 ol_init_ini_config(ol_ctx, &cfg);
8878}
8879
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07008880#ifdef FEATURE_RUNTIME_PM
8881/**
8882 * hdd_populate_runtime_cfg() - populate runtime configuration
8883 * @hdd_ctx: hdd context
8884 * @cfg: pointer to the configuration memory being populated
8885 *
8886 * Return: void
8887 */
8888static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
8889 struct hif_config_info *cfg)
8890{
8891 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
8892 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
8893}
8894#else
8895static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
8896 struct hif_config_info *cfg)
8897{
8898}
8899#endif
8900
Komal Seelamec702b02016-02-24 18:42:16 +05308901/**
8902 * hdd_update_hif_config - API to update HIF configuration parameters
8903 * @hdd_ctx: HDD Context
8904 *
8905 * Return: void
8906 */
8907static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
8908{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05308909 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05308910 struct hif_config_info cfg;
8911
8912 if (!scn)
8913 return;
8914
8915 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07008916 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05308917 hif_init_ini_config(scn, &cfg);
8918}
8919
8920/**
8921 * hdd_update_config() - Initialize driver per module ini parameters
8922 * @hdd_ctx: HDD Context
8923 *
8924 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308925 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05308926 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308927int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05308928{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308929 int ret;
8930
Komal Seelamec702b02016-02-24 18:42:16 +05308931 hdd_update_ol_config(hdd_ctx);
8932 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308933 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
8934 ret = hdd_update_cds_config_ftm(hdd_ctx);
8935 else
8936 ret = hdd_update_cds_config(hdd_ctx);
8937
8938 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05308939}
8940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008941/* Register the module init/exit functions */
8942module_init(hdd_module_init);
8943module_exit(hdd_module_exit);
8944
8945MODULE_LICENSE("Dual BSD/GPL");
8946MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8947MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8948
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008949module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8950 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008951
8952module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
8953 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
8954
8955module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
8956
8957module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
8958
8959module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);