blob: 33f9cfc6a96d756928338bdb99ba3b72e67d996e [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
Jeff Johnson94be11c2016-08-15 15:39:25 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038/* Include Files */
39#include <wlan_hdd_includes.h>
40#include <cds_api.h>
41#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053042#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#include <linux/etherdevice.h>
44#include <linux/firmware.h>
45#include <wlan_hdd_tx_rx.h>
46#include <wni_api.h>
47#include <wlan_hdd_cfg.h>
48#include <wlan_ptt_sock_svc.h>
49#include <dbglog_host.h>
50#include <wlan_logging_sock_svc.h>
51#include <wlan_hdd_wowl.h>
52#include <wlan_hdd_misc.h>
53#include <wlan_hdd_wext.h>
54#include "wlan_hdd_trace.h"
55#include "wlan_hdd_ioctl.h"
56#include "wlan_hdd_ftm.h"
57#include "wlan_hdd_power.h"
58#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070059#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070062#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063
64#include <net/addrconf.h>
65#include <linux/wireless.h>
66#include <net/cfg80211.h>
67#include <linux/inetdevice.h>
68#include <net/addrconf.h>
69#include "wlan_hdd_cfg80211.h"
70#include "wlan_hdd_ext_scan.h"
71#include "wlan_hdd_p2p.h"
72#include <linux/rtnetlink.h>
73#include "sap_api.h"
74#include <linux/semaphore.h>
75#include <linux/ctype.h>
76#include <linux/compat.h>
77#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078#include <soc/qcom/subsystem_restart.h>
79#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080080#include <wlan_hdd_hostapd.h>
81#include <wlan_hdd_softap_tx_rx.h>
82#include "cfg_api.h"
83#include "qwlan_version.h"
84#include "wma_types.h"
85#include "wlan_hdd_tdls.h"
86#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053087#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080088#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070090#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080091#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#include "wlan_hdd_nan.h"
93#include "wlan_hdd_debugfs.h"
94#include "wlan_hdd_driver_ops.h"
95#include "epping_main.h"
96#include "wlan_hdd_memdump.h"
97
98#include <wlan_hdd_ipa.h>
99#include "hif.h"
100#include "wma.h"
101#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700102#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530104#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700105#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530106#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700107#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530108#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700109#include <wlan_hdd_napi.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110
111#ifdef MODULE
112#define WLAN_MODULE_NAME module_name(THIS_MODULE)
113#else
114#define WLAN_MODULE_NAME "wlan"
115#endif
116
117#ifdef TIMER_MANAGER
118#define TIMER_MANAGER_STR " +TIMER_MANAGER"
119#else
120#define TIMER_MANAGER_STR ""
121#endif
122
123#ifdef MEMORY_DEBUG
124#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
125#else
126#define MEMORY_DEBUG_STR ""
127#endif
128
Arun Khandavallifae92942016-08-01 13:31:08 +0530129#ifndef MODULE
130static struct gwlan_loader *wlan_loader;
131static ssize_t wlan_boot_cb(struct kobject *kobj,
132 struct kobj_attribute *attr,
133 const char *buf, size_t count);
134struct gwlan_loader {
135 bool loaded_state;
136 struct kobject *boot_wlan_obj;
137 struct attribute_group *attr_group;
138};
139
140static struct kobj_attribute wlan_boot_attribute =
141 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
142
143static struct attribute *attrs[] = {
144 &wlan_boot_attribute.attr,
145 NULL,
146};
147
148#define MODULE_INITIALIZED 1
149#endif
150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151/* the Android framework expects this param even though we don't use it */
152#define BUF_LEN 20
153static char fwpath_buffer[BUF_LEN];
154static struct kparam_string fwpath = {
155 .string = fwpath_buffer,
156 .maxlen = BUF_LEN,
157};
158
159static char *country_code;
160static int enable_11d = -1;
161static int enable_dfs_chan_scan = -1;
162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163/*
164 * spinlock for synchronizing asynchronous request/response
165 * (full description of use in wlan_hdd_main.h)
166 */
167DEFINE_SPINLOCK(hdd_context_lock);
168
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800169#define WLAN_NLINK_CESIUM 30
170
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530171static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172
173#define WOW_MAX_FILTER_LISTS 1
174#define WOW_MAX_FILTERS_PER_LIST 4
175#define WOW_MIN_PATTERN_SIZE 6
176#define WOW_MAX_PATTERN_SIZE 64
177
178#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
179static const struct wiphy_wowlan_support wowlan_support_reg_init = {
180 .flags = WIPHY_WOWLAN_ANY |
181 WIPHY_WOWLAN_MAGIC_PKT |
182 WIPHY_WOWLAN_DISCONNECT |
183 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
184 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
185 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
186 WIPHY_WOWLAN_4WAY_HANDSHAKE |
187 WIPHY_WOWLAN_RFKILL_RELEASE,
188 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
189 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
190 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
191};
192#endif
193
194/* internal function declaration */
195
196struct sock *cesium_nl_srv_sock;
197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
199void wlan_hdd_auto_shutdown_cb(void);
200#endif
201
202/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530203 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
204 * @hdd_ctx: pointer to hdd_context_t
205 *
206 * Return: none
207 */
208void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
209{
210 hdd_adapter_t *adapter;
211 hdd_adapter_list_node_t *adapter_node, *next;
212 QDF_STATUS status = QDF_STATUS_SUCCESS;
213
214 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
215 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
216 adapter = adapter_node->pAdapter;
217 if (NULL != adapter)
218 hdd_send_rps_ind(adapter);
219 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
220 adapter_node = next;
221 }
222}
223
224/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
226 * @vdev_id: vdev_id
227 * @action: action type
228 * @reason: reason type
229 *
230 * Return: none
231 */
232void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
233 enum netif_action_type action, enum netif_reason_type reason)
234{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530235 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236 hdd_adapter_t *adapter;
237
238 if (!hdd_ctx) {
239 hdd_err("hdd ctx is NULL");
240 return;
241 }
242 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
243
244 wlan_hdd_netif_queue_control(adapter, action, reason);
245 return;
246}
247
248/*
249 * Store WLAN driver version info in a global variable such that crash debugger
250 * can extract it from driver debug symbol and crashdump for post processing
251 */
252uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
253
254/**
255 * hdd_device_mode_to_string() - return string conversion of device mode
256 * @device_mode: device mode
257 *
258 * This utility function helps log string conversion of device mode.
259 *
260 * Return: string conversion of device mode, if match found;
261 * "Unknown" otherwise.
262 */
263const char *hdd_device_mode_to_string(uint8_t device_mode)
264{
265 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800266 CASE_RETURN_STRING(QDF_STA_MODE);
267 CASE_RETURN_STRING(QDF_SAP_MODE);
268 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
269 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
270 CASE_RETURN_STRING(QDF_FTM_MODE);
271 CASE_RETURN_STRING(QDF_IBSS_MODE);
272 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
273 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700274 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275 default:
276 return "Unknown";
277 }
278}
279
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530280/**
281 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
282 * @adapter: HDD adapter
283 * @chan_number: Channel number
284 * @chan_bw: Bandwidth
285 *
286 * Checks if the given bandwidth is valid for the given channel number.
287 *
288 * Return: 0 for success, non-zero for failure
289 */
290int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
291 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800292 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530293{
294 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
295 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
296 bool found = false;
297 tHalHandle hal;
298
299 hal = WLAN_HDD_GET_HAL_CTX(adapter);
300 if (!hal) {
301 hdd_err("Invalid HAL context");
302 return -EINVAL;
303 }
304
305 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
306 hdd_err("No valid channel list");
307 return -EOPNOTSUPP;
308 }
309
310 for (i = 0; i < len; i++) {
311 if (chan[i] == chan_number) {
312 found = true;
313 break;
314 }
315 }
316
317 if (found == false) {
318 hdd_err("Channel not in driver's valid channel list");
319 return -EOPNOTSUPP;
320 }
321
322 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
323 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
324 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
325 return -EINVAL;
326 }
327
328 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
329 if (chan_bw == CH_WIDTH_80MHZ) {
330 hdd_err("BW80 not possible in 2.4GHz band");
331 return -EINVAL;
332 }
333 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
334 (chan_bw != CH_WIDTH_MAX)) {
335 hdd_err("Only BW20 possible on channel 14");
336 return -EINVAL;
337 }
338 }
339
340 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
341 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
342 (chan_bw != CH_WIDTH_MAX)) {
343 hdd_err("Only BW20 possible on channel 165");
344 return -EINVAL;
345 }
346 }
347
348 return 0;
349}
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351static int __hdd_netdev_notifier_call(struct notifier_block *nb,
352 unsigned long state, void *data)
353{
354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
355 struct netdev_notifier_info *dev_notif_info = data;
356 struct net_device *dev = dev_notif_info->dev;
357#else
358 struct net_device *dev = data;
359#endif
360 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
361 hdd_context_t *hdd_ctx;
362
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800363 ENTER_DEV(dev);
364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 /* Make sure that this callback corresponds to our device. */
366 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
367 return NOTIFY_DONE;
368
369 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
370 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700371 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800372 return NOTIFY_DONE;
373 }
374
375 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700376 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 return NOTIFY_DONE;
378 }
379
380 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
381 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700382 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530383 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 return NOTIFY_DONE;
385 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800386 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 return NOTIFY_DONE;
388
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700389 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 dev->name, state);
391
392 switch (state) {
393 case NETDEV_REGISTER:
394 break;
395
396 case NETDEV_UNREGISTER:
397 break;
398
399 case NETDEV_UP:
400 sme_ch_avoid_update_req(hdd_ctx->hHal);
401 break;
402
403 case NETDEV_DOWN:
404 break;
405
406 case NETDEV_CHANGE:
407 if (true == adapter->isLinkUpSvcNeeded)
408 complete(&adapter->linkup_event_var);
409 break;
410
411 case NETDEV_GOING_DOWN:
412 if (adapter->scan_info.mScanPending != false) {
413 unsigned long rc;
414 INIT_COMPLETION(adapter->scan_info.
415 abortscan_event_var);
416 hdd_abort_mac_scan(adapter->pHddCtx,
417 adapter->sessionId,
418 eCSR_SCAN_ABORT_DEFAULT);
419 rc = wait_for_completion_timeout(
420 &adapter->scan_info.abortscan_event_var,
421 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
422 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700423 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 }
425 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700426 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800427 }
428 break;
429
430 default:
431 break;
432 }
433
434 return NOTIFY_DONE;
435}
436
437/**
438 * hdd_netdev_notifier_call() - netdev notifier callback function
439 * @nb: pointer to notifier block
440 * @state: state
441 * @ndev: ndev pointer
442 *
443 * Return: 0 on success, error number otherwise.
444 */
445static int hdd_netdev_notifier_call(struct notifier_block *nb,
446 unsigned long state,
447 void *ndev)
448{
449 int ret;
450
451 cds_ssr_protect(__func__);
452 ret = __hdd_netdev_notifier_call(nb, state, ndev);
453 cds_ssr_unprotect(__func__);
454
455 return ret;
456}
457
458struct notifier_block hdd_netdev_notifier = {
459 .notifier_call = hdd_netdev_notifier_call,
460};
461
462/* variable to hold the insmod parameters */
463static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800464
465/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530468/**
469 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
470 * @ch_width: NL channel width
471 *
472 * Converts the NL channel width to the driver's internal representation
473 *
474 * Return: Converted channel width. In case of non matching NL channel width,
475 * CH_WIDTH_MAX will be returned.
476 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800477enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530478{
479 switch (ch_width) {
480 case NL80211_CHAN_WIDTH_20_NOHT:
481 case NL80211_CHAN_WIDTH_20:
482 return CH_WIDTH_20MHZ;
483 case NL80211_CHAN_WIDTH_40:
484 return CH_WIDTH_40MHZ;
485 break;
486 case NL80211_CHAN_WIDTH_80:
487 return CH_WIDTH_80MHZ;
488 case NL80211_CHAN_WIDTH_80P80:
489 return CH_WIDTH_80P80MHZ;
490 case NL80211_CHAN_WIDTH_160:
491 return CH_WIDTH_160MHZ;
492 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800493 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530494 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800495 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530496 default:
497 hdd_err("Invalid channel width %d, setting to default",
498 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800499 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530500 }
501}
502
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530503/* wlan_hdd_find_opclass() - Find operating class for a channel
504 * @hal: handler to HAL
505 * @channel: channel id
506 * @bw_offset: bandwidth offset
507 *
508 * Function invokes sme api to find the operating class
509 *
510 * Return: operating class
511 */
512uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
513 uint8_t bw_offset)
514{
515 uint8_t opclass = 0;
516
517 sme_get_opclass(hal, channel, bw_offset, &opclass);
518 return opclass;
519}
520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530522 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523 * @moduleId: Module whose trace level is being configured
524 * @bitmask: Bitmask of log levels to be enabled
525 *
526 * Called immediately after the cfg.ini is read in order to configure
527 * the desired trace levels.
528 *
529 * Return: None
530 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530533 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534
535 /*
536 * if the bitmask is the default value, then a bitmask was not
537 * specified in cfg.ini, so leave the logging level alone (it
538 * will remain at the "compiled in" default value)
539 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530540 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 return;
542 }
543
544 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530545 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546
547 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530548 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 while (0 != bitmask) {
550 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530551 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552 }
553 level++;
554 bitmask >>= 1;
555 }
556}
557
558/**
559 * wlan_hdd_validate_context() - check the HDD context
560 * @hdd_ctx: HDD context pointer
561 *
562 * Return: 0 if the context is valid. Error code otherwise
563 */
564int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
565{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530567 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 return -ENODEV;
569 }
570
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800571 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530572 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
573 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574 return -EAGAIN;
575 }
576
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800577 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530578 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
579 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 return -EAGAIN;
581 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530582
583 if (hdd_ctx->start_modules_in_progress ||
584 hdd_ctx->stop_modules_in_progress) {
585 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
586 (void *)_RET_IP_);
587 return -EAGAIN;
588 }
589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590 return 0;
591}
592
593void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
594{
595 hdd_adapter_t *adapter = NULL;
596 hdd_station_ctx_t *pHddStaCtx = NULL;
597 eCsrPhyMode phyMode;
598 struct hdd_config *cfg_param = NULL;
599
600 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700601 hdd_alert("HDD Context is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 return;
603 }
604
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800605 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606 if (NULL == adapter) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700607 hdd_alert("adapter is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608 return;
609 }
610
611 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
612
613 cfg_param = hdd_ctx->config;
614 if (NULL == cfg_param) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700615 hdd_alert("cfg_params not available !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 return;
617 }
618
619 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
620
621 if (!hdd_ctx->isVHT80Allowed) {
622 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
623 (eCSR_DOT11_MODE_11ac == phyMode) ||
624 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700625 hdd_notice("Setting phymode to 11n!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
627 eCSR_DOT11_MODE_11n);
628 }
629 } else {
630 /*
631 * New country Supports 11ac as well resetting value back from
632 * .ini
633 */
634 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
635 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
636 dot11Mode));
637 return;
638 }
639
640 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
641 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
642 || (eCSR_CFG_DOT11_MODE_11AC ==
643 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530644 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645
646 /* need to issue a disconnect to CSR. */
647 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530648 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 adapter->sessionId,
650 eCSR_DISCONNECT_REASON_UNSPECIFIED);
651
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530652 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 unsigned long rc;
654
655 rc = wait_for_completion_timeout(
656 &adapter->disconnect_comp_var,
657 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
658 if (!rc)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700659 hdd_err("failure waiting for disconnect_comp_var");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660 }
661 }
662}
663
664/**
665 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
666 * @hdd_adapter_t Hdd adapter.
667 *
668 * This function sets the IBSS power save config parameters to WMA
669 * which will send it to firmware if FW supports IBSS power save
670 * before vdev start.
671 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530672 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800673 * on failure.
674 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530675QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676{
677 int ret;
678 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
679
680 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700681 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530682 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683 }
684
685 ret = wma_cli_set_command(adapter->sessionId,
686 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
687 hdd_ctx->config->ibssATIMWinSize,
688 VDEV_CMD);
689 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700690 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530691 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692 }
693
694 ret = wma_cli_set_command(adapter->sessionId,
695 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
696 hdd_ctx->config->isIbssPowerSaveAllowed,
697 VDEV_CMD);
698 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700699 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
700 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530701 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 }
703
704 ret = wma_cli_set_command(adapter->sessionId,
705 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
706 hdd_ctx->config->
707 isIbssPowerCollapseAllowed, VDEV_CMD);
708 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700709 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
710 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530711 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800712 }
713
714 ret = wma_cli_set_command(adapter->sessionId,
715 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
716 hdd_ctx->config->isIbssAwakeOnTxRx,
717 VDEV_CMD);
718 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700719 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530720 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800721 }
722
723 ret = wma_cli_set_command(adapter->sessionId,
724 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
725 hdd_ctx->config->ibssInactivityCount,
726 VDEV_CMD);
727 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700728 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530729 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730 }
731
732 ret = wma_cli_set_command(adapter->sessionId,
733 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
734 hdd_ctx->config->ibssTxSpEndInactivityTime,
735 VDEV_CMD);
736 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700737 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
738 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530739 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800740 }
741
742 ret = wma_cli_set_command(adapter->sessionId,
743 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
744 hdd_ctx->config->ibssPsWarmupTime,
745 VDEV_CMD);
746 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700747 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
748 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530749 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800750 }
751
752 ret = wma_cli_set_command(adapter->sessionId,
753 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
754 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
755 VDEV_CMD);
756 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700757 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
758 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530759 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760 }
761
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530762 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763}
764
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800765#define INTF_MACADDR_MASK 0x7
766
767/**
768 * hdd_update_macaddr() - update mac address
769 * @config: hdd configuration
770 * @hw_macaddr: mac address
771 *
772 * Mac address for multiple virtual interface is found as following
773 * i) The mac address of the first interface is just the actual hw mac address.
774 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
775 * define the mac address for the remaining interfaces and locally
776 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
777 * supported virtual interfaces, right now this is 0x07 (meaning 8
778 * interface).
779 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
780 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
781 *
782 * Return: None
783 */
784void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530785 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786{
787 int8_t i;
788 uint8_t macaddr_b3, tmp_br3;
789
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530790 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530791 QDF_MAC_ADDR_SIZE);
792 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530793 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530794 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795 macaddr_b3 = config->intfMacAddr[i].bytes[3];
796 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
797 INTF_MACADDR_MASK;
798 macaddr_b3 += tmp_br3;
799
800 /* XOR-ing bit-24 of the mac address. This will give enough
801 * mac address range before collision
802 */
803 macaddr_b3 ^= (1 << 7);
804
805 /* Set locally administered bit */
806 config->intfMacAddr[i].bytes[0] |= 0x02;
807 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700808 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800809 MAC_ADDRESS_STR, i,
810 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
811 }
812}
813
814static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
815 struct wma_tgt_services *cfg)
816{
817 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818
819 /* Set up UAPSD */
820 config->apUapsdEnabled &= cfg->uapsd;
821
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 /* 11AC mode support */
823 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
824 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
825 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826
827 /* ARP offload: override user setting if invalid */
828 config->fhostArpOffload &= cfg->arp_offload;
829
830#ifdef FEATURE_WLAN_SCAN_PNO
831 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700832 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 if (cfg->pno_offload)
834 config->PnoOffload = true;
835#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800836#ifdef FEATURE_WLAN_TDLS
837 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530838 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
839 cfg->en_tdls_offchan;
840 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
841 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
843 config->fEnableTDLSSleepSta = true;
844 } else {
845 config->fEnableTDLSSleepSta = false;
846 }
847#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848#ifdef WLAN_FEATURE_ROAM_OFFLOAD
849 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
850#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700851 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852
853}
854
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700855/**
856 * hdd_update_vdev_nss() - sets the vdev nss
857 * @hdd_ctx: HDD context
858 *
859 * Sets the Nss per vdev type based on INI
860 *
861 * Return: None
862 */
863static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
864{
865 struct hdd_config *cfg_ini = hdd_ctx->config;
866 uint8_t max_supp_nss = 1;
867
868 if (cfg_ini->enable2x2)
869 max_supp_nss = 2;
870
871 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
872 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
873
874 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
875 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
876}
877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
879 struct wma_tgt_ht_cap *cfg)
880{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530881 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 uint32_t value, val32;
883 uint16_t val16;
884 struct hdd_config *pconfig = hdd_ctx->config;
885 tSirMacHTCapabilityInfo *phtCapInfo;
886 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
887 uint8_t enable_tx_stbc;
888
889 /* check and update RX STBC */
890 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
891 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
892
893 /* get the MPDU density */
894 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
895
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530896 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700897 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898 value = 0;
899 }
900
901 /*
902 * MPDU density:
903 * override user's setting if value is larger
904 * than the one supported by target
905 */
906 if (value > cfg->mpdu_density) {
907 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
908 cfg->mpdu_density);
909
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530910 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700911 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 }
913
914 /* get the HT capability info */
915 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530916 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700917 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800918 return;
919 }
920 val16 = (uint16_t) val32;
921 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
922
923 /* Set the LDPC capability */
924 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
925
926 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
927 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
928
929 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
930 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
931
932 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
933 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
934
935 enable_tx_stbc = pconfig->enableTxSTBC;
936
937 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
938 pconfig->enable2x2 = 1;
939 } else {
940 pconfig->enable2x2 = 0;
941 enable_tx_stbc = 0;
942
943 /* 1x1 */
944 /* Update Rx Highest Long GI data Rate */
945 if (sme_cfg_set_int(hdd_ctx->hHal,
946 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700947 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530948 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700949 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 }
951
952 /* Update Tx Highest Long GI data Rate */
953 if (sme_cfg_set_int
954 (hdd_ctx->hHal,
955 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700956 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530957 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700958 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959 }
960 }
961 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
962 enable_tx_stbc = 0;
963 phtCapInfo->txSTBC = enable_tx_stbc;
964
965 val32 = val16;
966 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530967 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700968 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
970 value = SIZE_OF_SUPPORTED_MCS_SET;
971 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530972 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700973 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974
975 if (pconfig->enable2x2) {
976 for (value = 0; value < cfg->num_rf_chains; value++)
977 mcs_set[value] =
978 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
979
980 status =
981 sme_cfg_set_str(hdd_ctx->hHal,
982 WNI_CFG_SUPPORTED_MCS_SET,
983 mcs_set,
984 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530985 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700986 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987 }
988 }
989#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
990}
991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
993 struct wma_tgt_vht_cap *cfg)
994{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530995 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996 uint32_t value = 0;
997 struct hdd_config *pconfig = hdd_ctx->config;
998 struct wiphy *wiphy = hdd_ctx->wiphy;
999 struct ieee80211_supported_band *band_5g =
1000 wiphy->bands[IEEE80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001001 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001002
1003 /* Get the current MPDU length */
1004 status =
1005 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1006 &value);
1007
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301008 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001009 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010 value = 0;
1011 }
1012
1013 /*
1014 * VHT max MPDU length:
1015 * override if user configured value is too high
1016 * that the target cannot support
1017 */
1018 if (value > cfg->vht_max_mpdu) {
1019 status = sme_cfg_set_int(hdd_ctx->hHal,
1020 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1021 cfg->vht_max_mpdu);
1022
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301023 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001024 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025 }
1026 }
1027
1028 /* Get the current supported chan width */
1029 status = sme_cfg_get_int(hdd_ctx->hHal,
1030 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1031 &value);
1032
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301033 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001034 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001035 value = 0;
1036 }
1037
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001038 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1039 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1040
1041 if (pconfig->enable2x2)
1042 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1043
1044 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1045 QDF_STATUS_E_FAILURE) {
1046 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1047 }
1048
1049 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1050 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1051 if (pconfig->enable2x2)
1052 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1053
1054 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1055 QDF_STATUS_E_FAILURE) {
1056 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1057 }
1058
1059 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1060 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1061 if (pconfig->enable2x2)
1062 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1063
1064 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1065 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1066
1067 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1068 QDF_STATUS_E_FAILURE) {
1069 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1070 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001072 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001073 &value);
1074
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301075 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001076 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001077 value = 0;
1078 }
1079
1080 /* Set the LDPC capability */
1081 if (value && !cfg->vht_rx_ldpc) {
1082 status = sme_cfg_set_int(hdd_ctx->hHal,
1083 WNI_CFG_VHT_LDPC_CODING_CAP,
1084 cfg->vht_rx_ldpc);
1085
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301086 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001087 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001088 }
1089 }
1090
1091 /* Get current GI 80 value */
1092 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1093 &value);
1094
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301095 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001096 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001097 value = 0;
1098 }
1099
1100 /* set the Guard interval 80MHz */
1101 if (value && !cfg->vht_short_gi_80) {
1102 status = sme_cfg_set_int(hdd_ctx->hHal,
1103 WNI_CFG_VHT_SHORT_GI_80MHZ,
1104 cfg->vht_short_gi_80);
1105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301106 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001107 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 }
1109 }
1110
1111 /* Get current GI 160 value */
1112 status = sme_cfg_get_int(hdd_ctx->hHal,
1113 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1114 &value);
1115
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301116 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001117 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118 value = 0;
1119 }
1120
1121 /* Get VHT TX STBC cap */
1122 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1123
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301124 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001125 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126 value = 0;
1127 }
1128
1129 /* VHT TX STBC cap */
1130 if (value && !cfg->vht_tx_stbc) {
1131 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1132 cfg->vht_tx_stbc);
1133
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301134 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001135 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 }
1137 }
1138
1139 /* Get VHT RX STBC cap */
1140 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1141
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301142 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001143 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 value = 0;
1145 }
1146
1147 /* VHT RX STBC cap */
1148 if (value && !cfg->vht_rx_stbc) {
1149 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1150 cfg->vht_rx_stbc);
1151
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301152 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001153 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 }
1155 }
1156
1157 /* Get VHT SU Beamformer cap */
1158 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1159 &value);
1160
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301161 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001162 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001163 value = 0;
1164 }
1165
1166 /* set VHT SU Beamformer cap */
1167 if (value && !cfg->vht_su_bformer) {
1168 status = sme_cfg_set_int(hdd_ctx->hHal,
1169 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1170 cfg->vht_su_bformer);
1171
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301172 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001173 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 }
1175 }
1176
1177 /* check and update SU BEAMFORMEE capabality */
1178 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1179 pconfig->enableTxBF = cfg->vht_su_bformee;
1180
1181 status = sme_cfg_set_int(hdd_ctx->hHal,
1182 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1183 pconfig->enableTxBF);
1184
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301185 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001186 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001187 }
1188
1189 /* Get VHT MU Beamformer cap */
1190 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1191 &value);
1192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301193 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001194 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 value = 0;
1196 }
1197
1198 /* set VHT MU Beamformer cap */
1199 if (value && !cfg->vht_mu_bformer) {
1200 status = sme_cfg_set_int(hdd_ctx->hHal,
1201 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1202 cfg->vht_mu_bformer);
1203
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301204 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001205 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 }
1207 }
1208
1209 /* Get VHT MU Beamformee cap */
1210 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1211 &value);
1212
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301213 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001214 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 value = 0;
1216 }
1217
1218 /* set VHT MU Beamformee cap */
1219 if (value && !cfg->vht_mu_bformee) {
1220 status = sme_cfg_set_int(hdd_ctx->hHal,
1221 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1222 cfg->vht_mu_bformee);
1223
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301224 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001225 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226 }
1227 }
1228
1229 /* Get VHT MAX AMPDU Len exp */
1230 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1231 &value);
1232
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301233 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001234 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 value = 0;
1236 }
1237
1238 /*
1239 * VHT max AMPDU len exp:
1240 * override if user configured value is too high
1241 * that the target cannot support.
1242 * Even though Rome publish ampdu_len=7, it can
1243 * only support 4 because of some h/w bug.
1244 */
1245
1246 if (value > cfg->vht_max_ampdu_len_exp) {
1247 status = sme_cfg_set_int(hdd_ctx->hHal,
1248 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1249 cfg->vht_max_ampdu_len_exp);
1250
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301251 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001252 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 }
1254 }
1255
1256 /* Get VHT TXOP PS CAP */
1257 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1258
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301259 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001260 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 value = 0;
1262 }
1263
1264 /* set VHT TXOP PS cap */
1265 if (value && !cfg->vht_txop_ps) {
1266 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1267 cfg->vht_txop_ps);
1268
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301269 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001270 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 }
1272 }
1273
1274 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1275 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1276 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1277 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1278 else
1279 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1280
1281
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001282 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 band_5g->vht_cap.cap |=
1284 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001285 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286 band_5g->vht_cap.cap |=
1287 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001288
1289 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1290 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1291
1292 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1293 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1294 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1295 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1296
1297 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1298 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1299
1300 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1301 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1302 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1303 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1304 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1305 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1306
1307 band_5g->vht_cap.cap |=
1308 (cfg->vht_max_ampdu_len_exp <<
1309 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1310
1311 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1312 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1313 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1314 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1315 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1316 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1317 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1318 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1319
1320 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1321 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1322
1323}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001325/**
1326 * hdd_generate_macaddr_auto() - Auto-generate mac address
1327 * @hdd_ctx: Pointer to the HDD context
1328 *
1329 * Auto-generate mac address using device serial number.
1330 * Keep the first 3 bytes of OUI as before and replace
1331 * the last 3 bytes with the lower 3 bytes of serial number.
1332 *
1333 * Return: 0 for success
1334 * Non zero failure code for errors
1335 */
1336static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1337{
1338 unsigned int serialno = 0;
1339 struct qdf_mac_addr mac_addr = {
1340 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1341 };
1342
Yuanyuan Liuf97e8222016-09-21 10:31:38 -07001343 serialno = pld_socinfo_get_serial_number(hdd_ctx->parent_dev);
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001344 if (serialno == 0)
1345 return -EINVAL;
1346
1347 serialno &= 0x00ffffff;
1348
1349 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1350 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1351 mac_addr.bytes[5] = serialno & 0xff;
1352
1353 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1354 return 0;
1355}
1356
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301357/**
1358 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1359 * configuration to cfg_ini in HDD
1360 * @hdd_ctx: Pointer to hdd_ctx
1361 * @cfg: target configuration
1362 *
1363 * Return: None
1364 */
1365#ifdef FEATURE_WLAN_RA_FILTERING
1366static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1367 struct wma_tgt_cfg *cfg)
1368{
1369 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1370}
1371#else
1372static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1373 struct wma_tgt_cfg *cfg)
1374{
1375}
1376#endif
1377
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378void hdd_update_tgt_cfg(void *context, void *param)
1379{
1380 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1381 struct wma_tgt_cfg *cfg = param;
1382 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001383 struct cds_config_info *cds_cfg = cds_get_ini_config();
1384
1385 if (cds_cfg) {
1386 if (hdd_ctx->config->enable_sub_20_channel_width !=
1387 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1388 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1389 cds_cfg->sub_20_channel_width =
1390 WLAN_SUB_20_CH_WIDTH_NONE;
1391 } else {
1392 cds_cfg->sub_20_channel_width =
1393 hdd_ctx->config->enable_sub_20_channel_width;
1394 }
1395 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396
1397 /* first store the INI band capability */
1398 temp_band_cap = hdd_ctx->config->nBandCapability;
1399
1400 hdd_ctx->config->nBandCapability = cfg->band_cap;
1401
1402 /* now overwrite the target band capability with INI
1403 setting if INI setting is a subset */
1404
1405 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1406 (temp_band_cap != eCSR_BAND_ALL))
1407 hdd_ctx->config->nBandCapability = temp_band_cap;
1408 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1409 (temp_band_cap != eCSR_BAND_ALL) &&
1410 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001411 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412 }
1413
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001414 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001415 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1416 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1417 }
1418
1419 /* This can be extended to other configurations like ht, vht cap... */
1420
Anurag Chouhanc5548422016-02-24 18:33:27 +05301421 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001423 hdd_ctx->update_mac_addr_to_fw = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001424 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001425 static struct qdf_mac_addr default_mac_addr = {
1426 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1427 };
1428 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1429 &default_mac_addr)) {
1430 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1431 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1432 MAC_ADDRESS_STR,
1433 MAC_ADDR_ARRAY(hdd_ctx->config->
1434 intfMacAddr[0].bytes));
1435 } else {
1436 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1437 MAC_ADDRESS_STR,
1438 MAC_ADDR_ARRAY(hdd_ctx->config->
1439 intfMacAddr[0].bytes));
1440 }
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07001441 hdd_ctx->update_mac_addr_to_fw = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442 }
1443
1444 hdd_ctx->target_fw_version = cfg->target_fw_version;
1445
1446 hdd_ctx->max_intf_count = cfg->max_intf_count;
1447
Jeff Johnsonc875e242016-09-23 18:12:34 -07001448 hdd_lpass_target_config(hdd_ctx, cfg);
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07001449 hdd_green_ap_target_config(hdd_ctx, cfg);
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1452 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1453
1454 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001457
1458 hdd_update_vdev_nss(hdd_ctx);
1459
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001460 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001461 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001462 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001463 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001464
1465 hdd_ctx->current_antenna_mode =
1466 (hdd_ctx->config->enable2x2 == 0x01) ?
1467 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1468 hdd_info("Init current antenna mode: %d",
1469 hdd_ctx->current_antenna_mode);
1470
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001471 hdd_info("Target BPF %d Host BPF %d",
1472 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1473 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1474 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301475 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301476
Arun Khandavallid454d422016-08-17 12:47:05 +05301477 /*
1478 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1479 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1480 * configure the STA mode wow pattern.
1481 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301482 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301483 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301484
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05301485 hdd_ctx->wmi_max_len = cfg->wmi_max_len;
1486
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001487 /* Configure NAN datapath features */
1488 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001489}
1490
1491/**
1492 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1493 * @context: HDD context pointer
1494 * @param: HDD radar indication pointer
1495 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001496 * This function is invoked in atomic context when a radar
1497 * is found on the SAP current operating channel and Data Tx
1498 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 * Actions: Stop the netif Tx queues,Indicate Radar present
1500 * in HDD context for future usage.
1501 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301502 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001503 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301504bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505{
1506 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1507 struct wma_dfs_radar_ind *hdd_radar_event =
1508 (struct wma_dfs_radar_ind *)param;
1509 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1510 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301511 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301512 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001513
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301514 if (!hdd_ctx || !hdd_radar_event ||
1515 hdd_ctx->config->disableDFSChSwitch)
1516 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001517
1518 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001519 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301520 /*
1521 * Application already triggered channel switch
1522 * on current channel, so return here.
1523 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301524 return false;
1525 }
1526
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001527 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301528 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301530 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1531 if ((QDF_SAP_MODE == adapter->device_mode ||
1532 QDF_P2P_GO_MODE == adapter->device_mode) &&
1533 (CHANNEL_STATE_DFS ==
1534 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1536 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301537 hdd_info("tx blocked for session:%d",
1538 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 }
1540
1541 status = hdd_get_next_adapter(hdd_ctx,
1542 adapterNode,
1543 &pNext);
1544 adapterNode = pNext;
1545 }
1546 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301547
1548 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001550
1551/**
1552 * hdd_is_valid_mac_address() - validate MAC address
1553 * @pMacAddr: Pointer to the input MAC address
1554 *
1555 * This function validates whether the given MAC address is valid or not
1556 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1557 * where X is the hexa decimal digit character and separated by ':'
1558 * This algorithm works even if MAC address is not separated by ':'
1559 *
1560 * This code checks given input string mac contains exactly 12 hexadecimal
1561 * digits and a separator colon : appears in the input string only after
1562 * an even number of hex digits.
1563 *
1564 * Return: 1 for valid and 0 for invalid
1565 */
1566bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1567{
1568 int xdigit = 0;
1569 int separator = 0;
1570 while (*pMacAddr) {
1571 if (isxdigit(*pMacAddr)) {
1572 xdigit++;
1573 } else if (':' == *pMacAddr) {
1574 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1575 break;
1576
1577 ++separator;
1578 } else {
1579 /* Invalid MAC found */
1580 return 0;
1581 }
1582 ++pMacAddr;
1583 }
1584 return xdigit == 12 && (separator == 5 || separator == 0);
1585}
1586
1587/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301588 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1589 * @dev: Handle to struct net_device to be updated.
1590 *
1591 * Return: None
1592 */
1593static void hdd_mon_mode_ether_setup(struct net_device *dev)
1594{
1595 dev->header_ops = NULL;
1596 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1597 dev->hard_header_len = ETH_HLEN;
1598 dev->mtu = ETH_DATA_LEN;
1599 dev->addr_len = ETH_ALEN;
1600 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1601 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1602 dev->priv_flags |= IFF_TX_SKB_SHARING;
1603
1604 memset(dev->broadcast, 0xFF, ETH_ALEN);
1605}
1606
1607/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001608 * __hdd__mon_open() - HDD Open function
1609 * @dev: Pointer to net_device structure
1610 *
1611 * This is called in response to ifconfig up
1612 *
1613 * Return: 0 for success; non-zero for failure
1614 */
1615static int __hdd_mon_open(struct net_device *dev)
1616{
1617 int ret;
1618
1619 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301620 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001621 ret = hdd_set_mon_rx_cb(dev);
1622 return ret;
1623}
1624
1625/**
1626 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1627 * @dev: Pointer to net_device structure
1628 *
1629 * This is called in response to ifconfig up
1630 *
1631 * Return: 0 for success; non-zero for failure
1632 */
1633int hdd_mon_open(struct net_device *dev)
1634{
1635 int ret;
1636
1637 cds_ssr_protect(__func__);
1638 ret = __hdd_mon_open(dev);
1639 cds_ssr_unprotect(__func__);
1640
1641 return ret;
1642}
1643
1644/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301645 * hdd_start_adapter() - Wrapper function for device specific adapter
1646 * @adapter: pointer to HDD adapter
1647 *
1648 * This function is called to start the device specific adapter for
1649 * the mode passed in the adapter's device_mode.
1650 *
1651 * Return: 0 for success; non-zero for failure
1652 */
1653int hdd_start_adapter(hdd_adapter_t *adapter)
1654{
1655
1656 int ret;
1657 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1658
1659 ENTER_DEV(adapter->dev);
1660 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1661
1662 switch (device_mode) {
1663 case QDF_P2P_CLIENT_MODE:
1664 case QDF_P2P_DEVICE_MODE:
1665 case QDF_OCB_MODE:
1666 case QDF_STA_MODE:
1667 case QDF_MONITOR_MODE:
1668 ret = hdd_start_station_adapter(adapter);
1669 if (ret)
1670 goto err_start_adapter;
1671 break;
1672 case QDF_P2P_GO_MODE:
1673 case QDF_SAP_MODE:
1674 ret = hdd_start_ap_adapter(adapter);
1675 if (ret)
1676 goto err_start_adapter;
1677 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301678 case QDF_IBSS_MODE:
1679 /*
1680 * For IBSS interface is initialized as part of
1681 * hdd_init_station_mode()
1682 */
1683 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301684 case QDF_FTM_MODE:
1685 ret = hdd_start_ftm_adapter(adapter);
1686 if (ret)
1687 goto err_start_adapter;
1688 break;
1689 default:
1690 hdd_err("Invalid session type %d", device_mode);
1691 QDF_ASSERT(0);
1692 goto err_start_adapter;
1693 }
1694 if (hdd_set_fw_params(adapter))
1695 hdd_err("Failed to set the FW params for the adapter!");
1696
1697 /*
1698 * Action frame registered in one adapter which will
1699 * applicable to all interfaces
1700 */
1701 wlan_hdd_cfg80211_register_frames(adapter);
1702 EXIT();
1703 return 0;
1704err_start_adapter:
1705 return -EINVAL;
1706}
1707
1708/**
1709 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1710 * @hdd_ctx: HDD context
1711 * @adapter: HDD adapter
1712 * @reinit: flag to indicate from SSR or normal path
1713 *
1714 * This function maintains the driver state machine it will be invoked from
1715 * startup, reinit and change interface. Depending on the driver state shall
1716 * perform the opening of the modules.
1717 *
1718 * Return: 0 for success; non-zero for failure
1719 */
1720int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1721 bool reinit)
1722{
1723 int ret;
1724 qdf_device_t qdf_dev;
1725 QDF_STATUS status;
1726 p_cds_contextType p_cds_context;
1727 bool unint = false;
1728 void *hif_ctx;
1729
1730 ENTER();
1731
1732 p_cds_context = cds_get_global_context();
1733 if (!p_cds_context) {
1734 hdd_err("Global Context is NULL");
1735 QDF_ASSERT(0);
1736 return -EINVAL;
1737 }
1738
1739 hdd_info("start modules called in state! :%d reinit: %d",
1740 hdd_ctx->driver_status, reinit);
1741
1742 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1743 if (!qdf_dev) {
1744 hdd_err("QDF Device Context is Invalid return");
1745 return -EINVAL;
1746 }
1747
1748 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301749 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301750
1751 if (QDF_TIMER_STATE_RUNNING ==
1752 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1753
1754 hdd_set_idle_ps_config(hdd_ctx, false);
1755 hdd_info("Interface change Timer running Stop timer");
1756 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1757 }
1758
1759 switch (hdd_ctx->driver_status) {
1760 case DRIVER_MODULES_UNINITIALIZED:
1761 unint = true;
1762 /* Fall through dont add break here */
1763 case DRIVER_MODULES_CLOSED:
1764 if (!reinit && !unint) {
1765 ret = pld_power_on(qdf_dev->dev);
1766 if (ret) {
1767 hdd_err("Failed to Powerup the device: %d", ret);
1768 goto release_lock;
1769 }
1770 }
1771 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1772 qdf_dev->bus_type,
1773 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1774 HIF_ENABLE_TYPE_PROBE);
1775 if (ret) {
1776 hdd_err("Failed to open hif: %d", ret);
1777 goto power_down;
1778 }
1779
1780 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301781 if (!hif_ctx) {
1782 hdd_err("hif context is null!!");
1783 goto power_down;
1784 }
1785
Arun Khandavallifae92942016-08-01 13:31:08 +05301786 status = ol_cds_init(qdf_dev, hif_ctx);
1787 if (status != QDF_STATUS_SUCCESS) {
1788 hdd_err("No Memory to Create BMI Context :%d", status);
1789 goto hif_close;
1790 }
1791
Arun Khandavallif6246632016-08-17 17:43:06 +05301792 ret = hdd_update_config(hdd_ctx);
1793 if (ret) {
1794 hdd_err("Failed to update configuration :%d", ret);
1795 goto ol_cds_free;
1796 }
1797
Arun Khandavallifae92942016-08-01 13:31:08 +05301798 status = cds_open();
1799 if (!QDF_IS_STATUS_SUCCESS(status)) {
1800 hdd_err("Failed to Open CDS: %d", status);
1801 goto ol_cds_free;
1802 }
1803
1804 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1805
1806 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1807
1808 status = cds_pre_enable(hdd_ctx->pcds_context);
1809 if (!QDF_IS_STATUS_SUCCESS(status)) {
1810 hdd_err("Failed to pre-enable CDS: %d", status);
1811 goto close;
1812 }
1813
1814 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1815 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1816 hdd_ftm_mc_process_msg);
1817 break;
1818 }
1819 if (unint) {
1820 hdd_info("In phase-1 initialization don't enable modules");
1821 break;
1822 }
1823 /* Fall through dont add break here */
1824 case DRIVER_MODULES_OPENED:
1825 if (!adapter) {
1826 hdd_alert("adapter is Null");
1827 goto close;
1828 }
1829 if (hdd_configure_cds(hdd_ctx, adapter)) {
1830 hdd_err("Failed to Enable cds modules");
1831 goto close;
1832 }
1833 hdd_info("Driver Modules Successfully Enabled");
1834 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1835 break;
1836 case DRIVER_MODULES_ENABLED:
1837 hdd_info("Driver modules already Enabled");
1838 break;
1839 default:
1840 hdd_err("WLAN start invoked in wrong state! :%d\n",
1841 hdd_ctx->driver_status);
1842 goto release_lock;
1843 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301844 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301845 mutex_unlock(&hdd_ctx->iface_change_lock);
1846 EXIT();
1847 return 0;
1848
1849close:
1850 cds_close(p_cds_context);
1851
1852ol_cds_free:
1853 ol_cds_free();
1854
1855hif_close:
1856 hdd_hif_close(p_cds_context->pHIFContext);
1857power_down:
1858 if (!reinit && !unint)
1859 pld_power_off(qdf_dev->dev);
1860release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301861 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301862 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301863 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301864 return -EINVAL;
1865}
1866
1867/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 * __hdd_open() - HDD Open function
1869 * @dev: Pointer to net_device structure
1870 *
1871 * This is called in response to ifconfig up
1872 *
1873 * Return: 0 for success; non-zero for failure
1874 */
1875static int __hdd_open(struct net_device *dev)
1876{
1877 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1878 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1879 int ret;
1880
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001881 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301882 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301883 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884
1885 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301886 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301888
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889
Arun Khandavallifae92942016-08-01 13:31:08 +05301890 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1891 if (ret) {
1892 hdd_err("Failed to start WLAN modules return");
1893 return -ret;
1894 }
1895
1896
1897 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1898 ret = hdd_start_adapter(adapter);
1899 if (ret) {
1900 hdd_err("Failed to start adapter :%d",
1901 adapter->device_mode);
1902 return ret;
1903 }
1904 }
1905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1907 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301908 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 /* Enable TX queues only when we are connected */
1910 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301911 WLAN_START_ALL_NETIF_QUEUE,
1912 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 }
1914
1915 return ret;
1916}
1917
Arun Khandavallifae92942016-08-01 13:31:08 +05301918
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919/**
1920 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1921 * @dev: Pointer to net_device structure
1922 *
1923 * This is called in response to ifconfig up
1924 *
1925 * Return: 0 for success; non-zero for failure
1926 */
1927int hdd_open(struct net_device *dev)
1928{
1929 int ret;
1930
1931 cds_ssr_protect(__func__);
1932 ret = __hdd_open(dev);
1933 cds_ssr_unprotect(__func__);
1934
1935 return ret;
1936}
1937
1938/**
1939 * __hdd_stop() - HDD stop function
1940 * @dev: Pointer to net_device structure
1941 *
1942 * This is called in response to ifconfig down
1943 *
1944 * Return: 0 for success; non-zero for failure
1945 */
1946static int __hdd_stop(struct net_device *dev)
1947{
1948 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1949 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301950 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301952 bool close_modules = true;
1953 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001955 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301957 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958 adapter->sessionId, adapter->device_mode));
1959
1960 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301961 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963
1964 /* Nothing to be done if the interface is not opened */
1965 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001966 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001967 return -ENODEV;
1968 }
1969
1970 /* Make sure the interface is marked as closed */
1971 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001972 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973
1974 /*
1975 * Disable TX on the interface, after this hard_start_xmit() will not
1976 * be called on that interface
1977 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001978 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1980 WLAN_CONTROL_PATH);
1981
1982 /*
1983 * The interface is marked as down for outside world (aka kernel)
1984 * But the driver is pretty much alive inside. The driver needs to
1985 * tear down the existing connection on the netdev (session)
1986 * cleanup the data pipes and wait until the control plane is stabilized
1987 * for this interface. The call also needs to wait until the above
1988 * mentioned actions are completed before returning to the caller.
1989 * Notice that the hdd_stop_adapter is requested not to close the session
1990 * That is intentional to be able to scan if it is a STA/P2P interface
1991 */
Arun Khandavallifae92942016-08-01 13:31:08 +05301992 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993
1994 /* DeInit the adapter. This ensures datapath cleanup as well */
1995 hdd_deinit_adapter(hdd_ctx, adapter, true);
1996
Arun Khandavallifae92942016-08-01 13:31:08 +05301997
1998 /*
1999 * Find if any iface is up. If any iface is up then can't put device to
2000 * sleep/power save mode
2001 */
2002 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2003 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2004 if (test_bit(DEVICE_IFACE_OPENED,
2005 &adapternode->pAdapter->event_flags)) {
2006 hdd_info("Still other ifaces are up cannot close modules");
2007 close_modules = false;
2008 break;
2009 }
2010 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2011 adapternode = next;
2012
2013 }
2014
2015 if (close_modules) {
2016 hdd_info("Closing all modules from the hdd_stop");
2017 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2018 hdd_ctx->config->iface_change_wait_time
2019 * 50000);
2020 }
2021
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022 EXIT();
2023 return 0;
2024}
2025
2026/**
2027 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2028 * @dev: pointer to net_device structure
2029 *
2030 * This is called in response to ifconfig down
2031 *
2032 * Return: 0 for success and error number for failure
2033 */
2034int hdd_stop(struct net_device *dev)
2035{
2036 int ret;
2037
2038 cds_ssr_protect(__func__);
2039 ret = __hdd_stop(dev);
2040 cds_ssr_unprotect(__func__);
2041
2042 return ret;
2043}
2044
2045/**
2046 * __hdd_uninit() - HDD uninit function
2047 * @dev: Pointer to net_device structure
2048 *
2049 * This is called during the netdev unregister to uninitialize all data
2050 * associated with the device
2051 *
2052 * Return: None
2053 */
2054static void __hdd_uninit(struct net_device *dev)
2055{
2056 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2057
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002058 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059
2060 do {
2061 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002062 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 break;
2064 }
2065
2066 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002067 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068 break;
2069 }
2070
2071 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002072 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002073 /*
2074 * we haven't validated all cases so let this go for
2075 * now
2076 */
2077 }
2078
2079 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2080
2081 /* after uninit our adapter structure will no longer be valid */
2082 adapter->dev = NULL;
2083 adapter->magic = 0;
2084 } while (0);
2085
2086 EXIT();
2087}
2088
2089/**
2090 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2091 * @dev: pointer to net_device structure
2092 *
2093 * This is called during the netdev unregister to uninitialize all data
2094 * associated with the device
2095 *
2096 * Return: none
2097 */
2098static void hdd_uninit(struct net_device *dev)
2099{
2100 cds_ssr_protect(__func__);
2101 __hdd_uninit(dev);
2102 cds_ssr_unprotect(__func__);
2103}
2104
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002105static int hdd_open_cesium_nl_sock(void)
2106{
2107#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2108 struct netlink_kernel_cfg cfg = {
2109 .groups = WLAN_NLINK_MCAST_GRP_ID,
2110 .input = NULL
2111 };
2112#endif
2113 int ret = 0;
2114
2115#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2116 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2117#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2118 THIS_MODULE,
2119#endif
2120 &cfg);
2121#else
2122 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2123 WLAN_NLINK_MCAST_GRP_ID,
2124 NULL, NULL, THIS_MODULE);
2125#endif
2126
2127 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002128 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002129 ret = -ECONNREFUSED;
2130 }
2131
2132 return ret;
2133}
2134
2135static void hdd_close_cesium_nl_sock(void)
2136{
2137 if (NULL != cesium_nl_srv_sock) {
2138 netlink_kernel_release(cesium_nl_srv_sock);
2139 cesium_nl_srv_sock = NULL;
2140 }
2141}
2142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143/**
2144 * __hdd_set_mac_address() - set the user specified mac address
2145 * @dev: Pointer to the net device.
2146 * @addr: Pointer to the sockaddr.
2147 *
2148 * This function sets the user specified mac address using
2149 * the command ifconfig wlanX hw ether <mac adress>.
2150 *
2151 * Return: 0 for success, non zero for failure
2152 */
2153static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2154{
2155 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2156 hdd_context_t *hdd_ctx;
2157 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302158 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002159 int ret;
2160
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002161 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162
2163 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2164 ret = wlan_hdd_validate_context(hdd_ctx);
2165 if (0 != ret)
2166 return ret;
2167
2168 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2169 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2170
2171 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302172 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173}
2174
2175/**
2176 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2177 * function from SSR
2178 * @dev: pointer to net_device structure
2179 * @addr: Pointer to the sockaddr
2180 *
2181 * This function sets the user specified mac address using
2182 * the command ifconfig wlanX hw ether <mac adress>.
2183 *
2184 * Return: 0 for success.
2185 */
2186static int hdd_set_mac_address(struct net_device *dev, void *addr)
2187{
2188 int ret;
2189
2190 cds_ssr_protect(__func__);
2191 ret = __hdd_set_mac_address(dev, addr);
2192 cds_ssr_unprotect(__func__);
2193
2194 return ret;
2195}
2196
2197uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2198{
2199 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302200 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2202 break;
2203 }
2204
Anurag Chouhan6d760662016-02-20 16:05:43 +05302205 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 return NULL;
2207
2208 hdd_ctx->config->intfAddrMask |= (1 << i);
2209 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2210}
2211
2212void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2213{
2214 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302215 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216 if (!memcmp(releaseAddr,
2217 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2218 6)) {
2219 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2220 break;
2221 }
2222 }
2223 return;
2224}
2225
2226#ifdef WLAN_FEATURE_PACKET_FILTERING
2227/**
2228 * __hdd_set_multicast_list() - set the multicast address list
2229 * @dev: Pointer to the WLAN device.
2230 * @skb: Pointer to OS packet (sk_buff).
2231 *
2232 * This funciton sets the multicast address list.
2233 *
2234 * Return: None
2235 */
2236static void __hdd_set_multicast_list(struct net_device *dev)
2237{
2238 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2239 int mc_count;
2240 int i = 0, status;
2241 struct netdev_hw_addr *ha;
2242 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2243 static const uint8_t ipv6_router_solicitation[]
2244 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2245
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002246 ENTER_DEV(dev);
2247
Anurag Chouhan6d760662016-02-20 16:05:43 +05302248 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302249 return;
2250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302252 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254
2255 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002256 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257 adapter->mc_addr_list.mc_cnt = 0;
2258 } else {
2259 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302260 hdd_notice("mc_count : %u", mc_count);
2261
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Dustin Brown61269462016-09-19 13:25:45 -07002263 hdd_notice("Exceeded max MC filter addresses (%d). Allowing all MC frames by disabling MC address filtering",
2264 WLAN_HDD_MAX_MC_ADDR_LIST);
2265 wlan_hdd_set_mc_addr_list(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002266 adapter->mc_addr_list.mc_cnt = 0;
2267 return;
2268 }
2269
2270 adapter->mc_addr_list.mc_cnt = mc_count;
2271
2272 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302273 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2274 i, MAC_ADDR_ARRAY(ha->addr));
2275
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276 if (i == mc_count)
2277 break;
2278 /*
2279 * Skip following addresses:
2280 * 1)IPv6 router solicitation address
2281 * 2)Any other address pattern if its set during
2282 * RXFILTER REMOVE driver command based on
2283 * addr_filter_pattern
2284 */
2285 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2286 ETH_ALEN)) ||
2287 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2288 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002289 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290 MAC_ADDR_ARRAY(ha->addr));
2291 adapter->mc_addr_list.mc_cnt--;
2292 continue;
2293 }
2294
2295 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2296 ETH_ALEN);
2297 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2298 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002299 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2301 i++;
2302 }
2303 }
2304 if (hdd_ctx->config->active_mode_offload) {
2305 hdd_info("enable mc filtering");
2306 wlan_hdd_set_mc_addr_list(adapter, true);
2307 } else {
2308 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2309 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302310 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 return;
2312}
2313
2314/**
2315 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2316 * @dev: pointer to net_device
2317 *
2318 * Return: none
2319 */
2320static void hdd_set_multicast_list(struct net_device *dev)
2321{
2322 cds_ssr_protect(__func__);
2323 __hdd_set_multicast_list(dev);
2324 cds_ssr_unprotect(__func__);
2325}
2326#endif
2327
2328/**
2329 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2330 * @dev: Pointer to the WLAN device.
2331 * @skb: Pointer to OS packet (sk_buff).
2332 *
2333 * This function is registered with the Linux OS for network
2334 * core to decide which queue to use first.
2335 *
2336 * Return: ac, Queue Index/access category corresponding to UP in IP header
2337 */
2338static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2339#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2340 , void *accel_priv
2341#endif
2342#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2343 , select_queue_fallback_t fallback
2344#endif
2345)
2346{
2347 return hdd_wmm_select_queue(dev, skb);
2348}
2349
2350static struct net_device_ops wlan_drv_ops = {
2351 .ndo_open = hdd_open,
2352 .ndo_stop = hdd_stop,
2353 .ndo_uninit = hdd_uninit,
2354 .ndo_start_xmit = hdd_hard_start_xmit,
2355 .ndo_tx_timeout = hdd_tx_timeout,
2356 .ndo_get_stats = hdd_get_stats,
2357 .ndo_do_ioctl = hdd_ioctl,
2358 .ndo_set_mac_address = hdd_set_mac_address,
2359 .ndo_select_queue = hdd_select_queue,
2360#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362#endif
2363};
2364
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002365/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2366static struct net_device_ops wlan_mon_drv_ops = {
2367 .ndo_open = hdd_mon_open,
2368 .ndo_stop = hdd_stop,
2369 .ndo_get_stats = hdd_get_stats,
2370};
2371
2372/**
2373 * hdd_set_station_ops() - update net_device ops for monitor mode
2374 * @pWlanDev: Handle to struct net_device to be updated.
2375 * Return: None
2376 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377void hdd_set_station_ops(struct net_device *pWlanDev)
2378{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002379 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2380 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2381 else
2382 pWlanDev->netdev_ops = &wlan_drv_ops;
2383}
2384
2385/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002386 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2387 * @hdd_ctx: global hdd context
2388 * @macAddr: mac address to assign to the interface
2389 * @name: User-visible name of the interface
2390 *
2391 * hdd adapter pointer would point to the netdev->priv space, this function
2392 * would retrive the pointer, and setup the hdd adapter configuration.
2393 *
2394 * Return: the pointer to hdd adapter, otherwise NULL
2395 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2397 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002398 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002399 const char *name)
2400{
2401 struct net_device *pWlanDev = NULL;
2402 hdd_adapter_t *adapter = NULL;
2403 /*
2404 * cfg80211 initialization and registration....
2405 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002406 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2407#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2408 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002410 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2411 hdd_mon_mode_ether_setup : ether_setup),
2412 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413
2414 if (pWlanDev != NULL) {
2415
2416 /* Save the pointer to the net_device in the HDD adapter */
2417 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2418
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302419 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420
2421 adapter->dev = pWlanDev;
2422 adapter->pHddCtx = hdd_ctx;
2423 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302424 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425
2426 init_completion(&adapter->session_open_comp_var);
2427 init_completion(&adapter->session_close_comp_var);
2428 init_completion(&adapter->disconnect_comp_var);
2429 init_completion(&adapter->linkup_event_var);
2430 init_completion(&adapter->cancel_rem_on_chan_var);
2431 init_completion(&adapter->rem_on_chan_ready_event);
2432 init_completion(&adapter->sta_authorized_event);
2433 init_completion(&adapter->offchannel_tx_event);
2434 init_completion(&adapter->tx_action_cnf_event);
2435#ifdef FEATURE_WLAN_TDLS
2436 init_completion(&adapter->tdls_add_station_comp);
2437 init_completion(&adapter->tdls_del_station_comp);
2438 init_completion(&adapter->tdls_mgmt_comp);
2439 init_completion(&adapter->tdls_link_establish_req_comp);
2440#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002441 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 init_completion(&adapter->change_country_code);
2443
2444
2445 init_completion(&adapter->scan_info.abortscan_event_var);
2446
2447 adapter->offloads_configured = false;
2448 adapter->isLinkUpSvcNeeded = false;
2449 adapter->higherDtimTransition = true;
2450 /* Init the net_device structure */
2451 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2452
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302453 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302455 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 sizeof(tSirMacAddr));
2457 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458
2459 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2460 pWlanDev->features |=
2461 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2462 pWlanDev->features |= NETIF_F_RXCSUM;
2463
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002464 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 hdd_set_station_ops(adapter->dev);
2467
2468 pWlanDev->destructor = free_netdev;
2469 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002470 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471 adapter->wdev.wiphy = hdd_ctx->wiphy;
2472 adapter->wdev.netdev = pWlanDev;
2473 /* set pWlanDev's parent to underlying device */
2474 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2475 hdd_wmm_init(adapter);
2476 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302477 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 }
2479
2480 return adapter;
2481}
2482
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302483QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002484 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485{
2486 struct net_device *pWlanDev = adapter->dev;
2487 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
2488 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302489 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002491 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002492 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2493 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002494 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302495 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 }
2497 }
2498 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002499 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302500 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501 }
2502 } else {
2503 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002504 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302505 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 }
2507 }
2508 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302510 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511}
2512
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002513QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514{
2515 hdd_adapter_t *adapter = pContext;
2516
2517 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002518 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302519 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 }
2521
2522 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002523 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302524 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525 }
2526
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002527 /*
2528 * For NAN Data interface, the close session results in the final
2529 * indication to the userspace
2530 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002531 if (adapter->device_mode == QDF_NDI_MODE)
2532 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002533
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 /*
2537 * We can be blocked while waiting for scheduled work to be
2538 * flushed, and the adapter structure can potentially be freed, in
2539 * which case the magic will have been reset. So make sure the
2540 * magic is still good, and hence the adapter structure is still
2541 * valid, before signaling completion
2542 */
2543 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2544 complete(&adapter->session_close_comp_var);
2545
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302546 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547}
2548
Krunal Soni8c37e322016-02-03 16:08:37 -08002549/**
2550 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2551 * @adapter: pointer to device adapter
2552 * @type: type of interface
2553 *
2554 * This routine will check the mode of adapter and if it is required then it
2555 * will initialize the TDLS operations
2556 *
2557 * Return: QDF_STATUS
2558 */
2559#ifdef FEATURE_WLAN_TDLS
2560static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2561{
2562 if (QDF_IBSS_MODE != type) {
2563 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002564 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002565 return QDF_STATUS_E_FAILURE;
2566 }
2567 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2568 }
2569 return QDF_STATUS_SUCCESS;
2570}
2571#else
2572static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2573{
2574 return QDF_STATUS_SUCCESS;
2575}
2576#endif
2577
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302578QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579{
2580 struct net_device *pWlanDev = adapter->dev;
2581 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2582 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302583 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302584 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585 uint32_t type, subType;
2586 unsigned long rc;
2587 int ret_val;
2588
2589 INIT_COMPLETION(adapter->session_open_comp_var);
2590 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002591 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302593 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002594 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 goto error_sme_open;
2596 }
2597 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302598 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2600 (uint8_t *) &adapter->macAddressCurrent,
2601 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302602 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002603 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302604 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302605 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 goto error_sme_open;
2607 }
2608 /* Block on a completion variable. Can't wait forever though. */
2609 rc = wait_for_completion_timeout(
2610 &adapter->session_open_comp_var,
2611 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2612 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002613 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302615 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002616 goto error_sme_open;
2617 }
2618
Naveen Rawata410c5a2016-09-19 14:22:33 -07002619 sme_set_vdev_ies_per_band(hdd_ctx->hHal, adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302621 qdf_ret_status = hdd_register_wext(pWlanDev);
2622 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002623 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302624 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302625 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 goto error_register_wext;
2627 }
2628 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002629 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2631
2632 /* Set the default operation channel */
2633 pHddStaCtx->conn_info.operationChannel =
2634 hdd_ctx->config->OperatingChannel;
2635
2636 /* Make the default Auth Type as OPEN */
2637 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2638
2639 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302640 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002641 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002642 status, status);
2643 goto error_init_txrx;
2644 }
2645
2646 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2647
2648 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302649 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002650 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651 status, status);
2652 goto error_wmm_init;
2653 }
2654
2655 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2656
2657 ret_val = wma_cli_set_command(adapter->sessionId,
2658 WMI_PDEV_PARAM_BURST_ENABLE,
2659 hdd_ctx->config->enableSifsBurst,
2660 PDEV_CMD);
2661
2662 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002663 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 ret_val);
2665 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002666 status = hdd_check_and_init_tdls(adapter, type);
2667 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302670 status = hdd_lro_enable(hdd_ctx, adapter);
2671 if (status != QDF_STATUS_SUCCESS)
2672 goto error_lro_enable;
2673
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302674 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302676error_lro_enable:
2677 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678error_tdls_init:
2679 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2680 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681error_wmm_init:
2682 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2683 hdd_deinit_tx_rx(adapter);
2684error_init_txrx:
2685 hdd_unregister_wext(pWlanDev);
2686error_register_wext:
2687 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2688 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302689 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690 adapter->sessionId,
2691 hdd_sme_close_session_callback,
2692 adapter)) {
2693 unsigned long rc;
2694
2695 /*
2696 * Block on a completion variable.
2697 * Can't wait forever though.
2698 */
2699 rc = wait_for_completion_timeout(
2700 &adapter->session_close_comp_var,
2701 msecs_to_jiffies
2702 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2703 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002704 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 rc);
2706 }
2707 }
2708error_sme_open:
2709 return status;
2710}
2711
2712void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2713{
2714 hdd_cfg80211_state_t *cfgState;
2715
2716 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2717
2718 if (NULL != cfgState->buf) {
2719 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 rc = wait_for_completion_timeout(
2721 &adapter->tx_action_cnf_event,
2722 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2723 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002724 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302725 /*
2726 * Inform tx status as FAILURE to upper layer and free
2727 * cfgState->buf
2728 */
2729 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730 }
2731 }
2732 return;
2733}
2734
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302735/**
2736 * hdd_station_adapter_deinit() - De-initialize the station adapter
2737 * @hdd_ctx: global hdd context
2738 * @adapter: HDD adapter
2739 *
2740 * This function De-initializes the STA/P2P/OCB adapter.
2741 *
2742 * Return: None.
2743 */
2744void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302745 hdd_adapter_t *adapter,
2746 bool rtnl_held)
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302747{
2748 ENTER_DEV(adapter->dev);
2749
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302750 if (adapter->dev) {
2751 if (rtnl_held)
2752 adapter->dev->wireless_handlers = NULL;
2753 else {
2754 rtnl_lock();
2755 adapter->dev->wireless_handlers = NULL;
2756 rtnl_unlock();
2757 }
2758 }
2759
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302760 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2761 hdd_deinit_tx_rx(adapter);
2762 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2763 }
2764
2765 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2766 hdd_wmm_adapter_close(adapter);
2767 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2768 }
2769
2770 hdd_cleanup_actionframe(hdd_ctx, adapter);
2771 wlan_hdd_tdls_exit(adapter);
2772
2773 EXIT();
2774}
2775
2776/**
2777 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2778 * @hdd_ctx: global hdd context
2779 * @adapter: HDD adapter
2780 * @rtnl_held: the rtnl lock hold flag
2781 * This function De-initializes the AP/P2PGo adapter.
2782 *
2783 * Return: None.
2784 */
2785void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2786 bool rtnl_held)
2787{
2788 ENTER_DEV(adapter->dev);
2789
2790 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2791 hdd_wmm_adapter_close(adapter);
2792 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2793 }
2794
2795 hdd_cleanup_actionframe(hdd_ctx, adapter);
2796
2797 hdd_unregister_hostapd(adapter, rtnl_held);
2798
2799 EXIT();
2800}
2801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002802void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2803 bool rtnl_held)
2804{
2805 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002808 case QDF_STA_MODE:
2809 case QDF_P2P_CLIENT_MODE:
2810 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 {
Hanumanth Reddy Pothula7a657402016-09-07 20:59:18 +05302812 hdd_station_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 break;
2814 }
2815
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002816 case QDF_SAP_MODE:
2817 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818 {
2819
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302820 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 break;
2822 }
2823
2824 default:
2825 break;
2826 }
2827
2828 EXIT();
2829}
2830
2831void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002832 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833{
2834 struct net_device *pWlanDev = NULL;
2835
2836 if (adapter)
2837 pWlanDev = adapter->dev;
2838 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002839 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 return;
2841 }
2842
Rajeev Kumardca5f812016-02-04 17:28:06 -08002843 hdd_debugfs_exit(adapter);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05302844
2845 if (adapter->scan_info.default_scan_ies) {
2846 qdf_mem_free(adapter->scan_info.default_scan_ies);
2847 adapter->scan_info.default_scan_ies = NULL;
2848 }
2849
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002850 /*
2851 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2852 * the driver is almost closed and cannot handle either control
2853 * messages or data. However, unregister_netdevice() call above will
2854 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2855 * to close the active connections (basically excites control path) which
2856 * is not right. Setting this flag helps hdd_stop() to recognize that
2857 * the interface is closed and restricts any operations on that
2858 */
2859 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2860
2861 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2862 if (rtnl_held) {
2863 unregister_netdevice(pWlanDev);
2864 } else {
2865 unregister_netdev(pWlanDev);
2866 }
2867 /*
2868 * Note that the adapter is no longer valid at this point
2869 * since the memory has been reclaimed
2870 */
2871 }
2872}
2873
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302874QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002875 tSirMacAddr macAddr)
2876{
2877 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2878 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302879 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302881 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882 adapter = adapterNode->pAdapter;
2883 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302884 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302886 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 }
2888 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2889 adapterNode = pNext;
2890 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302891 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002893
Arun Khandavalli2358d522016-05-16 18:05:37 +05302894#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2895/**
2896 * hdd_set_fw_log_params() - Set log parameters to FW
2897 * @hdd_ctx: HDD Context
2898 * @adapter: HDD Adapter
2899 *
2900 * This function set the FW Debug log level based on the INI.
2901 *
2902 * Return: None
2903 */
2904static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2905 hdd_adapter_t *adapter)
2906{
2907 uint8_t count = 0, numentries = 0,
2908 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2909 uint32_t value = 0;
2910 int ret;
2911
Arun Khandavallifae92942016-08-01 13:31:08 +05302912 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
2913 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302914 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
2915 return;
2916 }
2917
Arun Khandavallifae92942016-08-01 13:31:08 +05302918 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05302919 hdd_ctx->fw_log_settings.dl_type =
2920 hdd_ctx->config->enableFwLogType;
2921 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302922 WMI_DBGLOG_TYPE,
2923 hdd_ctx->config->enableFwLogType,
2924 DBG_CMD);
2925 if (ret != 0)
2926 hdd_err("Failed to enable FW log type ret %d",
2927 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302928
2929 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05302930 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05302931 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302932 WMI_DBGLOG_LOG_LEVEL,
2933 hdd_ctx->config->enableFwLogLevel,
2934 DBG_CMD);
2935 if (ret != 0)
2936 hdd_err("Failed to enable FW log level ret %d",
2937 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302938
2939 hdd_string_to_u8_array(
2940 hdd_ctx->config->enableFwModuleLogLevel,
2941 moduleloglevel,
2942 &numentries,
2943 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2944
2945 while (count < numentries) {
2946 /*
2947 * FW module log level input string looks like
2948 * below:
2949 * gFwDebugModuleLoglevel=<FW Module ID>,
2950 * <Log Level>,...
2951 * For example:
2952 * gFwDebugModuleLoglevel=
2953 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
2954 * Above input string means :
2955 * For FW module ID 1 enable log level 0
2956 * For FW module ID 2 enable log level 1
2957 * For FW module ID 3 enable log level 2
2958 * For FW module ID 4 enable log level 3
2959 * For FW module ID 5 enable log level 4
2960 * For FW module ID 6 enable log level 5
2961 * For FW module ID 7 enable log level 6
2962 */
2963
Arun Khandavallifae92942016-08-01 13:31:08 +05302964 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05302965 * Module ID * 10 + Module Log level
2966 */
2967 value = ((moduleloglevel[count] * 10) +
2968 moduleloglevel[count + 1]);
2969 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302970 WMI_DBGLOG_MOD_LOG_LEVEL,
2971 value, DBG_CMD);
2972 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05302973 hdd_err("Failed to enable FW module log level %d ret %d",
2974 value, ret);
2975
2976 count += 2;
2977 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302978
Arun Khandavalli2358d522016-05-16 18:05:37 +05302979}
2980#else
2981static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2982 hdd_adapter_t *adapter)
2983{
2984}
2985
2986#endif
2987
2988/**
2989 * hdd_set_fw_params() - Set parameters to firmware
2990 * @adapter: HDD adapter
2991 *
2992 * This function Sets various parameters to fw once the
2993 * adapter is started.
2994 *
2995 * Return: 0 on success or errno on failure
2996 */
2997int hdd_set_fw_params(hdd_adapter_t *adapter)
2998{
2999 int ret;
3000 hdd_context_t *hdd_ctx;
3001
3002 ENTER_DEV(adapter->dev);
3003
3004 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
3005 if (!hdd_ctx)
3006 return -EINVAL;
3007
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003008 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05303009 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05303010#define HDD_DTIM_1CHAIN_RX_ID 0x5
3011#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003012 /*
3013 * Disable DTIM 1 chain Rx when in 1x1,
3014 * we are passing two value
3015 * as param_id << 29 | param_value.
3016 * Below param_value = 0(disable)
3017 */
3018 ret = wma_cli_set_command(adapter->sessionId,
3019 WMI_STA_SMPS_PARAM_CMDID,
3020 HDD_DTIM_1CHAIN_RX_ID <<
3021 HDD_SMPS_PARAM_VALUE_S,
3022 VDEV_CMD);
3023 if (ret) {
3024 hdd_err("DTIM 1 chain set failed %d", ret);
3025 goto error;
3026 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303027
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003028 ret = wma_cli_set_command(adapter->sessionId,
3029 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3030 hdd_ctx->config->txchainmask1x1,
3031 PDEV_CMD);
3032 if (ret) {
3033 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3034 ret);
3035 goto error;
3036 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303037
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003038 ret = wma_cli_set_command(adapter->sessionId,
3039 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3040 hdd_ctx->config->rxchainmask1x1,
3041 PDEV_CMD);
3042 if (ret) {
3043 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3044 ret);
3045 goto error;
3046 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303047#undef HDD_DTIM_1CHAIN_RX_ID
3048#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003049 } else {
3050 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3051 }
3052
Arun Khandavallifae92942016-08-01 13:31:08 +05303053 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3054 ret = wma_cli_set_command(adapter->sessionId,
3055 WMI_PDEV_PARAM_HYST_EN,
3056 hdd_ctx->config->enableMemDeepSleep,
3057 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303058
Arun Khandavallifae92942016-08-01 13:31:08 +05303059 if (ret) {
3060 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3061 ret);
3062 goto error;
3063 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303064 }
3065
3066 hdd_set_fw_log_params(hdd_ctx, adapter);
3067
3068 EXIT();
3069 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303070
Arun Khandavalli2358d522016-05-16 18:05:37 +05303071error:
3072 return -EINVAL;
3073}
3074
Ryan Hsu07495ea2016-01-21 15:25:39 -08003075/**
3076 * hdd_open_adapter() - open and setup the hdd adatper
3077 * @hdd_ctx: global hdd context
3078 * @session_type: type of the interface to be created
3079 * @iface_name: User-visible name of the interface
3080 * @macAddr: MAC address to assign to the interface
3081 * @name_assign_type: the name of assign type of the netdev
3082 * @rtnl_held: the rtnl lock hold flag
3083 *
3084 * This function open and setup the hdd adpater according to the device
3085 * type request, assign the name, the mac address assigned, and then prepared
3086 * the hdd related parameters, queue, lock and ready to start.
3087 *
3088 * Return: the pointer of hdd adapter, otherwise NULL.
3089 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3091 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003092 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003093 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003094{
3095 hdd_adapter_t *adapter = NULL;
3096 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303097 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099
Arun Khandavallifae92942016-08-01 13:31:08 +05303100 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101
3102 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3103 /*
3104 * Max limit reached on the number of vdevs configured by the
3105 * host. Return error
3106 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303107 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3108 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 return NULL;
3110 }
3111
3112 if (macAddr == NULL) {
3113 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303114 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 return NULL;
3116 }
3117 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303118 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303119 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3120 " already exists",
3121 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122 return NULL;
3123 }
3124
3125 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003126 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003127 /* Reset locally administered bit if the device mode is STA */
3128 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3129 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003130 case QDF_P2P_CLIENT_MODE:
3131 case QDF_P2P_DEVICE_MODE:
3132 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003133 case QDF_NDI_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003134 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3135 name_assign_type,
3136 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137
3138 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303139 hdd_err("failed to allocate adapter for session %d",
3140 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 return NULL;
3142 }
3143
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003144 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003146 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003147 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 else
3149 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3150
3151 adapter->device_mode = session_type;
3152
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303153 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003154 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303155 if (QDF_STATUS_SUCCESS != status)
3156 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303157 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 /*
3160 * Workqueue which gets scheduled in IPv4 notification
3161 * callback
3162 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3164 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165
3166#ifdef WLAN_NS_OFFLOAD
3167 /*
3168 * Workqueue which gets scheduled in IPv6
3169 * notification callback.
3170 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3172 hdd_ipv6_notifier_work_queue);
3173#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303175 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3177 goto err_lro_cleanup;
3178 }
3179
3180 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303181 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303183 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3184 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003188 case QDF_P2P_GO_MODE:
3189 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003190 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3191 name_assign_type,
3192 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303194 hdd_alert("failed to allocate adapter for session %d",
3195 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 return NULL;
3197 }
3198
3199 adapter->wdev.iftype =
3200 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003201 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 NL80211_IFTYPE_P2P_GO;
3203 adapter->device_mode = session_type;
3204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303206 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3208 goto err_free_netdev;
3209 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303210 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303212 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3213 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303216 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303217 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003218 return NULL;
3219 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220
3221 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3222 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3223
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303224 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 /* Add it to the hdd's session list. */
3226 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303227 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303229 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 } else {
3231 pHddAdapterNode->pAdapter = adapter;
3232 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3233 }
3234 }
3235
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303236 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 if (NULL != adapter) {
3238 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3239 adapter = NULL;
3240 }
3241 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303242 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 }
3244 return NULL;
3245 }
3246
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303247 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003248 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249
3250 /* Initialize the WoWL service */
3251 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003252 hdd_alert("hdd_init_wowl failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253 goto err_lro_cleanup;
3254 }
3255
3256 /* Adapter successfully added. Increment the vdev count */
3257 hdd_ctx->current_intf_count++;
3258
Jeff Johnson5880d792016-08-15 13:32:30 -07003259 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 hdd_ctx->current_intf_count);
3261
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003262 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 }
3264
Rajeev Kumardca5f812016-02-04 17:28:06 -08003265 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3266 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267
3268 return adapter;
3269
3270err_lro_cleanup:
3271 hdd_lro_disable(hdd_ctx, adapter);
3272err_free_netdev:
3273 free_netdev(adapter->dev);
3274 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
3275
3276 return NULL;
3277}
3278
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303279QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003280 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281{
3282 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303283 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284
3285 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303286 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003287 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288 status);
3289 return status;
3290 }
3291
3292 while (pCurrent->pAdapter != adapter) {
3293 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303294 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 break;
3296
3297 pCurrent = pNext;
3298 }
3299 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303300 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003301 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003302 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3303
3304 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303305 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 adapterNode = NULL;
3307
3308 /* Adapter removed. Decrement vdev count */
3309 if (hdd_ctx->current_intf_count != 0)
3310 hdd_ctx->current_intf_count--;
3311
3312 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303313 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303315 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316}
3317
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003318/**
3319 * hdd_close_all_adapters - Close all open adapters
3320 * @hdd_ctx: Hdd context
3321 * rtnl_held: True if RTNL lock held
3322 *
3323 * Close all open adapters.
3324 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303325 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003326 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303327QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328{
3329 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303330 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331
3332 ENTER();
3333
3334 do {
3335 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303336 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003338 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303339 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303341 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342
3343 EXIT();
3344
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303345 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346}
3347
3348void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3349{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303350 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 tSirUpdateIE updateIE;
3352 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003353 case QDF_STA_MODE:
3354 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355 {
3356 hdd_station_ctx_t *pHddStaCtx =
3357 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003358 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359 break;
3360 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003361 case QDF_SAP_MODE:
3362 case QDF_P2P_GO_MODE:
3363 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003365 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003366 break;
3367 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003368 case QDF_FTM_MODE:
3369 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003370 default:
3371 /*
3372 * wlan_hdd_reset_prob_rspies should not have been called
3373 * for these kind of devices
3374 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003375 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003376 pHostapdAdapter->device_mode);
3377 return;
3378 }
3379
Anurag Chouhanc5548422016-02-24 18:33:27 +05303380 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003381 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3382 updateIE.ieBufferlength = 0;
3383 updateIE.pAdditionIEBuffer = NULL;
3384 updateIE.append = true;
3385 updateIE.notify = false;
3386 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3387 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303388 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003389 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003390 }
3391}
3392
Peng Xu66162de2016-02-11 17:01:20 -08003393/**
3394 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3395 * @hdd_ctx: HDD context which is already NULL validated
3396 * @adapter: HDD adapter which is already NULL validated
3397 *
3398 * Close the SME session and wait for its completion, if needed.
3399 *
3400 * Return: None
3401 */
3402static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3403 hdd_adapter_t *adapter)
3404{
3405 unsigned long rc;
3406
3407 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3408 hdd_err("session is not opened:%d", adapter->sessionId);
3409 return;
3410 }
3411
3412 INIT_COMPLETION(adapter->session_close_comp_var);
3413 if (QDF_STATUS_SUCCESS ==
3414 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3415 hdd_sme_close_session_callback,
3416 adapter)) {
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05303417 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003418 /*
3419 * Block on a completion variable. Can't wait
3420 * forever though.
3421 */
3422 rc = wait_for_completion_timeout(
3423 &adapter->session_close_comp_var,
3424 msecs_to_jiffies
3425 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Sandeep Puligillaada72922016-09-29 19:31:21 -07003426 if (!rc) {
Peng Xu66162de2016-02-11 17:01:20 -08003427 hdd_err("failure waiting for session_close_comp_var");
Sandeep Puligillaada72922016-09-29 19:31:21 -07003428 if (adapter->device_mode == QDF_NDI_MODE)
3429 hdd_ndp_session_end_handler(adapter);
3430 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
3431 }
Peng Xu66162de2016-02-11 17:01:20 -08003432 }
3433}
3434
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303435QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 const bool bCloseSession)
3437{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303438 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003439 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3440 union iwreq_data wrqu;
3441 tSirUpdateIE updateIE;
3442 unsigned long rc;
Sachin Ahuja988fd102016-09-15 17:16:25 +05303443 hdd_scaninfo_t *scan_info = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003444
3445 ENTER();
3446
Sachin Ahuja988fd102016-09-15 17:16:25 +05303447 scan_info = &adapter->scan_info;
Jeff Johnson5880d792016-08-15 13:32:30 -07003448 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003449 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3450 WLAN_CONTROL_PATH);
3451 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003452 case QDF_STA_MODE:
3453 case QDF_P2P_CLIENT_MODE:
3454 case QDF_IBSS_MODE:
3455 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003456 case QDF_NDI_MODE:
3457 if ((QDF_NDI_MODE == adapter->device_mode) ||
3458 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3460 hdd_is_connecting(
3461 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003462 INIT_COMPLETION(adapter->disconnect_comp_var);
3463 /*
3464 * For NDI do not use pWextState from sta_ctx, if needed
3465 * extract from ndi_ctx.
3466 */
3467 if (QDF_NDI_MODE == adapter->device_mode)
3468 qdf_ret_status = sme_roam_disconnect(
3469 hdd_ctx->hHal,
3470 adapter->sessionId,
3471 eCSR_DISCONNECT_REASON_NDI_DELETE);
3472 else if (pWextState->roamProfile.BSSType ==
3473 eCSR_BSS_TYPE_START_IBSS)
3474 qdf_ret_status = sme_roam_disconnect(
3475 hdd_ctx->hHal,
3476 adapter->sessionId,
3477 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003478 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003479 qdf_ret_status = sme_roam_disconnect(
3480 hdd_ctx->hHal,
3481 adapter->sessionId,
3482 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303484 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485 rc = wait_for_completion_timeout(
3486 &adapter->disconnect_comp_var,
3487 msecs_to_jiffies
3488 (WLAN_WAIT_TIME_DISCONNECT));
3489 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003490 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 }
3492 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003493 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003494 }
3495 memset(&wrqu, '\0', sizeof(wrqu));
3496 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3497 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3498 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3499 NULL);
Sachin Ahuja988fd102016-09-15 17:16:25 +05303500 }
3501 if (scan_info != NULL && scan_info->mScanPending) {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303502 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003503 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303504 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303505 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506
3507#ifdef WLAN_OPEN_SOURCE
3508 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3509#endif
3510
3511 hdd_deregister_tx_flow_control(adapter);
3512
3513#ifdef WLAN_NS_OFFLOAD
3514#ifdef WLAN_OPEN_SOURCE
3515 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3516#endif
3517#endif
3518
3519 /*
3520 * It is possible that the caller of this function does not
3521 * wish to close the session
3522 */
Peng Xu66162de2016-02-11 17:01:20 -08003523 if (true == bCloseSession)
3524 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525 break;
3526
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003527 case QDF_SAP_MODE:
3528 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003530 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 /*
3532 * Before stopping the sap adapter, lets make sure there
3533 * is no sap restart work pending.
3534 */
3535 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003536 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003537 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538 }
3539 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003540 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3542
3543 hdd_deregister_tx_flow_control(adapter);
3544
3545 mutex_lock(&hdd_ctx->sap_lock);
3546 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303547 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303548 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549
3550 /* Stop Bss. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 status = wlansap_stop_bss(
3552 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003553
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303554 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555 hdd_hostapd_state_t *hostapd_state =
3556 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303557 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303558 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303559 qdf_status =
3560 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303561 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 BSS_WAIT_TIMEOUT);
3563
Anurag Chouhance0dc992016-02-16 18:18:03 +05303564 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003565 hdd_err("failure waiting for wlansap_stop_bss %d",
3566 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003567 }
3568 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003569 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570 }
3571 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003572 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573 adapter->device_mode,
3574 adapter->sessionId);
3575
Anurag Chouhanc5548422016-02-24 18:33:27 +05303576 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003577 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 updateIE.smeSessionId = adapter->sessionId;
3579 updateIE.ieBufferlength = 0;
3580 updateIE.pAdditionIEBuffer = NULL;
3581 updateIE.append = false;
3582 updateIE.notify = false;
3583 /* Probe bcn reset */
3584 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3585 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303586 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003587 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588 }
3589 /* Assoc resp reset */
3590 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3591 &updateIE,
3592 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303593 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003594 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595 }
3596 /* Reset WNI_CFG_PROBE_RSP Flags */
3597 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303598 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003599 adapter->sessionCtx.ap.beacon = NULL;
3600 }
3601 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003602 if (true == bCloseSession)
3603 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003604 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003605 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003606 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3607 conn_info.staId[0]);
3608 break;
3609 default:
3610 break;
3611 }
3612
3613 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303614 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003615}
3616
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303617QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618{
3619 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303620 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621 hdd_adapter_t *adapter;
3622
3623 ENTER();
3624
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303625 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3626
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3628
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303629 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003630 adapter = adapterNode->pAdapter;
3631 hdd_stop_adapter(hdd_ctx, adapter, true);
3632 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3633 adapterNode = pNext;
3634 }
3635
3636 EXIT();
3637
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303638 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003639}
3640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303641QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642{
3643 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303644 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003645 hdd_adapter_t *adapter;
3646
3647 ENTER();
3648
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303649 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3650
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003651 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3652
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303653 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003655 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 wlan_hdd_netif_queue_control(adapter,
3657 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3658 WLAN_CONTROL_PATH);
3659
3660 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3661
3662 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003663 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 adapter->sessionId);
3665 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3666 hdd_wmm_adapter_close(adapter);
3667 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3668 }
3669
3670 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3671 adapterNode = pNext;
3672 }
3673
3674 EXIT();
3675
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303676 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003677}
3678
Arun Khandavallifae92942016-08-01 13:31:08 +05303679/**
3680 * hdd_is_interface_up()- Checkfor interface up before ssr
3681 * @hdd_ctx: HDD context
3682 *
3683 * check if there are any wlan interfaces before SSR accordingly start
3684 * the interface.
3685 *
3686 * Return: 0 if interface was opened else false
3687 */
3688static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3689{
3690 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3691 return true;
3692 else
3693 return false;
3694}
3695
Anurag Chouhanc4092922016-09-08 15:56:11 +05303696#if defined CFG80211_CONNECT_BSS
3697#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
3698 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
3699struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3700 struct ieee80211_channel *channel,
3701 const u8 *bssid, const u8 *ssid,
3702 size_t ssid_len)
3703{
3704 return cfg80211_get_bss(wiphy, channel, bssid,
3705 ssid, ssid_len,
3706 WLAN_CAPABILITY_ESS,
3707 WLAN_CAPABILITY_ESS);
3708}
3709#else
3710struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3711 struct ieee80211_channel *channel,
3712 const u8 *bssid, const u8 *ssid,
3713 size_t ssid_len)
3714{
3715 return cfg80211_get_bss(wiphy, channel, bssid,
3716 ssid, ssid_len,
3717 IEEE80211_BSS_TYPE_ESS,
3718 IEEE80211_PRIVACY_ANY);
3719}
3720#endif
3721#endif
3722
Abhishek Singha84d3952016-09-13 13:45:05 +05303723#if defined CFG80211_CONNECT_BSS
3724/**
3725 * hdd_connect_bss() - API to send connection status to supplicant
3726 * @dev: network device
3727 * @bssid: bssid to which we want to associate
3728 * @req_ie: Request Information Element
3729 * @req_ie_len: len of the req IE
3730 * @resp_ie: Response IE
3731 * @resp_ie_len: len of ht response IE
3732 * @status: status
3733 * @gfp: Kernel Flag
3734 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
3735 *
3736 * The API is a wrapper to send connection status to supplicant
3737 *
3738 * Return: Void
3739 */
3740#if defined CFG80211_CONNECT_TIMEOUT
3741static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3742 struct cfg80211_bss *bss, const u8 *req_ie,
3743 size_t req_ie_len, const u8 *resp_ie,
3744 size_t resp_ie_len, int status, gfp_t gfp,
3745 bool connect_timeout)
3746{
3747 if (connect_timeout)
3748 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
3749 else
3750 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3751 resp_ie, resp_ie_len, status, gfp);
3752}
3753#else
3754static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3755 struct cfg80211_bss *bss, const u8 *req_ie,
3756 size_t req_ie_len, const u8 *resp_ie,
3757 size_t resp_ie_len, int status, gfp_t gfp,
3758 bool connect_timeout)
3759{
3760 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3761 resp_ie, resp_ie_len, status, gfp);
3762}
3763#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303764
3765/**
3766 * hdd_connect_result() - API to send connection status to supplicant
3767 * @dev: network device
3768 * @bssid: bssid to which we want to associate
3769 * @roam_info: information about connected bss
3770 * @req_ie: Request Information Element
3771 * @req_ie_len: len of the req IE
3772 * @resp_ie: Response IE
3773 * @resp_ie_len: len of ht response IE
3774 * @status: status
3775 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05303776 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
Anurag Chouhanc4092922016-09-08 15:56:11 +05303777 *
3778 * The API is a wrapper to send connection status to supplicant
3779 * and allow runtime suspend
3780 *
3781 * Return: Void
3782 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303783void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3784 tCsrRoamInfo *roam_info, const u8 *req_ie,
3785 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303786 size_t resp_ie_len, u16 status, gfp_t gfp,
3787 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303788{
3789 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3790 struct cfg80211_bss *bss = NULL;
3791
3792 if (WLAN_STATUS_SUCCESS == status) {
3793 struct ieee80211_channel *chan;
3794 int freq;
3795 int chan_no = roam_info->pBssDesc->channelId;
3796
3797 if (chan_no <= 14)
3798 freq = ieee80211_channel_to_frequency(chan_no,
3799 IEEE80211_BAND_2GHZ);
3800 else
3801 freq = ieee80211_channel_to_frequency(chan_no,
3802 IEEE80211_BAND_5GHZ);
3803
3804 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
3805 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
3806 roam_info->u.pConnectedProfile->SSID.ssId,
3807 roam_info->u.pConnectedProfile->SSID.length);
3808 }
Abhishek Singha84d3952016-09-13 13:45:05 +05303809 hdd_connect_bss(dev, bssid, bss, req_ie,
3810 req_ie_len, resp_ie, resp_ie_len,
3811 status, gfp, connect_timeout);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303812}
3813#else
3814void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3815 tCsrRoamInfo *roam_info, const u8 *req_ie,
3816 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303817 size_t resp_ie_len, u16 status, gfp_t gfp,
3818 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303819{
3820 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
3821 resp_ie, resp_ie_len, status, gfp);
3822}
3823#endif
3824
3825
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303826QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827{
3828 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303829 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830 hdd_adapter_t *adapter;
3831#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303832 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003833#endif
3834 eConnectionState connState;
3835
3836 ENTER();
3837
3838 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303839 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 adapter = adapterNode->pAdapter;
3841
Arun Khandavallifae92942016-08-01 13:31:08 +05303842 if (!hdd_is_interface_up(adapter))
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05303843 goto get_adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05303844
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 hdd_wmm_init(adapter);
3846
3847 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003848 case QDF_STA_MODE:
3849 case QDF_P2P_CLIENT_MODE:
3850 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003851
3852 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3853 ->conn_info.connState;
3854
3855 hdd_init_station_mode(adapter);
3856 /* Open the gates for HDD to receive Wext commands */
3857 adapter->isLinkUpSvcNeeded = false;
3858 adapter->scan_info.mScanPending = false;
3859
3860 /* Indicate disconnect event to supplicant if associated previously */
3861 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003862 eConnectionState_IbssConnected == connState ||
3863 eConnectionState_NotConnected == connState ||
3864 eConnectionState_IbssDisconnected == connState ||
3865 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 union iwreq_data wrqu;
3867 memset(&wrqu, '\0', sizeof(wrqu));
3868 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3869 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3870 wireless_send_event(adapter->dev, SIOCGIWAP,
3871 &wrqu, NULL);
3872 adapter->sessionCtx.station.
3873 hdd_ReassocScenario = false;
3874
3875 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05303876 wlan_hdd_cfg80211_indicate_disconnect(
3877 adapter->dev, false,
3878 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 } else if (eConnectionState_Connecting == connState) {
3880 /*
3881 * Indicate connect failure to supplicant if we were in the
3882 * process of connecting
3883 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303884 hdd_connect_result(adapter->dev, NULL, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 NULL, 0, NULL, 0,
3886 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Abhishek Singha84d3952016-09-13 13:45:05 +05303887 GFP_KERNEL, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003888 }
3889
3890 hdd_register_tx_flow_control(adapter,
3891 hdd_tx_resume_timer_expired_handler,
3892 hdd_tx_resume_cb);
3893
3894 break;
3895
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003896 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897 /* softAP can handle SSR */
3898 break;
3899
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003900 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003901#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07003902 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3904#else
Jeff Johnson5880d792016-08-15 13:32:30 -07003905 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003906 /* event supplicant to restart */
3907 cfg80211_del_sta(adapter->dev,
3908 (const u8 *)&bcastMac.bytes[0],
3909 GFP_KERNEL);
3910#endif
3911 break;
3912
3913 default:
3914 break;
3915 }
Hanumanth Reddy Pothulac1c4d2b2016-09-22 15:45:16 +05303916get_adapter:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3918 adapterNode = pNext;
3919 }
3920
3921 EXIT();
3922
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303923 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924}
3925
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303926QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927 hdd_adapter_list_node_t **padapterNode)
3928{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303929 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003930 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303931 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3932 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003933 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 return status;
3935}
3936
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303937QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938 hdd_adapter_list_node_t *adapterNode,
3939 hdd_adapter_list_node_t **pNextAdapterNode)
3940{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303941 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003942 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303943 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3944 (qdf_list_node_t *) adapterNode,
3945 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003946
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003947 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003948 return status;
3949}
3950
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303951QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003952 hdd_adapter_list_node_t *adapterNode)
3953{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303954 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003955 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303956 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003958 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003959 return status;
3960}
3961
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303962QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 hdd_adapter_list_node_t **padapterNode)
3964{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303965 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003966 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303967 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3968 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003969 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970 return status;
3971}
3972
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303973QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003974 hdd_adapter_list_node_t *adapterNode)
3975{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303976 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003977 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303978 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3979 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003980 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003981 return status;
3982}
3983
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303984QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003985 hdd_adapter_list_node_t *adapterNode)
3986{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303987 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003988 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303989 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3990 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003991 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 return status;
3993}
3994
3995hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3996 tSirMacAddr macAddr)
3997{
3998 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3999 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304000 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001
4002 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4003
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304004 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005 adapter = adapterNode->pAdapter;
4006
4007 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304008 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009 macAddr, sizeof(tSirMacAddr))) {
4010 return adapter;
4011 }
4012 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4013 adapterNode = pNext;
4014 }
4015
4016 return NULL;
4017
4018}
4019
4020hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4021 uint32_t vdev_id)
4022{
4023 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4024 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304025 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304027 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304029 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 adapter = adapterNode->pAdapter;
4031
4032 if (adapter->sessionId == vdev_id)
4033 return adapter;
4034
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304035 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4037 adapterNode = pNext;
4038 }
4039
Jeff Johnson5880d792016-08-15 13:32:30 -07004040 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041
4042 return NULL;
4043}
4044
Abhishek Singh7996eb72015-12-30 17:24:02 +05304045/**
4046 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4047 * the sessionid
4048 * @hdd_ctx: hdd context.
4049 * @sme_session_id: sme session is for the adapter to get.
4050 *
4051 * This function is used to get the adapter with provided session id
4052 *
4053 * Return: adapter pointer if found
4054 *
4055 */
4056hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4057 uint32_t sme_session_id)
4058{
4059 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4060 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304061 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304062
4063
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304064 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304065
4066 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304067 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304068 adapter = adapter_node->pAdapter;
4069
4070 if (adapter &&
4071 adapter->sessionId == sme_session_id)
4072 return adapter;
4073
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304074 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304075 hdd_get_next_adapter(hdd_ctx,
4076 adapter_node, &next);
4077 adapter_node = next;
4078 }
4079 return NULL;
4080}
4081
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004082/**
4083 * hdd_get_adapter() - to get adapter matching the mode
4084 * @hdd_ctx: hdd context
4085 * @mode: adapter mode
4086 *
4087 * This routine will return the pointer to adapter matching
4088 * with the passed mode.
4089 *
4090 * Return: pointer to adapter or null
4091 */
4092hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4093 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094{
4095 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4096 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304097 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098
4099 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304101 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102 adapter = adapterNode->pAdapter;
4103
4104 if (adapter && (mode == adapter->device_mode))
4105 return adapter;
4106
4107 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4108 adapterNode = pNext;
4109 }
4110
4111 return NULL;
4112
4113}
4114
4115/**
4116 * hdd_get_operating_channel() - return operating channel of the device mode
4117 * @hdd_ctx: Pointer to the HDD context.
4118 * @mode: Device mode for which operating channel is required.
4119 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004120 * QDF_STA_MODE,
4121 * QDF_P2P_CLIENT_MODE,
4122 * QDF_SAP_MODE,
4123 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124 *
4125 * This API returns the operating channel of the requested device mode
4126 *
4127 * Return: channel number. "0" id the requested device is not found OR it is
4128 * not connected.
4129 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004130uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4131 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132{
4133 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304134 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 hdd_adapter_t *adapter;
4136 uint8_t operatingChannel = 0;
4137
4138 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304140 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004141 adapter = adapterNode->pAdapter;
4142
4143 if (mode == adapter->device_mode) {
4144 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004145 case QDF_STA_MODE:
4146 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 if (hdd_conn_is_connected
4148 (WLAN_HDD_GET_STATION_CTX_PTR
4149 (adapter))) {
4150 operatingChannel =
4151 (WLAN_HDD_GET_STATION_CTX_PTR
4152 (adapter))->conn_info.
4153 operationChannel;
4154 }
4155 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004156 case QDF_SAP_MODE:
4157 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 /* softap connection info */
4159 if (test_bit
4160 (SOFTAP_BSS_STARTED,
4161 &adapter->event_flags))
4162 operatingChannel =
4163 (WLAN_HDD_GET_AP_CTX_PTR
4164 (adapter))->operatingChannel;
4165 break;
4166 default:
4167 break;
4168 }
4169
4170 break; /* Found the device of interest. break the loop */
4171 }
4172
4173 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4174 adapterNode = pNext;
4175 }
4176 return operatingChannel;
4177}
4178
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304179static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 hdd_ctx)
4181{
4182 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304183 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184 hdd_adapter_t *adapter;
4185
4186 ENTER();
4187
4188 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4189
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304190 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004192 if ((adapter->device_mode == QDF_STA_MODE) ||
4193 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4194 (adapter->device_mode == QDF_IBSS_MODE) ||
4195 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4196 (adapter->device_mode == QDF_SAP_MODE) ||
4197 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004198 wlan_hdd_cfg80211_deregister_frames(adapter);
4199 hdd_unregister_wext(adapter->dev);
4200 }
4201 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4202 adapterNode = pNext;
4203 }
4204
4205 EXIT();
4206
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304207 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004208}
4209
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304210QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211{
4212 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304213 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004214 hdd_adapter_t *adapter;
4215
4216 ENTER();
4217
4218 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4219
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304220 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004222 if ((adapter->device_mode == QDF_STA_MODE) ||
4223 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4224 (adapter->device_mode == QDF_IBSS_MODE) ||
4225 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4226 (adapter->device_mode == QDF_SAP_MODE) ||
4227 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004228 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4229 eCSR_SCAN_ABORT_DEFAULT);
4230 }
4231 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4232 adapterNode = pNext;
4233 }
4234
4235 EXIT();
4236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304237 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004238}
4239
4240#ifdef WLAN_NS_OFFLOAD
4241/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004242 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243 * @hdd_ctx: Pointer to hdd context
4244 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004245 * Unregister for IPv6 address change notifications.
4246 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 * Return: None
4248 */
4249static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4250{
4251 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4252
4253 return;
4254}
4255
4256/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004257 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004258 * @hdd_ctx: Pointer to hdd context
4259 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004260 * Register for IPv6 address change notifications.
4261 *
4262 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004264static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004265{
4266 int ret;
4267
4268 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4269 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004270 if (ret) {
4271 hdd_err("Failed to register IPv6 notifier: %d", ret);
4272 goto out;
4273 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004275 hdd_info("Registered IPv6 notifier");
4276out:
4277 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278}
4279#else
4280/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004281 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004282 * @hdd_ctx: Pointer to hdd context
4283 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004284 * Unregister for IPv6 address change notifications.
4285 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 * Return: None
4287 */
4288static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4289{
4290}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004293 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004294 * @hdd_ctx: Pointer to hdd context
4295 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004296 * Register for IPv6 address change notifications.
4297 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298 * Return: None
4299 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004300static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004302 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303}
4304#endif
4305
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304306#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4307/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004308 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304309 * @hdd_ctx: HDD context
4310 *
4311 * Activates the logging service
4312 *
4313 * Return: Zero in case of success, negative value otherwise
4314 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004315static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304316{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004317 int ret;
4318 struct hdd_config *config = hdd_ctx->config;
4319
4320 if (!config->wlanLoggingEnable)
4321 return 0;
4322
4323 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4324 config->wlanLoggingNumBuf);
4325 if (ret)
4326 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4327 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304328}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004329
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304330/**
4331 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4332 * @hdd_ctx: HDD context
4333 *
4334 * Deactivates the logging service
4335 *
4336 * Return: 0 on deactivating the logging service
4337 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004338static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304339{
4340 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4341 return wlan_logging_sock_deactivate_svc();
4342
4343 return 0;
4344}
4345#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004346static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304347{
4348 return 0;
4349}
4350
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004351static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304352{
4353 return 0;
4354}
4355#endif
4356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004358 * hdd_register_notifiers - Register netdev notifiers.
4359 * @hdd_ctx: HDD context
4360 *
4361 * Register netdev notifiers like IPv4 and IPv6.
4362 *
4363 * Return: 0 on success and errno on failure
4364 */
4365static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4366{
4367 int ret;
4368
4369 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4370 if (ret) {
4371 hdd_err("register_netdevice_notifier failed: %d", ret);
4372 goto out;
4373 }
4374
4375 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4376 if (ret)
4377 goto unregister_notifier;
4378
4379 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4380 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4381 if (ret) {
4382 hdd_err("Failed to register IPv4 notifier: %d", ret);
4383 goto unregister_ip6_notifier;
4384 }
4385
4386 return 0;
4387
4388unregister_ip6_notifier:
4389 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4390unregister_notifier:
4391 unregister_netdevice_notifier(&hdd_netdev_notifier);
4392out:
4393 return ret;
4394
4395}
4396
4397/**
4398 * hdd_unregister_notifiers - Unregister netdev notifiers.
4399 * @hdd_ctx: HDD context
4400 *
4401 * Unregister netdev notifiers like IPv4 and IPv6.
4402 *
4403 * Return: None.
4404 */
4405static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4406{
4407 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4408
4409 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4410
4411 unregister_netdevice_notifier(&hdd_netdev_notifier);
4412}
4413
4414/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004415 * hdd_exit_netlink_services - Exit netlink services
4416 * @hdd_ctx: HDD context
4417 *
4418 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4419 * nl service.
4420 *
4421 * Return: None.
4422 */
4423static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4424{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004425 hdd_close_cesium_nl_sock();
4426
4427 ptt_sock_deactivate_svc();
4428
4429 nl_srv_exit();
4430}
4431
4432/**
4433 * hdd_init_netlink_services- Init netlink services
4434 * @hdd_ctx: HDD context
4435 *
4436 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4437 * nl service.
4438 *
4439 * Return: 0 on success and errno on failure.
4440 */
4441static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4442{
4443 int ret;
4444
Ryan Hsuceddceb2016-04-28 10:20:14 -07004445 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004446 if (ret) {
4447 hdd_alert("nl_srv_init failed: %d", ret);
4448 goto out;
4449 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004450 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004451
4452 ret = oem_activate_service(hdd_ctx);
4453 if (ret) {
4454 hdd_alert("oem_activate_service failed: %d", ret);
4455 goto err_nl_srv;
4456 }
4457
4458 ret = ptt_sock_activate_svc();
4459 if (ret) {
4460 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4461 goto err_nl_srv;
4462 }
4463
4464 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004465 if (ret)
4466 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004467
4468 ret = cnss_diag_activate_service();
4469 if (ret) {
4470 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4471 goto err_close_cesium;
4472 }
4473
4474 return 0;
4475
4476err_close_cesium:
4477 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004478 ptt_sock_deactivate_svc();
4479err_nl_srv:
4480 nl_srv_exit();
4481out:
4482 return ret;
4483}
4484
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004485#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4486/**
4487 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4488 * @hdd_ctx: HDD context.
4489 *
4490 * Destroy RX wakelock.
4491 *
4492 * Return: None.
4493 */
4494static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4495{
4496 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4497}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004498
4499/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004500 * hdd_rx_wake_lock_create() - Create RX wakelock
4501 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004502 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004503 * Create RX wakelock.
4504 *
4505 * Return: None.
4506 */
4507static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4508{
4509 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4510}
4511#else
4512static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { }
4513static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { }
4514#endif
4515
4516/**
4517 * hdd_roc_context_init() - Init ROC context
4518 * @hdd_ctx: HDD context.
4519 *
4520 * Initialize ROC context.
4521 *
4522 * Return: 0 on success and errno on failure.
4523 */
4524static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4525{
4526 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4527 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4528
4529 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4530
4531 return 0;
4532}
4533
4534/**
4535 * hdd_roc_context_destroy() - Destroy ROC context
4536 * @hdd_ctx: HDD context.
4537 *
4538 * Destroy roc list and flush the pending roc work.
4539 *
4540 * Return: None.
4541 */
4542static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4543{
4544 flush_delayed_work(&hdd_ctx->roc_req_work);
4545 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4546}
4547
4548/**
4549 * hdd_context_destroy() - Destroy HDD context
4550 * @hdd_ctx: HDD context to be destroyed.
4551 *
4552 * Free config and HDD context as well as destroy all the resources.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004553 *
4554 * Return: None
4555 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004556static void hdd_context_destroy(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004557{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304558 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004559 hdd_logging_sock_deactivate_svc(hdd_ctx);
4560
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004561 hdd_roc_context_destroy(hdd_ctx);
4562
4563 hdd_sap_context_destroy(hdd_ctx);
4564
4565 hdd_rx_wake_lock_destroy(hdd_ctx);
4566
4567 hdd_tdls_context_destroy(hdd_ctx);
4568
4569 hdd_scan_context_destroy(hdd_ctx);
4570
4571 qdf_list_destroy(&hdd_ctx->hddAdapters);
4572
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304573 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004574 hdd_ctx->config = NULL;
4575
4576 wiphy_free(hdd_ctx->wiphy);
4577}
4578
4579/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 * hdd_wlan_exit() - HDD WLAN exit function
4581 * @hdd_ctx: Pointer to the HDD Context
4582 *
4583 * This is the driver exit point (invoked during rmmod)
4584 *
4585 * Return: None
4586 */
4587void hdd_wlan_exit(hdd_context_t *hdd_ctx)
4588{
4589 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304590 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004591 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304592 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593
4594 ENTER();
4595
Arun Khandavallifae92942016-08-01 13:31:08 +05304596 if (QDF_TIMER_STATE_RUNNING ==
4597 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4598 hdd_info("Stpp interface change timer");
4599 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004600 }
4601
Arun Khandavallifae92942016-08-01 13:31:08 +05304602 if (!QDF_IS_STATUS_SUCCESS
4603 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4604 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004605
Arun Khandavallifae92942016-08-01 13:31:08 +05304606
4607 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608
4609#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05304610 if (QDF_TIMER_STATE_RUNNING ==
4611 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
4612 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Ravi Joshib89e7f72016-09-07 13:43:15 -07004613 hdd_reset_tcp_delack(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 }
4615
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304616 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304617 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004618 hdd_err("Cannot deallocate Bus bandwidth timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004619 }
4620#endif
4621
4622#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304623 if (QDF_TIMER_STATE_RUNNING ==
4624 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4625 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626 }
4627
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304628 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304629 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004630 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004631 }
4632#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633
Arun Khandavallifae92942016-08-01 13:31:08 +05304634 mutex_lock(&hdd_ctx->iface_change_lock);
4635 driver_status = hdd_ctx->driver_status;
4636 mutex_unlock(&hdd_ctx->iface_change_lock);
4637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638 /*
4639 * Powersave Offload Case
4640 * Disable Idle Power Save Mode
4641 */
4642 hdd_set_idle_ps_config(hdd_ctx, false);
4643
Arun Khandavallifae92942016-08-01 13:31:08 +05304644 if (driver_status != DRIVER_MODULES_CLOSED) {
4645 hdd_unregister_wext_all_adapters(hdd_ctx);
4646 /*
4647 * Cancel any outstanding scan requests. We are about to close
4648 * all of our adapters, but an adapter structure is what SME
4649 * passes back to our callback function. Hence if there
4650 * are any outstanding scan requests then there is a
4651 * race condition between when the adapter is closed and
4652 * when the callback is invoked. We try to resolve that
4653 * race condition here by canceling any outstanding scans
4654 * before we close the adapters.
4655 * Note that the scans may be cancelled in an asynchronous
4656 * manner, so ideally there needs to be some kind of
4657 * synchronization. Rather than introduce a new
4658 * synchronization here, we will utilize the fact that we are
4659 * about to Request Full Power, and since that is synchronized,
4660 * the expectation is that by the time Request Full Power has
4661 * completed, all scans will be cancelled
4662 */
4663 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4664 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 }
4666
Arun Khandavallifae92942016-08-01 13:31:08 +05304667 hdd_wlan_stop_modules(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668 /*
4669 * Close the scheduler before calling cds_close to make sure no thread
4670 * is scheduled after the each module close is called i.e after all the
4671 * data structures are freed.
4672 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304673 qdf_status = cds_sched_close(p_cds_context);
4674 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004675 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304676 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004678
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304679 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4680 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4681 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4682
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 /*
4684 * Close CDS
4685 * This frees pMac(HAL) context. There should not be any call
4686 * that requires pMac access after this.
4687 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07004689 hdd_green_ap_deinit(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004691 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692
4693 hdd_ipa_cleanup(hdd_ctx);
4694
4695 /* Free up RoC request queue and flush workqueue */
4696 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697
Arun Khandavallifae92942016-08-01 13:31:08 +05304698
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304700 wlansap_global_deinit();
Nirav Shahed34b212016-04-25 10:59:16 +05304701 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004702 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304703 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004704
Jeff Johnsonf7f66f02016-09-23 14:50:11 -07004705 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004706
Arun Khandavallifae92942016-08-01 13:31:08 +05304707 hdd_exit_netlink_services(hdd_ctx);
4708 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004709 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710}
4711
4712void __hdd_wlan_exit(void)
4713{
4714 hdd_context_t *hdd_ctx;
4715
4716 ENTER();
4717
Anurag Chouhan6d760662016-02-20 16:05:43 +05304718 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004719 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004720 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 EXIT();
4722 return;
4723 }
4724
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004725 /* Check IPA HW Pipe shutdown */
4726 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4727
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004728 memdump_deinit();
4729
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730 /* Do all the cleanup before deregistering the driver */
4731 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004733 EXIT();
4734}
4735
4736#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4737void hdd_skip_acs_scan_timer_handler(void *data)
4738{
4739 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4740
Jeff Johnson760350b2016-08-15 14:01:52 -07004741 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4743
4744 if (!hdd_ctx->hHal)
4745 return;
4746 sme_scan_flush_result(hdd_ctx->hHal);
4747}
4748#endif
4749
4750#ifdef QCA_HT_2040_COEX
4751/**
4752 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4753 * @adapter: pointer to adapter
4754 * @staId: station id
4755 * @macAddrSTA: station MAC address
4756 * @channel_type: channel type
4757 *
4758 * This function notifies FW with HT20/HT40 mode
4759 *
4760 * Return: 0 if successful, error number otherwise
4761 */
4762int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304763 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764{
4765 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304766 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767 hdd_context_t *hdd_ctx = NULL;
4768
4769 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4770
4771 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304772 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004773 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775 if (!hdd_ctx->hHal)
4776 return -EINVAL;
4777
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304778 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304780 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004781 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004782 return -EINVAL;
4783 }
4784
4785 return 0;
4786}
4787#endif
4788
4789/**
4790 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4791 * @state: state
4792 *
4793 * This function notifies FW with modem power status
4794 *
4795 * Return: 0 if successful, error number otherwise
4796 */
4797int hdd_wlan_notify_modem_power_state(int state)
4798{
4799 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304800 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004801 hdd_context_t *hdd_ctx;
4802
Anurag Chouhan6d760662016-02-20 16:05:43 +05304803 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304805 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004806 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808 if (!hdd_ctx->hHal)
4809 return -EINVAL;
4810
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304811 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4812 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004813 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004814 state);
4815 return -EINVAL;
4816 }
4817 return 0;
4818}
4819
4820/**
4821 *
4822 * hdd_post_cds_enable_config() - HDD post cds start config helper
4823 * @adapter - Pointer to the HDD
4824 *
4825 * Return: None
4826 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304827QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004828{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304829 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004830
4831 /*
4832 * Send ready indication to the HDD. This will kick off the MAC
4833 * into a 'running' state and should kick off an initial scan.
4834 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304835 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4836 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004837 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
4838 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304839 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004840 }
4841
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304842 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843}
4844
4845/* wake lock APIs for HDD */
4846void hdd_prevent_suspend(uint32_t reason)
4847{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304848 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849}
4850
4851void hdd_allow_suspend(uint32_t reason)
4852{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304853 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854}
4855
4856void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
4857{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05304858 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
4859 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860}
4861
4862/**
4863 * hdd_exchange_version_and_caps() - exchange version and capability with target
4864 * @hdd_ctx: Pointer to HDD context
4865 *
4866 * This is the HDD function to exchange version and capability information
4867 * between Host and Target
4868 *
4869 * This function gets reported version of FW.
4870 * It also finds the version of target headers used to compile the host;
4871 * It compares the above two and prints a warning if they are different;
4872 * It gets the SW and HW version string;
4873 * Finally, it exchanges capabilities between host and target i.e. host
4874 * and target exchange a msg indicating the features they support through a
4875 * bitmap
4876 *
4877 * Return: None
4878 */
4879void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4880{
4881
4882 tSirVersionType versionCompiled;
4883 tSirVersionType versionReported;
4884 tSirVersionString versionString;
4885 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304886 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887
4888 memset(&versionCompiled, 0, sizeof(versionCompiled));
4889 memset(&versionReported, 0, sizeof(versionReported));
4890
4891 /* retrieve and display WCNSS version information */
4892 do {
4893
4894 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4895 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304896 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004897 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004898 break;
4899 }
4900
4901 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4902 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304903 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004904 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 break;
4906 }
4907
4908 if ((versionCompiled.major != versionReported.major) ||
4909 (versionCompiled.minor != versionReported.minor) ||
4910 (versionCompiled.version != versionReported.version) ||
4911 (versionCompiled.revision != versionReported.revision)) {
4912 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4913 "Host expected %u.%u.%u.%u\n",
4914 WLAN_MODULE_NAME,
4915 (int)versionReported.major,
4916 (int)versionReported.minor,
4917 (int)versionReported.version,
4918 (int)versionReported.revision,
4919 (int)versionCompiled.major,
4920 (int)versionCompiled.minor,
4921 (int)versionCompiled.version,
4922 (int)versionCompiled.revision);
4923 } else {
4924 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4925 WLAN_MODULE_NAME,
4926 (int)versionReported.major,
4927 (int)versionReported.minor,
4928 (int)versionReported.version,
4929 (int)versionReported.revision);
4930 }
4931
4932 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4933 versionString,
4934 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304935 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004936 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004937 break;
4938 }
4939
4940 pr_info("%s: WCNSS software version %s\n",
4941 WLAN_MODULE_NAME, versionString);
4942
4943 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4944 versionString,
4945 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304946 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07004947 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948 break;
4949 }
4950
4951 pr_info("%s: WCNSS hardware version %s\n",
4952 WLAN_MODULE_NAME, versionString);
4953
4954 /*
4955 * 1.Check if FW version is greater than 0.1.1.0. Only then
4956 * send host-FW capability exchange message
4957 * 2.Host-FW capability exchange message is only present on
4958 * target 1.1 so send the message only if it the target is 1.1
4959 * minor numbers for different target branches:
4960 * 0 -> (1.0)Mainline Build
4961 * 1 -> (1.1)Mainline Build
4962 * 2->(1.04) Stability Build
4963 */
4964 if (((versionReported.major > 0) || (versionReported.minor > 1)
4965 || ((versionReported.minor >= 1)
4966 && (versionReported.version >= 1)))
4967 && ((versionReported.major == 1)
4968 && (versionReported.minor >= 1)))
4969 fwFeatCapsMsgSupported = 1;
4970
4971 if (fwFeatCapsMsgSupported) {
4972 /*
4973 * Indicate if IBSS heartbeat monitoring needs to be
4974 * offloaded
4975 */
4976 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4977 sme_disable_feature_capablity
4978 (IBSS_HEARTBEAT_OFFLOAD);
4979 }
4980
4981 sme_feature_caps_exchange(hdd_ctx->hHal);
4982 }
4983
4984 } while (0);
4985
4986}
4987
4988/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304989QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990{
4991 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4992 hdd_ctx->reg.cc_src);
4993}
4994
4995/**
4996 * hdd_is_5g_supported() - check if hardware supports 5GHz
4997 * @hdd_ctx: Pointer to the hdd context
4998 *
4999 * HDD function to know if hardware supports 5GHz
5000 *
5001 * Return: true if hardware supports 5GHz
5002 */
5003bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
5004{
5005 /*
5006 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
5007 * then hardware support 5Ghz.
5008 */
5009 return true;
5010}
5011
Amar Singhale4f28ee2015-10-21 14:36:56 -07005012static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013{
5014 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005015 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005016
5017 wiphy = hdd_ctx->wiphy;
5018
5019 /*
5020 * The channel information in
5021 * wiphy needs to be initialized before wiphy registration
5022 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005023 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5024 if (ret_val) {
5025 hdd_alert("regulatory init failed");
5026 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 }
5028
5029#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5030 wiphy->wowlan = &wowlan_support_reg_init;
5031#else
5032 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5033 WIPHY_WOWLAN_MAGIC_PKT |
5034 WIPHY_WOWLAN_DISCONNECT |
5035 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5036 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5037 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5038 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5039 WIPHY_WOWLAN_RFKILL_RELEASE;
5040
5041 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5042 WOW_MAX_FILTERS_PER_LIST);
5043 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5044 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5045#endif
5046
5047 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005048 ret_val = wlan_hdd_cfg80211_register(wiphy);
5049 if (0 > ret_val)
5050 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005051
Amar Singhale4f28ee2015-10-21 14:36:56 -07005052 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053}
5054
Ravi Joshie2331e82015-07-01 18:18:54 -07005055/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005056 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005057 * @hdd_ctx - handle to hdd context
5058 * @tx_packets - transmit packet count
5059 * @rx_packets - receive packet count
5060 *
5061 * The function controls the bus bandwidth and dynamic control of
5062 * tcp delayed ack configuration
5063 *
5064 * Returns: None
5065 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005066#ifdef MSM_PLATFORM
Yuanyuan Liu13738502016-04-06 17:41:37 -07005067void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08005068 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005069{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005070 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005071 uint64_t temp_rx = 0;
5072 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005073 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005074 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5075 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005076 uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005078 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005079 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005080 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005081 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005082 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005083 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005084 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005085 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005086
Mohit Khannae71e2262015-11-10 09:37:24 -08005087 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5088 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005089
5090 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005091 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5092 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005093 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005094 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305095 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305096 if (hdd_ctx->hbw_requested) {
5097 pld_remove_pm_qos(hdd_ctx->parent_dev);
5098 hdd_ctx->hbw_requested = false;
5099 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305100 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005101 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305102 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305103 if (!hdd_ctx->hbw_requested) {
5104 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5105 hdd_ctx->hbw_requested = true;
5106 }
5107
Nirav Shah3bbfa512016-05-12 16:43:49 +05305108 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005109 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305110 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005111 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005112 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005113
5114 /* fine-tuning parameters for RX Flows */
5115 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117 hdd_ctx->prev_rx = rx_packets;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005118 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh &&
5119 (hdd_ctx->cur_rx_level != WLAN_SVC_TP_HIGH &&
5120 ++hdd_ctx->rx_high_ind_cnt == delack_timer_cnt)) {
Mohit Khannae71e2262015-11-10 09:37:24 -08005121 next_rx_level = WLAN_SVC_TP_HIGH;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005122 } else {
Mohit Khannae71e2262015-11-10 09:37:24 -08005123 next_rx_level = WLAN_SVC_TP_LOW;
Ravi Joshib89e7f72016-09-07 13:43:15 -07005124 hdd_ctx->rx_high_ind_cnt = 0;
5125 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005126
Mohit Khannae71e2262015-11-10 09:37:24 -08005127 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5128 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005129
5130 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005131 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005132 next_rx_level, temp_rx);
5133 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005134 /* Send throughput indication only if it is enabled.
5135 * Disabling tcp_del_ack will revert the tcp stack behavior
5136 * to default delayed ack. Note that this will disable the
5137 * dynamic delayed ack mechanism across the system
5138 */
5139 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305140 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5141 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 &next_rx_level,
5143 sizeof(next_rx_level));
5144 }
5145
Mohit Khannae71e2262015-11-10 09:37:24 -08005146 /* fine-tuning parameters for TX Flows */
5147 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5148 hdd_ctx->prev_tx = tx_packets;
5149 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5150 next_tx_level = WLAN_SVC_TP_HIGH;
5151 else
5152 next_tx_level = WLAN_SVC_TP_LOW;
5153
5154 if (hdd_ctx->cur_tx_level != next_tx_level) {
5155 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5156 next_tx_level, temp_tx);
5157 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305158 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5159 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005160 &next_tx_level,
5161 sizeof(next_tx_level));
5162 }
5163
5164 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5165 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166 hdd_ctx->hdd_txrx_hist_idx++;
5167 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168}
5169
5170#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
5171static void hdd_bus_bw_compute_cbk(void *priv)
5172{
5173 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
5174 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305175 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305176 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5177 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 uint64_t total_tx = 0, total_rx = 0;
5179 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305180 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305181 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005182 bool connected = false;
5183 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5184
5185 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305186 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187 status =
5188 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5189
5190 if (adapterNode->pAdapter == NULL)
5191 continue;
5192 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305193 /*
5194 * Validate magic so we don't end up accessing
5195 * an invalid adapter.
5196 */
5197 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5198 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005200 if ((adapter->device_mode == QDF_STA_MODE ||
5201 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5203 != eConnectionState_Associated) {
5204
5205 continue;
5206 }
5207
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005208 if ((adapter->device_mode == QDF_SAP_MODE ||
5209 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5211
5212 continue;
5213 }
5214
5215 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5216 adapter->prev_tx_packets);
5217 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5218 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305219
5220 if (adapter->device_mode == QDF_SAP_MODE ||
5221 adapter->device_mode == QDF_P2P_GO_MODE ||
5222 adapter->device_mode == QDF_IBSS_MODE) {
5223
5224 ret = ol_get_intra_bss_fwd_pkts_count(
5225 adapter->sessionId,
5226 &fwd_tx_packets, &fwd_rx_packets);
5227 if (ret == A_OK) {
5228 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5229 fwd_tx_packets,
5230 adapter->prev_fwd_tx_packets);
5231 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5232 fwd_tx_packets,
5233 adapter->prev_fwd_rx_packets);
5234 }
5235 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236
5237 total_rx += adapter->stats.rx_packets;
5238 total_tx += adapter->stats.tx_packets;
5239
5240 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5241 adapter->prev_tx_packets = adapter->stats.tx_packets;
5242 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305243 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5244 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5246 connected = true;
5247 }
5248
5249 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5250 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5251 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5252 rx_packets;
5253 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5254 tx_packets;
5255
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305256 /* add intra bss forwarded tx and rx packets */
5257 tx_packets += fwd_tx_packets_diff;
5258 rx_packets += fwd_rx_packets_diff;
5259
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5261 tx_packets += (uint64_t)ipa_tx_packets;
5262 rx_packets += (uint64_t)ipa_rx_packets;
5263
5264 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005265 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 return;
5267 }
5268
Yuanyuan Liu13738502016-04-06 17:41:37 -07005269 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005270
5271 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5272 hdd_ipa_uc_stat_request(adapter, 2);
5273
Anurag Chouhan210db072016-02-22 18:42:15 +05305274 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 hdd_ctx->config->busBandwidthComputeInterval);
5276}
5277#endif
5278
5279/**
Nirav Shahed34b212016-04-25 10:59:16 +05305280 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5281 * @hdd_ctx: hdd context
5282 *
5283 * Return: 0 for success or error code
5284 */
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07005285static int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
Nirav Shahed34b212016-04-25 10:59:16 +05305286{
5287 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5288 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5289 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005290 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305291 return -ENOMEM;
5292 }
5293 return 0;
5294}
5295
5296/**
5297 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5298 * @hdd_ctx: hdd context
5299 *
5300 * Return: none
5301 */
5302void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5303{
5304 if (hdd_ctx->hdd_txrx_hist) {
5305 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5306 hdd_ctx->hdd_txrx_hist = NULL;
5307 }
5308}
5309
Nirav Shahda008342016-05-17 18:50:40 +05305310static uint8_t *convert_level_to_string(uint32_t level)
5311{
5312 switch (level) {
5313 /* initialize the wlan sub system */
5314 case WLAN_SVC_TP_NONE:
5315 return "NONE";
5316 case WLAN_SVC_TP_LOW:
5317 return "LOW";
5318 case WLAN_SVC_TP_MEDIUM:
5319 return "MED";
5320 case WLAN_SVC_TP_HIGH:
5321 return "HIGH";
5322 default:
5323 return "INVAL";
5324 }
5325}
5326
Nirav Shahed34b212016-04-25 10:59:16 +05305327
5328/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5330 * @hdd_ctx: hdd context
5331 *
5332 * Return: none
5333 */
5334void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5335{
5336 int i;
5337
5338#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005339 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305340 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005341 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 hdd_ctx->config->busBandwidthHighThreshold,
5343 hdd_ctx->config->busBandwidthMediumThreshold,
5344 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005345 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305346 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005347 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 hdd_ctx->config->tcpDelackThresholdHigh,
5349 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005350 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305351 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005352#endif
5353
Jeff Johnson760350b2016-08-15 14:01:52 -07005354 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305355 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5356
Jeff Johnson760350b2016-08-15 14:01:52 -07005357 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 -08005358
5359 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005360 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5362 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5363 hdd_ctx->hdd_txrx_hist[i].total_tx,
5364 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305365 convert_level_to_string(
5366 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5367 convert_level_to_string(
5368 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5369 convert_level_to_string(
5370 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 }
5372 return;
5373}
5374
5375/**
5376 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5377 * @hdd_ctx: hdd context
5378 *
5379 * Return: none
5380 */
5381void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5382{
5383 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305384 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5385 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386}
5387
5388/**
5389 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5390 * @pHddCtx: hdd context
5391 *
5392 * Return: none
5393 */
5394void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5395{
5396
5397 hdd_adapter_t *adapter = NULL;
5398 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305399 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305401 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402
5403 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305404 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405 adapter = adapter_node->pAdapter;
5406
Jeff Johnson760350b2016-08-15 14:01:52 -07005407 hdd_err("\nNetif queue operation statistics:");
5408 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305409 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005410 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305411 curr_time = qdf_system_ticks();
5412 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305413 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305414 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305415 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305416 unpause = adapter->total_unpause_time;
5417 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305418 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305419 pause = adapter->total_pause_time;
5420 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005421 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305422 qdf_system_ticks_to_msecs(total),
5423 qdf_system_ticks_to_msecs(pause),
5424 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005425 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426
Nirav Shahda008342016-05-17 18:50:40 +05305427 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5428 qdf_time_t pause_delta = 0;
5429
5430 if (adapter->pause_map & (1 << i))
5431 pause_delta = delta;
5432
Jeff Johnson760350b2016-08-15 14:01:52 -07005433 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 hdd_reason_type_to_string(i),
5435 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305436 adapter->queue_oper_stats[i].unpause_count,
5437 qdf_system_ticks_to_msecs(
5438 adapter->queue_oper_stats[i].total_pause_time +
5439 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440 }
5441
Jeff Johnson760350b2016-08-15 14:01:52 -07005442 hdd_err("\nNetif queue operation history:");
5443 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305444 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5445
Jeff Johnson760350b2016-08-15 14:01:52 -07005446 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447
5448 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005449 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305450 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005451 adapter->queue_oper_history[i].time),
5452 hdd_action_type_to_string(
5453 adapter->queue_oper_history[i].netif_action),
5454 hdd_reason_type_to_string(
5455 adapter->queue_oper_history[i].netif_reason),
5456 adapter->queue_oper_history[i].pause_map);
5457 }
5458
5459 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5460 adapter_node = next;
5461 }
5462
5463
5464}
5465
5466/**
5467 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5468 * @hdd_ctx: hdd context
5469 *
5470 * Return: none
5471 */
5472void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5473{
5474 hdd_adapter_t *adapter = NULL;
5475 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305476 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477
5478 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305479 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005480 adapter = adapter_node->pAdapter;
5481
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305482 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005483 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305484 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005485 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305486 adapter->history_index = 0;
5487 adapter->start_time = adapter->last_time = qdf_system_ticks();
5488 adapter->total_pause_time = 0;
5489 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005490 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5491 adapter_node = next;
5492 }
5493}
5494
5495/**
5496 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5497 * @halHandle: Hal handle
5498 * @pContext: Pointer to the context
5499 * @sessionId: Session ID
5500 * @scanId: Scan ID
5501 * @status: Status
5502 *
5503 * This is the callback to be executed when 11d scan is completed to flush out
5504 * the scan results
5505 *
5506 * 11d scan is done during driver load and is a passive scan on all
5507 * channels supported by the device, 11d scans may find some APs on
5508 * frequencies which are forbidden to be used in the regulatory domain
5509 * the device is operating in. If these APs are notified to the supplicant
5510 * it may try to connect to these APs, thus flush out all the scan results
5511 * which are present in SME after 11d scan is done.
5512 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305513 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305515static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516 uint8_t sessionId, uint32_t scanId,
5517 eCsrScanStatus status)
5518{
5519 ENTER();
5520
5521 sme_scan_flush_result(halHandle);
5522
5523 EXIT();
5524
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305525 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526}
5527
5528#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5529/**
5530 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5531 * @hdd_ctx: hdd global context
5532 *
5533 * Return: none
5534 */
5535static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5536{
5537 uint8_t i;
5538
5539 mutex_init(&hdd_ctx->op_ctx.op_lock);
5540 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5541 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5542 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5543 }
5544}
5545#else
5546static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5547{
5548}
5549#endif
5550
5551#ifdef WLAN_FEATURE_FASTPATH
5552/**
5553 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5554 * @hdd_cfg: hdd config
5555 * @context: lower layer context
5556 *
5557 * Return: none
5558 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305559void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560 void *context)
5561{
5562 if (hdd_cfg->fastpath_enable)
5563 hif_enable_fastpath(context);
5564}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565#endif
5566
Yuanyuan Liu13738502016-04-06 17:41:37 -07005567#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005568/**
5569 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005570 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 * @level: thermal level
5572 *
5573 * Change IPA data path to SW path when the thermal throttle level greater
5574 * than 0, and restore the original data path when throttle level is 0
5575 *
5576 * Return: none
5577 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005578static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005580 hdd_context_t *hdd_ctx = context;
5581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 /* Change IPA to SW path when throttle level greater than 0 */
5583 if (level > THROTTLE_LEVEL_0)
5584 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5585 else
5586 /* restore original concurrency mode */
5587 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5588}
5589
5590/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305591 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5592 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305593 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005594 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305595 * Get a safe channel to restart SAP. PCL already takes into account the
5596 * unsafe channels. So, the PCL is validated with the ACS range to provide
5597 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305599 * Return: Channel number to restart SAP in case of success. In case of any
5600 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005601 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305602static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5603 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305605 struct sir_pcl_list pcl;
5606 QDF_STATUS status;
5607 uint32_t i, j;
5608 tHalHandle *hal_handle;
5609 hdd_context_t *hdd_ctx;
5610 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305612 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5613 if (!hdd_ctx) {
5614 hdd_err("invalid HDD context");
5615 return INVALID_CHANNEL_ID;
5616 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005617
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305618 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5619 if (!hal_handle) {
5620 hdd_err("invalid HAL handle");
5621 return INVALID_CHANNEL_ID;
5622 }
5623
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305624 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5625 pcl.pcl_list, &pcl.pcl_len,
5626 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5627 if (QDF_IS_STATUS_ERROR(status)) {
5628 hdd_err("Get PCL failed");
5629 return INVALID_CHANNEL_ID;
5630 }
5631
5632 if (!pcl.pcl_len) {
5633 hdd_alert("pcl length is zero. this is not expected");
5634 return INVALID_CHANNEL_ID;
5635 }
5636
5637 hdd_info("start:%d end:%d",
5638 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5639 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5640
5641 /* PCL already takes unsafe channel into account */
5642 for (i = 0; i < pcl.pcl_len; i++) {
5643 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5644 if ((pcl.pcl_list[i] >=
5645 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5646 (pcl.pcl_list[i] <=
5647 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5648 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5649 return pcl.pcl_list[i];
5650 }
5651 }
5652
5653 hdd_info("no safe channel from PCL found in ACS range");
5654
5655 /* Try for safe channel from all valid channel */
5656 pcl.pcl_len = MAX_NUM_CHAN;
5657 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5658 &pcl.pcl_len);
5659 if (QDF_IS_STATUS_ERROR(status)) {
5660 hdd_err("error in getting valid channel list");
5661 return INVALID_CHANNEL_ID;
5662 }
5663
5664 for (i = 0; i < pcl.pcl_len; i++) {
5665 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5666 found = false;
5667 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
5668 if (cds_chan_to_freq(pcl.pcl_list[i]) ==
5669 hdd_ctx->unsafe_channel_list[j]) {
5670 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5671 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 break;
5673 }
5674 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305675
5676 if (found)
5677 continue;
5678
5679 if ((pcl.pcl_list[i] >=
5680 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5681 (pcl.pcl_list[i] <=
5682 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5683 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5684 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005685 }
5686 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305687
5688 return INVALID_CHANNEL_ID;
5689}
5690
5691/**
5692 * hdd_restart_sap() - Restarts SAP on the given channel
5693 * @adapter: AP adapter
5694 * @channel: Channel
5695 *
5696 * Restarts the SAP interface by invoking the function which executes the
5697 * callback to perform channel switch using (E)CSA.
5698 *
5699 * Return: None
5700 */
5701void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
5702{
5703 hdd_ap_ctx_t *hdd_ap_ctx;
5704 tHalHandle *hal_handle;
5705
5706 if (!adapter) {
5707 hdd_err("invalid adapter");
5708 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005709 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305710
5711 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5712
5713 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5714 if (!hal_handle) {
5715 hdd_err("invalid HAL handle");
5716 return;
5717 }
5718
5719 hdd_ap_ctx->sapConfig.channel = channel;
5720 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5721 hdd_ap_ctx->sapConfig.ch_width_orig;
5722
5723 hdd_info("chan:%d width:%d",
5724 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5725
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005726 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305727 hdd_ap_ctx->sapConfig.sec_ch,
5728 &hdd_ap_ctx->sapConfig.ch_params);
5729
5730 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005731}
Agrawal Ashish467dde42016-09-08 18:44:22 +05305732/**
5733 * hdd_unsafe_channel_restart_sap() - restart sap if sap is on unsafe channel
5734 * @hdd_ctx: hdd context pointer
5735 *
5736 * hdd_unsafe_channel_restart_sap check all unsafe channel list
5737 * and if ACS is enabled, driver will ask userspace to restart the
5738 * sap. User space on LTE coex indication restart driver.
5739 *
5740 * Return - none
5741 */
5742void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctxt)
5743{
5744 QDF_STATUS status;
5745 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
5746 hdd_adapter_t *adapter_temp;
5747 uint32_t i;
5748 bool found = false;
5749 uint8_t restart_chan;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750
Agrawal Ashish467dde42016-09-08 18:44:22 +05305751 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
5752 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5753 adapter_temp = adapter_node->pAdapter;
5754
5755 if (!adapter_temp) {
5756 hdd_err("adapter is NULL, moving to next one");
5757 goto next_adapater;
5758 }
5759
5760 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
5761 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
5762 hdd_info("skip device mode:%d acs:%d",
5763 adapter_temp->device_mode,
5764 adapter_temp->sessionCtx.ap.sapConfig.
5765 acs_cfg.acs_mode);
5766 goto next_adapater;
5767 }
5768
5769 found = false;
5770 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
5771 if (cds_chan_to_freq(
5772 adapter_temp->sessionCtx.ap.operatingChannel) ==
5773 hdd_ctxt->unsafe_channel_list[i]) {
5774 found = true;
5775 hdd_info("operating ch:%d is unsafe",
5776 adapter_temp->sessionCtx.ap.operatingChannel);
5777 break;
5778 }
5779 }
5780
5781 if (!found) {
5782 hdd_info("ch:%d is safe. no need to change channel",
5783 adapter_temp->sessionCtx.ap.operatingChannel);
5784 goto next_adapater;
5785 }
5786
5787 restart_chan =
5788 hdd_get_safe_channel_from_pcl_and_acs_range(
5789 adapter_temp);
5790 if (!restart_chan) {
5791 hdd_alert("fail to restart SAP");
5792 } else {
5793 hdd_info("sending coex indication");
5794 wlan_hdd_send_svc_nlink_msg(hdd_ctxt->radio_index,
5795 WLAN_SVC_LTE_COEX_IND, NULL, 0);
5796 hdd_restart_sap(adapter_temp, restart_chan);
5797 }
5798
5799next_adapater:
5800 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
5801 adapter_node = next;
5802 }
5803}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005804/**
5805 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
5806 * @adapter: HDD adapter pointer
5807 * @indParam: Channel avoid notification parameter
5808 *
5809 * Avoid channel notification from FW handler.
5810 * FW will send un-safe channel list to avoid over wrapping.
5811 * hostapd should not use notified channel
5812 *
5813 * Return: None
5814 */
Agrawal Ashish467dde42016-09-08 18:44:22 +05305815void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005816{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817 hdd_context_t *hdd_ctxt;
5818 tSirChAvoidIndType *ch_avoid_indi;
5819 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08005820 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
5821 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 uint16_t start_channel;
5823 uint16_t end_channel;
5824 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005825 tHddAvoidFreqList hdd_avoid_freq_list;
5826 uint32_t i;
5827
5828 /* Basic sanity */
5829 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005830 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831 return;
5832 }
5833
5834 hdd_ctxt = (hdd_context_t *) hdd_context;
5835 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
5836 cds_context = hdd_ctxt->pcds_context;
5837
5838 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07005839 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840 ch_avoid_indi->avoid_range_count);
5841
5842 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305843 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
5845 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
5846 ch_avoid_indi->avoid_freq_range[i].start_freq;
5847 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
5848 ch_avoid_indi->avoid_freq_range[i].end_freq;
5849 }
5850 hdd_avoid_freq_list.avoidFreqRangeCount =
5851 ch_avoid_indi->avoid_range_count;
5852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853 /* clear existing unsafe channel cache */
5854 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305855 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856 sizeof(hdd_ctxt->unsafe_channel_list));
5857
5858 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
5859 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08005860 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005861 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 break;
5863 }
5864
5865 start_channel = ieee80211_frequency_to_channel(
5866 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
5867 end_channel = ieee80211_frequency_to_channel(
5868 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07005869 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
5871 start_channel,
5872 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
5873 end_channel);
5874
5875 /* do not process frequency bands that are not mapped to
5876 * predefined channels
5877 */
5878 if (start_channel == 0 || end_channel == 0)
5879 continue;
5880
Amar Singhalb8d4f152016-02-10 10:21:43 -08005881 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5882 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005883 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005884 ch_avoid_indi->avoid_freq_range[
5885 range_loop].start_freq) {
5886 start_channel_idx = channel_loop;
5887 break;
5888 }
5889 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08005890 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5891 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005892 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893 ch_avoid_indi->avoid_freq_range[
5894 range_loop].end_freq) {
5895 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07005896 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005897 ch_avoid_indi->avoid_freq_range[
5898 range_loop].end_freq)
5899 end_channel_idx--;
5900 break;
5901 }
5902 }
5903
Amar Singhalb8d4f152016-02-10 10:21:43 -08005904 if (start_channel_idx == INVALID_CHANNEL ||
5905 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005906 continue;
5907
5908 for (channel_loop = start_channel_idx; channel_loop <=
5909 end_channel_idx; channel_loop++) {
5910 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07005911 hdd_ctxt->unsafe_channel_count++] =
5912 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08005914 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005915 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005916 break;
5917 }
5918 }
5919 }
5920
Jeff Johnson34c88b72016-08-15 14:27:11 -07005921 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 hdd_ctxt->unsafe_channel_count);
5923
Yuanyuan Liu13738502016-04-06 17:41:37 -07005924 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
5925 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926 hdd_ctxt->unsafe_channel_count)) {
5927 hdd_err("Failed to set unsafe channel");
5928
5929 /* clear existing unsafe channel cache */
5930 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305931 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005932 sizeof(hdd_ctxt->unsafe_channel_list));
5933
5934 return;
5935 }
5936
5937 for (channel_loop = 0;
5938 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005939 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940 hdd_ctxt->unsafe_channel_list[channel_loop]);
5941 }
5942
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05305943 /*
5944 * first update the unsafe channel list to the platform driver and
5945 * send the avoid freq event to the application
5946 */
5947 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
5948
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305949 if (!hdd_ctxt->unsafe_channel_count) {
5950 hdd_info("no unsafe channels - not restarting SAP");
5951 return;
5952 }
Agrawal Ashish467dde42016-09-08 18:44:22 +05305953 hdd_unsafe_channel_restart_sap(hdd_ctxt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005954 return;
5955}
5956
5957/**
5958 * hdd_init_channel_avoidance() - Initialize channel avoidance
5959 * @hdd_ctx: HDD global context
5960 *
5961 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07005962 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005963 * down to the lower layers. Then subscribe to subsequent channel
5964 * avoidance events.
5965 *
5966 * Return: None
5967 */
5968static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5969{
5970 uint16_t unsafe_channel_count;
5971 int index;
5972
Yuanyuan Liu13738502016-04-06 17:41:37 -07005973 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
5974 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005975 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08005976 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005977
Jeff Johnson34c88b72016-08-15 14:27:11 -07005978 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005979 hdd_ctx->unsafe_channel_count);
5980
Anurag Chouhan6d760662016-02-20 16:05:43 +05305981 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08005982 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005983
5984 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005985 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986 hdd_ctx->unsafe_channel_list[index]);
5987
5988 }
5989
5990 /* Plug in avoid channel notification callback */
5991 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
5992}
5993#else
5994static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5995{
5996}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005997static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005998{
5999}
Yuanyuan Liu13738502016-04-06 17:41:37 -07006000#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006001
6002/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08006003 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
6004 * user space
6005 * @frame_ind: Management frame data to be informed.
6006 *
6007 * This function is used to indicate management frame to
6008 * user space
6009 *
6010 * Return: None
6011 *
6012 */
6013void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
6014{
6015 hdd_context_t *hdd_ctx = NULL;
6016 hdd_adapter_t *adapter = NULL;
6017 void *cds_context = NULL;
6018 int i;
6019
6020 /* Get the global VOSS context.*/
6021 cds_context = cds_get_global_context();
6022 if (!cds_context) {
6023 hdd_err("Global CDS context is Null");
6024 return;
6025 }
6026 /* Get the HDD context.*/
6027 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
6028
6029 if (0 != wlan_hdd_validate_context(hdd_ctx))
6030 return;
6031
6032 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
6033 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6034 adapter =
6035 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6036 if (adapter)
6037 break;
6038 }
6039 } else {
6040 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6041 frame_ind->sessionId);
6042 }
6043
6044 if ((NULL != adapter) &&
6045 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6046 __hdd_indicate_mgmt_frame(adapter,
6047 frame_ind->frame_len,
6048 frame_ind->frameBuf,
6049 frame_ind->frameType,
6050 frame_ind->rxChan,
6051 frame_ind->rxRssi);
6052 return;
6053}
6054
6055/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6057 * @hdd_ctx: HDD context
6058 *
6059 * Disables all the dual mac features like DBS, Agile DFS etc.
6060 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306061 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006062 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306063static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006064{
6065 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306066 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006067
6068 if (!hdd_ctx) {
6069 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306070 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006071 }
6072
6073 cfg.scan_config = 0;
6074 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306075 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006076
6077 hdd_debug("Disabling all dual mac features...");
6078
6079 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306080 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006081 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6082 return status;
6083 }
6084
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306085 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006086}
6087
6088/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006089 * hdd_override_ini_config - Override INI config
6090 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006091 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006092 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006093 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006094 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006096static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006099 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6100 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6101 hdd_notice("Module enable_dfs_chan_scan set to %d",
6102 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006103 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006104 if (0 == enable_11d || 1 == enable_11d) {
6105 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6106 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006107 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006108}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006109
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006110/**
6111 * hdd_set_trace_level_for_each - Set trace level for each INI config
6112 * @hdd_ctx - HDD context
6113 *
6114 * Set trace level for each module based on INI config.
6115 *
6116 * Return: None
6117 */
6118static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6119{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306120 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6121 hdd_ctx->config->qdf_trace_enable_wdi);
6122 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6123 hdd_ctx->config->qdf_trace_enable_hdd);
6124 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6125 hdd_ctx->config->qdf_trace_enable_sme);
6126 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6127 hdd_ctx->config->qdf_trace_enable_pe);
6128 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6129 hdd_ctx->config->qdf_trace_enable_wma);
6130 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6131 hdd_ctx->config->qdf_trace_enable_sys);
6132 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6133 hdd_ctx->config->qdf_trace_enable_qdf);
6134 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6135 hdd_ctx->config->qdf_trace_enable_sap);
6136 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6137 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6138 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6139 hdd_ctx->config->qdf_trace_enable_bmi);
6140 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6141 hdd_ctx->config->qdf_trace_enable_cfg);
6142 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6143 hdd_ctx->config->qdf_trace_enable_epping);
6144 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6145 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6146 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306147 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306148 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6149 hdd_ctx->config->qdf_trace_enable_htc);
6150 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6151 hdd_ctx->config->qdf_trace_enable_hif);
6152 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6153 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6154 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6155 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006157 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006158}
6159
6160/**
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006161 * hdd_context_deinit() - Deinitialize HDD context
6162 * @hdd_ctx: HDD context.
6163 *
6164 * Deinitialize HDD context along with all the feature specific contexts but
6165 * do not free hdd context itself. Caller of this API is supposed to free
6166 * HDD context.
6167 *
6168 * return: 0 on success and errno on failure.
6169 */
6170static int hdd_context_deinit(hdd_context_t *hdd_ctx)
6171{
6172 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
6173
6174 hdd_roc_context_destroy(hdd_ctx);
6175
6176 hdd_sap_context_destroy(hdd_ctx);
6177
6178 hdd_rx_wake_lock_destroy(hdd_ctx);
6179
6180 hdd_tdls_context_destroy(hdd_ctx);
6181
6182 hdd_scan_context_destroy(hdd_ctx);
6183
6184 qdf_list_destroy(&hdd_ctx->hddAdapters);
6185
6186 return 0;
6187}
6188
6189
6190/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006191 * hdd_context_init() - Initialize HDD context
6192 * @hdd_ctx: HDD context.
6193 *
6194 * Initialize HDD context along with all the feature specific contexts.
6195 *
6196 * return: 0 on success and errno on failure.
6197 */
6198static int hdd_context_init(hdd_context_t *hdd_ctx)
6199{
6200 int ret;
6201
6202 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6203 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6204
6205 hdd_init_ll_stats_ctx();
6206
6207 init_completion(&hdd_ctx->mc_sus_event_var);
6208 init_completion(&hdd_ctx->ready_to_suspend);
6209
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306210 hdd_init_bpf_completion();
6211
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006212 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306213 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006214 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306215
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006216 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6217
6218 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6219
6220 ret = hdd_scan_context_init(hdd_ctx);
6221 if (ret)
6222 goto list_destroy;
6223
6224 hdd_tdls_context_init(hdd_ctx);
6225
6226 hdd_rx_wake_lock_create(hdd_ctx);
6227
6228 ret = hdd_sap_context_init(hdd_ctx);
6229 if (ret)
6230 goto scan_destroy;
6231
6232 ret = hdd_roc_context_init(hdd_ctx);
6233 if (ret)
6234 goto sap_destroy;
6235
6236 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6237
6238 hdd_init_offloaded_packets_ctx(hdd_ctx);
6239
6240 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6241 hdd_ctx->config);
6242 if (ret)
6243 goto roc_destroy;
6244
6245 return 0;
6246
6247roc_destroy:
6248 hdd_roc_context_destroy(hdd_ctx);
6249
6250sap_destroy:
6251 hdd_sap_context_destroy(hdd_ctx);
6252
6253scan_destroy:
6254 hdd_scan_context_destroy(hdd_ctx);
6255 hdd_rx_wake_lock_destroy(hdd_ctx);
6256 hdd_tdls_context_destroy(hdd_ctx);
6257
6258list_destroy:
6259 qdf_list_destroy(&hdd_ctx->hddAdapters);
6260 return ret;
6261}
6262
6263/**
6264 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306265 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006266 *
6267 * Allocate and initialize HDD context. HDD context is allocated as part of
6268 * wiphy allocation and then context is initialized.
6269 *
6270 * Return: HDD context on success and ERR_PTR on failure
6271 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306272hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006273{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306274 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006275 int ret = 0;
6276 hdd_context_t *hdd_ctx;
6277 v_CONTEXT_t p_cds_context;
6278
6279 ENTER();
6280
6281 p_cds_context = cds_get_global_context();
6282 if (p_cds_context == NULL) {
6283 hdd_alert("Failed to get CDS global context");
6284 ret = -EINVAL;
6285 goto err_out;
6286 }
6287
6288 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6289
6290 if (hdd_ctx == NULL) {
6291 ret = -ENOMEM;
6292 goto err_out;
6293 }
6294
6295 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006296 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006297
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306298 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006299 if (hdd_ctx->config == NULL) {
6300 hdd_alert("Failed to alloc memory for HDD config!");
6301 ret = -ENOMEM;
6302 goto err_free_hdd_context;
6303 }
6304
6305 /* Read and parse the qcom_cfg.ini file */
6306 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306307 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306308 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006309 WLAN_INI_FILE);
6310 ret = -EINVAL;
6311 goto err_free_config;
6312 }
6313
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006314 hdd_ctx->configuredMcastBcastFilter =
6315 hdd_ctx->config->mcastBcastFilterSetting;
6316
6317 hdd_notice("Setting configuredMcastBcastFilter: %d",
6318 hdd_ctx->config->mcastBcastFilterSetting);
6319
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306320 if (hdd_ctx->config->fhostNSOffload)
6321 hdd_ctx->ns_offload_enable = true;
6322
Abhishek Singh5ea86532016-04-27 14:10:53 +05306323 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6324
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006325 hdd_override_ini_config(hdd_ctx);
6326
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006327 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006328
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006329 ret = hdd_context_init(hdd_ctx);
6330
6331 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006332 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006333
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006334
Yuanyuan Liu13738502016-04-06 17:41:37 -07006335 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6336 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006337
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006338
6339 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306340 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006341
Anurag Chouhan6d760662016-02-20 16:05:43 +05306342 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006343 goto skip_multicast_logging;
6344
6345 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6346
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006347 ret = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6348 if (ret)
6349 goto err_deinit_hdd_context;
Nirav Shahed34b212016-04-25 10:59:16 +05306350
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006351 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6352 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306353 goto err_free_histogram;
6354
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006355
6356 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306357 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006358 * levels of the code need not be set when the logger thread
6359 * is not enabled.
6360 */
6361 if (cds_is_multicast_logging())
6362 wlan_logging_set_log_level();
6363
6364skip_multicast_logging:
6365 hdd_set_trace_level_for_each(hdd_ctx);
6366
6367 return hdd_ctx;
6368
Nirav Shahed34b212016-04-25 10:59:16 +05306369err_free_histogram:
6370 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6371
Rajeev Kumarfb02a5e2016-09-20 16:16:17 -07006372err_deinit_hdd_context:
6373 hdd_context_deinit(hdd_ctx);
6374
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006375err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306376 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006377
6378err_free_hdd_context:
6379 wiphy_free(hdd_ctx->wiphy);
6380
6381err_out:
6382 return ERR_PTR(ret);
6383}
6384
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006385#ifdef WLAN_OPEN_P2P_INTERFACE
6386/**
6387 * hdd_open_p2p_interface - Open P2P interface
6388 * @hdd_ctx: HDD context
6389 * @rtnl_held: True if RTNL lock held
6390 *
6391 * Open P2P interface during probe. This function called to open the P2P
6392 * interface at probe along with STA interface.
6393 *
6394 * Return: 0 on success and errno on failure
6395 */
6396static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6397{
6398 hdd_adapter_t *adapter;
6399 uint8_t *p2p_dev_addr;
6400
6401 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6402 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306403 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006404 hdd_ctx->config->intfMacAddr[0].bytes,
6405 sizeof(tSirMacAddr));
6406
6407 /*
6408 * Generate the P2P Device Address. This consists of
6409 * the device's primary MAC address with the locally
6410 * administered bit set.
6411 */
6412 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6413 } else {
6414 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6415 if (p2p_dev_addr == NULL) {
6416 hdd_alert("Failed to allocate mac_address for p2p_device");
6417 return -ENOSPC;
6418 }
6419
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306420 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306421 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006422 }
6423
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006424 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006425 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006426 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006427
6428 if (NULL == adapter) {
6429 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6430 return -ENOSPC;
6431 }
6432
6433 return 0;
6434}
6435#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306436static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006437 bool rtnl_held)
6438{
6439 return 0;
6440}
6441#endif
6442
6443/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306444 * hdd_start_station_adapter()- Start the Station Adapter
6445 * @adapter: HDD adapter
6446 *
6447 * This function initializes the adapter for the station mode.
6448 *
6449 * Return: 0 on success or errno on failure.
6450 */
6451int hdd_start_station_adapter(hdd_adapter_t *adapter)
6452{
6453 QDF_STATUS status;
6454
6455 ENTER_DEV(adapter->dev);
6456
6457 status = hdd_init_station_mode(adapter);
6458
6459 if (QDF_STATUS_SUCCESS != status) {
6460 hdd_err("Error Initializing station mode: %d", status);
6461 return qdf_status_to_os_return(status);
6462 }
6463
Arun Khandavallifae92942016-08-01 13:31:08 +05306464 hdd_register_tx_flow_control(adapter,
6465 hdd_tx_resume_timer_expired_handler,
6466 hdd_tx_resume_cb);
6467
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306468 EXIT();
6469 return 0;
6470}
6471
6472/**
6473 * hdd_start_ap_adapter()- Start AP Adapter
6474 * @adapter: HDD adapter
6475 *
6476 * This function initializes the adapter for the AP mode.
6477 *
6478 * Return: 0 on success errno on failure.
6479 */
6480int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6481{
6482 QDF_STATUS status;
6483
6484 ENTER();
6485
6486 status = hdd_init_ap_mode(adapter);
6487
6488 if (QDF_STATUS_SUCCESS != status) {
6489 hdd_err("Error Initializing the AP mode: %d", status);
6490 return qdf_status_to_os_return(status);
6491 }
6492
Arun Khandavallifae92942016-08-01 13:31:08 +05306493 hdd_register_tx_flow_control(adapter,
6494 hdd_softap_tx_resume_timer_expired_handler,
6495 hdd_softap_tx_resume_cb);
6496
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306497 EXIT();
6498 return 0;
6499}
6500
6501/**
6502 * hdd_start_ftm_adapter()- Start FTM adapter
6503 * @adapter: HDD adapter
6504 *
6505 * This function initializes the adapter for the FTM mode.
6506 *
6507 * Return: 0 on success or errno on failure.
6508 */
6509int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6510{
6511 QDF_STATUS qdf_status;
6512
6513 ENTER_DEV(adapter->dev);
6514
6515 qdf_status = hdd_init_tx_rx(adapter);
6516
6517 if (QDF_STATUS_SUCCESS != qdf_status) {
6518 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6519 return qdf_status_to_os_return(qdf_status);
6520 }
6521
6522 return 0;
6523 EXIT();
6524}
6525
6526/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006527 * hdd_open_interfaces - Open all required interfaces
6528 * hdd_ctx: HDD context
6529 * rtnl_held: True if RTNL lock is held
6530 *
6531 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6532 *
6533 * Return: Primary adapter on success and PTR_ERR on failure
6534 */
6535static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6536 bool rtnl_held)
6537{
6538 hdd_adapter_t *adapter = NULL;
6539 hdd_adapter_t *adapter_11p = NULL;
6540 int ret;
6541
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006542 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306543 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006544 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006545 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006546 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006547
6548 if (adapter == NULL)
6549 return ERR_PTR(-ENOSPC);
6550
6551 return adapter;
6552 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006553 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006554 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006555 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006556
6557 if (adapter == NULL)
6558 return ERR_PTR(-ENOSPC);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006559 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6560 if (ret)
6561 goto err_close_adapter;
6562
6563 /* Open 802.11p Interface */
6564 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006565 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006566 "wlanocb%d",
6567 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006568 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006569 if (adapter_11p == NULL) {
6570 hdd_err("Failed to open 802.11p interface");
6571 goto err_close_adapter;
6572 }
6573 }
6574
6575 return adapter;
6576
6577err_close_adapter:
6578 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6579 return ERR_PTR(ret);
6580}
6581
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006582/**
6583 * hdd_update_country_code - Update country code
6584 * @hdd_ctx: HDD context
6585 * @adapter: Primary adapter context
6586 *
6587 * Update country code based on module parameter country_code at SME and wait
6588 * for the settings to take effect.
6589 *
6590 * Return: 0 on success and errno on failure
6591 */
6592static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6593 hdd_adapter_t *adapter)
6594{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306595 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006596 int ret = 0;
6597 unsigned long rc;
6598
6599 if (country_code == NULL)
6600 return 0;
6601
6602 INIT_COMPLETION(adapter->change_country_code);
6603
6604 status = sme_change_country_code(hdd_ctx->hHal,
6605 wlan_hdd_change_country_code_callback,
6606 country_code, adapter,
6607 hdd_ctx->pcds_context, eSIR_TRUE,
6608 eSIR_TRUE);
6609
6610
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306611 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006612 hdd_err("SME Change Country code from module param fail ret=%d",
6613 ret);
6614 return -EINVAL;
6615 }
6616
6617 rc = wait_for_completion_timeout(&adapter->change_country_code,
6618 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6619 if (!rc) {
6620 hdd_err("SME while setting country code timed out");
6621 ret = -ETIMEDOUT;
6622 }
6623
6624 return ret;
6625}
6626
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306627#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6628/**
6629 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6630 * @cds_cfg: CDS Configuration
6631 * @hdd_ctx: Pointer to hdd context
6632 *
6633 * Return: none
6634 */
6635static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6636 *cds_cfg,
6637 hdd_context_t *hdd_ctx)
6638{
6639 cds_cfg->tx_flow_stop_queue_th =
6640 hdd_ctx->config->TxFlowStopQueueThreshold;
6641 cds_cfg->tx_flow_start_queue_offset =
6642 hdd_ctx->config->TxFlowStartQueueOffset;
6643}
6644#else
6645static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6646 *cds_cfg,
6647 hdd_context_t *hdd_ctx)
6648{
6649}
6650#endif
6651
6652#ifdef FEATURE_WLAN_RA_FILTERING
6653/**
6654 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6655 * @cds_cfg: CDS Configuration
6656 * @hdd_ctx: Pointer to hdd context
6657 *
6658 * Return: none
6659 */
6660inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6661 hdd_context_t *hdd_ctx)
6662{
6663 cds_cfg->ra_ratelimit_interval =
6664 hdd_ctx->config->RArateLimitInterval;
6665 cds_cfg->is_ra_ratelimit_enabled =
6666 hdd_ctx->config->IsRArateLimitEnabled;
6667}
6668#else
6669inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6670 hdd_context_t *hdd_ctx)
6671{
6672}
6673#endif
6674
6675/**
6676 * hdd_update_cds_config() - API to update cds configuration parameters
6677 * @hdd_ctx: HDD Context
6678 *
6679 * Return: 0 for Success, errno on failure
6680 */
6681int hdd_update_cds_config(hdd_context_t *hdd_ctx)
6682{
6683 struct cds_config_info *cds_cfg;
6684
6685 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6686 if (!cds_cfg) {
6687 hdd_err("failed to allocate cds config");
6688 return -ENOMEM;
6689 }
6690
6691 qdf_mem_zero(cds_cfg, sizeof(*cds_cfg));
6692
6693 /* UMA is supported in hardware for performing the
6694 * frame translation 802.11 <-> 802.3
6695 */
6696 cds_cfg->frame_xln_reqd = 1;
6697 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
6698 cds_cfg->powersave_offload_enabled =
6699 hdd_ctx->config->enablePowersaveOffload;
6700 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
6701 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
6702 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
6703 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
6704 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
6705
6706 /* Here ol_ini_info is used to store ini status of arp offload
6707 * ns offload and others. Currently 1st bit is used for arp
6708 * off load and 2nd bit for ns offload currently, rest bits are unused
6709 */
6710 if (hdd_ctx->config->fhostArpOffload)
6711 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
6712 if (hdd_ctx->config->fhostNSOffload)
6713 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
6714
6715 /*
6716 * Copy the DFS Phyerr Filtering Offload status.
6717 * This parameter reflects the value of the
6718 * dfs_phyerr_filter_offload flag as set in the ini.
6719 */
6720 cds_cfg->dfs_phyerr_filter_offload =
6721 hdd_ctx->config->fDfsPhyerrFilterOffload;
6722 if (hdd_ctx->config->ssdp)
6723 cds_cfg->ssdp = hdd_ctx->config->ssdp;
6724
6725 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
6726 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
6727
6728 cds_cfg->ap_maxoffload_reorderbuffs =
6729 hdd_ctx->config->apMaxOffloadReorderBuffs;
6730
6731 cds_cfg->ap_disable_intrabss_fwd =
6732 hdd_ctx->config->apDisableIntraBssFwd;
6733
6734 cds_cfg->dfs_pri_multiplier =
6735 hdd_ctx->config->dfsRadarPriMultiplier;
6736 cds_cfg->reorder_offload =
6737 hdd_ctx->config->reorderOffloadSupport;
6738
6739 /* IPA micro controller data path offload resource config item */
6740 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
6741 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
6742 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
6743 cds_cfg->uc_rxind_ringcount =
6744 hdd_ctx->config->IpaUcRxIndRingCount;
6745 cds_cfg->uc_tx_partition_base =
6746 hdd_ctx->config->IpaUcTxPartitionBase;
6747 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
6748
6749 cds_cfg->ip_tcp_udp_checksum_offload =
6750 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05306751 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306752 cds_cfg->ce_classify_enabled =
6753 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07006754 cds_cfg->bpf_packet_filter_enable =
6755 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306756 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
6757 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
6758 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07006759 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07006760 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306761
6762 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
6763 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
6764 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
Jeff Johnson9078bdc2016-09-23 17:18:11 -07006765 hdd_lpass_populate_cds_config(cds_cfg, hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306766 cds_init_ini_config(cds_cfg);
6767 return 0;
6768}
6769
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006770/**
6771 * hdd_init_thermal_info - Initialize thermal level
6772 * @hdd_ctx: HDD context
6773 *
6774 * Initialize thermal level at SME layer and set the thermal level callback
6775 * which would be called when a configured thermal threshold is hit.
6776 *
6777 * Return: 0 on success and errno on failure
6778 */
6779static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
6780{
6781 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306782 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006783
6784 thermal_param.smeThermalMgmtEnabled =
6785 hdd_ctx->config->thermalMitigationEnable;
6786 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
6787
Poddar, Siddarth83905022016-04-16 17:56:08 -07006788 thermal_param.sme_throttle_duty_cycle_tbl[0] =
6789 hdd_ctx->config->throttle_dutycycle_level0;
6790 thermal_param.sme_throttle_duty_cycle_tbl[1] =
6791 hdd_ctx->config->throttle_dutycycle_level1;
6792 thermal_param.sme_throttle_duty_cycle_tbl[2] =
6793 hdd_ctx->config->throttle_dutycycle_level2;
6794 thermal_param.sme_throttle_duty_cycle_tbl[3] =
6795 hdd_ctx->config->throttle_dutycycle_level3;
6796
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006797 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
6798 hdd_ctx->config->thermalTempMinLevel0;
6799 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
6800 hdd_ctx->config->thermalTempMaxLevel0;
6801 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
6802 hdd_ctx->config->thermalTempMinLevel1;
6803 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
6804 hdd_ctx->config->thermalTempMaxLevel1;
6805 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
6806 hdd_ctx->config->thermalTempMinLevel2;
6807 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
6808 hdd_ctx->config->thermalTempMaxLevel2;
6809 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
6810 hdd_ctx->config->thermalTempMinLevel3;
6811 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
6812 hdd_ctx->config->thermalTempMaxLevel3;
6813
6814 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
6815
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306816 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05306817 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006818
6819 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
6820 hdd_set_thermal_level_cb);
6821
6822 return 0;
6823
6824}
6825
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006826#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
6827/**
6828 * hdd_hold_rtnl_lock - Hold RTNL lock
6829 *
6830 * Hold RTNL lock
6831 *
6832 * Return: True if held and false otherwise
6833 */
6834static inline bool hdd_hold_rtnl_lock(void)
6835{
6836 rtnl_lock();
6837 return true;
6838}
6839
6840/**
6841 * hdd_release_rtnl_lock - Release RTNL lock
6842 *
6843 * Release RTNL lock
6844 *
6845 * Return: None
6846 */
6847static inline void hdd_release_rtnl_lock(void)
6848{
6849 rtnl_unlock();
6850}
6851#else
6852static inline bool hdd_hold_rtnl_lock(void) { return false; }
6853static inline void hdd_release_rtnl_lock(void) { }
6854#endif
6855
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006856#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006857
6858/**
6859 * hdd_process_pktlog_command() - process pktlog command
6860 * @hdd_ctx: hdd context
6861 * @set_value: value set by user
6862 *
6863 * Return: 0 for success or error.
6864 */
6865int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value)
6866{
6867 int ret;
6868 bool enable;
6869 uint8_t user_triggered = 0;
6870
6871 ret = wlan_hdd_validate_context(hdd_ctx);
6872 if (0 != ret)
6873 return ret;
6874
6875 hdd_info("set pktlog %d", set_value);
6876
6877 if (set_value > 2) {
6878 hdd_err("invalid pktlog value %d", set_value);
6879 return -EINVAL;
6880 }
6881
6882 /*
6883 * set_value = 0 then disable packetlog
6884 * set_value = 1 enable packetlog forcefully
6885 * set_vlaue = 2 then disable packetlog if disabled through ini or
6886 * enable packetlog with AUTO type.
6887 */
6888 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
6889 true : false;
6890
6891 if (1 == set_value) {
6892 enable = true;
6893 user_triggered = 1;
6894 }
6895
6896 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered);
6897}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006898/**
6899 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
6900 * @hdd_ctx: HDD context
6901 * @enable: Flag to enable/disable
6902 *
6903 * Return: 0 on success; error number otherwise
6904 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006905int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
6906 uint8_t user_triggered)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006907{
6908 struct sir_wifi_start_log start_log;
6909 QDF_STATUS status;
6910
6911 start_log.ring_id = RING_ID_PER_PACKET_STATS;
6912 start_log.verbose_level =
6913 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006914 start_log.ini_triggered = cds_is_packet_log_enabled();
6915 start_log.user_triggered = user_triggered;
Poddar, Siddartheefe3482016-09-21 18:12:59 +05306916 /*
6917 * Use "is_iwpriv_command" flag to distinguish iwpriv command from other
6918 * commands. Host uses this flag to decide whether to send pktlog
6919 * disable command to fw without sending pktlog enable command
6920 * previously. For eg, If vendor sends pktlog disable command without
6921 * sending pktlog enable command, then host discards the packet
6922 * but for iwpriv command, host will send it to fw.
6923 */
6924 start_log.is_iwpriv_command = 1;
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006925 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
6926 if (!QDF_IS_STATUS_SUCCESS(status)) {
6927 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
6928 EXIT();
6929 return -EINVAL;
6930 }
6931
6932 return 0;
6933}
6934#endif /* REMOVE_PKT_LOG */
6935
6936
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05306937#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
6938/**
6939 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
6940 * switch without restart
6941 *
6942 * Registers callback function to change the operating channel of SAP by using
6943 * channel switch announcements instead of restarting SAP.
6944 *
6945 * Return: QDF_STATUS
6946 */
6947QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
6948{
6949 QDF_STATUS status;
6950
6951 status = cds_register_sap_restart_channel_switch_cb(
6952 (void *)hdd_sap_restart_with_channel_switch);
6953 if (!QDF_IS_STATUS_SUCCESS(status))
6954 hdd_err("restart cb registration failed");
6955
6956 return status;
6957}
6958#endif
6959
Komal Seelam92fff912016-03-24 11:51:41 +05306960#ifdef CONFIG_CNSS
6961/**
6962 * hdd_get_cnss_wlan_mac_buff() - API to query platform driver for MAC address
6963 * @dev: Device Pointer
6964 * @num: Number of Valid Mac address
6965 *
6966 * Return: Pointer to MAC address buffer
6967 */
6968static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6969{
6970 return cnss_common_get_wlan_mac_address(dev, num);
6971}
6972#else
6973static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6974{
6975 *num = 0;
6976 return NULL;
6977}
6978#endif
6979
6980/**
6981 * hdd_populate_random_mac_addr() - API to populate random mac addresses
6982 * @hdd_ctx: HDD Context
6983 * @num: Number of random mac addresses needed
6984 *
6985 * Generate random addresses using bit manipulation on the base mac address
6986 *
6987 * Return: None
6988 */
6989static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
6990{
6991 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
6992 uint32_t iter;
6993 struct hdd_config *ini = hdd_ctx->config;
6994 uint8_t *buf = NULL;
6995 uint8_t macaddr_b3, tmp_br3;
6996 uint8_t *src = ini->intfMacAddr[0].bytes;
6997
6998 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
6999 buf = ini->intfMacAddr[iter].bytes;
7000 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
7001 macaddr_b3 = buf[3];
7002 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
7003 INTF_MACADDR_MASK;
7004 macaddr_b3 += tmp_br3;
7005 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
7006 buf[0] |= 0x02;
7007 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07007008 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307009 }
7010}
7011
7012/**
7013 * hdd_cnss_wlan_mac() - API to get mac addresses from cnss platform driver
7014 * @hdd_ctx: HDD Context
7015 *
7016 * API to get mac addresses from platform driver and update the driver
7017 * structures and configure FW with the base mac address.
7018 * Return: int
7019 */
7020static int hdd_cnss_wlan_mac(hdd_context_t *hdd_ctx)
7021{
7022 uint32_t no_of_mac_addr, iter;
7023 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
7024 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
7025 uint8_t *addr, *buf;
7026 struct device *dev = hdd_ctx->parent_dev;
7027 struct hdd_config *ini = hdd_ctx->config;
7028 tSirMacAddr mac_addr;
7029 QDF_STATUS status;
7030
7031 addr = hdd_get_cnss_wlan_mac_buff(dev, &no_of_mac_addr);
7032
7033 if (no_of_mac_addr == 0 || !addr) {
7034 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
7035 return -EINVAL;
7036 }
7037
7038 if (no_of_mac_addr > max_mac_addr)
7039 no_of_mac_addr = max_mac_addr;
7040
7041 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
7042
7043 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
7044 buf = ini->intfMacAddr[iter].bytes;
7045 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07007046 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05307047 }
7048
7049 status = sme_set_custom_mac_addr(mac_addr);
7050
7051 if (!QDF_IS_STATUS_SUCCESS(status))
7052 return -EAGAIN;
7053 if (no_of_mac_addr < max_mac_addr)
7054 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
7055 no_of_mac_addr);
7056 return 0;
7057}
7058
7059/**
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007060 * hdd_update_mac_addr_to_fw() - API to update wlan mac addresses to FW
7061 * @hdd_ctx: HDD Context
7062 *
7063 * Update MAC address to FW. If MAC address passed by FW is invalid, host
7064 * will generate its own MAC and update it to FW.
7065 *
7066 * Return: 0 for success
7067 * Non-zero error code for failure
7068 */
7069static int hdd_update_mac_addr_to_fw(hdd_context_t *hdd_ctx)
7070{
7071 tSirMacAddr customMacAddr;
7072 QDF_STATUS status;
7073
7074 qdf_mem_copy(&customMacAddr,
7075 &hdd_ctx->config->intfMacAddr[0].bytes[0],
7076 sizeof(tSirMacAddr));
7077 status = sme_set_custom_mac_addr(customMacAddr);
7078 if (!QDF_IS_STATUS_SUCCESS(status))
7079 return -EAGAIN;
7080 return 0;
7081}
7082
7083/**
Komal Seelam92fff912016-03-24 11:51:41 +05307084 * hdd_initialize_mac_address() - API to get wlan mac addresses
7085 * @hdd_ctx: HDD Context
7086 *
7087 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
7088 * is provisioned with mac addresses, driver uses it, else it will use
7089 * wlan_mac.bin to update HW MAC addresses.
7090 *
7091 * Return: None
7092 */
7093static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
7094{
7095 QDF_STATUS status;
7096 int ret;
7097
7098 ret = hdd_cnss_wlan_mac(hdd_ctx);
7099 if (ret == 0)
7100 return;
7101
7102 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7103
7104 status = hdd_update_mac_config(hdd_ctx);
7105
Yuanyuan Liu245a3e42016-09-14 12:15:16 -07007106 if (QDF_IS_STATUS_SUCCESS(status))
7107 return;
7108
7109 hdd_warn("can't update mac config via wlan_mac.bin, using MAC from ini file or auto-gen");
7110
7111 if (hdd_ctx->update_mac_addr_to_fw)
7112 ret = hdd_update_mac_addr_to_fw(hdd_ctx);
7113
7114 if (ret != 0) {
7115 hdd_err("MAC address out-of-sync, ret:%d", ret);
7116 QDF_ASSERT(ret);
7117 }
Komal Seelam92fff912016-03-24 11:51:41 +05307118}
7119
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007120/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007121 * hdd_tsf_init() - Initialize the TSF synchronization interface
7122 * @hdd_ctx: HDD global context
7123 *
7124 * When TSF synchronization via GPIO is supported by the driver and
7125 * has been enabled in the configuration file, this function plumbs
7126 * the GPIO value down to firmware via SME.
7127 *
7128 * Return: None
7129 */
7130#ifdef WLAN_FEATURE_TSF
7131static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7132{
7133 QDF_STATUS status;
7134
7135 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7136 return;
7137
7138 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7139 hdd_ctx->config->tsf_gpio_pin);
7140 if (!QDF_IS_STATUS_SUCCESS(status))
7141 hdd_err("Set tsf GPIO failed, status: %d", status);
7142}
7143#else
7144static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7145{
7146}
7147#endif
7148
7149/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007150 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7151 * @hdd_ctx: HDD context
7152 *
7153 * Pre configurations to be done at lower layer before calling cds enable.
7154 *
7155 * Return: 0 on success and errno on failure.
7156 */
7157static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7158{
7159 int ret;
7160 QDF_STATUS status;
7161 tSirRetStatus hal_status;
7162
7163 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
7164
7165 /*
7166 * Set 802.11p config
7167 * TODO-OCB: This has been temporarily added here to ensure this
7168 * parameter is set in CSR when we init the channel list. This should
7169 * be removed once the 5.9 GHz channels are added to the regulatory
7170 * domain.
7171 */
7172 hdd_set_dot11p_config(hdd_ctx);
7173
7174 /*
7175 * Note that the cds_pre_enable() sequence triggers the cfg download.
7176 * The cfg download must occur before we update the SME config
7177 * since the SME config operation must access the cfg database
7178 */
7179 status = hdd_set_sme_config(hdd_ctx);
7180
7181 if (QDF_STATUS_SUCCESS != status) {
7182 hdd_alert("Failed hdd_set_sme_config: %d", status);
7183 ret = qdf_status_to_os_return(status);
7184 goto out;
7185 }
7186
7187 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7188 hdd_ctx->config->tx_chain_mask_1ss,
7189 PDEV_CMD);
7190 if (0 != ret) {
7191 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7192 goto out;
7193 }
7194
7195 hdd_program_country_code(hdd_ctx);
7196
7197 status = hdd_set_sme_chan_list(hdd_ctx);
7198 if (status != QDF_STATUS_SUCCESS) {
7199 hdd_alert("Failed to init channel list: %d", status);
7200 ret = qdf_status_to_os_return(status);
7201 goto out;
7202 }
7203
7204 /* Apply the cfg.ini to cfg.dat */
Krunal Sonidf0f8742016-09-26 14:56:31 -07007205 if (!hdd_update_config_cfg(hdd_ctx)) {
Prashanth Bhatta07998752016-04-28 12:35:33 -07007206 hdd_alert("config update failed");
7207 ret = -EINVAL;
7208 goto out;
7209 }
7210
Komal Seelam92fff912016-03-24 11:51:41 +05307211 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007212
7213 /*
7214 * Set the MAC Address Currently this is used by HAL to add self sta.
7215 * Remove this once self sta is added as part of session open.
7216 */
7217 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7218 hdd_ctx->config->intfMacAddr[0].bytes,
7219 sizeof(hdd_ctx->config->intfMacAddr[0]));
7220
7221 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7222 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7223 hal_status, hal_status);
7224 ret = -EINVAL;
7225 goto out;
7226 }
7227
7228 hdd_init_channel_avoidance(hdd_ctx);
7229
7230out:
7231 return ret;
7232}
7233
7234/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007235 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7236 * @context_ptr - hdd context pointer
7237 * @event_ptr - event structure pointer
7238 *
7239 * This is the p2p listen offload stop event handler, it sends vendor
7240 * event back to supplicant to notify the stop reason.
7241 *
7242 * Return: None
7243 */
7244static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7245 void *event_ptr)
7246{
7247 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7248 struct sir_p2p_lo_event *evt = event_ptr;
7249 struct sk_buff *vendor_event;
7250
7251 ENTER();
7252
7253 if (hdd_ctx == NULL) {
7254 hdd_err("Invalid HDD context pointer");
7255 return;
7256 }
7257
7258 vendor_event =
7259 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7260 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7261 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7262 GFP_KERNEL);
7263
7264 if (!vendor_event) {
7265 hdd_err("cfg80211_vendor_event_alloc failed");
7266 return;
7267 }
7268
7269 if (nla_put_u32(vendor_event,
7270 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7271 evt->reason_code)) {
7272 hdd_err("nla put failed");
7273 kfree_skb(vendor_event);
7274 return;
7275 }
7276
7277 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7278}
7279
7280/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307281 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7282 * @hdd_ctx: HDD context
7283 *
7284 * This function sends the adaptive dwell time config configuration to the
7285 * firmware via WMA
7286 *
7287 * Return: 0 - success, < 0 - failure
7288 */
7289static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7290{
7291 QDF_STATUS status;
7292 struct adaptive_dwelltime_params dwelltime_params;
7293
7294 dwelltime_params.is_enabled =
7295 hdd_ctx->config->adaptive_dwell_mode_enabled;
7296 dwelltime_params.dwelltime_mode =
7297 hdd_ctx->config->global_adapt_dwelltime_mode;
7298 dwelltime_params.lpf_weight =
7299 hdd_ctx->config->adapt_dwell_lpf_weight;
7300 dwelltime_params.passive_mon_intval =
7301 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7302 dwelltime_params.wifi_act_threshold =
7303 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7304
7305 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7306 &dwelltime_params);
7307
7308 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7309 if (!QDF_IS_STATUS_SUCCESS(status)) {
7310 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7311 return -EAGAIN;
7312 }
7313 return 0;
7314}
7315
Arun Khandavallid4349a92016-07-25 11:10:43 +05307316#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7317/**
7318 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7319 * @hdd_ctx: HDD context
7320 *
7321 * Set auto shutdown callback to get indications from firmware to indicate
7322 * userspace to shutdown WLAN after a configured amount of inactivity.
7323 *
7324 * Return: 0 on success and errno on failure.
7325 */
7326static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7327{
7328 QDF_STATUS status;
7329
7330 if (!hdd_ctx->config->WlanAutoShutdown)
7331 return 0;
7332
7333 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7334 wlan_hdd_auto_shutdown_cb);
7335 if (status != QDF_STATUS_SUCCESS)
7336 hdd_err("Auto shutdown feature could not be enabled: %d",
7337 status);
7338
7339 return qdf_status_to_os_return(status);
7340}
7341#else
7342static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7343{
7344 return 0;
7345}
7346#endif
7347
7348/**
7349 * hdd_features_init() - Init features
7350 * @hdd_ctx: HDD context
7351 * @adapter: Primary adapter context
7352 *
7353 * Initialize features and their feature context after WLAN firmware is up.
7354 *
7355 * Return: 0 on success and errno on failure.
7356 */
7357static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7358{
7359 tSirTxPowerLimit hddtxlimit;
7360 QDF_STATUS status;
7361 int ret;
7362
7363 ENTER();
7364
7365 ret = hdd_update_country_code(hdd_ctx, adapter);
7366 if (ret) {
7367 hdd_err("Failed to update country code: %d", ret);
7368 goto out;
7369 }
7370
7371 /* FW capabilities received, Set the Dot11 mode */
7372 sme_setdef_dot11mode(hdd_ctx->hHal);
7373
Arun Khandavallid4349a92016-07-25 11:10:43 +05307374
7375 if (hdd_ctx->config->fIsImpsEnabled)
7376 hdd_set_idle_ps_config(hdd_ctx, true);
7377 else
7378 hdd_set_idle_ps_config(hdd_ctx, false);
7379
7380 if (hdd_lro_init(hdd_ctx))
7381 hdd_err("Unable to initialize LRO in fw");
7382
7383 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7384 hdd_err("Unable to send adaptive dwelltime setting to FW");
7385
7386 ret = hdd_init_thermal_info(hdd_ctx);
7387 if (ret) {
7388 hdd_err("Error while initializing thermal information");
7389 goto deregister_frames;
7390 }
7391
7392 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7393 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7394 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7395 if (!QDF_IS_STATUS_SUCCESS(status))
7396 hdd_err("Error setting txlimit in sme: %d", status);
7397
7398 hdd_tsf_init(hdd_ctx);
7399
Arun Khandavallid4349a92016-07-25 11:10:43 +05307400 ret = hdd_register_cb(hdd_ctx);
7401 if (ret) {
7402 hdd_err("Failed to register HDD callbacks!");
7403 goto deregister_frames;
7404 }
7405
7406 if (hdd_ctx->config->dual_mac_feature_disable) {
7407 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7408 if (status != QDF_STATUS_SUCCESS) {
7409 hdd_err("Failed to disable dual mac features");
7410 goto deregister_cb;
7411 }
7412 }
7413
7414 /* register P2P Listen Offload event callback */
7415 if (wma_is_p2p_lo_capable())
7416 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7417 wlan_hdd_p2p_lo_event_callback);
7418
7419 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7420
7421 if (ret)
7422 goto deregister_cb;
7423
7424 EXIT();
7425 return 0;
7426
7427deregister_cb:
7428 hdd_deregister_cb(hdd_ctx);
7429deregister_frames:
7430 wlan_hdd_cfg80211_deregister_frames(adapter);
7431out:
7432 return -EINVAL;
7433
7434}
7435
7436
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307437/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307438 * hdd_configure_cds() - Configure cds modules
7439 * @hdd_ctx: HDD context
7440 * @adapter: Primary adapter context
7441 *
7442 * Enable Cds modules after WLAN firmware is up.
7443 *
7444 * Return: 0 on success and errno on failure.
7445 */
7446int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7447{
7448 int ret;
7449 QDF_STATUS status;
7450 /* structure of function pointers to be used by CDS */
7451 struct cds_sme_cbacks sme_cbacks;
7452
7453 ret = hdd_pre_enable_configure(hdd_ctx);
7454 if (ret) {
7455 hdd_err("Failed to pre-configure cds");
7456 goto out;
7457 }
7458
7459 /*
7460 * Start CDS which starts up the SME/MAC/HAL modules and everything
7461 * else
7462 */
7463 status = cds_enable(hdd_ctx->pcds_context);
7464
7465 if (!QDF_IS_STATUS_SUCCESS(status)) {
7466 hdd_alert("cds_enable failed");
7467 goto out;
7468 }
7469
7470 status = hdd_post_cds_enable_config(hdd_ctx);
7471 if (!QDF_IS_STATUS_SUCCESS(status)) {
7472 hdd_alert("hdd_post_cds_enable_config failed");
7473 goto out;
7474 }
7475
7476 ret = hdd_features_init(hdd_ctx, adapter);
7477 if (ret)
7478 goto out;
7479
7480 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7481 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7482 status = cds_init_policy_mgr(&sme_cbacks);
7483 if (!QDF_IS_STATUS_SUCCESS(status)) {
7484 hdd_err("Policy manager initialization failed");
7485 goto out;
7486 }
7487
7488 return 0;
7489out:
7490 return -EINVAL;
7491}
7492
7493/**
7494 * hdd_deconfigure_cds() -De-Configure cds
7495 * @hdd_ctx: HDD context
7496 *
7497 * Deconfigure Cds modules before WLAN firmware is down.
7498 *
7499 * Return: 0 on success and errno on failure.
7500 */
7501int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
7502{
7503 QDF_STATUS qdf_status;
7504
7505 ENTER();
7506 /* De-register the SME callbacks */
7507 hdd_deregister_cb(hdd_ctx);
7508
7509 /* De-init Policy Manager */
7510 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7511 hdd_err("Failed to deinit policy manager");
7512 /* Proceed and complete the clean up */
7513 return -EINVAL;
7514 }
7515
7516 qdf_status = cds_disable(hdd_ctx->pcds_context);
7517 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7518 hdd_err("Failed to Disable the CDS Modules! :%d",
7519 qdf_status);
7520 return -EINVAL;
7521 }
7522
7523 EXIT();
7524 return 0;
7525}
7526
7527
7528/**
7529 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7530 * @hdd_ctx: HDD context
7531 * @shutdown: flag to indicate from SSR or normal path
7532 *
7533 * This function maintains the driver state machine it will be invoked from
7534 * exit, shutdown and con_mode change handler. Depending on the driver state
7535 * shall perform the stopping/closing of the modules.
7536 *
7537 * Return: 0 for success; non-zero for failure
7538 */
7539int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
7540{
7541 void *hif_ctx;
7542 qdf_device_t qdf_ctx;
7543 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307544 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307545 p_cds_sched_context cds_sched_context = NULL;
7546
7547 ENTER();
7548
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307549
Arun Khandavallifae92942016-08-01 13:31:08 +05307550 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7551 if (!qdf_ctx) {
7552 hdd_err("QDF device context NULL");
7553 return -EINVAL;
7554 }
7555
7556 cds_sched_context = get_cds_sched_ctxt();
7557 if (!cds_sched_context) {
7558 hdd_err("cds scheduler context NULL");
7559 return -EINVAL;
7560 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307561 mutex_lock(&hdd_ctx->iface_change_lock);
7562 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307563
7564 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7565
7566 switch (hdd_ctx->driver_status) {
7567 case DRIVER_MODULES_UNINITIALIZED:
7568 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307569 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307570 case DRIVER_MODULES_CLOSED:
7571 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307572 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307573 case DRIVER_MODULES_ENABLED:
7574 if (hdd_deconfigure_cds(hdd_ctx)) {
7575 hdd_alert("Failed to de-configure CDS");
7576 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307577 ret = -EINVAL;
7578 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307579 }
7580 hdd_info("successfully Disabled the CDS modules!");
7581 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7582 break;
7583 case DRIVER_MODULES_OPENED:
7584 hdd_info("Closing CDS modules!");
7585 break;
7586 default:
7587 hdd_err("Trying to stop wlan in a wrong state: %d",
7588 hdd_ctx->driver_status);
7589 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307590 ret = -EINVAL;
7591 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307592 }
7593
7594 qdf_status = cds_close(hdd_ctx->pcds_context);
7595 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7596 hdd_warn("Failed to stop CDS:%d", qdf_status);
7597 QDF_ASSERT(0);
7598 }
7599 /* Clean up message queues of TX, RX and MC thread */
7600 cds_sched_flush_mc_mqs(cds_sched_context);
7601
7602 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
7603 if (!hif_ctx) {
7604 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307605 ret = -EINVAL;
7606 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307607 }
7608
7609 hdd_hif_close(hif_ctx);
7610
7611 ol_cds_free();
7612
7613 if (!shutdown) {
7614 ret = pld_power_off(qdf_ctx->dev);
7615 if (ret)
7616 hdd_err("CNSS power down failed put device into Low power mode:%d",
7617 ret);
7618 }
7619 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
7620
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307621done:
7622 hdd_ctx->stop_modules_in_progress = false;
7623 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05307624 EXIT();
7625
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307626 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307627
7628}
7629
7630/**
7631 * hdd_iface_change_callback() - Function invoked when stop modules expires
7632 * @priv: pointer to hdd context
7633 *
7634 * This function is invoked when the timer waiting for the interface change
7635 * expires, it shall cut-down the power to wlan and stop all the modules.
7636 *
7637 * Return: void
7638 */
7639static void hdd_iface_change_callback(void *priv)
7640{
7641 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
7642 int ret;
7643 int status = wlan_hdd_validate_context(hdd_ctx);
7644
7645 if (status)
7646 return;
7647
7648 ENTER();
7649 hdd_info("Interface change timer expired close the modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05307650 ret = hdd_wlan_stop_modules(hdd_ctx, false);
7651 if (ret)
7652 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05307653 EXIT();
7654}
7655
7656/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007657 * hdd_wlan_startup() - HDD init function
7658 * @dev: Pointer to the underlying device
7659 *
7660 * This is the driver startup code executed once a WLAN device has been detected
7661 *
7662 * Return: 0 for success, < 0 for failure
7663 */
Arun Khandavallifae92942016-08-01 13:31:08 +05307664int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007665{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307666 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007667 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007668 hdd_context_t *hdd_ctx = NULL;
7669 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307670 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007671 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05307672 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007673
7674 ENTER();
7675
Arun Khandavallifae92942016-08-01 13:31:08 +05307676 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007677
7678 if (IS_ERR(hdd_ctx))
7679 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007680
Arun Khandavallifae92942016-08-01 13:31:08 +05307681 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
7682 hdd_iface_change_callback, (void *)hdd_ctx);
7683
7684 mutex_init(&hdd_ctx->iface_change_lock);
7685
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007686 ret = hdd_init_netlink_services(hdd_ctx);
7687 if (ret)
7688 goto err_hdd_free_context;
7689
Jeff Johnsona7e5eed2016-09-28 15:19:13 -07007690 hdd_green_ap_init(hdd_ctx);
Arun Khandavallifae92942016-08-01 13:31:08 +05307691
Arun Khandavallifae92942016-08-01 13:31:08 +05307692 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
7693 if (ret) {
7694 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007695 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007696 }
7697
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007698 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007699
Anurag Chouhan6d760662016-02-20 16:05:43 +05307700 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007701
7702 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007703 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05307704 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007705 }
7706
Prashanth Bhatta07998752016-04-28 12:35:33 -07007707 ret = hdd_wiphy_init(hdd_ctx);
7708 if (ret) {
7709 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05307710 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007711 }
7712
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05307713 if (hdd_ctx->config->enable_dp_trace)
7714 qdf_dp_trace_init();
7715
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307716 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007717 goto err_wiphy_unregister;
7718
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08007719
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007720 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007721
Arun Khandavallifae92942016-08-01 13:31:08 +05307722
7723 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007724
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007725 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007726 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007727 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05307728 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007729 }
7730
Arun Khandavallifae92942016-08-01 13:31:08 +05307731 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Anurag Chouhance6a4052016-09-14 18:20:42 +05307732 if (!hif_sc) {
7733 hdd_err("HIF context is NULL");
7734 goto err_close_adapter;
7735 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007736 /*
7737 * target hw version/revision would only be retrieved after firmware
7738 * donwload
7739 */
7740 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
7741 &hdd_ctx->target_hw_revision,
7742 &hdd_ctx->target_hw_name);
7743
7744 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05307745 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007746
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007747 hdd_release_rtnl_lock();
7748 rtnl_held = false;
7749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007750#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05307751 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307752 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007753 hdd_skip_acs_scan_timer_handler,
7754 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307755 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07007756 hdd_err("Failed to init ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007757#endif
7758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007759#ifdef MSM_PLATFORM
7760 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05307761 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307762 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007763 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
7764#endif
7765
Jeff Johnson9afc5012016-09-23 13:56:27 -07007766 hdd_lpass_notify_start(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007767
Nirav Shahbd36b062016-07-18 11:12:59 +05307768 if (hdd_ctx->rps)
7769 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07007770
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007771
7772 if (cds_is_packet_log_enabled())
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007773 hdd_pktlog_enable_disable(hdd_ctx, true, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007774
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007775 ret = hdd_register_notifiers(hdd_ctx);
7776 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05307777 goto err_debugfs_exit;
7778
7779 status = wlansap_global_init();
7780 if (QDF_IS_STATUS_ERROR(status))
7781 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007782
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007783 memdump_init();
7784
Arun Khandavallifae92942016-08-01 13:31:08 +05307785 if (hdd_ctx->config->fIsImpsEnabled)
7786 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307787
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05307788 if (hdd_ctx->config->sifs_burst_duration) {
7789 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
7790 hdd_ctx->config->sifs_burst_duration;
7791
7792 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
7793 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
7794 set_value, PDEV_CMD);
7795 }
7796
Arun Khandavallifae92942016-08-01 13:31:08 +05307797 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
7798 hdd_ctx->config->iface_change_wait_time * 5000);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05307799
7800 if (hdd_ctx->config->goptimize_chan_avoid_event) {
7801 status = sme_enable_disable_chanavoidind_event(
7802 hdd_ctx->hHal, 0);
7803 if (!QDF_IS_STATUS_SUCCESS(status))
7804 hdd_err("Failed to disable Chan Avoidance Indication");
7805 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007806 goto success;
7807
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007808err_debugfs_exit:
7809 hdd_debugfs_exit(adapter);
Anurag Chouhance6a4052016-09-14 18:20:42 +05307810
7811err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007812 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007813
Arun Khandavallid4349a92016-07-25 11:10:43 +05307814 if (rtnl_held)
7815 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007816
Anurag Chouhance6a4052016-09-14 18:20:42 +05307817err_ipa_cleanup:
7818 hdd_ipa_cleanup(hdd_ctx);
Yun Park6a46ad82016-01-04 16:48:19 -08007819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007820err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007821 wiphy_unregister(hdd_ctx->wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05307822 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007823
Arun Khandavallifae92942016-08-01 13:31:08 +05307824err_stop_modules:
7825 hdd_wlan_stop_modules(hdd_ctx, false);
7826
7827
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007828 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307829 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007830 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307831 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007832 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007833
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007834err_exit_nl_srv:
7835 hdd_exit_netlink_services(hdd_ctx);
7836
7837 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7838 hdd_err("Failed to deinit policy manager");
7839 /* Proceed and complete the clean up */
7840 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307841 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007842err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05307843 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
7844 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007845 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307846 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007847
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007848 return -EIO;
7849
7850success:
7851 EXIT();
7852 return 0;
7853}
7854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007855/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307856 * hdd_wlan_update_target_info() - update target type info
7857 * @hdd_ctx: HDD context
7858 * @context: hif context
7859 *
7860 * Update target info received from firmware in hdd context
7861 * Return:None
7862 */
7863
7864void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
7865{
7866 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
7867
7868 if (!tgt_info) {
7869 hdd_err("Target info is Null");
7870 return;
7871 }
7872
7873 hdd_ctx->target_type = tgt_info->target_type;
7874}
7875
7876/**
7877 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307878 * @hdd_ctx: HDD context
7879 *
7880 * Register the HDD callbacks to CDS/SME.
7881 *
7882 * Return: 0 for success or Error code for failure
7883 */
7884int hdd_register_cb(hdd_context_t *hdd_ctx)
7885{
7886 QDF_STATUS status;
7887 int ret = 0;
7888
7889 ENTER();
7890
7891 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
7892
7893 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
7894 hdd_send_oem_data_rsp_msg);
7895
7896 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
7897 wlan_hdd_cfg80211_fw_mem_dump_cb);
7898 if (!QDF_IS_STATUS_SUCCESS(status)) {
7899 hdd_err("Failed to register memdump callback");
7900 ret = -EINVAL;
7901 return ret;
7902 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05307903 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
7904 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307905 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
7906 sme_nan_register_callback(hdd_ctx->hHal,
7907 wlan_hdd_cfg80211_nan_callback);
7908 sme_stats_ext_register_callback(hdd_ctx->hHal,
7909 wlan_hdd_cfg80211_stats_ext_callback);
7910
7911 sme_ext_scan_register_callback(hdd_ctx->hHal,
7912 wlan_hdd_cfg80211_extscan_callback);
7913
7914 status = cds_register_sap_restart_channel_switch_cb(
7915 (void *)hdd_sap_restart_with_channel_switch);
7916 if (!QDF_IS_STATUS_SUCCESS(status)) {
7917 hdd_err("restart cb registration failed");
7918 ret = -EINVAL;
7919 return ret;
7920 }
7921
7922 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
7923 hdd_rssi_threshold_breached);
7924
7925 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
7926 hdd_get_bpf_offload_cb);
7927 if (!QDF_IS_STATUS_SUCCESS(status)) {
7928 hdd_err("set bpf offload callback failed");
7929 ret = -EINVAL;
7930 return ret;
7931 }
7932
7933 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
7934 wlan_hdd_cfg80211_link_layer_stats_callback);
7935
7936 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
7937
7938 EXIT();
7939
7940 return ret;
7941}
7942
7943/**
7944 * hdd_deregister_cb() - De-Register HDD callbacks.
7945 * @hdd_ctx: HDD context
7946 *
7947 * De-Register the HDD callbacks to CDS/SME.
7948 *
7949 * Return: void
7950 */
7951void hdd_deregister_cb(hdd_context_t *hdd_ctx)
7952{
7953 QDF_STATUS status;
7954
7955 ENTER();
7956
7957 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
7958 if (!QDF_IS_STATUS_SUCCESS(status))
7959 hdd_err("De-register of dcc stats callback failed: %d",
7960 status);
7961
7962 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
7963 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
7964 if (!QDF_IS_STATUS_SUCCESS(status))
7965 hdd_err("De-register bpf offload callback failed: %d",
7966 status);
7967 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
7968
7969 status = cds_deregister_sap_restart_channel_switch_cb();
7970 if (!QDF_IS_STATUS_SUCCESS(status))
7971 hdd_err("De-register restart cb registration failed: %d",
7972 status);
7973
7974 sme_stats_ext_register_callback(hdd_ctx->hHal,
7975 wlan_hdd_cfg80211_stats_ext_callback);
7976
7977 sme_nan_deregister_callback(hdd_ctx->hHal);
7978 status = sme_reset_tsfcb(hdd_ctx->hHal);
7979 if (!QDF_IS_STATUS_SUCCESS(status))
7980 hdd_err("Failed to de-register tsfcb the callback:%d",
7981 status);
7982 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
7983 if (!QDF_IS_STATUS_SUCCESS(status))
7984 hdd_err("Failed to de-register the fw mem dump callback: %d",
7985 status);
7986
7987 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
7988 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
7989
7990 EXIT();
7991}
7992
7993/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007994 * hdd_softap_sta_deauth() - handle deauth req from HDD
7995 * @adapter: Pointer to the HDD
7996 * @enable: bool value
7997 *
7998 * This to take counter measure to handle deauth req from HDD
7999 *
8000 * Return: None
8001 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308002QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008003 struct tagCsrDelStaParams *pDelStaParams)
8004{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308005 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008006
8007 ENTER();
8008
Jeff Johnson34c88b72016-08-15 14:27:11 -07008009 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008010 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8011
8012 /* Ignore request to deauth bcmc station */
8013 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308014 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008015
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308016 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008017 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8018 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008019
8020 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308021 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008022}
8023
8024/**
8025 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
8026 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308027 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008028 *
8029 * This to take counter measure to handle deauth req from HDD
8030 *
8031 * Return: None
8032 */
8033void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308034 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008035{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008036 ENTER();
8037
Jeff Johnson34c88b72016-08-15 14:27:11 -07008038 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008039 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8040
8041 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308042 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008043 return;
8044
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008045 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05308046 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008047}
8048
8049void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
8050 bool enable)
8051{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008052 ENTER();
8053
Jeff Johnson34c88b72016-08-15 14:27:11 -07008054 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008055 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
8056
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008057 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8058 (bool) enable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008059}
8060
8061/**
8062 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
8063 * @hdd_ctx: HDD Context
8064 *
8065 * API to find if there is any STA or P2P-Client is connected
8066 *
8067 * Return: true if connected; false otherwise
8068 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308069QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008070{
8071 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
8072}
8073
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008074/**
8075 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
8076 * @adapter: HDD adapter pointer
8077 *
8078 * This function loop through each adapter and disable roaming on each STA
8079 * device mode except the input adapter.
8080 *
8081 * Note: On the input adapter roaming is not enabled yet hence no need to
8082 * disable.
8083 *
8084 * Return: None
8085 */
8086void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8087{
8088 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8089 hdd_adapter_t *adapterIdx = NULL;
8090 hdd_adapter_list_node_t *adapterNode = NULL;
8091 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308092 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008093
8094 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8095 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008096 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008097 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008098 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008099 adapter->sessionId);
8100 /*
8101 * Loop through adapter and disable roaming for each STA device
8102 * mode except the input adapter.
8103 */
8104 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308106 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008107 adapterIdx = adapterNode->pAdapter;
8108
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008109 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008110 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008111 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008112 adapterIdx->sessionId);
8113 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8114 (adapterIdx),
8115 adapterIdx->sessionId, 0);
8116 }
8117
8118 status = hdd_get_next_adapter(hdd_ctx,
8119 adapterNode,
8120 &pNext);
8121 adapterNode = pNext;
8122 }
8123 }
8124}
8125
8126/**
8127 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8128 * @adapter: HDD adapter pointer
8129 *
8130 * This function loop through each adapter and enable roaming on each STA
8131 * device mode except the input adapter.
8132 * Note: On the input adapter no need to enable roaming because link got
8133 * disconnected on this.
8134 *
8135 * Return: None
8136 */
8137void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8138{
8139 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8140 hdd_adapter_t *adapterIdx = NULL;
8141 hdd_adapter_list_node_t *adapterNode = NULL;
8142 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308143 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008144
8145 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8146 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008147 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008148 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008149 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008150 adapter->sessionId);
8151 /*
8152 * Loop through adapter and enable roaming for each STA device
8153 * mode except the input adapter.
8154 */
8155 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8156
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308157 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008158 adapterIdx = adapterNode->pAdapter;
8159
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008160 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008161 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008162 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008163 adapterIdx->sessionId);
8164 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8165 (adapterIdx),
8166 adapterIdx->sessionId,
8167 REASON_CONNECT);
8168 }
8169
8170 status = hdd_get_next_adapter(hdd_ctx,
8171 adapterNode,
8172 &pNext);
8173 adapterNode = pNext;
8174 }
8175 }
8176}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008177
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308178void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008179{
8180 struct sk_buff *skb;
8181 struct nlmsghdr *nlh;
8182 tAniMsgHdr *ani_hdr;
8183 void *nl_data = NULL;
8184 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308185 struct radio_index_tlv *radio_info;
8186 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008187
8188 if (in_interrupt() || irqs_disabled() || in_atomic())
8189 flags = GFP_ATOMIC;
8190
8191 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8192
8193 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008194 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008195 return;
8196 }
8197
8198 nlh = (struct nlmsghdr *)skb->data;
8199 nlh->nlmsg_pid = 0; /* from kernel */
8200 nlh->nlmsg_flags = 0;
8201 nlh->nlmsg_seq = 0;
8202 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8203
8204 ani_hdr = NLMSG_DATA(nlh);
8205 ani_hdr->type = type;
8206
8207 switch (type) {
8208 case WLAN_SVC_FW_CRASHED_IND:
Komal Seelam78ff65a2016-08-18 15:25:24 +05308209 case WLAN_SVC_FW_SHUTDOWN_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008210 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008211 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008212 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008213 ani_hdr->length = 0;
8214 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8215 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8216 break;
8217 case WLAN_SVC_WLAN_STATUS_IND:
8218 case WLAN_SVC_WLAN_VERSION_IND:
8219 case WLAN_SVC_DFS_CAC_START_IND:
8220 case WLAN_SVC_DFS_CAC_END_IND:
8221 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8222 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8223 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008224 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308225 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008226 ani_hdr->length = len;
8227 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8228 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8229 memcpy(nl_data, data, len);
8230 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
8231 break;
8232
8233 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008234 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008235 type);
8236 kfree_skb(skb);
8237 return;
8238 }
8239
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308240 /*
8241 * Add radio index at the end of the svc event in TLV format to maintain
8242 * the backward compatibility with userspace applications.
8243 */
8244
8245 tlv_len = 0;
8246
8247 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8248 < WLAN_NL_MAX_PAYLOAD) {
8249 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8250 sizeof(*ani_hdr) + len);
8251 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8252 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8253 radio_info->radio = radio;
8254 tlv_len = sizeof(*radio_info);
8255 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8256 "Added radio index tlv - radio index %d",
8257 radio_info->radio);
8258 }
8259
8260 nlh->nlmsg_len += tlv_len;
8261 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8262
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008263 nl_srv_bcast(skb);
8264
8265 return;
8266}
8267
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008268#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8269void wlan_hdd_auto_shutdown_cb(void)
8270{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008271 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308272
8273 if (!hdd_ctx)
8274 return;
8275
Jeff Johnson28f8a772016-08-15 15:30:36 -07008276 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308277 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8278 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008279}
8280
8281void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8282{
8283 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308284 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008285 hdd_adapter_t *adapter;
8286 bool ap_connected = false, sta_connected = false;
8287 tHalHandle hal_handle;
8288
8289 hal_handle = hdd_ctx->hHal;
8290 if (hal_handle == NULL)
8291 return;
8292
8293 if (hdd_ctx->config->WlanAutoShutdown == 0)
8294 return;
8295
8296 if (enable == false) {
8297 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308298 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008299 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008300 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308301 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008302 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008303 return;
8304 }
8305
8306 /* To enable shutdown timer check conncurrency */
8307 if (cds_concurrent_open_sessions_running()) {
8308 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8309
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308310 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008311 adapter = adapterNode->pAdapter;
8312 if (adapter
8313 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008314 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008315 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8316 conn_info.connState ==
8317 eConnectionState_Associated) {
8318 sta_connected = true;
8319 break;
8320 }
8321 }
8322 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008323 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008324 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8325 bApActive == true) {
8326 ap_connected = true;
8327 break;
8328 }
8329 }
8330 status = hdd_get_next_adapter(hdd_ctx,
8331 adapterNode,
8332 &pNext);
8333 adapterNode = pNext;
8334 }
8335 }
8336
8337 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008338 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008339 return;
8340 } else {
8341 if (sme_set_auto_shutdown_timer(hal_handle,
8342 hdd_ctx->config->
8343 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308344 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008345 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008346 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008347 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008348 hdd_ctx->config->WlanAutoShutdown);
8349
8350 }
8351}
8352#endif
8353
8354hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8355 bool check_start_bss)
8356{
8357 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8358 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308359 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008360 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8361
8362 con_sap_adapter = NULL;
8363
8364 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308365 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008366 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008367 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8368 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008369 adapter != this_sap_adapter) {
8370 if (check_start_bss) {
8371 if (test_bit(SOFTAP_BSS_STARTED,
8372 &adapter->event_flags)) {
8373 con_sap_adapter = adapter;
8374 break;
8375 }
8376 } else {
8377 con_sap_adapter = adapter;
8378 break;
8379 }
8380 }
8381 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8382 adapterNode = pNext;
8383 }
8384
8385 return con_sap_adapter;
8386}
8387
8388#ifdef MSM_PLATFORM
8389void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8390{
8391 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8392
Anurag Chouhan210db072016-02-22 18:42:15 +05308393 if (QDF_TIMER_STATE_RUNNING ==
8394 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008395 return;
8396
Anurag Chouhan210db072016-02-22 18:42:15 +05308397 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008398 hdd_ctx->config->busBandwidthComputeInterval);
8399}
8400
8401void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8402{
8403 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308404 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008405 bool can_stop = true;
8406 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8407
Anurag Chouhan210db072016-02-22 18:42:15 +05308408 if (QDF_TIMER_STATE_RUNNING !=
8409 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008410 /* trying to stop timer, when not running is not good */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008411 hdd_err("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008412 return;
8413 }
8414
8415 if (cds_concurrent_open_sessions_running()) {
8416 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8417
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308418 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008419 adapter = adapterNode->pAdapter;
8420 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008421 && (adapter->device_mode == QDF_STA_MODE
8422 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008423 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8424 conn_info.connState ==
8425 eConnectionState_Associated) {
8426 can_stop = false;
8427 break;
8428 }
8429 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008430 && (adapter->device_mode == QDF_SAP_MODE
8431 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008432 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8433 true) {
8434 can_stop = false;
8435 break;
8436 }
8437 status = hdd_get_next_adapter(hdd_ctx,
8438 adapterNode,
8439 &pNext);
8440 adapterNode = pNext;
8441 }
8442 }
8443
Ravi Joshib89e7f72016-09-07 13:43:15 -07008444 if (can_stop == true) {
Anurag Chouhan210db072016-02-22 18:42:15 +05308445 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Ravi Joshib89e7f72016-09-07 13:43:15 -07008446 hdd_reset_tcp_delack(hdd_ctx);
8447 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008448}
8449#endif
8450
8451/**
8452 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8453 * and sta's operating channel.
8454 * @sta_adapter: Describe the first argument to foobar.
8455 * @ap_adapter: Describe the second argument to foobar.
8456 * @roam_profile: Roam profile of AP to which STA wants to connect.
8457 * @concurrent_chnl_same: If both SAP and STA channels are same then
8458 * set this flag to true else false.
8459 *
8460 * This function checks the sap's operating channel and sta's operating channel.
8461 * if both are same then it will return false else it will restart the sap in
8462 * sta's channel and return true.
8463 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308464 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008465 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308466QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008467 hdd_adapter_t *ap_adapter,
8468 tCsrRoamProfile *roam_profile,
8469 tScanResultHandle *scan_cache,
8470 bool *concurrent_chnl_same)
8471{
8472 hdd_ap_ctx_t *hdd_ap_ctx;
8473 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308474 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008475 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008476 *concurrent_chnl_same = true;
8477
8478 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8479 status =
8480 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8481 roam_profile,
8482 scan_cache,
8483 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308484 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008485 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008486 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8487 if (hdd_ap_ctx->operatingChannel != channel_id) {
8488 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008489 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008490 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008491 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008492 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8493 if (hdd_ap_ctx->operatingChannel != channel_id) {
8494 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008495 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008496 }
8497 }
8498 } else {
8499 /*
8500 * Lets handle worst case scenario here, Scan cache lookup is
8501 * failed so we have to stop the SAP to avoid any channel
8502 * discrepancy between SAP's channel and STA's channel.
8503 * Return the status as failure so caller function could know
8504 * that scan look up is failed.
8505 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008506 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308507 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008508 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308509 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008510}
8511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008512/**
8513 * wlan_hdd_stop_sap() - This function stops bss of SAP.
8514 * @ap_adapter: SAP adapter
8515 *
8516 * This function will process the stopping of sap adapter.
8517 *
8518 * Return: None
8519 */
8520void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
8521{
8522 hdd_ap_ctx_t *hdd_ap_ctx;
8523 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308524 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008525 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008526
8527 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008528 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008529 return;
8530 }
8531
8532 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8533 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308534 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008535 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008537 mutex_lock(&hdd_ctx->sap_lock);
8538 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08008539 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008540 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
8541 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008542 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308543 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308544 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008545 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05308546 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308547 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008548 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308549 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008550 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008551 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008552 return;
8553 }
8554 }
8555 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008556 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008557 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008558 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008559 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008560 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008561 }
8562 mutex_unlock(&hdd_ctx->sap_lock);
8563 return;
8564}
8565
8566/**
8567 * wlan_hdd_start_sap() - this function starts bss of SAP.
8568 * @ap_adapter: SAP adapter
8569 *
8570 * This function will process the starting of sap adapter.
8571 *
8572 * Return: None
8573 */
8574void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
8575{
8576 hdd_ap_ctx_t *hdd_ap_ctx;
8577 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308578 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008579 hdd_context_t *hdd_ctx;
8580 tsap_Config_t *sap_config;
8581
8582 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008583 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008584 return;
8585 }
8586
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008587 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07008588 hdd_err("SoftAp role has not been enabled");
8589 return;
8590 }
8591
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008592 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
8593 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8594 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8595 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
8596
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308597 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008598 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308599
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008600 mutex_lock(&hdd_ctx->sap_lock);
8601 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
8602 goto end;
8603
8604 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008605 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008606 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
8607 goto end;
8608 }
8609
8610 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
8611 &hdd_ap_ctx->sapConfig,
8612 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308613 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008614 goto end;
8615
Jeff Johnson28f8a772016-08-15 15:30:36 -07008616 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308617 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008618 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308619 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008620 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008621 goto end;
8622 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07008623 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008624 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008625 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008626 ap_adapter->sessionId);
8627 hostapd_state->bCommit = true;
8628
8629end:
8630 mutex_unlock(&hdd_ctx->sap_lock);
8631 return;
8632}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008633
8634/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08008635 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
8636 * mac scan config
8637 * @status: Status of set antenna mode
8638 *
8639 * Callback on setting the dual mac configuration
8640 *
8641 * Return: None
8642 */
8643void wlan_hdd_soc_set_antenna_mode_cb(
8644 enum set_antenna_mode_status status)
8645{
8646 hdd_context_t *hdd_ctx;
8647
8648 hdd_info("Status: %d", status);
8649
8650 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8651 if (0 != wlan_hdd_validate_context(hdd_ctx))
8652 return;
8653
8654 /* Signal the completion of set dual mac config */
8655 complete(&hdd_ctx->set_antenna_mode_cmpl);
8656}
8657
8658/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008659 * hdd_get_fw_version() - Get FW version
8660 * @hdd_ctx: pointer to HDD context.
8661 * @major_spid: FW version - major spid.
8662 * @minor_spid: FW version - minor spid
8663 * @ssid: FW version - ssid
8664 * @crmid: FW version - crmid
8665 *
8666 * This function is called to get the firmware build version stored
8667 * as part of the HDD context
8668 *
8669 * Return: None
8670 */
8671void hdd_get_fw_version(hdd_context_t *hdd_ctx,
8672 uint32_t *major_spid, uint32_t *minor_spid,
8673 uint32_t *siid, uint32_t *crmid)
8674{
8675 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
8676 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
8677 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
8678 *crmid = hdd_ctx->target_fw_version & 0x7fff;
8679}
8680
8681#ifdef QCA_CONFIG_SMP
8682/**
8683 * wlan_hdd_get_cpu() - get cpu_index
8684 *
8685 * Return: cpu_index
8686 */
8687int wlan_hdd_get_cpu(void)
8688{
8689 int cpu_index = get_cpu();
8690 put_cpu();
8691 return cpu_index;
8692}
8693#endif
8694
8695/**
8696 * hdd_get_fwpath() - get framework path
8697 *
8698 * This function is used to get the string written by
8699 * userspace to start the wlan driver
8700 *
8701 * Return: string
8702 */
8703const char *hdd_get_fwpath(void)
8704{
8705 return fwpath.string;
8706}
8707
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008708/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008709 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008710 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008711 * This function initilizes CDS global context with the help of cds_init. This
8712 * has to be the first function called after probe to get a valid global
8713 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008714 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008715 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008716 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008717int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008718{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008719 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008720 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008721
8722#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8723 wlan_logging_sock_init_svc();
8724#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008725 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008726
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008727 if (p_cds_context == NULL) {
8728 hdd_alert("Failed to allocate CDS context");
8729 ret = -ENOMEM;
8730 goto err_out;
8731 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008732
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008733 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008734
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008735err_out:
8736 return ret;
8737}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008738
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008739/**
8740 * hdd_deinit() - Deinitialize Driver
8741 *
8742 * This function frees CDS global context with the help of cds_deinit. This
8743 * has to be the last function call in remove callback to free the global
8744 * context.
8745 */
8746void hdd_deinit(void)
8747{
8748 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008749
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008750#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8751 wlan_logging_sock_deinit_svc();
8752#endif
8753}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008754
8755#ifdef QCA_WIFI_3_0_ADRASTEA
8756#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
8757#else
8758#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
8759#endif
8760
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008761/**
8762 * __hdd_module_init - Module init helper
8763 *
8764 * Module init helper function used by both module and static driver.
8765 *
8766 * Return: 0 for success, errno on failure
8767 */
8768static int __hdd_module_init(void)
8769{
8770 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008771
Arun Khandavallifae92942016-08-01 13:31:08 +05308772 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008773 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008774
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008775 pld_init();
8776
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308777 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008778
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008779 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008780
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008781 ret = wlan_hdd_register_driver();
8782 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07008783 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
8784 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008785 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008786 }
8787
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308788 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008789
8790 return 0;
8791out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308792 qdf_wake_lock_destroy(&wlan_wake_lock);
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008793 pld_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008794 return ret;
8795}
8796
8797/**
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05308798 * hdd_wait_for_recovery_completion() - Wait for cds recovery completion
8799 *
8800 * Block the unloading of the driver until the cds recovery is completed
8801 *
8802 * Return: None
8803 */
8804static void hdd_wait_for_recovery_completion(void)
8805{
8806 int retry = 0;
8807
8808 /* Wait for recovery to complete */
8809 while (cds_is_driver_recovering()) {
8810 hdd_alert("Recovery in progress; wait here!!!");
8811 msleep(1000);
8812 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8813 hdd_alert("SSR never completed, fatal error");
8814 QDF_BUG(0);
8815 }
8816 }
8817}
8818
8819/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008820 * __hdd_module_exit - Module exit helper
8821 *
8822 * Module exit helper function used by both module and static driver.
8823 */
8824static void __hdd_module_exit(void)
8825{
8826 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
8827 QWLAN_VERSIONSTR);
8828
Arunk Khandavalli07ec8f62016-09-27 21:51:01 +05308829 hdd_wait_for_recovery_completion();
8830
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008831 wlan_hdd_unregister_driver();
8832
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308833 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008834
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008835 pld_deinit();
8836
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008837 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008838}
8839
Arun Khandavallifae92942016-08-01 13:31:08 +05308840#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008841/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308842 * wlan_boot_cb() - Wlan boot callback
8843 * @kobj: object whose directory we're creating the link in.
8844 * @attr: attribute the user is interacting with
8845 * @buff: the buffer containing the user data
8846 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008847 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308848 * This callback is invoked when the fs is ready to start the
8849 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008850 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308851 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008852 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308853static ssize_t wlan_boot_cb(struct kobject *kobj,
8854 struct kobj_attribute *attr,
8855 const char *buf,
8856 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008857{
Arun Khandavallifae92942016-08-01 13:31:08 +05308858
8859 int ret = 0;
8860
8861 if (wlan_loader->loaded_state) {
8862 pr_info("Wlan driver already initialized");
8863 return 0;
8864 }
8865
8866
8867 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8868 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8869
8870 if (__hdd_module_init()) {
8871 pr_err("%s: Failed to register handler\n", __func__);
8872 ret = -EINVAL;
8873 } else
8874 wlan_loader->loaded_state = MODULE_INITIALIZED;
8875
8876 return count;
8877
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008878}
Arun Khandavallifae92942016-08-01 13:31:08 +05308879
8880/**
8881 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
8882 * ready
8883 *
8884 * This is creates the syfs entry boot_wlan. Which shall be invoked
8885 * when the filesystem is ready.
8886 *
8887 * Return: None
8888 */
8889static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008890{
Arun Khandavallifae92942016-08-01 13:31:08 +05308891 int ret = -EINVAL;
8892
8893 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
8894 if (!wlan_loader) {
8895 pr_err("%s: memory alloc failed\n", __func__);
8896 ret = -ENOMEM;
8897 return ret;
8898 }
8899
8900 wlan_loader->boot_wlan_obj = NULL;
8901 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
8902 GFP_KERNEL);
8903 if (!wlan_loader->attr_group) {
8904 pr_err("%s: malloc attr_group failed\n", __func__);
8905 ret = -ENOMEM;
8906 goto error_return;
8907 }
8908
8909 wlan_loader->loaded_state = 0;
8910 wlan_loader->attr_group->attrs = attrs;
8911
8912 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
8913 kernel_kobj);
8914 if (!wlan_loader->boot_wlan_obj) {
8915 pr_err("%s: sysfs create and add failed\n", __func__);
8916 ret = -ENOMEM;
8917 goto error_return;
8918 }
8919
8920 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
8921 wlan_loader->attr_group);
8922 if (ret) {
8923 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
8924 goto error_return;
8925 }
8926
8927 return 0;
8928
8929error_return:
8930
8931 if (wlan_loader->boot_wlan_obj) {
8932 kobject_del(wlan_loader->boot_wlan_obj);
8933 wlan_loader->boot_wlan_obj = NULL;
8934 }
8935
8936 return ret;
8937}
8938
8939/**
8940 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
8941 *
8942 * Return: 0 on success or errno on failure
8943 */
8944static int wlan_deinit_sysfs(void)
8945{
8946
8947 if (!wlan_loader) {
8948 hdd_alert("wlan loader context is Null!");
8949 return -EINVAL;
8950 }
8951
8952 if (wlan_loader->boot_wlan_obj) {
8953 sysfs_remove_group(wlan_loader->boot_wlan_obj,
8954 wlan_loader->attr_group);
8955 kobject_del(wlan_loader->boot_wlan_obj);
8956 wlan_loader->boot_wlan_obj = NULL;
8957 }
8958
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008959 return 0;
8960}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008961
Arun Khandavallifae92942016-08-01 13:31:08 +05308962#endif
8963
8964#ifdef MODULE
8965/**
8966 * __hdd_module_init - Module init helper
8967 *
8968 * Module init helper function used by both module and static driver.
8969 *
8970 * Return: 0 for success, errno on failure
8971 */
8972static int hdd_module_init(void)
8973{
8974 int ret = 0;
8975
8976 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8977 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8978
8979 if (__hdd_module_init()) {
8980 pr_err("%s: Failed to register handler\n", __func__);
8981 ret = -EINVAL;
8982 }
8983
8984 return ret;
8985}
8986#else
8987static int __init hdd_module_init(void)
8988{
8989 int ret = -EINVAL;
8990
8991 ret = wlan_init_sysfs();
8992 if (!ret)
8993 pr_err("Failed to create sysfs entry for loading wlan");
8994
8995 return ret;
8996}
8997#endif
8998
8999
9000#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009001/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009002 * hdd_module_exit() - Exit function
9003 *
9004 * This is the driver exit point (invoked when module is unloaded using rmmod)
9005 *
9006 * Return: None
9007 */
9008static void __exit hdd_module_exit(void)
9009{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009010 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009011}
Arun Khandavallifae92942016-08-01 13:31:08 +05309012#else
9013static void __exit hdd_module_exit(void)
9014{
9015 __hdd_module_exit();
9016 wlan_deinit_sysfs();
9017}
9018#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009019
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009020static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
9021{
9022 return param_set_copystring(kmessage, kp);
9023}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08009024
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309025/**
9026 * is_con_mode_valid() check con mode is valid or not
9027 * @mode: global con mode
9028 *
9029 * Return: TRUE on success FALSE on failure
9030 */
9031static bool is_con_mode_valid(enum tQDF_GLOBAL_CON_MODE mode)
9032{
9033 switch (mode) {
9034 case QDF_GLOBAL_MONITOR_MODE:
9035 case QDF_GLOBAL_FTM_MODE:
9036 case QDF_GLOBAL_EPPING_MODE:
9037 return true;
9038 default:
9039 return false;
9040 }
9041}
9042
9043/**
9044 * hdd_get_adpter_mode() - returns adapter mode based on global con mode
9045 * @mode: global con mode
9046 *
9047 * Return: adapter mode
9048 */
9049static enum tQDF_ADAPTER_MODE hdd_get_adpter_mode(
9050 enum tQDF_GLOBAL_CON_MODE mode)
9051{
9052
9053 switch (mode) {
9054 case QDF_GLOBAL_MISSION_MODE:
9055 return QDF_STA_MODE;
9056 case QDF_GLOBAL_MONITOR_MODE:
9057 return QDF_MONITOR_MODE;
9058 case QDF_GLOBAL_FTM_MODE:
9059 return QDF_MONITOR_MODE;
9060 case QDF_GLOBAL_EPPING_MODE:
9061 return QDF_EPPING_MODE;
9062 case QDF_GLOBAL_QVIT_MODE:
9063 return QDF_QVIT_MODE;
9064 default:
9065 return QDF_MAX_NO_OF_MODE;
9066 }
9067}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009068
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009069/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009070 * con_mode_handler() - Handles module param con_mode change
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309071 * @kmessage: con mode name on which driver to be bring up
9072 * @kp: The associated kernel parameter
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009073 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309074 * This function is invoked when user updates con mode using sys entry,
9075 * to initialize and bring-up driver in that specific mode.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009076 *
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309077 * Return - 0 on success and failure code on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009078 */
9079static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
9080{
9081 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05309082 hdd_context_t *hdd_ctx;
9083 hdd_adapter_t *adapter;
9084 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309085 enum tQDF_GLOBAL_CON_MODE curr_mode;
9086 enum tQDF_ADAPTER_MODE adapter_mode;
Arun Khandavallifae92942016-08-01 13:31:08 +05309087 QDF_STATUS status;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009088
Arun Khandavallifae92942016-08-01 13:31:08 +05309089 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009090 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05309091
9092 if (!qdf_dev) {
9093 hdd_err("qdf device context is Null return!");
9094 return -EINVAL;
9095 }
9096
9097 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
9098 if (!hdd_ctx) {
9099 hdd_err("Hdd context Null return!");
9100 return -EINVAL;
9101 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05309102
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309103 if (!(is_con_mode_valid(con_mode))) {
9104 hdd_err("invlaid con_mode %d", con_mode);
9105 return -EINVAL;
9106 }
9107 curr_mode = hdd_get_conparam();
9108 if (curr_mode == con_mode) {
9109 hdd_err("curr mode: %d is same as user triggered mode %d",
9110 curr_mode, con_mode);
9111 return 0;
9112 }
9113
9114 adapter_mode = hdd_get_adpter_mode(curr_mode);
9115 if (adapter_mode == QDF_MAX_NO_OF_MODE) {
9116 hdd_err("invalid adapter");
9117 return -EINVAL;
9118 }
9119
Arun Khandavallifae92942016-08-01 13:31:08 +05309120 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05309121 if (ret) {
9122 hdd_err("Stop wlan modules failed");
9123 return -EINVAL;
9124 }
9125
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309126 adapter = hdd_get_adapter(hdd_ctx, adapter_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309127 if (!adapter) {
Hanumanth Reddy Pothula7d51b1d2016-09-21 19:11:20 +05309128 hdd_err("Failed to get adapter, mode: %d", curr_mode);
Arun Khandavallifae92942016-08-01 13:31:08 +05309129 return -EINVAL;
9130 }
9131
9132 if (con_mode == QDF_GLOBAL_FTM_MODE) {
9133 adapter->device_mode = QDF_FTM_MODE;
9134 hdd_set_conparam(QDF_GLOBAL_FTM_MODE);
9135 } else if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
9136 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9137 adapter->device_mode = QDF_MONITOR_MODE;
9138 hdd_set_conparam(QDF_GLOBAL_MONITOR_MODE);
9139 hdd_set_station_ops(adapter->dev);
9140 } else if (con_mode == QDF_GLOBAL_EPPING_MODE) {
9141 hdd_set_conparam(QDF_GLOBAL_EPPING_MODE);
9142 status = epping_open();
9143 if (status != QDF_STATUS_SUCCESS) {
9144 hdd_err("Failed to open in eeping mode: %d", status);
9145 return -EINVAL;
9146 }
9147 ret = epping_enable(qdf_dev->dev);
9148 if (ret) {
9149 hdd_err("Failed to enable in epping mode : %d", ret);
9150 epping_close();
9151 return -EINVAL;
9152 }
9153 hdd_info("epping mode successfully enabled");
9154 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05309155 }
9156
9157 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
9158 if (ret) {
9159 hdd_err("Start wlan modules failed: %d", ret);
9160 return -EINVAL;
9161 }
9162
9163 if (hdd_start_adapter(adapter)) {
9164 hdd_err("Failed to start %s adapter", kmessage);
9165 return -EINVAL;
9166 } else {
9167 hdd_info("Mode successfully changed to %s", kmessage);
9168 ret = 0;
9169 }
9170
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009171 return ret;
9172}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009173
9174/**
9175 * hdd_get_conparam() - driver exit point
9176 *
9177 * This is the driver exit point (invoked when module is unloaded using rmmod)
9178 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309179 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009180 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309181enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009182{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309183 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009184}
9185
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009186void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009187{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009188 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009189}
9190
Komal Seelamc11bb222016-01-27 18:57:10 +05309191/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309192 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9193 * @hdd_ctx: HDD context
9194 *
9195 * Cleans up the pre cac interface, if it exists
9196 *
9197 * Return: None
9198 */
9199void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9200{
9201 uint8_t session_id;
9202 QDF_STATUS status;
9203 struct hdd_adapter_s *precac_adapter;
9204
9205 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9206 if (QDF_IS_STATUS_ERROR(status)) {
9207 hdd_err("failed to get pre cac vdev id");
9208 return;
9209 }
9210
9211 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9212 if (!precac_adapter) {
9213 hdd_err("invalid pre cac adapater");
9214 return;
9215 }
9216
9217 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9218 wlan_hdd_sap_pre_cac_failure,
9219 (void *)precac_adapter);
9220 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9221
9222}
9223
9224/**
Komal Seelamec702b02016-02-24 18:42:16 +05309225 * hdd_update_ol_config - API to update ol configuration parameters
9226 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309227 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309228 * Return: void
9229 */
Komal Seelamec702b02016-02-24 18:42:16 +05309230static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309231{
Komal Seelamec702b02016-02-24 18:42:16 +05309232 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309233 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309234
Komal Seelamec702b02016-02-24 18:42:16 +05309235 if (!ol_ctx)
9236 return;
9237
9238 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9239 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9240 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9241 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
Jeff Johnsonb8bf9072016-09-23 17:39:27 -07009242 cfg.enable_lpass_support = hdd_lpass_is_supported(hdd_ctx);
Komal Seelamec702b02016-02-24 18:42:16 +05309243
9244 ol_init_ini_config(ol_ctx, &cfg);
9245}
9246
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009247#ifdef FEATURE_RUNTIME_PM
9248/**
9249 * hdd_populate_runtime_cfg() - populate runtime configuration
9250 * @hdd_ctx: hdd context
9251 * @cfg: pointer to the configuration memory being populated
9252 *
9253 * Return: void
9254 */
9255static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9256 struct hif_config_info *cfg)
9257{
9258 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9259 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9260}
9261#else
9262static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9263 struct hif_config_info *cfg)
9264{
9265}
9266#endif
9267
Komal Seelamec702b02016-02-24 18:42:16 +05309268/**
9269 * hdd_update_hif_config - API to update HIF configuration parameters
9270 * @hdd_ctx: HDD Context
9271 *
9272 * Return: void
9273 */
9274static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9275{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309276 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309277 struct hif_config_info cfg;
9278
9279 if (!scn)
9280 return;
9281
9282 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009283 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05309284 hif_init_ini_config(scn, &cfg);
9285}
9286
9287/**
9288 * hdd_update_config() - Initialize driver per module ini parameters
9289 * @hdd_ctx: HDD Context
9290 *
9291 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309292 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05309293 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309294int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05309295{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309296 int ret;
9297
Komal Seelamec702b02016-02-24 18:42:16 +05309298 hdd_update_ol_config(hdd_ctx);
9299 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309300 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
9301 ret = hdd_update_cds_config_ftm(hdd_ctx);
9302 else
9303 ret = hdd_update_cds_config(hdd_ctx);
9304
9305 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05309306}
9307
Agrawal Ashish65634612016-08-18 13:24:32 +05309308/**
9309 * wlan_hdd_get_dfs_mode() - get ACS DFS mode
9310 * @mode : cfg80211 DFS mode
9311 *
9312 * Return: return SAP ACS DFS mode else return ACS_DFS_MODE_NONE
9313 */
9314enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode)
9315{
9316 switch (mode) {
9317 case DFS_MODE_ENABLE:
9318 return ACS_DFS_MODE_ENABLE;
9319 break;
9320 case DFS_MODE_DISABLE:
9321 return ACS_DFS_MODE_DISABLE;
9322 break;
9323 case DFS_MODE_DEPRIORITIZE:
9324 return ACS_DFS_MODE_DEPRIORITIZE;
9325 break;
9326 default:
9327 hdd_err("ACS dfs mode is NONE");
9328 return ACS_DFS_MODE_NONE;
9329 }
9330}
9331
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05309332/**
9333 * hdd_enable_disable_ca_event() - enable/disable channel avoidance event
9334 * @hddctx: pointer to hdd context
9335 * @set_value: enable/disable
9336 *
9337 * When Host sends vendor command enable, FW will send *ONE* CA ind to
9338 * Host(even though it is duplicate). When Host send vendor command
9339 * disable,FW doesn't perform any action. Whenever any change in
9340 * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host.
9341 *
9342 * return - 0 on success, appropriate error values on failure.
9343 */
9344int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value)
9345{
9346 QDF_STATUS status;
9347
9348 if (0 != wlan_hdd_validate_context(hddctx)) {
9349 return -EAGAIN;
9350 }
9351
9352 if (!hddctx->config->goptimize_chan_avoid_event) {
9353 hdd_warn("goptimize_chan_avoid_event ini param disabled");
9354 return -EINVAL;
9355 }
9356
9357 status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value);
9358 if (!QDF_IS_STATUS_SUCCESS(status)) {
9359 hdd_err("Failed to send chan avoid command to SME");
9360 return -EINVAL;
9361 }
9362 return 0;
9363}
Agrawal Ashish65634612016-08-18 13:24:32 +05309364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009365/* Register the module init/exit functions */
9366module_init(hdd_module_init);
9367module_exit(hdd_module_exit);
9368
9369MODULE_LICENSE("Dual BSD/GPL");
9370MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9371MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009373module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9374 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009375
9376module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
9377 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
9378
9379module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
9380
9381module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
9382
9383module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);