blob: c39bf4b00322fa859337827c302f8ac01111ab02 [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
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
39#ifdef WLAN_FEATURE_LPSS
40#include <cds_utils.h>
41#endif
42#include <linux/etherdevice.h>
43#include <linux/firmware.h>
44#include <wlan_hdd_tx_rx.h>
45#include <wni_api.h>
46#include <wlan_hdd_cfg.h>
47#include <wlan_ptt_sock_svc.h>
48#include <dbglog_host.h>
49#include <wlan_logging_sock_svc.h>
50#include <wlan_hdd_wowl.h>
51#include <wlan_hdd_misc.h>
52#include <wlan_hdd_wext.h>
53#include "wlan_hdd_trace.h"
54#include "wlan_hdd_ioctl.h"
55#include "wlan_hdd_ftm.h"
56#include "wlan_hdd_power.h"
57#include "wlan_hdd_stats.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053058#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053059#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070060#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080061
62#include <net/addrconf.h>
63#include <linux/wireless.h>
64#include <net/cfg80211.h>
65#include <linux/inetdevice.h>
66#include <net/addrconf.h>
67#include "wlan_hdd_cfg80211.h"
68#include "wlan_hdd_ext_scan.h"
69#include "wlan_hdd_p2p.h"
70#include <linux/rtnetlink.h>
71#include "sap_api.h"
72#include <linux/semaphore.h>
73#include <linux/ctype.h>
74#include <linux/compat.h>
75#ifdef MSM_PLATFORM
76#ifdef CONFIG_CNSS
77#include <soc/qcom/subsystem_restart.h>
78#endif
79#endif
80#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
87#ifdef CONFIG_CNSS
88#include <net/cnss.h>
89#endif
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053090#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080091#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#endif /* FEATURE_WLAN_CH_AVOID */
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080093#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094#include "wlan_hdd_nan.h"
95#include "wlan_hdd_debugfs.h"
96#include "wlan_hdd_driver_ops.h"
97#include "epping_main.h"
98#include "wlan_hdd_memdump.h"
99
100#include <wlan_hdd_ipa.h>
101#include "hif.h"
102#include "wma.h"
103#include "cds_concurrency.h"
104#include "wlan_hdd_green_ap.h"
Yuanyuan Liuedcbc302015-12-02 10:39:51 -0800105#include "platform_icnss.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530106#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700107#include <wlan_hdd_regulatory.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108
109#ifdef MODULE
110#define WLAN_MODULE_NAME module_name(THIS_MODULE)
111#else
112#define WLAN_MODULE_NAME "wlan"
113#endif
114
115#ifdef TIMER_MANAGER
116#define TIMER_MANAGER_STR " +TIMER_MANAGER"
117#else
118#define TIMER_MANAGER_STR ""
119#endif
120
121#ifdef MEMORY_DEBUG
122#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
123#else
124#define MEMORY_DEBUG_STR ""
125#endif
126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127/* the Android framework expects this param even though we don't use it */
128#define BUF_LEN 20
129static char fwpath_buffer[BUF_LEN];
130static struct kparam_string fwpath = {
131 .string = fwpath_buffer,
132 .maxlen = BUF_LEN,
133};
134
135static char *country_code;
136static int enable_11d = -1;
137static int enable_dfs_chan_scan = -1;
138
139#ifndef MODULE
140static int wlan_hdd_inited;
141#endif
142
143/*
144 * spinlock for synchronizing asynchronous request/response
145 * (full description of use in wlan_hdd_main.h)
146 */
147DEFINE_SPINLOCK(hdd_context_lock);
148
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800149#define WLAN_NLINK_CESIUM 30
150
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530151static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152
153#define WOW_MAX_FILTER_LISTS 1
154#define WOW_MAX_FILTERS_PER_LIST 4
155#define WOW_MIN_PATTERN_SIZE 6
156#define WOW_MAX_PATTERN_SIZE 64
157
158#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
159static const struct wiphy_wowlan_support wowlan_support_reg_init = {
160 .flags = WIPHY_WOWLAN_ANY |
161 WIPHY_WOWLAN_MAGIC_PKT |
162 WIPHY_WOWLAN_DISCONNECT |
163 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
164 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
165 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
166 WIPHY_WOWLAN_4WAY_HANDSHAKE |
167 WIPHY_WOWLAN_RFKILL_RELEASE,
168 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
169 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
170 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
171};
172#endif
173
174/* internal function declaration */
175
176struct sock *cesium_nl_srv_sock;
177
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
179void wlan_hdd_auto_shutdown_cb(void);
180#endif
181
182/**
183 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
184 * @vdev_id: vdev_id
185 * @action: action type
186 * @reason: reason type
187 *
188 * Return: none
189 */
190void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
191 enum netif_action_type action, enum netif_reason_type reason)
192{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530193 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194 hdd_adapter_t *adapter;
195
196 if (!hdd_ctx) {
197 hdd_err("hdd ctx is NULL");
198 return;
199 }
200 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
201
202 wlan_hdd_netif_queue_control(adapter, action, reason);
203 return;
204}
205
206/*
207 * Store WLAN driver version info in a global variable such that crash debugger
208 * can extract it from driver debug symbol and crashdump for post processing
209 */
210uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
211
212/**
213 * hdd_device_mode_to_string() - return string conversion of device mode
214 * @device_mode: device mode
215 *
216 * This utility function helps log string conversion of device mode.
217 *
218 * Return: string conversion of device mode, if match found;
219 * "Unknown" otherwise.
220 */
221const char *hdd_device_mode_to_string(uint8_t device_mode)
222{
223 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800224 CASE_RETURN_STRING(QDF_STA_MODE);
225 CASE_RETURN_STRING(QDF_SAP_MODE);
226 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
227 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
228 CASE_RETURN_STRING(QDF_FTM_MODE);
229 CASE_RETURN_STRING(QDF_IBSS_MODE);
230 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
231 CASE_RETURN_STRING(QDF_OCB_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 default:
233 return "Unknown";
234 }
235}
236
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530237/**
238 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
239 * @adapter: HDD adapter
240 * @chan_number: Channel number
241 * @chan_bw: Bandwidth
242 *
243 * Checks if the given bandwidth is valid for the given channel number.
244 *
245 * Return: 0 for success, non-zero for failure
246 */
247int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
248 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800249 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530250{
251 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
252 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
253 bool found = false;
254 tHalHandle hal;
255
256 hal = WLAN_HDD_GET_HAL_CTX(adapter);
257 if (!hal) {
258 hdd_err("Invalid HAL context");
259 return -EINVAL;
260 }
261
262 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
263 hdd_err("No valid channel list");
264 return -EOPNOTSUPP;
265 }
266
267 for (i = 0; i < len; i++) {
268 if (chan[i] == chan_number) {
269 found = true;
270 break;
271 }
272 }
273
274 if (found == false) {
275 hdd_err("Channel not in driver's valid channel list");
276 return -EOPNOTSUPP;
277 }
278
279 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
280 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
281 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
282 return -EINVAL;
283 }
284
285 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
286 if (chan_bw == CH_WIDTH_80MHZ) {
287 hdd_err("BW80 not possible in 2.4GHz band");
288 return -EINVAL;
289 }
290 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
291 (chan_bw != CH_WIDTH_MAX)) {
292 hdd_err("Only BW20 possible on channel 14");
293 return -EINVAL;
294 }
295 }
296
297 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
298 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
299 (chan_bw != CH_WIDTH_MAX)) {
300 hdd_err("Only BW20 possible on channel 165");
301 return -EINVAL;
302 }
303 }
304
305 return 0;
306}
307
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800308static int __hdd_netdev_notifier_call(struct notifier_block *nb,
309 unsigned long state, void *data)
310{
311#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
312 struct netdev_notifier_info *dev_notif_info = data;
313 struct net_device *dev = dev_notif_info->dev;
314#else
315 struct net_device *dev = data;
316#endif
317 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
318 hdd_context_t *hdd_ctx;
319
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800320 ENTER_DEV(dev);
321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322 /* Make sure that this callback corresponds to our device. */
323 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
324 return NOTIFY_DONE;
325
326 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
327 (adapter->dev != dev)) {
328 hddLog(LOGE, FL("device adapter is not matching!!!"));
329 return NOTIFY_DONE;
330 }
331
332 if (!dev->ieee80211_ptr) {
333 hddLog(LOGE, FL("ieee80211_ptr is NULL!!!"));
334 return NOTIFY_DONE;
335 }
336
337 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
338 if (NULL == hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530339 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HDD Context Null Pointer"));
340 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341 return NOTIFY_DONE;
342 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800343 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800344 return NOTIFY_DONE;
345
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530346 hddLog(QDF_TRACE_LEVEL_INFO, FL("%s New Net Device State = %lu"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800347 dev->name, state);
348
349 switch (state) {
350 case NETDEV_REGISTER:
351 break;
352
353 case NETDEV_UNREGISTER:
354 break;
355
356 case NETDEV_UP:
357 sme_ch_avoid_update_req(hdd_ctx->hHal);
358 break;
359
360 case NETDEV_DOWN:
361 break;
362
363 case NETDEV_CHANGE:
364 if (true == adapter->isLinkUpSvcNeeded)
365 complete(&adapter->linkup_event_var);
366 break;
367
368 case NETDEV_GOING_DOWN:
369 if (adapter->scan_info.mScanPending != false) {
370 unsigned long rc;
371 INIT_COMPLETION(adapter->scan_info.
372 abortscan_event_var);
373 hdd_abort_mac_scan(adapter->pHddCtx,
374 adapter->sessionId,
375 eCSR_SCAN_ABORT_DEFAULT);
376 rc = wait_for_completion_timeout(
377 &adapter->scan_info.abortscan_event_var,
378 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
379 if (!rc) {
380 hddLog(LOGE,
381 FL("Timeout occurred while waiting for abortscan"));
382 }
383 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530384 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 FL("Scan is not Pending from user"));
386 }
387 break;
388
389 default:
390 break;
391 }
392
393 return NOTIFY_DONE;
394}
395
396/**
397 * hdd_netdev_notifier_call() - netdev notifier callback function
398 * @nb: pointer to notifier block
399 * @state: state
400 * @ndev: ndev pointer
401 *
402 * Return: 0 on success, error number otherwise.
403 */
404static int hdd_netdev_notifier_call(struct notifier_block *nb,
405 unsigned long state,
406 void *ndev)
407{
408 int ret;
409
410 cds_ssr_protect(__func__);
411 ret = __hdd_netdev_notifier_call(nb, state, ndev);
412 cds_ssr_unprotect(__func__);
413
414 return ret;
415}
416
417struct notifier_block hdd_netdev_notifier = {
418 .notifier_call = hdd_netdev_notifier_call,
419};
420
421/* variable to hold the insmod parameters */
422static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800423
424/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800426
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530427/**
428 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
429 * @ch_width: NL channel width
430 *
431 * Converts the NL channel width to the driver's internal representation
432 *
433 * Return: Converted channel width. In case of non matching NL channel width,
434 * CH_WIDTH_MAX will be returned.
435 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800436enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530437{
438 switch (ch_width) {
439 case NL80211_CHAN_WIDTH_20_NOHT:
440 case NL80211_CHAN_WIDTH_20:
441 return CH_WIDTH_20MHZ;
442 case NL80211_CHAN_WIDTH_40:
443 return CH_WIDTH_40MHZ;
444 break;
445 case NL80211_CHAN_WIDTH_80:
446 return CH_WIDTH_80MHZ;
447 case NL80211_CHAN_WIDTH_80P80:
448 return CH_WIDTH_80P80MHZ;
449 case NL80211_CHAN_WIDTH_160:
450 return CH_WIDTH_160MHZ;
451 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800452 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530453 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800454 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530455 default:
456 hdd_err("Invalid channel width %d, setting to default",
457 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800458 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530459 }
460}
461
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530462/* wlan_hdd_find_opclass() - Find operating class for a channel
463 * @hal: handler to HAL
464 * @channel: channel id
465 * @bw_offset: bandwidth offset
466 *
467 * Function invokes sme api to find the operating class
468 *
469 * Return: operating class
470 */
471uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
472 uint8_t bw_offset)
473{
474 uint8_t opclass = 0;
475
476 sme_get_opclass(hal, channel, bw_offset, &opclass);
477 return opclass;
478}
479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530481 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800482 * @moduleId: Module whose trace level is being configured
483 * @bitmask: Bitmask of log levels to be enabled
484 *
485 * Called immediately after the cfg.ini is read in order to configure
486 * the desired trace levels.
487 *
488 * Return: None
489 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530490static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800491{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530492 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800493
494 /*
495 * if the bitmask is the default value, then a bitmask was not
496 * specified in cfg.ini, so leave the logging level alone (it
497 * will remain at the "compiled in" default value)
498 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530499 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 return;
501 }
502
503 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530504 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505
506 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530507 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 while (0 != bitmask) {
509 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530510 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800511 }
512 level++;
513 bitmask >>= 1;
514 }
515}
516
517/**
518 * wlan_hdd_validate_context() - check the HDD context
519 * @hdd_ctx: HDD context pointer
520 *
521 * Return: 0 if the context is valid. Error code otherwise
522 */
523int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
524{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
526 hddLog(LOGE, FL("HDD context is Null"));
527 return -ENODEV;
528 }
529
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800530 if (cds_is_driver_recovering()) {
531 hdd_err("Recovery in Progress. State: 0x%x Ignore!!!",
532 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800533 return -EAGAIN;
534 }
535
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800536 if (cds_is_load_or_unload_in_progress()) {
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800537 hdd_err("Unloading/Loading in Progress. Ignore!!!: 0x%x",
538 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 return -EAGAIN;
540 }
541 return 0;
542}
543
544void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
545{
546 hdd_adapter_t *adapter = NULL;
547 hdd_station_ctx_t *pHddStaCtx = NULL;
548 eCsrPhyMode phyMode;
549 struct hdd_config *cfg_param = NULL;
550
551 if (NULL == hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530552 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HDD Context is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 return;
554 }
555
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800556 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530558 hddLog(QDF_TRACE_LEVEL_FATAL, FL("adapter is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 return;
560 }
561
562 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
563
564 cfg_param = hdd_ctx->config;
565 if (NULL == cfg_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530566 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567 FL("cfg_params not available !!"));
568 return;
569 }
570
571 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
572
573 if (!hdd_ctx->isVHT80Allowed) {
574 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
575 (eCSR_DOT11_MODE_11ac == phyMode) ||
576 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530577 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 FL("Setting phymode to 11n!!"));
579 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
580 eCSR_DOT11_MODE_11n);
581 }
582 } else {
583 /*
584 * New country Supports 11ac as well resetting value back from
585 * .ini
586 */
587 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
588 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
589 dot11Mode));
590 return;
591 }
592
593 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
594 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
595 || (eCSR_CFG_DOT11_MODE_11AC ==
596 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530597 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598
599 /* need to issue a disconnect to CSR. */
600 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530601 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 adapter->sessionId,
603 eCSR_DISCONNECT_REASON_UNSPECIFIED);
604
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530605 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606 unsigned long rc;
607
608 rc = wait_for_completion_timeout(
609 &adapter->disconnect_comp_var,
610 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
611 if (!rc)
612 hddLog(LOGE,
613 FL("failure waiting for disconnect_comp_var"));
614 }
615 }
616}
617
618/**
619 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
620 * @hdd_adapter_t Hdd adapter.
621 *
622 * This function sets the IBSS power save config parameters to WMA
623 * which will send it to firmware if FW supports IBSS power save
624 * before vdev start.
625 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530626 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627 * on failure.
628 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530629QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630{
631 int ret;
632 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
633
634 if (hdd_ctx == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530635 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636 FL("HDD context is null"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530637 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 }
639
640 ret = wma_cli_set_command(adapter->sessionId,
641 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
642 hdd_ctx->config->ibssATIMWinSize,
643 VDEV_CMD);
644 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530645 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646 FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530647 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 }
649
650 ret = wma_cli_set_command(adapter->sessionId,
651 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
652 hdd_ctx->config->isIbssPowerSaveAllowed,
653 VDEV_CMD);
654 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530655 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"),
657 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530658 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800659 }
660
661 ret = wma_cli_set_command(adapter->sessionId,
662 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
663 hdd_ctx->config->
664 isIbssPowerCollapseAllowed, VDEV_CMD);
665 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530666 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"),
668 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530669 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800670 }
671
672 ret = wma_cli_set_command(adapter->sessionId,
673 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
674 hdd_ctx->config->isIbssAwakeOnTxRx,
675 VDEV_CMD);
676 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530677 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530679 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 }
681
682 ret = wma_cli_set_command(adapter->sessionId,
683 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
684 hdd_ctx->config->ibssInactivityCount,
685 VDEV_CMD);
686 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530687 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530689 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 }
691
692 ret = wma_cli_set_command(adapter->sessionId,
693 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
694 hdd_ctx->config->ibssTxSpEndInactivityTime,
695 VDEV_CMD);
696 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530697 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 FL(
699 "WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d"
700 ),
701 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530702 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 }
704
705 ret = wma_cli_set_command(adapter->sessionId,
706 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
707 hdd_ctx->config->ibssPsWarmupTime,
708 VDEV_CMD);
709 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530710 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"),
712 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530713 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 }
715
716 ret = wma_cli_set_command(adapter->sessionId,
717 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
718 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
719 VDEV_CMD);
720 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530721 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 FL(
723 "WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d"
724 ),
725 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530726 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727 }
728
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530729 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730}
731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800732#define INTF_MACADDR_MASK 0x7
733
734/**
735 * hdd_update_macaddr() - update mac address
736 * @config: hdd configuration
737 * @hw_macaddr: mac address
738 *
739 * Mac address for multiple virtual interface is found as following
740 * i) The mac address of the first interface is just the actual hw mac address.
741 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
742 * define the mac address for the remaining interfaces and locally
743 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
744 * supported virtual interfaces, right now this is 0x07 (meaning 8
745 * interface).
746 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
747 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
748 *
749 * Return: None
750 */
751void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530752 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800753{
754 int8_t i;
755 uint8_t macaddr_b3, tmp_br3;
756
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530757 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530758 QDF_MAC_ADDR_SIZE);
759 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530760 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530761 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762 macaddr_b3 = config->intfMacAddr[i].bytes[3];
763 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
764 INTF_MACADDR_MASK;
765 macaddr_b3 += tmp_br3;
766
767 /* XOR-ing bit-24 of the mac address. This will give enough
768 * mac address range before collision
769 */
770 macaddr_b3 ^= (1 << 7);
771
772 /* Set locally administered bit */
773 config->intfMacAddr[i].bytes[0] |= 0x02;
774 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530775 hddLog(QDF_TRACE_LEVEL_INFO, "config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 MAC_ADDRESS_STR, i,
777 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
778 }
779}
780
781static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
782 struct wma_tgt_services *cfg)
783{
784 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785
786 /* Set up UAPSD */
787 config->apUapsdEnabled &= cfg->uapsd;
788
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789 /* 11AC mode support */
790 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
791 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
792 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793
794 /* ARP offload: override user setting if invalid */
795 config->fhostArpOffload &= cfg->arp_offload;
796
797#ifdef FEATURE_WLAN_SCAN_PNO
798 /* PNO offload */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530799 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800 FL("PNO Capability in f/w = %d"), cfg->pno_offload);
801 if (cfg->pno_offload)
802 config->PnoOffload = true;
803#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804#ifdef FEATURE_WLAN_TDLS
805 config->fEnableTDLSSupport &= cfg->en_tdls;
806 config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan;
807 config->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta;
808 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
809 config->fEnableTDLSSleepSta = true;
810 } else {
811 config->fEnableTDLSSleepSta = false;
812 }
813#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814#ifdef WLAN_FEATURE_ROAM_OFFLOAD
815 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
816#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700817 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818
819}
820
821static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
822 struct wma_tgt_ht_cap *cfg)
823{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530824 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 uint32_t value, val32;
826 uint16_t val16;
827 struct hdd_config *pconfig = hdd_ctx->config;
828 tSirMacHTCapabilityInfo *phtCapInfo;
829 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
830 uint8_t enable_tx_stbc;
831
832 /* check and update RX STBC */
833 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
834 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
835
836 /* get the MPDU density */
837 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
838
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530839 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530840 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 FL("could not get MPDU DENSITY"));
842 value = 0;
843 }
844
845 /*
846 * MPDU density:
847 * override user's setting if value is larger
848 * than the one supported by target
849 */
850 if (value > cfg->mpdu_density) {
851 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
852 cfg->mpdu_density);
853
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530854 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530855 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800856 FL("could not set MPDU DENSITY to CCM"));
857 }
858
859 /* get the HT capability info */
860 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530861 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530862 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800863 FL("could not get HT capability info"));
864 return;
865 }
866 val16 = (uint16_t) val32;
867 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
868
869 /* Set the LDPC capability */
870 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
871
872 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
873 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
874
875 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
876 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
877
878 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
879 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
880
881 enable_tx_stbc = pconfig->enableTxSTBC;
882
883 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
884 pconfig->enable2x2 = 1;
885 } else {
886 pconfig->enable2x2 = 0;
887 enable_tx_stbc = 0;
888
889 /* 1x1 */
890 /* Update Rx Highest Long GI data Rate */
891 if (sme_cfg_set_int(hdd_ctx->hHal,
892 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
893 HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530894 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800895 hddLog(LOGE,
896 FL(
897 "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"
898 ));
899 }
900
901 /* Update Tx Highest Long GI data Rate */
902 if (sme_cfg_set_int
903 (hdd_ctx->hHal,
904 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
905 HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530906 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800907 hddLog(LOGE,
908 FL(
909 "Could not pass on HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"
910 ));
911 }
912 }
913 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
914 enable_tx_stbc = 0;
915 phtCapInfo->txSTBC = enable_tx_stbc;
916
917 val32 = val16;
918 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530919 if (status != QDF_STATUS_SUCCESS)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530920 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921 FL("could not set HT capability to CCM"));
922#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
923 value = SIZE_OF_SUPPORTED_MCS_SET;
924 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530925 &value) == QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530926 hddLog(QDF_TRACE_LEVEL_INFO, FL("Read MCS rate set"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800927
928 if (pconfig->enable2x2) {
929 for (value = 0; value < cfg->num_rf_chains; value++)
930 mcs_set[value] =
931 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
932
933 status =
934 sme_cfg_set_str(hdd_ctx->hHal,
935 WNI_CFG_SUPPORTED_MCS_SET,
936 mcs_set,
937 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530938 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530939 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940 FL("could not set MCS SET to CCM"));
941 }
942 }
943#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
944}
945
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800946static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
947 struct wma_tgt_vht_cap *cfg)
948{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530949 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 uint32_t value = 0;
951 struct hdd_config *pconfig = hdd_ctx->config;
952 struct wiphy *wiphy = hdd_ctx->wiphy;
953 struct ieee80211_supported_band *band_5g =
954 wiphy->bands[IEEE80211_BAND_5GHZ];
955
956 /* Get the current MPDU length */
957 status =
958 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
959 &value);
960
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530962 hddLog(QDF_TRACE_LEVEL_ERROR, FL("could not get MPDU LENGTH"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 value = 0;
964 }
965
966 /*
967 * VHT max MPDU length:
968 * override if user configured value is too high
969 * that the target cannot support
970 */
971 if (value > cfg->vht_max_mpdu) {
972 status = sme_cfg_set_int(hdd_ctx->hHal,
973 WNI_CFG_VHT_MAX_MPDU_LENGTH,
974 cfg->vht_max_mpdu);
975
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530976 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530977 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 FL("could not set VHT MAX MPDU LENGTH"));
979 }
980 }
981
982 /* Get the current supported chan width */
983 status = sme_cfg_get_int(hdd_ctx->hHal,
984 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
985 &value);
986
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530987 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530988 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989 FL("could not get MPDU LENGTH"));
990 value = 0;
991 }
992
993 /* Get the current RX LDPC setting */
994 status =
995 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
996 &value);
997
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530998 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530999 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 FL("could not get VHT LDPC CODING CAP"));
1001 value = 0;
1002 }
1003
1004 /* Set the LDPC capability */
1005 if (value && !cfg->vht_rx_ldpc) {
1006 status = sme_cfg_set_int(hdd_ctx->hHal,
1007 WNI_CFG_VHT_LDPC_CODING_CAP,
1008 cfg->vht_rx_ldpc);
1009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301010 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301011 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 FL("could not set VHT LDPC CODING CAP to CCM"));
1013 }
1014 }
1015
1016 /* Get current GI 80 value */
1017 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1018 &value);
1019
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301020 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301021 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001022 FL("could not get SHORT GI 80MHZ"));
1023 value = 0;
1024 }
1025
1026 /* set the Guard interval 80MHz */
1027 if (value && !cfg->vht_short_gi_80) {
1028 status = sme_cfg_set_int(hdd_ctx->hHal,
1029 WNI_CFG_VHT_SHORT_GI_80MHZ,
1030 cfg->vht_short_gi_80);
1031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301032 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301033 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001034 FL("could not set SHORT GI 80MHZ to CCM"));
1035 }
1036 }
1037
1038 /* Get current GI 160 value */
1039 status = sme_cfg_get_int(hdd_ctx->hHal,
1040 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1041 &value);
1042
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301043 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301044 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001045 FL("could not get SHORT GI 80 & 160"));
1046 value = 0;
1047 }
1048
1049 /* Get VHT TX STBC cap */
1050 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1051
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301052 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301053 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001054 FL("could not get VHT TX STBC"));
1055 value = 0;
1056 }
1057
1058 /* VHT TX STBC cap */
1059 if (value && !cfg->vht_tx_stbc) {
1060 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1061 cfg->vht_tx_stbc);
1062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301063 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301064 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001065 FL("could not set the VHT TX STBC to CCM"));
1066 }
1067 }
1068
1069 /* Get VHT RX STBC cap */
1070 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1071
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301072 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301073 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 FL("could not get VHT RX STBC"));
1075 value = 0;
1076 }
1077
1078 /* VHT RX STBC cap */
1079 if (value && !cfg->vht_rx_stbc) {
1080 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1081 cfg->vht_rx_stbc);
1082
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301083 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301084 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001085 FL("could not set the VHT RX STBC to CCM"));
1086 }
1087 }
1088
1089 /* Get VHT SU Beamformer cap */
1090 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1091 &value);
1092
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301093 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301094 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001095 FL("could not get VHT SU BEAMFORMER CAP"));
1096 value = 0;
1097 }
1098
1099 /* set VHT SU Beamformer cap */
1100 if (value && !cfg->vht_su_bformer) {
1101 status = sme_cfg_set_int(hdd_ctx->hHal,
1102 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1103 cfg->vht_su_bformer);
1104
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301105 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301106 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107 FL("could not set VHT SU BEAMFORMER CAP"));
1108 }
1109 }
1110
1111 /* check and update SU BEAMFORMEE capabality */
1112 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1113 pconfig->enableTxBF = cfg->vht_su_bformee;
1114
1115 status = sme_cfg_set_int(hdd_ctx->hHal,
1116 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1117 pconfig->enableTxBF);
1118
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301119 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301120 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 FL("could not set VHT SU BEAMFORMEE CAP"));
1122 }
1123
1124 /* Get VHT MU Beamformer cap */
1125 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1126 &value);
1127
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301128 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301129 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130 FL("could not get VHT MU BEAMFORMER CAP"));
1131 value = 0;
1132 }
1133
1134 /* set VHT MU Beamformer cap */
1135 if (value && !cfg->vht_mu_bformer) {
1136 status = sme_cfg_set_int(hdd_ctx->hHal,
1137 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1138 cfg->vht_mu_bformer);
1139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301140 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301141 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 FL(
1143 "could not set the VHT MU BEAMFORMER CAP to CCM"
1144 ));
1145 }
1146 }
1147
1148 /* Get VHT MU Beamformee cap */
1149 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1150 &value);
1151
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301152 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301153 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 FL("could not get VHT MU BEAMFORMEE CAP"));
1155 value = 0;
1156 }
1157
1158 /* set VHT MU Beamformee cap */
1159 if (value && !cfg->vht_mu_bformee) {
1160 status = sme_cfg_set_int(hdd_ctx->hHal,
1161 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1162 cfg->vht_mu_bformee);
1163
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301164 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301165 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166 FL("could not set VHT MU BEAMFORMER CAP"));
1167 }
1168 }
1169
1170 /* Get VHT MAX AMPDU Len exp */
1171 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1172 &value);
1173
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301174 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301175 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001176 FL("could not get VHT AMPDU LEN"));
1177 value = 0;
1178 }
1179
1180 /*
1181 * VHT max AMPDU len exp:
1182 * override if user configured value is too high
1183 * that the target cannot support.
1184 * Even though Rome publish ampdu_len=7, it can
1185 * only support 4 because of some h/w bug.
1186 */
1187
1188 if (value > cfg->vht_max_ampdu_len_exp) {
1189 status = sme_cfg_set_int(hdd_ctx->hHal,
1190 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1191 cfg->vht_max_ampdu_len_exp);
1192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301193 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301194 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 FL("could not set the VHT AMPDU LEN EXP"));
1196 }
1197 }
1198
1199 /* Get VHT TXOP PS CAP */
1200 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1201
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301202 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301203 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204 FL("could not get VHT TXOP PS"));
1205 value = 0;
1206 }
1207
1208 /* set VHT TXOP PS cap */
1209 if (value && !cfg->vht_txop_ps) {
1210 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1211 cfg->vht_txop_ps);
1212
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301213 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301214 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 FL("could not set the VHT TXOP PS"));
1216 }
1217 }
1218
1219 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1220 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1221 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1222 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1223 else
1224 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1225
1226
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001227 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001228 band_5g->vht_cap.cap |=
1229 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001230 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 band_5g->vht_cap.cap |=
1232 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233
1234 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1235 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1236
1237 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1238 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1239 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1240 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1241
1242 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1243 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1244
1245 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1246 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1247 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1248 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1249 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1250 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1251
1252 band_5g->vht_cap.cap |=
1253 (cfg->vht_max_ampdu_len_exp <<
1254 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1255
1256 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1257 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1258 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1259 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1260 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1261 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1262 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1263 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1264
1265 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1266 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1267
1268}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269
1270void hdd_update_tgt_cfg(void *context, void *param)
1271{
1272 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1273 struct wma_tgt_cfg *cfg = param;
1274 uint8_t temp_band_cap;
1275
1276 /* first store the INI band capability */
1277 temp_band_cap = hdd_ctx->config->nBandCapability;
1278
1279 hdd_ctx->config->nBandCapability = cfg->band_cap;
1280
1281 /* now overwrite the target band capability with INI
1282 setting if INI setting is a subset */
1283
1284 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1285 (temp_band_cap != eCSR_BAND_ALL))
1286 hdd_ctx->config->nBandCapability = temp_band_cap;
1287 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1288 (temp_band_cap != eCSR_BAND_ALL) &&
1289 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301290 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 FL("ini BandCapability not supported by the target"));
1292 }
1293
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001294 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1296 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1297 }
1298
1299 /* This can be extended to other configurations like ht, vht cap... */
1300
Anurag Chouhanc5548422016-02-24 18:33:27 +05301301 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1303 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301304 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 FL(
1306 "Invalid MAC passed from target, using MAC from ini file"
1307 MAC_ADDRESS_STR),
1308 MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes));
1309 }
1310
1311 hdd_ctx->target_fw_version = cfg->target_fw_version;
1312
1313 hdd_ctx->max_intf_count = cfg->max_intf_count;
1314
1315#ifdef WLAN_FEATURE_LPSS
1316 hdd_ctx->lpss_support = cfg->lpss_support;
1317#endif
1318
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001319 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1320
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001321 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1322 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1323
1324 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1325
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001327 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001328 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001329 hdd_info(FL("fine_time_meas_cap: 0x%x"),
1330 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001331
1332 hdd_ctx->current_antenna_mode =
1333 (hdd_ctx->config->enable2x2 == 0x01) ?
1334 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1335 hdd_info("Init current antenna mode: %d",
1336 hdd_ctx->current_antenna_mode);
1337
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001338}
1339
1340/**
1341 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1342 * @context: HDD context pointer
1343 * @param: HDD radar indication pointer
1344 *
1345 * This function is invoked when a radar in found on the
1346 * SAP current operating channel and Data Tx from netif
1347 * has to be stopped to honor the DFS regulations.
1348 * Actions: Stop the netif Tx queues,Indicate Radar present
1349 * in HDD context for future usage.
1350 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301351 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301353bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001354{
1355 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1356 struct wma_dfs_radar_ind *hdd_radar_event =
1357 (struct wma_dfs_radar_ind *)param;
1358 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1359 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301360 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301362 if (!hdd_ctx || !hdd_radar_event ||
1363 hdd_ctx->config->disableDFSChSwitch)
1364 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365
1366 if (true == hdd_radar_event->dfs_radar_status) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301367 mutex_lock(&hdd_ctx->dfs_lock);
1368 if (hdd_ctx->dfs_radar_found) {
1369 /*
1370 * Application already triggered channel switch
1371 * on current channel, so return here.
1372 */
1373 mutex_unlock(&hdd_ctx->dfs_lock);
1374 return false;
1375 }
1376
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 hdd_ctx->dfs_radar_found = true;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301378 mutex_unlock(&hdd_ctx->dfs_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379
1380 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301381 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08001383 if (QDF_SAP_MODE == adapter->device_mode ||
1384 QDF_P2P_GO_MODE == adapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1386 dfs_cac_block_tx = true;
1387 }
1388
1389 status = hdd_get_next_adapter(hdd_ctx,
1390 adapterNode,
1391 &pNext);
1392 adapterNode = pNext;
1393 }
1394 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301395
1396 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398
1399/**
1400 * hdd_is_valid_mac_address() - validate MAC address
1401 * @pMacAddr: Pointer to the input MAC address
1402 *
1403 * This function validates whether the given MAC address is valid or not
1404 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1405 * where X is the hexa decimal digit character and separated by ':'
1406 * This algorithm works even if MAC address is not separated by ':'
1407 *
1408 * This code checks given input string mac contains exactly 12 hexadecimal
1409 * digits and a separator colon : appears in the input string only after
1410 * an even number of hex digits.
1411 *
1412 * Return: 1 for valid and 0 for invalid
1413 */
1414bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1415{
1416 int xdigit = 0;
1417 int separator = 0;
1418 while (*pMacAddr) {
1419 if (isxdigit(*pMacAddr)) {
1420 xdigit++;
1421 } else if (':' == *pMacAddr) {
1422 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1423 break;
1424
1425 ++separator;
1426 } else {
1427 /* Invalid MAC found */
1428 return 0;
1429 }
1430 ++pMacAddr;
1431 }
1432 return xdigit == 12 && (separator == 5 || separator == 0);
1433}
1434
1435/**
1436 * __hdd_open() - HDD Open function
1437 * @dev: Pointer to net_device structure
1438 *
1439 * This is called in response to ifconfig up
1440 *
1441 * Return: 0 for success; non-zero for failure
1442 */
1443static int __hdd_open(struct net_device *dev)
1444{
1445 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1446 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1447 int ret;
1448
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001449 ENTER_DEV(dev);
1450
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301451 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001452 adapter->sessionId, adapter->device_mode));
1453
1454 ret = wlan_hdd_validate_context(hdd_ctx);
1455 if (0 != ret) {
1456 hddLog(LOGE, FL("HDD context is not valid"));
1457 return ret;
1458 }
1459
1460 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1461 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
1462 hddLog(LOG1, FL("Enabling Tx Queues"));
1463 /* Enable TX queues only when we are connected */
1464 wlan_hdd_netif_queue_control(adapter,
1465 WLAN_START_ALL_NETIF_QUEUE,
1466 WLAN_CONTROL_PATH);
1467 }
1468
1469 return ret;
1470}
1471
1472/**
1473 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1474 * @dev: Pointer to net_device structure
1475 *
1476 * This is called in response to ifconfig up
1477 *
1478 * Return: 0 for success; non-zero for failure
1479 */
1480int hdd_open(struct net_device *dev)
1481{
1482 int ret;
1483
1484 cds_ssr_protect(__func__);
1485 ret = __hdd_open(dev);
1486 cds_ssr_unprotect(__func__);
1487
1488 return ret;
1489}
1490
1491/**
1492 * __hdd_stop() - HDD stop function
1493 * @dev: Pointer to net_device structure
1494 *
1495 * This is called in response to ifconfig down
1496 *
1497 * Return: 0 for success; non-zero for failure
1498 */
1499static int __hdd_stop(struct net_device *dev)
1500{
1501 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1502 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1503 int ret;
1504
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001505 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301507 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 adapter->sessionId, adapter->device_mode));
1509
1510 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301511 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001512 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001513
1514 /* Nothing to be done if the interface is not opened */
1515 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301516 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001517 FL("NETDEV Interface is not OPENED"));
1518 return -ENODEV;
1519 }
1520
1521 /* Make sure the interface is marked as closed */
1522 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301523 hddLog(QDF_TRACE_LEVEL_INFO, FL("Disabling OS Tx queues"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001524
1525 /*
1526 * Disable TX on the interface, after this hard_start_xmit() will not
1527 * be called on that interface
1528 */
1529 hddLog(LOG1, FL("Disabling queues"));
1530 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1531 WLAN_CONTROL_PATH);
1532
1533 /*
1534 * The interface is marked as down for outside world (aka kernel)
1535 * But the driver is pretty much alive inside. The driver needs to
1536 * tear down the existing connection on the netdev (session)
1537 * cleanup the data pipes and wait until the control plane is stabilized
1538 * for this interface. The call also needs to wait until the above
1539 * mentioned actions are completed before returning to the caller.
1540 * Notice that the hdd_stop_adapter is requested not to close the session
1541 * That is intentional to be able to scan if it is a STA/P2P interface
1542 */
1543 hdd_stop_adapter(hdd_ctx, adapter, false);
1544
1545 /* DeInit the adapter. This ensures datapath cleanup as well */
1546 hdd_deinit_adapter(hdd_ctx, adapter, true);
1547
1548 EXIT();
1549 return 0;
1550}
1551
1552/**
1553 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
1554 * @dev: pointer to net_device structure
1555 *
1556 * This is called in response to ifconfig down
1557 *
1558 * Return: 0 for success and error number for failure
1559 */
1560int hdd_stop(struct net_device *dev)
1561{
1562 int ret;
1563
1564 cds_ssr_protect(__func__);
1565 ret = __hdd_stop(dev);
1566 cds_ssr_unprotect(__func__);
1567
1568 return ret;
1569}
1570
1571/**
1572 * __hdd_uninit() - HDD uninit function
1573 * @dev: Pointer to net_device structure
1574 *
1575 * This is called during the netdev unregister to uninitialize all data
1576 * associated with the device
1577 *
1578 * Return: None
1579 */
1580static void __hdd_uninit(struct net_device *dev)
1581{
1582 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1583
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001584 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001585
1586 do {
1587 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1588 hddLog(LOGP, FL("Invalid magic"));
1589 break;
1590 }
1591
1592 if (NULL == adapter->pHddCtx) {
1593 hddLog(LOGP, FL("NULL hdd_ctx"));
1594 break;
1595 }
1596
1597 if (dev != adapter->dev) {
1598 hddLog(LOGP, FL("Invalid device reference"));
1599 /*
1600 * we haven't validated all cases so let this go for
1601 * now
1602 */
1603 }
1604
1605 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
1606
1607 /* after uninit our adapter structure will no longer be valid */
1608 adapter->dev = NULL;
1609 adapter->magic = 0;
1610 } while (0);
1611
1612 EXIT();
1613}
1614
1615/**
1616 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
1617 * @dev: pointer to net_device structure
1618 *
1619 * This is called during the netdev unregister to uninitialize all data
1620 * associated with the device
1621 *
1622 * Return: none
1623 */
1624static void hdd_uninit(struct net_device *dev)
1625{
1626 cds_ssr_protect(__func__);
1627 __hdd_uninit(dev);
1628 cds_ssr_unprotect(__func__);
1629}
1630
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08001631static int hdd_open_cesium_nl_sock(void)
1632{
1633#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1634 struct netlink_kernel_cfg cfg = {
1635 .groups = WLAN_NLINK_MCAST_GRP_ID,
1636 .input = NULL
1637 };
1638#endif
1639 int ret = 0;
1640
1641#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1642 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
1643#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
1644 THIS_MODULE,
1645#endif
1646 &cfg);
1647#else
1648 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
1649 WLAN_NLINK_MCAST_GRP_ID,
1650 NULL, NULL, THIS_MODULE);
1651#endif
1652
1653 if (cesium_nl_srv_sock == NULL) {
1654 hddLog(QDF_TRACE_LEVEL_ERROR,
1655 FL("NLINK: cesium netlink_kernel_create failed"));
1656 ret = -ECONNREFUSED;
1657 }
1658
1659 return ret;
1660}
1661
1662static void hdd_close_cesium_nl_sock(void)
1663{
1664 if (NULL != cesium_nl_srv_sock) {
1665 netlink_kernel_release(cesium_nl_srv_sock);
1666 cesium_nl_srv_sock = NULL;
1667 }
1668}
1669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001670/**
1671 * __hdd_set_mac_address() - set the user specified mac address
1672 * @dev: Pointer to the net device.
1673 * @addr: Pointer to the sockaddr.
1674 *
1675 * This function sets the user specified mac address using
1676 * the command ifconfig wlanX hw ether <mac adress>.
1677 *
1678 * Return: 0 for success, non zero for failure
1679 */
1680static int __hdd_set_mac_address(struct net_device *dev, void *addr)
1681{
1682 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1683 hdd_context_t *hdd_ctx;
1684 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301685 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001686 int ret;
1687
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001688 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689
1690 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1691 ret = wlan_hdd_validate_context(hdd_ctx);
1692 if (0 != ret)
1693 return ret;
1694
1695 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1696 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1697
1698 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301699 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001700}
1701
1702/**
1703 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
1704 * function from SSR
1705 * @dev: pointer to net_device structure
1706 * @addr: Pointer to the sockaddr
1707 *
1708 * This function sets the user specified mac address using
1709 * the command ifconfig wlanX hw ether <mac adress>.
1710 *
1711 * Return: 0 for success.
1712 */
1713static int hdd_set_mac_address(struct net_device *dev, void *addr)
1714{
1715 int ret;
1716
1717 cds_ssr_protect(__func__);
1718 ret = __hdd_set_mac_address(dev, addr);
1719 cds_ssr_unprotect(__func__);
1720
1721 return ret;
1722}
1723
1724uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
1725{
1726 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301727 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
1729 break;
1730 }
1731
Anurag Chouhan6d760662016-02-20 16:05:43 +05301732 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 return NULL;
1734
1735 hdd_ctx->config->intfAddrMask |= (1 << i);
1736 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
1737}
1738
1739void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
1740{
1741 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301742 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743 if (!memcmp(releaseAddr,
1744 &hdd_ctx->config->intfMacAddr[i].bytes[0],
1745 6)) {
1746 hdd_ctx->config->intfAddrMask &= ~(1 << i);
1747 break;
1748 }
1749 }
1750 return;
1751}
1752
1753#ifdef WLAN_FEATURE_PACKET_FILTERING
1754/**
1755 * __hdd_set_multicast_list() - set the multicast address list
1756 * @dev: Pointer to the WLAN device.
1757 * @skb: Pointer to OS packet (sk_buff).
1758 *
1759 * This funciton sets the multicast address list.
1760 *
1761 * Return: None
1762 */
1763static void __hdd_set_multicast_list(struct net_device *dev)
1764{
1765 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1766 int mc_count;
1767 int i = 0, status;
1768 struct netdev_hw_addr *ha;
1769 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1770 static const uint8_t ipv6_router_solicitation[]
1771 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
1772
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001773 ENTER_DEV(dev);
1774
Anurag Chouhan6d760662016-02-20 16:05:43 +05301775 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05301776 return;
1777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301779 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781
1782 if (dev->flags & IFF_ALLMULTI) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301783 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784 FL("allow all multicast frames"));
1785 adapter->mc_addr_list.mc_cnt = 0;
1786 } else {
1787 mc_count = netdev_mc_count(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301788 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001789 FL("mc_count = %u"), mc_count);
1790 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301791 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001792 FL(
1793 "No free filter available; allow all multicast frames"
1794 ));
1795 adapter->mc_addr_list.mc_cnt = 0;
1796 return;
1797 }
1798
1799 adapter->mc_addr_list.mc_cnt = mc_count;
1800
1801 netdev_for_each_mc_addr(ha, dev) {
1802 if (i == mc_count)
1803 break;
1804 /*
1805 * Skip following addresses:
1806 * 1)IPv6 router solicitation address
1807 * 2)Any other address pattern if its set during
1808 * RXFILTER REMOVE driver command based on
1809 * addr_filter_pattern
1810 */
1811 if ((!memcmp(ha->addr, ipv6_router_solicitation,
1812 ETH_ALEN)) ||
1813 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
1814 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08001815 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 MAC_ADDR_ARRAY(ha->addr));
1817 adapter->mc_addr_list.mc_cnt--;
1818 continue;
1819 }
1820
1821 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
1822 ETH_ALEN);
1823 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
1824 ETH_ALEN);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301825 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 FL("mlist[%d] = " MAC_ADDRESS_STR), i,
1827 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
1828 i++;
1829 }
1830 }
1831 if (hdd_ctx->config->active_mode_offload) {
1832 hdd_info("enable mc filtering");
1833 wlan_hdd_set_mc_addr_list(adapter, true);
1834 } else {
1835 hdd_info("skip mc filtering enable it during cfg80211 suspend");
1836 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301837 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 return;
1839}
1840
1841/**
1842 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
1843 * @dev: pointer to net_device
1844 *
1845 * Return: none
1846 */
1847static void hdd_set_multicast_list(struct net_device *dev)
1848{
1849 cds_ssr_protect(__func__);
1850 __hdd_set_multicast_list(dev);
1851 cds_ssr_unprotect(__func__);
1852}
1853#endif
1854
1855/**
1856 * hdd_select_queue() - used by Linux OS to decide which queue to use first
1857 * @dev: Pointer to the WLAN device.
1858 * @skb: Pointer to OS packet (sk_buff).
1859 *
1860 * This function is registered with the Linux OS for network
1861 * core to decide which queue to use first.
1862 *
1863 * Return: ac, Queue Index/access category corresponding to UP in IP header
1864 */
1865static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
1866#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
1867 , void *accel_priv
1868#endif
1869#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1870 , select_queue_fallback_t fallback
1871#endif
1872)
1873{
1874 return hdd_wmm_select_queue(dev, skb);
1875}
1876
1877static struct net_device_ops wlan_drv_ops = {
1878 .ndo_open = hdd_open,
1879 .ndo_stop = hdd_stop,
1880 .ndo_uninit = hdd_uninit,
1881 .ndo_start_xmit = hdd_hard_start_xmit,
1882 .ndo_tx_timeout = hdd_tx_timeout,
1883 .ndo_get_stats = hdd_get_stats,
1884 .ndo_do_ioctl = hdd_ioctl,
1885 .ndo_set_mac_address = hdd_set_mac_address,
1886 .ndo_select_queue = hdd_select_queue,
1887#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889#endif
1890};
1891
1892void hdd_set_station_ops(struct net_device *pWlanDev)
1893{
1894 pWlanDev->netdev_ops = &wlan_drv_ops;
1895}
1896
Ryan Hsu07495ea2016-01-21 15:25:39 -08001897/**
1898 * hdd_alloc_station_adapter() - allocate the station hdd adapter
1899 * @hdd_ctx: global hdd context
1900 * @macAddr: mac address to assign to the interface
1901 * @name: User-visible name of the interface
1902 *
1903 * hdd adapter pointer would point to the netdev->priv space, this function
1904 * would retrive the pointer, and setup the hdd adapter configuration.
1905 *
1906 * Return: the pointer to hdd adapter, otherwise NULL
1907 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
1909 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08001910 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 const char *name)
1912{
1913 struct net_device *pWlanDev = NULL;
1914 hdd_adapter_t *adapter = NULL;
1915 /*
1916 * cfg80211 initialization and registration....
1917 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08001918 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
1919#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
1920 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921#endif
Ryan Hsu07495ea2016-01-21 15:25:39 -08001922 ether_setup, NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923
1924 if (pWlanDev != NULL) {
1925
1926 /* Save the pointer to the net_device in the HDD adapter */
1927 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
1928
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301929 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930
1931 adapter->dev = pWlanDev;
1932 adapter->pHddCtx = hdd_ctx;
1933 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1934
1935 init_completion(&adapter->session_open_comp_var);
1936 init_completion(&adapter->session_close_comp_var);
1937 init_completion(&adapter->disconnect_comp_var);
1938 init_completion(&adapter->linkup_event_var);
1939 init_completion(&adapter->cancel_rem_on_chan_var);
1940 init_completion(&adapter->rem_on_chan_ready_event);
1941 init_completion(&adapter->sta_authorized_event);
1942 init_completion(&adapter->offchannel_tx_event);
1943 init_completion(&adapter->tx_action_cnf_event);
1944#ifdef FEATURE_WLAN_TDLS
1945 init_completion(&adapter->tdls_add_station_comp);
1946 init_completion(&adapter->tdls_del_station_comp);
1947 init_completion(&adapter->tdls_mgmt_comp);
1948 init_completion(&adapter->tdls_link_establish_req_comp);
1949#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08001950 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 init_completion(&adapter->change_country_code);
1952
1953
1954 init_completion(&adapter->scan_info.abortscan_event_var);
1955
1956 adapter->offloads_configured = false;
1957 adapter->isLinkUpSvcNeeded = false;
1958 adapter->higherDtimTransition = true;
1959 /* Init the net_device structure */
1960 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1961
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301962 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301964 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 sizeof(tSirMacAddr));
1966 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001967
1968 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
1969 pWlanDev->features |=
1970 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
1971 pWlanDev->features |= NETIF_F_RXCSUM;
1972
Dhanashri Atre83d373d2015-07-28 16:45:59 -07001973 hdd_set_tso_flags(hdd_ctx, pWlanDev);
1974
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975 hdd_set_station_ops(adapter->dev);
1976
1977 pWlanDev->destructor = free_netdev;
1978 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08001979 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 adapter->wdev.wiphy = hdd_ctx->wiphy;
1981 adapter->wdev.netdev = pWlanDev;
1982 /* set pWlanDev's parent to underlying device */
1983 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
1984 hdd_wmm_init(adapter);
1985 spin_lock_init(&adapter->pause_map_lock);
1986 }
1987
1988 return adapter;
1989}
1990
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301991QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001992 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993{
1994 struct net_device *pWlanDev = adapter->dev;
1995 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
1996 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301997 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001999 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2001 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302002 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003 FL("Failed:dev_alloc_name"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302004 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 }
2006 }
2007 if (register_netdevice(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302008 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302010 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 }
2012 } else {
2013 if (register_netdev(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302014 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302016 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 }
2018 }
2019 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2020
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302021 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022}
2023
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302024static QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025{
2026 hdd_adapter_t *adapter = pContext;
2027
2028 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302029 hddLog(QDF_TRACE_LEVEL_FATAL, FL("NULL adapter"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302030 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002031 }
2032
2033 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302034 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid magic"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302035 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002036 }
2037
2038 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2039
2040#if !defined (CONFIG_CNSS) && \
2041 !defined (WLAN_OPEN_SOURCE)
2042 /*
2043 * need to make sure all of our scheduled work has completed.
2044 * This callback is called from MC thread context, so it is safe to
2045 * to call below flush workqueue API from here.
2046 *
2047 * Even though this is called from MC thread context, if there is a faulty
2048 * work item in the system, that can hang this call forever. So flushing
2049 * this global work queue is not safe; and now we make sure that
2050 * individual work queues are stopped correctly. But the cancel work queue
2051 * is a GPL only API, so the proprietary version of the driver would still
2052 * rely on the global work queue flush.
2053 */
2054 flush_scheduled_work();
2055#endif
2056
2057 /*
2058 * We can be blocked while waiting for scheduled work to be
2059 * flushed, and the adapter structure can potentially be freed, in
2060 * which case the magic will have been reset. So make sure the
2061 * magic is still good, and hence the adapter structure is still
2062 * valid, before signaling completion
2063 */
2064 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2065 complete(&adapter->session_close_comp_var);
2066
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302067 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068}
2069
Krunal Soni8c37e322016-02-03 16:08:37 -08002070/**
2071 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2072 * @adapter: pointer to device adapter
2073 * @type: type of interface
2074 *
2075 * This routine will check the mode of adapter and if it is required then it
2076 * will initialize the TDLS operations
2077 *
2078 * Return: QDF_STATUS
2079 */
2080#ifdef FEATURE_WLAN_TDLS
2081static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2082{
2083 if (QDF_IBSS_MODE != type) {
2084 if (0 != wlan_hdd_tdls_init(adapter)) {
2085 hddLog(LOGE, FL("wlan_hdd_tdls_init failed"));
2086 return QDF_STATUS_E_FAILURE;
2087 }
2088 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2089 }
2090 return QDF_STATUS_SUCCESS;
2091}
2092#else
2093static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2094{
2095 return QDF_STATUS_SUCCESS;
2096}
2097#endif
2098
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302099QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100{
2101 struct net_device *pWlanDev = adapter->dev;
2102 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2103 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302104 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302105 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106 uint32_t type, subType;
2107 unsigned long rc;
2108 int ret_val;
2109
2110 INIT_COMPLETION(adapter->session_open_comp_var);
2111 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
2112 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302113 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114 hddLog(LOGE, FL("failed to get vdev type"));
2115 goto error_sme_open;
2116 }
2117 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302118 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2120 (uint8_t *) &adapter->macAddressCurrent,
2121 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302122 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123 hddLog(LOGP,
2124 FL("sme_open_session() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302125 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302126 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 goto error_sme_open;
2128 }
2129 /* Block on a completion variable. Can't wait forever though. */
2130 rc = wait_for_completion_timeout(
2131 &adapter->session_open_comp_var,
2132 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2133 if (!rc) {
2134 hddLog(LOGP,
2135 FL("Session is not opened within timeout period code %ld"),
2136 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302137 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002138 goto error_sme_open;
2139 }
2140
2141 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302142 qdf_ret_status = hdd_register_wext(pWlanDev);
2143 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144 hddLog(LOGP,
2145 FL("hdd_register_wext() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302146 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302147 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002148 goto error_register_wext;
2149 }
2150 /* Set the Connection State to Not Connected */
2151 hddLog(LOG1,
2152 FL("Set HDD connState to eConnectionState_NotConnected"));
2153 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2154
2155 /* Set the default operation channel */
2156 pHddStaCtx->conn_info.operationChannel =
2157 hdd_ctx->config->OperatingChannel;
2158
2159 /* Make the default Auth Type as OPEN */
2160 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2161
2162 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302163 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002164 hddLog(LOGP,
2165 FL("hdd_init_tx_rx() failed, status code %08d [x%08x]"),
2166 status, status);
2167 goto error_init_txrx;
2168 }
2169
2170 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2171
2172 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302173 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 hddLog(LOGP,
2175 FL("hdd_wmm_adapter_init() failed, status code %08d [x%08x]"),
2176 status, status);
2177 goto error_wmm_init;
2178 }
2179
2180 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2181
2182 ret_val = wma_cli_set_command(adapter->sessionId,
2183 WMI_PDEV_PARAM_BURST_ENABLE,
2184 hdd_ctx->config->enableSifsBurst,
2185 PDEV_CMD);
2186
2187 if (0 != ret_val) {
2188 hddLog(LOGE,
2189 FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
2190 ret_val);
2191 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002192 status = hdd_check_and_init_tdls(adapter, type);
2193 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002194 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302196 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197
2198#ifdef FEATURE_WLAN_TDLS
2199error_tdls_init:
2200 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2201 hdd_wmm_adapter_close(adapter);
2202#endif
2203error_wmm_init:
2204 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2205 hdd_deinit_tx_rx(adapter);
2206error_init_txrx:
2207 hdd_unregister_wext(pWlanDev);
2208error_register_wext:
2209 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2210 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302211 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 adapter->sessionId,
2213 hdd_sme_close_session_callback,
2214 adapter)) {
2215 unsigned long rc;
2216
2217 /*
2218 * Block on a completion variable.
2219 * Can't wait forever though.
2220 */
2221 rc = wait_for_completion_timeout(
2222 &adapter->session_close_comp_var,
2223 msecs_to_jiffies
2224 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2225 if (rc <= 0)
2226 hddLog(LOGE,
2227 FL("Session is not opened within timeout period code %ld"),
2228 rc);
2229 }
2230 }
2231error_sme_open:
2232 return status;
2233}
2234
2235void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2236{
2237 hdd_cfg80211_state_t *cfgState;
2238
2239 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2240
2241 if (NULL != cfgState->buf) {
2242 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002243 rc = wait_for_completion_timeout(
2244 &adapter->tx_action_cnf_event,
2245 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2246 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302247 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002248 FL("HDD Wait for Action Confirmation Failed!!"));
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302249 /*
2250 * Inform tx status as FAILURE to upper layer and free
2251 * cfgState->buf
2252 */
2253 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 }
2255 }
2256 return;
2257}
2258
2259void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2260 bool rtnl_held)
2261{
2262 ENTER();
2263 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002264 case QDF_STA_MODE:
2265 case QDF_P2P_CLIENT_MODE:
2266 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267 {
2268 if (test_bit
2269 (INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2270 hdd_deinit_tx_rx(adapter);
2271 clear_bit(INIT_TX_RX_SUCCESS,
2272 &adapter->event_flags);
2273 }
2274
2275 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2276 hdd_wmm_adapter_close(adapter);
2277 clear_bit(WMM_INIT_DONE,
2278 &adapter->event_flags);
2279 }
2280
2281 hdd_cleanup_actionframe(hdd_ctx, adapter);
2282 wlan_hdd_tdls_exit(adapter);
2283 break;
2284 }
2285
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002286 case QDF_SAP_MODE:
2287 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002288 {
2289
2290 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2291 hdd_wmm_adapter_close(adapter);
2292 clear_bit(WMM_INIT_DONE,
2293 &adapter->event_flags);
2294 }
2295
2296 hdd_cleanup_actionframe(hdd_ctx, adapter);
2297
2298 hdd_unregister_hostapd(adapter, rtnl_held);
2299
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 break;
2301 }
2302
2303 default:
2304 break;
2305 }
2306
2307 EXIT();
2308}
2309
2310void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002311 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312{
2313 struct net_device *pWlanDev = NULL;
2314
2315 if (adapter)
2316 pWlanDev = adapter->dev;
2317 else {
2318 hddLog(LOGE, FL("adapter is Null"));
2319 return;
2320 }
2321
2322 hdd_lro_disable(hdd_ctx, adapter);
Rajeev Kumardca5f812016-02-04 17:28:06 -08002323 hdd_debugfs_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 /*
2325 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2326 * the driver is almost closed and cannot handle either control
2327 * messages or data. However, unregister_netdevice() call above will
2328 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2329 * to close the active connections (basically excites control path) which
2330 * is not right. Setting this flag helps hdd_stop() to recognize that
2331 * the interface is closed and restricts any operations on that
2332 */
2333 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2334
2335 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2336 if (rtnl_held) {
2337 unregister_netdevice(pWlanDev);
2338 } else {
2339 unregister_netdev(pWlanDev);
2340 }
2341 /*
2342 * Note that the adapter is no longer valid at this point
2343 * since the memory has been reclaimed
2344 */
2345 }
2346}
2347
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302348QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 tSirMacAddr macAddr)
2350{
2351 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2352 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302353 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302355 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 adapter = adapterNode->pAdapter;
2357 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302358 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002359 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302360 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361 }
2362 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2363 adapterNode = pNext;
2364 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302365 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002367
2368/**
2369 * hdd_open_adapter() - open and setup the hdd adatper
2370 * @hdd_ctx: global hdd context
2371 * @session_type: type of the interface to be created
2372 * @iface_name: User-visible name of the interface
2373 * @macAddr: MAC address to assign to the interface
2374 * @name_assign_type: the name of assign type of the netdev
2375 * @rtnl_held: the rtnl lock hold flag
2376 *
2377 * This function open and setup the hdd adpater according to the device
2378 * type request, assign the name, the mac address assigned, and then prepared
2379 * the hdd related parameters, queue, lock and ready to start.
2380 *
2381 * Return: the pointer of hdd adapter, otherwise NULL.
2382 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
2384 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002385 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002386 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387{
2388 hdd_adapter_t *adapter = NULL;
2389 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302390 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391 hdd_cfg80211_state_t *cfgState;
2392 int ret;
2393
2394 hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type);
2395
2396 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
2397 /*
2398 * Max limit reached on the number of vdevs configured by the
2399 * host. Return error
2400 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302401 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002402 FL(
2403 "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d"
2404 ),
2405 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
2406 return NULL;
2407 }
2408
2409 if (macAddr == NULL) {
2410 /* Not received valid macAddr */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302411 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002412 FL(
2413 "Unable to add virtual intf: Not able to get valid mac address"
2414 ));
2415 return NULL;
2416 }
2417 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302418 if (QDF_STATUS_E_FAILURE == status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302419 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 "Duplicate MAC addr: " MAC_ADDRESS_STR
2421 " already exists",
2422 MAC_ADDR_ARRAY(macAddr));
2423 return NULL;
2424 }
2425
2426 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002427 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 /* Reset locally administered bit if the device mode is STA */
2429 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
2430 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002431 case QDF_P2P_CLIENT_MODE:
2432 case QDF_P2P_DEVICE_MODE:
2433 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 {
Ryan Hsu07495ea2016-01-21 15:25:39 -08002435 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
2436 name_assign_type,
2437 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438
2439 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302440 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 FL("failed to allocate adapter for session %d"),
2442 session_type);
2443 return NULL;
2444 }
2445
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002446 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002448 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 else
2451 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2452
2453 adapter->device_mode = session_type;
2454
2455 status = hdd_init_station_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302456 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 goto err_free_netdev;
2458
2459 hdd_lro_enable(hdd_ctx, adapter);
2460
2461 /*
2462 * Workqueue which gets scheduled in IPv4 notification
2463 * callback
2464 */
2465#ifdef CONFIG_CNSS
2466 cnss_init_work(&adapter->ipv4NotifierWorkQueue,
2467 hdd_ipv4_notifier_work_queue);
2468#else
2469 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
2470 hdd_ipv4_notifier_work_queue);
2471#endif
2472
2473#ifdef WLAN_NS_OFFLOAD
2474 /*
2475 * Workqueue which gets scheduled in IPv6
2476 * notification callback.
2477 */
2478#ifdef CONFIG_CNSS
2479 cnss_init_work(&adapter->ipv6NotifierWorkQueue,
2480 hdd_ipv6_notifier_work_queue);
2481#else
2482 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
2483 hdd_ipv6_notifier_work_queue);
2484#endif
2485#endif
2486 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302487 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2489 goto err_lro_cleanup;
2490 }
2491
2492 /* Stop the Interface TX queue. */
2493 hddLog(LOG1, FL("Disabling queues"));
2494 wlan_hdd_netif_queue_control(adapter,
2495 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2496 WLAN_CONTROL_PATH);
2497
2498 hdd_register_tx_flow_control(adapter,
2499 hdd_tx_resume_timer_expired_handler,
2500 hdd_tx_resume_cb);
2501
2502 break;
2503 }
2504
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002505 case QDF_P2P_GO_MODE:
2506 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002507 {
Ryan Hsu07495ea2016-01-21 15:25:39 -08002508 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
2509 name_assign_type,
2510 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302512 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002513 FL("failed to allocate adapter for session %d"),
2514 session_type);
2515 return NULL;
2516 }
2517
2518 adapter->wdev.iftype =
2519 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002520 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 NL80211_IFTYPE_P2P_GO;
2522 adapter->device_mode = session_type;
2523
2524 status = hdd_init_ap_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302525 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 goto err_free_netdev;
2527
2528 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302529 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002530 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2531 goto err_free_netdev;
2532 }
2533
2534 hddLog(LOG1, FL("Disabling queues"));
2535 wlan_hdd_netif_queue_control(adapter,
2536 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2537 WLAN_CONTROL_PATH);
2538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 break;
2540 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002541 case QDF_FTM_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 {
Ryan Hsu07495ea2016-01-21 15:25:39 -08002543 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
2544 name_assign_type,
2545 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546
2547 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302548 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 FL("failed to allocate adapter for session %d"),
2550 session_type);
2551 return NULL;
2552 }
2553
2554 /*
2555 * Assign NL80211_IFTYPE_STATION as interface type to resolve
2556 * Kernel Warning message while loading driver in FTM mode.
2557 */
2558 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2559 adapter->device_mode = session_type;
2560 status = hdd_register_interface(adapter, rtnl_held);
2561
2562 hdd_init_tx_rx(adapter);
2563
2564 /* Stop the Interface TX queue. */
2565 hddLog(LOG1, FL("Disabling queues"));
2566 wlan_hdd_netif_queue_control(adapter,
2567 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2568 WLAN_CONTROL_PATH);
2569 }
2570 break;
2571 default:
2572 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302573 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 FL("Invalid session type %d"),
2575 session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302576 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 return NULL;
2578 }
2579 }
2580
2581 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2582 mutex_init(&cfgState->remain_on_chan_ctx_lock);
2583
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302584 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585 /* Add it to the hdd's session list. */
2586 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302587 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002588 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302589 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590 } else {
2591 pHddAdapterNode->pAdapter = adapter;
2592 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
2593 }
2594 }
2595
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302596 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597 if (NULL != adapter) {
2598 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
2599 adapter = NULL;
2600 }
2601 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302602 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 }
2604 return NULL;
2605 }
2606
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302607 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002608 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609
2610 /* Initialize the WoWL service */
2611 if (!hdd_init_wowl(adapter)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302612 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 FL("hdd_init_wowl failed"));
2614 goto err_lro_cleanup;
2615 }
2616
2617 /* Adapter successfully added. Increment the vdev count */
2618 hdd_ctx->current_intf_count++;
2619
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302620 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002621 hdd_ctx->current_intf_count);
2622
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002623 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 }
2625
Anurag Chouhan6d760662016-02-20 16:05:43 +05302626 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002627 && (!hdd_ctx->config->enable2x2)) {
2628#define HDD_DTIM_1CHAIN_RX_ID 0x5
2629#define HDD_SMPS_PARAM_VALUE_S 29
2630
2631 /*
2632 * Disable DTIM 1 chain Rx when in 1x1, we are passing two value
2633 * as param_id << 29 | param_value.
2634 * Below param_value = 0(disable)
2635 */
2636 ret = wma_cli_set_command(adapter->sessionId,
2637 WMI_STA_SMPS_PARAM_CMDID,
2638 HDD_DTIM_1CHAIN_RX_ID <<
2639 HDD_SMPS_PARAM_VALUE_S,
2640 VDEV_CMD);
2641
2642 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302643 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644 FL("DTIM 1 chain set failed %d"), ret);
2645 goto err_lro_cleanup;
2646 }
2647
2648 ret = wma_cli_set_command(adapter->sessionId,
2649 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2650 hdd_ctx->config->txchainmask1x1,
2651 PDEV_CMD);
2652 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302653 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002654 FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"),
2655 ret);
2656 goto err_lro_cleanup;
2657 }
2658 ret = wma_cli_set_command(adapter->sessionId,
2659 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2660 hdd_ctx->config->rxchainmask1x1,
2661 PDEV_CMD);
2662 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302663 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"),
2665 ret);
2666 goto err_lro_cleanup;
2667 }
2668#undef HDD_DTIM_1CHAIN_RX_ID
2669#undef HDD_SMPS_PARAM_VALUE_S
2670 }
2671
Anurag Chouhan6d760662016-02-20 16:05:43 +05302672 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 ret = wma_cli_set_command(adapter->sessionId,
2674 WMI_PDEV_PARAM_HYST_EN,
2675 hdd_ctx->config->enableMemDeepSleep,
2676 PDEV_CMD);
2677
2678 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302679 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 FL("WMI_PDEV_PARAM_HYST_EN set failed %d"),
2681 ret);
2682 goto err_lro_cleanup;
2683 }
2684 }
2685
2686#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2687
2688 /* Enable FW logs based on INI configuration */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302689 if ((QDF_GLOBAL_FTM_MODE != cds_get_conparam()) &&
Komal Seelamc11bb222016-01-27 18:57:10 +05302690 (hdd_ctx->config->enable_fw_log)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002691 uint8_t count = 0;
2692 uint32_t value = 0;
2693 uint8_t numEntries = 0;
2694 uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2695
2696 hdd_ctx->fw_log_settings.dl_type =
2697 hdd_ctx->config->enableFwLogType;
2698 ret = wma_cli_set_command(adapter->sessionId,
2699 WMI_DBGLOG_TYPE,
2700 hdd_ctx->config->enableFwLogType,
2701 DBG_CMD);
2702 if (ret != 0) {
2703 hddLog(LOGE, FL("Failed to enable FW log type ret %d"),
2704 ret);
2705 }
2706
2707 hdd_ctx->fw_log_settings.dl_loglevel =
2708 hdd_ctx->config->enableFwLogLevel;
2709 ret = wma_cli_set_command(adapter->sessionId,
2710 WMI_DBGLOG_LOG_LEVEL,
2711 hdd_ctx->config->enableFwLogLevel,
2712 DBG_CMD);
2713 if (ret != 0) {
2714 hddLog(LOGE, FL("Failed to enable FW log level ret %d"),
2715 ret);
2716 }
2717
2718 hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel,
2719 moduleLoglevel,
2720 &numEntries,
2721 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2722 while (count < numEntries) {
2723 /*
2724 * FW module log level input string looks like below:
2725 * gFwDebugModuleLoglevel=<FW Module ID>,<Log Level>,...
2726 * For example:
2727 * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6
2728 * Above input string means :
2729 * For FW module ID 1 enable log level 0
2730 * For FW module ID 2 enable log level 1
2731 * For FW module ID 3 enable log level 2
2732 * For FW module ID 4 enable log level 3
2733 * For FW module ID 5 enable log level 4
2734 * For FW module ID 6 enable log level 5
2735 * For FW module ID 7 enable log level 6
2736 */
2737
2738 /* FW expects WMI command value =
2739 * Module ID * 10 + Module Log level
2740 */
2741 value = ((moduleLoglevel[count] * 10) +
2742 moduleLoglevel[count + 1]);
2743 ret = wma_cli_set_command(adapter->sessionId,
2744 WMI_DBGLOG_MOD_LOG_LEVEL,
2745 value, DBG_CMD);
2746 if (ret != 0) {
2747 hddLog(LOGE,
2748 FL
2749 ("Failed to enable FW module log level %d ret %d"),
2750 value, ret);
2751 }
2752
2753 count += 2;
2754 }
2755 }
2756#endif
Rajeev Kumardca5f812016-02-04 17:28:06 -08002757 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
2758 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759
2760 return adapter;
2761
2762err_lro_cleanup:
2763 hdd_lro_disable(hdd_ctx, adapter);
2764err_free_netdev:
2765 free_netdev(adapter->dev);
2766 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2767
2768 return NULL;
2769}
2770
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302771QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002772 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773{
2774 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302775 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776
2777 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302778 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302779 hddLog(QDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 status);
2781 return status;
2782 }
2783
2784 while (pCurrent->pAdapter != adapter) {
2785 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302786 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 break;
2788
2789 pCurrent = pNext;
2790 }
2791 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302792 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002793 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002794 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
2795
2796 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302797 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798 adapterNode = NULL;
2799
2800 /* Adapter removed. Decrement vdev count */
2801 if (hdd_ctx->current_intf_count != 0)
2802 hdd_ctx->current_intf_count--;
2803
2804 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302805 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302807 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808}
2809
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002810/**
2811 * hdd_close_all_adapters - Close all open adapters
2812 * @hdd_ctx: Hdd context
2813 * rtnl_held: True if RTNL lock held
2814 *
2815 * Close all open adapters.
2816 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302817 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002818 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302819QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820{
2821 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302822 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823
2824 ENTER();
2825
2826 do {
2827 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302828 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002830 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302831 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302833 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834
2835 EXIT();
2836
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302837 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002838}
2839
2840void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
2841{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302842 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 tSirUpdateIE updateIE;
2844 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002845 case QDF_STA_MODE:
2846 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 {
2848 hdd_station_ctx_t *pHddStaCtx =
2849 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002850 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 break;
2852 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002853 case QDF_SAP_MODE:
2854 case QDF_P2P_GO_MODE:
2855 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002857 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002858 break;
2859 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002860 case QDF_FTM_MODE:
2861 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002862 default:
2863 /*
2864 * wlan_hdd_reset_prob_rspies should not have been called
2865 * for these kind of devices
2866 */
2867 hddLog(LOGE,
2868 FL("Unexpected request for the current device type %d"),
2869 pHostapdAdapter->device_mode);
2870 return;
2871 }
2872
Anurag Chouhanc5548422016-02-24 18:33:27 +05302873 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874 updateIE.smeSessionId = pHostapdAdapter->sessionId;
2875 updateIE.ieBufferlength = 0;
2876 updateIE.pAdditionIEBuffer = NULL;
2877 updateIE.append = true;
2878 updateIE.notify = false;
2879 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
2880 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302881 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002882 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
2883 }
2884}
2885
Peng Xu66162de2016-02-11 17:01:20 -08002886/**
2887 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
2888 * @hdd_ctx: HDD context which is already NULL validated
2889 * @adapter: HDD adapter which is already NULL validated
2890 *
2891 * Close the SME session and wait for its completion, if needed.
2892 *
2893 * Return: None
2894 */
2895static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
2896 hdd_adapter_t *adapter)
2897{
2898 unsigned long rc;
2899
2900 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2901 hdd_err("session is not opened:%d", adapter->sessionId);
2902 return;
2903 }
2904
2905 INIT_COMPLETION(adapter->session_close_comp_var);
2906 if (QDF_STATUS_SUCCESS ==
2907 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2908 hdd_sme_close_session_callback,
2909 adapter)) {
2910 /*
2911 * Block on a completion variable. Can't wait
2912 * forever though.
2913 */
2914 rc = wait_for_completion_timeout(
2915 &adapter->session_close_comp_var,
2916 msecs_to_jiffies
2917 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2918 if (!rc)
2919 hdd_err("failure waiting for session_close_comp_var");
2920 }
2921}
2922
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302923QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 const bool bCloseSession)
2925{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302926 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
2928 union iwreq_data wrqu;
2929 tSirUpdateIE updateIE;
2930 unsigned long rc;
2931
2932 ENTER();
2933
2934 hddLog(LOG1, FL("Disabling queues"));
2935 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2936 WLAN_CONTROL_PATH);
2937 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002938 case QDF_STA_MODE:
2939 case QDF_P2P_CLIENT_MODE:
2940 case QDF_IBSS_MODE:
2941 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 if (hdd_conn_is_connected(
2943 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
2944 hdd_is_connecting(
2945 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
2946 if (pWextState->roamProfile.BSSType ==
2947 eCSR_BSS_TYPE_START_IBSS)
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302948 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 sme_roam_disconnect(hdd_ctx->hHal,
2950 adapter->sessionId,
2951 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2952 else
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302953 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 sme_roam_disconnect(hdd_ctx->hHal,
2955 adapter->sessionId,
2956 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2957 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302958 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002959 rc = wait_for_completion_timeout(
2960 &adapter->disconnect_comp_var,
2961 msecs_to_jiffies
2962 (WLAN_WAIT_TIME_DISCONNECT));
2963 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302964 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 FL(
2966 "wait on disconnect_comp_var failed"
2967 ));
2968 }
2969 } else {
2970 hddLog(LOGE,
2971 FL(
2972 "failed to post disconnect event to SME"
2973 ));
2974 }
2975 memset(&wrqu, '\0', sizeof(wrqu));
2976 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2977 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
2978 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
2979 NULL);
2980 } else {
2981 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
2982 eCSR_SCAN_ABORT_DEFAULT);
2983 }
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302984 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985
2986#ifdef WLAN_OPEN_SOURCE
2987 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
2988#endif
2989
2990 hdd_deregister_tx_flow_control(adapter);
2991
2992#ifdef WLAN_NS_OFFLOAD
2993#ifdef WLAN_OPEN_SOURCE
2994 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
2995#endif
2996#endif
2997
2998 /*
2999 * It is possible that the caller of this function does not
3000 * wish to close the session
3001 */
Peng Xu66162de2016-02-11 17:01:20 -08003002 if (true == bCloseSession)
3003 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003004 break;
3005
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003006 case QDF_SAP_MODE:
3007 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003009 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 /*
3011 * Before stopping the sap adapter, lets make sure there
3012 * is no sap restart work pending.
3013 */
3014 cds_flush_work(&hdd_ctx->sap_start_work);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303015 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 FL("Canceled the pending SAP restart work"));
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003017 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 }
3019 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003020 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3022
3023 hdd_deregister_tx_flow_control(adapter);
3024
3025 mutex_lock(&hdd_ctx->sap_lock);
3026 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303027 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303028 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029
3030 /* Stop Bss. */
3031#ifdef WLAN_FEATURE_MBSSID
3032 status = wlansap_stop_bss(
3033 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3034#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003035 status = wlansap_stop_bss(
3036 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037#endif
3038
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303039 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 hdd_hostapd_state_t *hostapd_state =
3041 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303042 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303043 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303044 qdf_status =
3045 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303046 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 BSS_WAIT_TIMEOUT);
3048
Anurag Chouhance0dc992016-02-16 18:18:03 +05303049 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 hddLog(LOGE,
3051 FL(
3052 "failure waiting for wlansap_stop_bss %d"
3053 ),
Anurag Chouhance0dc992016-02-16 18:18:03 +05303054 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 }
3056 } else {
3057 hddLog(LOGE, FL("failure in wlansap_stop_bss"));
3058 }
3059 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003060 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 adapter->device_mode,
3062 adapter->sessionId);
3063
Anurag Chouhanc5548422016-02-24 18:33:27 +05303064 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003065 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 updateIE.smeSessionId = adapter->sessionId;
3067 updateIE.ieBufferlength = 0;
3068 updateIE.pAdditionIEBuffer = NULL;
3069 updateIE.append = false;
3070 updateIE.notify = false;
3071 /* Probe bcn reset */
3072 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3073 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303074 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003075 hddLog(LOGE,
3076 FL(
3077 "Could not pass on PROBE_RSP_BCN data to PE"
3078 ));
3079 }
3080 /* Assoc resp reset */
3081 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3082 &updateIE,
3083 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303084 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003085 hddLog(LOGE,
3086 FL(
3087 "Could not pass on ASSOC_RSP data to PE"
3088 ));
3089 }
3090 /* Reset WNI_CFG_PROBE_RSP Flags */
3091 wlan_hdd_reset_prob_rspies(adapter);
3092 kfree(adapter->sessionCtx.ap.beacon);
3093 adapter->sessionCtx.ap.beacon = NULL;
3094 }
3095 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003096 if (true == bCloseSession)
3097 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003099 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3101 conn_info.staId[0]);
3102 break;
3103 default:
3104 break;
3105 }
3106
3107 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303108 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109}
3110
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303111QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112{
3113 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303114 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 hdd_adapter_t *adapter;
3116
3117 ENTER();
3118
3119 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303121 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122 adapter = adapterNode->pAdapter;
3123 hdd_stop_adapter(hdd_ctx, adapter, true);
3124 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3125 adapterNode = pNext;
3126 }
3127
3128 EXIT();
3129
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303130 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131}
3132
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303133QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134{
3135 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303136 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137 hdd_adapter_t *adapter;
3138
3139 ENTER();
3140
3141 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3142
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303143 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144 adapter = adapterNode->pAdapter;
3145 hddLog(LOG1, FL("Disabling queues"));
3146 wlan_hdd_netif_queue_control(adapter,
3147 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3148 WLAN_CONTROL_PATH);
3149
3150 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3151
3152 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003153 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 adapter->sessionId);
3155 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3156 hdd_wmm_adapter_close(adapter);
3157 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3158 }
3159
3160 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3161 adapterNode = pNext;
3162 }
3163
3164 EXIT();
3165
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303166 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167}
3168
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303169QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170{
3171 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303172 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 hdd_adapter_t *adapter;
3174#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303175 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176#endif
3177 eConnectionState connState;
3178
3179 ENTER();
3180
3181 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3182
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303183 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003184 adapter = adapterNode->pAdapter;
3185
3186 hdd_wmm_init(adapter);
3187
3188 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003189 case QDF_STA_MODE:
3190 case QDF_P2P_CLIENT_MODE:
3191 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192
3193 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3194 ->conn_info.connState;
3195
3196 hdd_init_station_mode(adapter);
3197 /* Open the gates for HDD to receive Wext commands */
3198 adapter->isLinkUpSvcNeeded = false;
3199 adapter->scan_info.mScanPending = false;
3200
3201 /* Indicate disconnect event to supplicant if associated previously */
3202 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003203 eConnectionState_IbssConnected == connState ||
3204 eConnectionState_NotConnected == connState ||
3205 eConnectionState_IbssDisconnected == connState ||
3206 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 union iwreq_data wrqu;
3208 memset(&wrqu, '\0', sizeof(wrqu));
3209 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3210 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3211 wireless_send_event(adapter->dev, SIOCGIWAP,
3212 &wrqu, NULL);
3213 adapter->sessionCtx.station.
3214 hdd_ReassocScenario = false;
3215
3216 /* indicate disconnected event to nl80211 */
3217 cfg80211_disconnected(adapter->dev,
3218 WLAN_REASON_UNSPECIFIED,
Ryan Hsua335c162016-01-21 12:12:20 -08003219 NULL, 0,
3220#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
3221 true,
3222#endif
3223 GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224 } else if (eConnectionState_Connecting == connState) {
3225 /*
3226 * Indicate connect failure to supplicant if we were in the
3227 * process of connecting
3228 */
3229 cfg80211_connect_result(adapter->dev, NULL,
3230 NULL, 0, NULL, 0,
3231 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3232 GFP_KERNEL);
3233 }
3234
3235 hdd_register_tx_flow_control(adapter,
3236 hdd_tx_resume_timer_expired_handler,
3237 hdd_tx_resume_cb);
3238
3239 break;
3240
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003241 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242 /* softAP can handle SSR */
3243 break;
3244
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003245 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303247 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 FL("[SSR] send stop ap to supplicant"));
3249 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3250#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303251 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 FL("[SSR] send restart supplicant"));
3253 /* event supplicant to restart */
3254 cfg80211_del_sta(adapter->dev,
3255 (const u8 *)&bcastMac.bytes[0],
3256 GFP_KERNEL);
3257#endif
3258 break;
3259
3260 default:
3261 break;
3262 }
3263
3264 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3265 adapterNode = pNext;
3266 }
3267
3268 EXIT();
3269
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303270 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271}
3272
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303273QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 hdd_adapter_list_node_t **padapterNode)
3275{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303276 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003277 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303278 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3279 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003280 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281 return status;
3282}
3283
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303284QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285 hdd_adapter_list_node_t *adapterNode,
3286 hdd_adapter_list_node_t **pNextAdapterNode)
3287{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303288 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003289 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303290 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3291 (qdf_list_node_t *) adapterNode,
3292 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003293
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003294 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 return status;
3296}
3297
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303298QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 hdd_adapter_list_node_t *adapterNode)
3300{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303301 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003302 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303303 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003305 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 return status;
3307}
3308
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303309QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310 hdd_adapter_list_node_t **padapterNode)
3311{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303312 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003313 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303314 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3315 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003316 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 return status;
3318}
3319
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303320QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 hdd_adapter_list_node_t *adapterNode)
3322{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303323 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003324 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303325 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3326 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003327 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328 return status;
3329}
3330
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303331QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003332 hdd_adapter_list_node_t *adapterNode)
3333{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303334 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003335 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303336 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3337 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003338 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339 return status;
3340}
3341
3342hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3343 tSirMacAddr macAddr)
3344{
3345 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3346 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303347 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348
3349 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3350
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303351 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 adapter = adapterNode->pAdapter;
3353
3354 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303355 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003356 macAddr, sizeof(tSirMacAddr))) {
3357 return adapter;
3358 }
3359 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3360 adapterNode = pNext;
3361 }
3362
3363 return NULL;
3364
3365}
3366
3367hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3368 uint32_t vdev_id)
3369{
3370 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3371 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303372 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303374 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303376 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 adapter = adapterNode->pAdapter;
3378
3379 if (adapter->sessionId == vdev_id)
3380 return adapter;
3381
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303382 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003383 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3384 adapterNode = pNext;
3385 }
3386
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303387 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 FL("vdev_id %d does not exist with host"), vdev_id);
3389
3390 return NULL;
3391}
3392
Abhishek Singh7996eb72015-12-30 17:24:02 +05303393/**
3394 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3395 * the sessionid
3396 * @hdd_ctx: hdd context.
3397 * @sme_session_id: sme session is for the adapter to get.
3398 *
3399 * This function is used to get the adapter with provided session id
3400 *
3401 * Return: adapter pointer if found
3402 *
3403 */
3404hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3405 uint32_t sme_session_id)
3406{
3407 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3408 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303409 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303410
3411
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303412 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303413
3414 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303415 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303416 adapter = adapter_node->pAdapter;
3417
3418 if (adapter &&
3419 adapter->sessionId == sme_session_id)
3420 return adapter;
3421
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303422 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303423 hdd_get_next_adapter(hdd_ctx,
3424 adapter_node, &next);
3425 adapter_node = next;
3426 }
3427 return NULL;
3428}
3429
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003430/**
3431 * hdd_get_adapter() - to get adapter matching the mode
3432 * @hdd_ctx: hdd context
3433 * @mode: adapter mode
3434 *
3435 * This routine will return the pointer to adapter matching
3436 * with the passed mode.
3437 *
3438 * Return: pointer to adapter or null
3439 */
3440hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
3441 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442{
3443 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3444 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303445 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003446
3447 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3448
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303449 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003450 adapter = adapterNode->pAdapter;
3451
3452 if (adapter && (mode == adapter->device_mode))
3453 return adapter;
3454
3455 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3456 adapterNode = pNext;
3457 }
3458
3459 return NULL;
3460
3461}
3462
3463/**
3464 * hdd_get_operating_channel() - return operating channel of the device mode
3465 * @hdd_ctx: Pointer to the HDD context.
3466 * @mode: Device mode for which operating channel is required.
3467 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003468 * QDF_STA_MODE,
3469 * QDF_P2P_CLIENT_MODE,
3470 * QDF_SAP_MODE,
3471 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472 *
3473 * This API returns the operating channel of the requested device mode
3474 *
3475 * Return: channel number. "0" id the requested device is not found OR it is
3476 * not connected.
3477 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003478uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
3479 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480{
3481 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303482 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 hdd_adapter_t *adapter;
3484 uint8_t operatingChannel = 0;
3485
3486 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3487
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303488 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 adapter = adapterNode->pAdapter;
3490
3491 if (mode == adapter->device_mode) {
3492 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003493 case QDF_STA_MODE:
3494 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003495 if (hdd_conn_is_connected
3496 (WLAN_HDD_GET_STATION_CTX_PTR
3497 (adapter))) {
3498 operatingChannel =
3499 (WLAN_HDD_GET_STATION_CTX_PTR
3500 (adapter))->conn_info.
3501 operationChannel;
3502 }
3503 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003504 case QDF_SAP_MODE:
3505 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506 /* softap connection info */
3507 if (test_bit
3508 (SOFTAP_BSS_STARTED,
3509 &adapter->event_flags))
3510 operatingChannel =
3511 (WLAN_HDD_GET_AP_CTX_PTR
3512 (adapter))->operatingChannel;
3513 break;
3514 default:
3515 break;
3516 }
3517
3518 break; /* Found the device of interest. break the loop */
3519 }
3520
3521 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3522 adapterNode = pNext;
3523 }
3524 return operatingChannel;
3525}
3526
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303527static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528 hdd_ctx)
3529{
3530 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303531 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 hdd_adapter_t *adapter;
3533
3534 ENTER();
3535
3536 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3537
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303538 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003540 if ((adapter->device_mode == QDF_STA_MODE) ||
3541 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
3542 (adapter->device_mode == QDF_IBSS_MODE) ||
3543 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
3544 (adapter->device_mode == QDF_SAP_MODE) ||
3545 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546 wlan_hdd_cfg80211_deregister_frames(adapter);
3547 hdd_unregister_wext(adapter->dev);
3548 }
3549 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3550 adapterNode = pNext;
3551 }
3552
3553 EXIT();
3554
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303555 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003556}
3557
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303558QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559{
3560 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303561 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 hdd_adapter_t *adapter;
3563
3564 ENTER();
3565
3566 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3567
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303568 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003569 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003570 if ((adapter->device_mode == QDF_STA_MODE) ||
3571 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
3572 (adapter->device_mode == QDF_IBSS_MODE) ||
3573 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
3574 (adapter->device_mode == QDF_SAP_MODE) ||
3575 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3577 eCSR_SCAN_ABORT_DEFAULT);
3578 }
3579 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3580 adapterNode = pNext;
3581 }
3582
3583 EXIT();
3584
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303585 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586}
3587
3588#ifdef WLAN_NS_OFFLOAD
3589/**
3590 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3591 * @hdd_ctx: Pointer to hdd context
3592 *
3593 * Return: None
3594 */
3595static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3596{
3597 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3598
3599 return;
3600}
3601
3602/**
3603 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3604 * @hdd_ctx: Pointer to hdd context
3605 *
3606 * Return: None
3607 */
3608static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3609{
3610 int ret;
3611
3612 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
3613 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3614 if (ret)
3615 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
3616 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003617 hdd_info("Registered IPv6 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618
3619 return;
3620}
3621#else
3622/**
3623 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3624 * @hdd_ctx: Pointer to hdd context
3625 *
3626 * Return: None
3627 */
3628static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3629{
3630}
3631/**
3632 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3633 * @hdd_ctx: Pointer to hdd context
3634 *
3635 * Return: None
3636 */
3637static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3638{
3639}
3640#endif
3641
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003642#ifdef QCA_WIFI_FTM
3643/**
3644 * hdd_disable_ftm() - Disable FTM mode
3645 * @hdd_ctx: HDD context
3646 *
3647 * Helper function to disable FTM mode.
3648 *
3649 * Return: None.
3650 */
3651static void hdd_disable_ftm(hdd_context_t *hdd_ctx)
3652{
3653 hdd_notice("Disabling FTM mode");
3654
3655 if (hdd_ftm_stop(hdd_ctx)) {
3656 hdd_alert("hdd_ftm_stop Failed!");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303657 QDF_ASSERT(0);
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003658 }
3659
3660 hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED;
3661
3662 wlan_hdd_ftm_close(hdd_ctx);
3663
3664 return;
3665}
3666
3667/**
3668 * hdd_enable_ftm() - Enable FTM mode
3669 * @hdd_ctx: HDD context
3670 *
3671 * Helper function to enable FTM mode.
3672 *
3673 * Return: 0 on success and errno on failure.
3674 */
3675int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3676{
3677 int ret;
3678
3679 ret = wlan_hdd_ftm_open(hdd_ctx);
3680 if (ret) {
3681 hdd_alert("wlan_hdd_ftm_open Failed: %d", ret);
3682 goto err_out;
3683 }
3684
3685 ret = hdd_ftm_start(hdd_ctx);
3686
3687 if (ret) {
3688 hdd_alert("hdd_ftm_start Failed: %d", ret);
3689 goto err_ftm_close;
3690 }
3691
3692 ret = wiphy_register(hdd_ctx->wiphy);
3693 if (ret) {
3694 hdd_alert("wiphy register failed: %d", ret);
3695 goto err_ftm_stop;
3696 }
3697
3698 hdd_err("FTM driver loaded");
3699
3700 return 0;
3701
3702err_ftm_stop:
3703 hdd_ftm_stop(hdd_ctx);
3704err_ftm_close:
3705 wlan_hdd_ftm_close(hdd_ctx);
3706err_out:
3707 return ret;
3708
3709}
3710#else
3711int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3712{
3713 hdd_err("Driver built without FTM feature enabled!");
3714
3715 return -ENOTSUPP;
3716}
3717
3718static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { }
3719#endif
3720
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303721#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3722/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003723 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303724 * @hdd_ctx: HDD context
3725 *
3726 * Activates the logging service
3727 *
3728 * Return: Zero in case of success, negative value otherwise
3729 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003730static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303731{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003732 int ret;
3733 struct hdd_config *config = hdd_ctx->config;
3734
3735 if (!config->wlanLoggingEnable)
3736 return 0;
3737
3738 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
3739 config->wlanLoggingNumBuf);
3740 if (ret)
3741 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
3742 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303743}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003744
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303745/**
3746 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
3747 * @hdd_ctx: HDD context
3748 *
3749 * Deactivates the logging service
3750 *
3751 * Return: 0 on deactivating the logging service
3752 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003753static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303754{
3755 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
3756 return wlan_logging_sock_deactivate_svc();
3757
3758 return 0;
3759}
3760#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003761static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303762{
3763 return 0;
3764}
3765
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003766static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303767{
3768 return 0;
3769}
3770#endif
3771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003773 * hdd_free_context - Free HDD context
3774 * @hdd_ctx: HDD context to be freed.
3775 *
3776 * Free config and HDD context.
3777 *
3778 * Return: None
3779 */
3780static void hdd_free_context(hdd_context_t *hdd_ctx)
3781{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303782 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003783 hdd_logging_sock_deactivate_svc(hdd_ctx);
3784
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303785 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003786 hdd_ctx->config = NULL;
3787
3788 wiphy_free(hdd_ctx->wiphy);
3789}
3790
3791/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 * hdd_wlan_exit() - HDD WLAN exit function
3793 * @hdd_ctx: Pointer to the HDD Context
3794 *
3795 * This is the driver exit point (invoked during rmmod)
3796 *
3797 * Return: None
3798 */
3799void hdd_wlan_exit(hdd_context_t *hdd_ctx)
3800{
3801 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303802 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803 struct wiphy *wiphy = hdd_ctx->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804
3805 ENTER();
3806
3807 hddLog(LOGE, FL("Unregister IPv6 notifier"));
3808 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3809 hddLog(LOGE, FL("Unregister IPv4 notifier"));
3810 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3811
3812 hdd_unregister_wext_all_adapters(hdd_ctx);
3813
Anurag Chouhan6d760662016-02-20 16:05:43 +05303814 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003815 hdd_disable_ftm(hdd_ctx);
3816
3817 hdd_alert("FTM driver unloaded");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818 goto free_hdd_ctx;
3819 }
3820
3821 /*
3822 * Cancel any outstanding scan requests. We are about to close all
3823 * of our adapters, but an adapter structure is what SME passes back
3824 * to our callback function. Hence if there are any outstanding scan
3825 * requests then there is a race condition between when the adapter
3826 * is closed and when the callback is invoked. We try to resolve that
3827 * race condition here by canceling any outstanding scans before we
3828 * close the adapters.
3829 * Note that the scans may be cancelled in an asynchronous manner, so
3830 * ideally there needs to be some kind of synchronization. Rather than
3831 * introduce a new synchronization here, we will utilize the fact that
3832 * we are about to Request Full Power, and since that is synchronized,
3833 * the expectation is that by the time Request Full Power has completed,
3834 * all scans will be cancelled
3835 */
3836 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3837
3838#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05303839 if (QDF_TIMER_STATE_RUNNING ==
3840 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
3841 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842 }
3843
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303844 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303845 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303846 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 FL("Cannot deallocate Bus bandwidth timer"));
3848 }
3849#endif
3850
3851#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05303852 if (QDF_TIMER_STATE_RUNNING ==
3853 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
3854 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 }
3856
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303857 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303858 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303859 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860 FL("Cannot deallocate ACS Skip timer"));
3861 }
3862#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003863
3864 /*
3865 * Powersave Offload Case
3866 * Disable Idle Power Save Mode
3867 */
3868 hdd_set_idle_ps_config(hdd_ctx, false);
3869
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003870 /* Unregister the Net Device Notifier */
3871 unregister_netdevice_notifier(&hdd_netdev_notifier);
3872
3873 /*
3874 * Stop all adapters, this will ensure the termination of active
3875 * connections on the interface. Make sure the cds_scheduler is
3876 * still available to handle those control messages
3877 */
3878 hdd_stop_all_adapters(hdd_ctx);
3879
3880 /* Stop all the modules */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303881 qdf_status = cds_disable(p_cds_context);
3882 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303883 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 FL("Failed to stop CDS"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303885 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003886 }
3887
3888 /*
3889 * Close the scheduler before calling cds_close to make sure no thread
3890 * is scheduled after the each module close is called i.e after all the
3891 * data structures are freed.
3892 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303893 qdf_status = cds_sched_close(p_cds_context);
3894 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303895 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303897 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 }
3899#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3900 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303901 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902#endif
3903 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303904 qdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905
3906 hdd_hostapd_channel_wakelock_deinit(hdd_ctx);
3907
3908 /*
3909 * Close CDS
3910 * This frees pMac(HAL) context. There should not be any call
3911 * that requires pMac access after this.
3912 */
3913 cds_close(p_cds_context);
3914
3915 hdd_wlan_green_ap_deinit(hdd_ctx);
3916
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917#ifdef WLAN_KD_READY_NOTIFIER
3918 cnss_diag_notify_wlan_close();
3919 ptt_sock_deactivate_svc();
3920#endif /* WLAN_KD_READY_NOTIFIER */
3921 nl_srv_exit();
3922
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003923 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08003925 hdd_close_cesium_nl_sock();
3926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927 hdd_ipa_cleanup(hdd_ctx);
3928
3929 /* Free up RoC request queue and flush workqueue */
3930 cds_flush_work(&hdd_ctx->roc_req_work);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303931 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
3932 qdf_list_destroy(&hdd_ctx->hdd_scan_req_q);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303934 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08003935 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936 /* Proceed and complete the clean up */
3937 }
3938
3939free_hdd_ctx:
3940
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003941 wiphy_unregister(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003942
3943 hdd_free_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944}
3945
3946void __hdd_wlan_exit(void)
3947{
3948 hdd_context_t *hdd_ctx;
3949
3950 ENTER();
3951
Anurag Chouhan6d760662016-02-20 16:05:43 +05303952 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003953 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303954 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955 EXIT();
3956 return;
3957 }
3958
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003959 /* Check IPA HW Pipe shutdown */
3960 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
3961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962#ifdef WLAN_FEATURE_LPSS
3963 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
3964#endif
3965
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003966 memdump_deinit();
3967
3968#ifdef QCA_PKT_PROTO_TRACE
3969 cds_pkt_proto_trace_close();
3970#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971 /* Do all the cleanup before deregistering the driver */
3972 hdd_wlan_exit(hdd_ctx);
3973 EXIT();
3974}
3975
3976#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3977void hdd_skip_acs_scan_timer_handler(void *data)
3978{
3979 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
3980
3981 hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
3982 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
3983
3984 if (!hdd_ctx->hHal)
3985 return;
3986 sme_scan_flush_result(hdd_ctx->hHal);
3987}
3988#endif
3989
3990#ifdef QCA_HT_2040_COEX
3991/**
3992 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
3993 * @adapter: pointer to adapter
3994 * @staId: station id
3995 * @macAddrSTA: station MAC address
3996 * @channel_type: channel type
3997 *
3998 * This function notifies FW with HT20/HT40 mode
3999 *
4000 * Return: 0 if successful, error number otherwise
4001 */
4002int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304003 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004004{
4005 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304006 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007 hdd_context_t *hdd_ctx = NULL;
4008
4009 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4010
4011 status = wlan_hdd_validate_context(hdd_ctx);
4012 if (0 != status) {
4013 hddLog(LOGE, FL("HDD context is not valid"));
4014 return status;
4015 }
4016 if (!hdd_ctx->hHal)
4017 return -EINVAL;
4018
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304019 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304021 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 hddLog(LOGE, "Fail to send notification with ht2040 mode");
4023 return -EINVAL;
4024 }
4025
4026 return 0;
4027}
4028#endif
4029
4030/**
4031 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4032 * @state: state
4033 *
4034 * This function notifies FW with modem power status
4035 *
4036 * Return: 0 if successful, error number otherwise
4037 */
4038int hdd_wlan_notify_modem_power_state(int state)
4039{
4040 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304041 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 hdd_context_t *hdd_ctx;
4043
Anurag Chouhan6d760662016-02-20 16:05:43 +05304044 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045 status = wlan_hdd_validate_context(hdd_ctx);
4046 if (0 != status) {
4047 hddLog(LOGE, FL("HDD context is not valid"));
4048 return status;
4049 }
4050 if (!hdd_ctx->hHal)
4051 return -EINVAL;
4052
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304053 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4054 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 hddLog(LOGE,
4056 "Fail to send notification with modem power state %d",
4057 state);
4058 return -EINVAL;
4059 }
4060 return 0;
4061}
4062
4063/**
4064 *
4065 * hdd_post_cds_enable_config() - HDD post cds start config helper
4066 * @adapter - Pointer to the HDD
4067 *
4068 * Return: None
4069 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304070QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304072 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073
4074 /*
4075 * Send ready indication to the HDD. This will kick off the MAC
4076 * into a 'running' state and should kick off an initial scan.
4077 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304078 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4079 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304080 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 FL(
4082 "sme_hdd_ready_ind() failed with status code %08d [x%08x]"
4083 ),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304084 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304085 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086 }
4087
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304088 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004089}
4090
4091/* wake lock APIs for HDD */
4092void hdd_prevent_suspend(uint32_t reason)
4093{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304094 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004095}
4096
4097void hdd_allow_suspend(uint32_t reason)
4098{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304099 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100}
4101
4102void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
4103{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304104 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105}
4106
4107/**
4108 * hdd_exchange_version_and_caps() - exchange version and capability with target
4109 * @hdd_ctx: Pointer to HDD context
4110 *
4111 * This is the HDD function to exchange version and capability information
4112 * between Host and Target
4113 *
4114 * This function gets reported version of FW.
4115 * It also finds the version of target headers used to compile the host;
4116 * It compares the above two and prints a warning if they are different;
4117 * It gets the SW and HW version string;
4118 * Finally, it exchanges capabilities between host and target i.e. host
4119 * and target exchange a msg indicating the features they support through a
4120 * bitmap
4121 *
4122 * Return: None
4123 */
4124void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4125{
4126
4127 tSirVersionType versionCompiled;
4128 tSirVersionType versionReported;
4129 tSirVersionString versionString;
4130 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304131 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132
4133 memset(&versionCompiled, 0, sizeof(versionCompiled));
4134 memset(&versionReported, 0, sizeof(versionReported));
4135
4136 /* retrieve and display WCNSS version information */
4137 do {
4138
4139 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4140 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304141 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304142 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004143 FL(
4144 "unable to retrieve WCNSS WLAN compiled version"
4145 ));
4146 break;
4147 }
4148
4149 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4150 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304151 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304152 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153 FL(
4154 "unable to retrieve WCNSS WLAN reported version"
4155 ));
4156 break;
4157 }
4158
4159 if ((versionCompiled.major != versionReported.major) ||
4160 (versionCompiled.minor != versionReported.minor) ||
4161 (versionCompiled.version != versionReported.version) ||
4162 (versionCompiled.revision != versionReported.revision)) {
4163 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4164 "Host expected %u.%u.%u.%u\n",
4165 WLAN_MODULE_NAME,
4166 (int)versionReported.major,
4167 (int)versionReported.minor,
4168 (int)versionReported.version,
4169 (int)versionReported.revision,
4170 (int)versionCompiled.major,
4171 (int)versionCompiled.minor,
4172 (int)versionCompiled.version,
4173 (int)versionCompiled.revision);
4174 } else {
4175 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4176 WLAN_MODULE_NAME,
4177 (int)versionReported.major,
4178 (int)versionReported.minor,
4179 (int)versionReported.version,
4180 (int)versionReported.revision);
4181 }
4182
4183 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4184 versionString,
4185 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304186 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304187 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188 FL(
4189 "unable to retrieve WCNSS software version string"
4190 ));
4191 break;
4192 }
4193
4194 pr_info("%s: WCNSS software version %s\n",
4195 WLAN_MODULE_NAME, versionString);
4196
4197 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4198 versionString,
4199 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304200 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304201 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 FL(
4203 "unable to retrieve WCNSS hardware version string"
4204 ));
4205 break;
4206 }
4207
4208 pr_info("%s: WCNSS hardware version %s\n",
4209 WLAN_MODULE_NAME, versionString);
4210
4211 /*
4212 * 1.Check if FW version is greater than 0.1.1.0. Only then
4213 * send host-FW capability exchange message
4214 * 2.Host-FW capability exchange message is only present on
4215 * target 1.1 so send the message only if it the target is 1.1
4216 * minor numbers for different target branches:
4217 * 0 -> (1.0)Mainline Build
4218 * 1 -> (1.1)Mainline Build
4219 * 2->(1.04) Stability Build
4220 */
4221 if (((versionReported.major > 0) || (versionReported.minor > 1)
4222 || ((versionReported.minor >= 1)
4223 && (versionReported.version >= 1)))
4224 && ((versionReported.major == 1)
4225 && (versionReported.minor >= 1)))
4226 fwFeatCapsMsgSupported = 1;
4227
4228 if (fwFeatCapsMsgSupported) {
4229 /*
4230 * Indicate if IBSS heartbeat monitoring needs to be
4231 * offloaded
4232 */
4233 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4234 sme_disable_feature_capablity
4235 (IBSS_HEARTBEAT_OFFLOAD);
4236 }
4237
4238 sme_feature_caps_exchange(hdd_ctx->hHal);
4239 }
4240
4241 } while (0);
4242
4243}
4244
4245/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304246QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247{
4248 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4249 hdd_ctx->reg.cc_src);
4250}
4251
4252/**
4253 * hdd_is_5g_supported() - check if hardware supports 5GHz
4254 * @hdd_ctx: Pointer to the hdd context
4255 *
4256 * HDD function to know if hardware supports 5GHz
4257 *
4258 * Return: true if hardware supports 5GHz
4259 */
4260bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4261{
4262 /*
4263 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4264 * then hardware support 5Ghz.
4265 */
4266 return true;
4267}
4268
Amar Singhale4f28ee2015-10-21 14:36:56 -07004269static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004270{
4271 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07004272 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004273
4274 wiphy = hdd_ctx->wiphy;
4275
4276 /*
4277 * The channel information in
4278 * wiphy needs to be initialized before wiphy registration
4279 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004280 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
4281 if (ret_val) {
4282 hdd_alert("regulatory init failed");
4283 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 }
4285
4286#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4287 wiphy->wowlan = &wowlan_support_reg_init;
4288#else
4289 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4290 WIPHY_WOWLAN_MAGIC_PKT |
4291 WIPHY_WOWLAN_DISCONNECT |
4292 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4293 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4294 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4295 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4296 WIPHY_WOWLAN_RFKILL_RELEASE;
4297
4298 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4299 WOW_MAX_FILTERS_PER_LIST);
4300 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4301 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4302#endif
4303
4304 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004305 ret_val = wlan_hdd_cfg80211_register(wiphy);
4306 if (0 > ret_val)
4307 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308
Amar Singhale4f28ee2015-10-21 14:36:56 -07004309 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310}
4311
Ravi Joshie2331e82015-07-01 18:18:54 -07004312/**
4313 * hdd_cnss_request_bus_bandwidth() - Function to control bus bandwidth
4314 * @hdd_ctx - handle to hdd context
4315 * @tx_packets - transmit packet count
4316 * @rx_packets - receive packet count
4317 *
4318 * The function controls the bus bandwidth and dynamic control of
4319 * tcp delayed ack configuration
4320 *
4321 * Returns: None
4322 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323#ifdef MSM_PLATFORM
4324void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004325 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004326{
4327#ifdef CONFIG_CNSS
4328 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004329 uint64_t temp_rx = 0;
4330 uint64_t temp_tx = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331 enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004332 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4333 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334
Mohit Khannae71e2262015-11-10 09:37:24 -08004335
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 if (total > hdd_ctx->config->busBandwidthHighThreshold)
4337 next_vote_level = CNSS_BUS_WIDTH_HIGH;
4338 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
4339 next_vote_level = CNSS_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004340 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 next_vote_level = CNSS_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004342 else
4343 next_vote_level = CNSS_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344
Mohit Khannae71e2262015-11-10 09:37:24 -08004345 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4346 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347
4348 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004349 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
4350 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351 hdd_ctx->cur_vote_level = next_vote_level;
4352 cnss_request_bus_bandwidth(next_vote_level);
4353 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004354
4355 /* fine-tuning parameters for RX Flows */
4356 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4357
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 hdd_ctx->prev_rx = rx_packets;
4359 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004360 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004362 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363
Mohit Khannae71e2262015-11-10 09:37:24 -08004364 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4365 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366
4367 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004368 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 next_rx_level, temp_rx);
4370 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07004371 /* Send throughput indication only if it is enabled.
4372 * Disabling tcp_del_ack will revert the tcp stack behavior
4373 * to default delayed ack. Note that this will disable the
4374 * dynamic delayed ack mechanism across the system
4375 */
4376 if (hdd_ctx->config->enable_tcp_delack)
4377 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 &next_rx_level,
4379 sizeof(next_rx_level));
4380 }
4381
Mohit Khannae71e2262015-11-10 09:37:24 -08004382 /* fine-tuning parameters for TX Flows */
4383 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4384 hdd_ctx->prev_tx = tx_packets;
4385 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4386 next_tx_level = WLAN_SVC_TP_HIGH;
4387 else
4388 next_tx_level = WLAN_SVC_TP_LOW;
4389
4390 if (hdd_ctx->cur_tx_level != next_tx_level) {
4391 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4392 next_tx_level, temp_tx);
4393 hdd_ctx->cur_tx_level = next_tx_level;
4394 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4395 &next_tx_level,
4396 sizeof(next_tx_level));
4397 }
4398
4399 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4400 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 hdd_ctx->hdd_txrx_hist_idx++;
4402 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
4403#endif
4404}
4405
4406#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4407static void hdd_bus_bw_compute_cbk(void *priv)
4408{
4409 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4410 hdd_adapter_t *adapter = NULL;
4411 uint64_t tx_packets = 0, rx_packets = 0;
4412 uint64_t total_tx = 0, total_rx = 0;
4413 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304414 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 bool connected = false;
4416 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4417
4418 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304419 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004420 status =
4421 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4422
4423 if (adapterNode->pAdapter == NULL)
4424 continue;
4425 adapter = adapterNode->pAdapter;
4426
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004427 if ((adapter->device_mode == QDF_STA_MODE ||
4428 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004429 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4430 != eConnectionState_Associated) {
4431
4432 continue;
4433 }
4434
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004435 if ((adapter->device_mode == QDF_SAP_MODE ||
4436 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004437 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4438
4439 continue;
4440 }
4441
4442 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4443 adapter->prev_tx_packets);
4444 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4445 adapter->prev_rx_packets);
4446
4447 total_rx += adapter->stats.rx_packets;
4448 total_tx += adapter->stats.tx_packets;
4449
4450 spin_lock_bh(&hdd_ctx->bus_bw_lock);
4451 adapter->prev_tx_packets = adapter->stats.tx_packets;
4452 adapter->prev_rx_packets = adapter->stats.rx_packets;
4453 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
4454 connected = true;
4455 }
4456
4457 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
4458 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
4459 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
4460 rx_packets;
4461 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
4462 tx_packets;
4463
4464 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
4465 tx_packets += (uint64_t)ipa_tx_packets;
4466 rx_packets += (uint64_t)ipa_rx_packets;
4467
4468 if (!connected) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304469 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470 FL("bus bandwidth timer running in disconnected state"));
4471 return;
4472 }
4473
4474 hdd_cnss_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
4475
4476 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
4477 hdd_ipa_uc_stat_request(adapter, 2);
4478
Anurag Chouhan210db072016-02-22 18:42:15 +05304479 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 hdd_ctx->config->busBandwidthComputeInterval);
4481}
4482#endif
4483
4484/**
4485 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
4486 * @hdd_ctx: hdd context
4487 *
4488 * Return: none
4489 */
4490void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
4491{
4492 int i;
4493
4494#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304495 hddLog(QDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496 hdd_ctx->config->busBandwidthComputeInterval,
4497 hdd_ctx->hdd_txrx_hist_idx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304498 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 "BW High TH: %d BW Med TH: %d BW Low TH: %d",
4500 hdd_ctx->config->busBandwidthHighThreshold,
4501 hdd_ctx->config->busBandwidthMediumThreshold,
4502 hdd_ctx->config->busBandwidthLowThreshold);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304503 hddLog(QDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004504 hdd_ctx->config->tcpDelackThresholdHigh,
4505 hdd_ctx->config->tcpDelackThresholdLow);
4506#endif
4507
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304508 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004509 "index, total_rx, interval_rx, total_tx, interval_tx, next_vote_level, next_rx_level, next_tx_level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510
4511 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304512 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004513 "%d: %llu, %llu, %llu, %llu, %d, %d, %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
4515 hdd_ctx->hdd_txrx_hist[i].interval_rx,
4516 hdd_ctx->hdd_txrx_hist[i].total_tx,
4517 hdd_ctx->hdd_txrx_hist[i].interval_tx,
4518 hdd_ctx->hdd_txrx_hist[i].next_vote_level,
Mohit Khannae71e2262015-11-10 09:37:24 -08004519 hdd_ctx->hdd_txrx_hist[i].next_rx_level,
4520 hdd_ctx->hdd_txrx_hist[i].next_tx_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 }
4522 return;
4523}
4524
4525/**
4526 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
4527 * @hdd_ctx: hdd context
4528 *
4529 * Return: none
4530 */
4531void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
4532{
4533 hdd_ctx->hdd_txrx_hist_idx = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304534 qdf_mem_zero(hdd_ctx->hdd_txrx_hist, sizeof(hdd_ctx->hdd_txrx_hist));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535}
4536
4537/**
4538 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
4539 * @pHddCtx: hdd context
4540 *
4541 * Return: none
4542 */
4543void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
4544{
4545
4546 hdd_adapter_t *adapter = NULL;
4547 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304548 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004549 int i;
4550
4551 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304552 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004553 adapter = adapter_node->pAdapter;
4554
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304555 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004556 "Session_id %d device mode %d current index %d",
4557 adapter->sessionId, adapter->device_mode,
4558 adapter->history_index);
4559
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304560 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004561 "Netif queue operation statistics:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304562 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563 "Current pause_map value %x", adapter->pause_map);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304564 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004565 " reason_type: pause_cnt: unpause_cnt");
4566
4567 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304568 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004569 "%s: %d: %d",
4570 hdd_reason_type_to_string(i),
4571 adapter->queue_oper_stats[i].pause_count,
4572 adapter->queue_oper_stats[i].unpause_count);
4573 }
4574
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304575 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 "Netif queue operation history:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304577 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 "index: time: action_type: reason_type: pause_map");
4579
4580 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304581 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05304583 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004584 adapter->queue_oper_history[i].time),
4585 hdd_action_type_to_string(
4586 adapter->queue_oper_history[i].netif_action),
4587 hdd_reason_type_to_string(
4588 adapter->queue_oper_history[i].netif_reason),
4589 adapter->queue_oper_history[i].pause_map);
4590 }
4591
4592 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4593 adapter_node = next;
4594 }
4595
4596
4597}
4598
4599/**
4600 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
4601 * @hdd_ctx: hdd context
4602 *
4603 * Return: none
4604 */
4605void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
4606{
4607 hdd_adapter_t *adapter = NULL;
4608 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304609 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610
4611 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304612 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613 adapter = adapter_node->pAdapter;
4614
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304615 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304617 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004618 sizeof(adapter->queue_oper_history));
4619
4620 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4621 adapter_node = next;
4622 }
4623}
4624
4625/**
4626 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
4627 * @halHandle: Hal handle
4628 * @pContext: Pointer to the context
4629 * @sessionId: Session ID
4630 * @scanId: Scan ID
4631 * @status: Status
4632 *
4633 * This is the callback to be executed when 11d scan is completed to flush out
4634 * the scan results
4635 *
4636 * 11d scan is done during driver load and is a passive scan on all
4637 * channels supported by the device, 11d scans may find some APs on
4638 * frequencies which are forbidden to be used in the regulatory domain
4639 * the device is operating in. If these APs are notified to the supplicant
4640 * it may try to connect to these APs, thus flush out all the scan results
4641 * which are present in SME after 11d scan is done.
4642 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304643 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304645static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004646 uint8_t sessionId, uint32_t scanId,
4647 eCsrScanStatus status)
4648{
4649 ENTER();
4650
4651 sme_scan_flush_result(halHandle);
4652
4653 EXIT();
4654
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304655 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004656}
4657
4658#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4659/**
4660 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
4661 * @hdd_ctx: hdd global context
4662 *
4663 * Return: none
4664 */
4665static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4666{
4667 uint8_t i;
4668
4669 mutex_init(&hdd_ctx->op_ctx.op_lock);
4670 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4671 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4672 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
4673 }
4674}
4675#else
4676static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4677{
4678}
4679#endif
4680
4681#ifdef WLAN_FEATURE_FASTPATH
4682/**
4683 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
4684 * @hdd_cfg: hdd config
4685 * @context: lower layer context
4686 *
4687 * Return: none
4688 */
4689static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4690 void *context)
4691{
4692 if (hdd_cfg->fastpath_enable)
4693 hif_enable_fastpath(context);
4694}
4695#else
4696static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4697 void *context)
4698{
4699}
4700#endif
4701
4702#if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS)
4703/**
4704 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004705 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 * @level: thermal level
4707 *
4708 * Change IPA data path to SW path when the thermal throttle level greater
4709 * than 0, and restore the original data path when throttle level is 0
4710 *
4711 * Return: none
4712 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004713static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004715 hdd_context_t *hdd_ctx = context;
4716
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 /* Change IPA to SW path when throttle level greater than 0 */
4718 if (level > THROTTLE_LEVEL_0)
4719 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
4720 else
4721 /* restore original concurrency mode */
4722 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
4723}
4724
4725/**
4726 * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel
4727 * @hdd_ctxt: hdd context pointer
4728 * @ap_adapter: hdd hostapd adapter pointer
4729 *
4730 * Try to find safe channel within preferred channel
4731 * In case auto channel selection enabled
4732 * - Preferred and safe channel should be used
4733 * - If no overlapping, preferred channel should be used
4734 *
4735 * Return: 1: found preferred safe channel
4736 * 0: could not found preferred safe channel
4737 */
4738static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt,
4739 hdd_adapter_t *ap_adapter)
4740{
Amar Singhalb8d4f152016-02-10 10:21:43 -08004741 uint16_t safe_channels[NUM_CHANNELS];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742 uint16_t safe_channel_count;
4743 uint16_t unsafe_channel_count;
4744 uint8_t is_unsafe = 1;
4745 uint16_t i;
4746 uint16_t channel_loop;
4747
4748 if (!hdd_ctxt || !ap_adapter) {
4749 hdd_err("invalid context/adapter");
4750 return 0;
4751 }
4752
4753 safe_channel_count = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304754 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctxt->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08004755 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004756
Amar Singhalb8d4f152016-02-10 10:21:43 -08004757 for (i = 0; i < NUM_CHANNELS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758 is_unsafe = 0;
4759 for (channel_loop = 0;
4760 channel_loop < unsafe_channel_count; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004761 if (CDS_CHANNEL_NUM(i) ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 hdd_ctxt->unsafe_channel_list[channel_loop]) {
4763 is_unsafe = 1;
4764 break;
4765 }
4766 }
4767 if (!is_unsafe) {
4768 safe_channels[safe_channel_count] =
Amar Singhal7a1726a2015-10-14 16:28:11 -07004769 CDS_CHANNEL_NUM(i);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304770 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004771 FL("safe channel %d"),
4772 safe_channels[safe_channel_count]);
4773 safe_channel_count++;
4774 }
4775 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304776 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004777 FL("perferred range %d - %d"),
4778 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
4779 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
4780 for (i = 0; i < safe_channel_count; i++) {
4781 if (safe_channels[i] >=
4782 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch
4783 && safe_channels[i] <=
4784 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304785 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 FL("safe channel %d is in perferred range"),
4787 safe_channels[i]);
4788 return 1;
4789 }
4790 }
4791 return 0;
4792}
4793
4794/**
4795 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
4796 * @adapter: HDD adapter pointer
4797 * @indParam: Channel avoid notification parameter
4798 *
4799 * Avoid channel notification from FW handler.
4800 * FW will send un-safe channel list to avoid over wrapping.
4801 * hostapd should not use notified channel
4802 *
4803 * Return: None
4804 */
4805static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
4806{
4807 hdd_adapter_t *hostapd_adapter = NULL;
4808 hdd_context_t *hdd_ctxt;
4809 tSirChAvoidIndType *ch_avoid_indi;
4810 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08004811 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
4812 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004813 uint16_t start_channel;
4814 uint16_t end_channel;
4815 v_CONTEXT_t cds_context;
4816 static int restart_sap_in_progress;
4817 tHddAvoidFreqList hdd_avoid_freq_list;
4818 uint32_t i;
4819
4820 /* Basic sanity */
4821 if (!hdd_context || !indi_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304822 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid arguments"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 return;
4824 }
4825
4826 hdd_ctxt = (hdd_context_t *) hdd_context;
4827 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
4828 cds_context = hdd_ctxt->pcds_context;
4829
4830 /* Make unsafe channel list */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304831 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832 FL("band count %d"),
4833 ch_avoid_indi->avoid_range_count);
4834
4835 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304836 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
4838 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
4839 ch_avoid_indi->avoid_freq_range[i].start_freq;
4840 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
4841 ch_avoid_indi->avoid_freq_range[i].end_freq;
4842 }
4843 hdd_avoid_freq_list.avoidFreqRangeCount =
4844 ch_avoid_indi->avoid_range_count;
4845
4846 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
4847
4848 /* clear existing unsafe channel cache */
4849 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304850 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851 sizeof(hdd_ctxt->unsafe_channel_list));
4852
4853 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
4854 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08004855 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004856 hddLog(LOGW, FL("LTE Coex unsafe channel list full"));
4857 break;
4858 }
4859
4860 start_channel = ieee80211_frequency_to_channel(
4861 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
4862 end_channel = ieee80211_frequency_to_channel(
4863 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
4864 hddLog(LOG1, "%s : start %d : %d, end %d : %d", __func__,
4865 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
4866 start_channel,
4867 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
4868 end_channel);
4869
4870 /* do not process frequency bands that are not mapped to
4871 * predefined channels
4872 */
4873 if (start_channel == 0 || end_channel == 0)
4874 continue;
4875
Amar Singhalb8d4f152016-02-10 10:21:43 -08004876 for (channel_loop = CHAN_ENUM_1; channel_loop <=
4877 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004878 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004879 ch_avoid_indi->avoid_freq_range[
4880 range_loop].start_freq) {
4881 start_channel_idx = channel_loop;
4882 break;
4883 }
4884 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08004885 for (channel_loop = CHAN_ENUM_1; channel_loop <=
4886 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004887 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 ch_avoid_indi->avoid_freq_range[
4889 range_loop].end_freq) {
4890 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07004891 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892 ch_avoid_indi->avoid_freq_range[
4893 range_loop].end_freq)
4894 end_channel_idx--;
4895 break;
4896 }
4897 }
4898
Amar Singhalb8d4f152016-02-10 10:21:43 -08004899 if (start_channel_idx == INVALID_CHANNEL ||
4900 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 continue;
4902
4903 for (channel_loop = start_channel_idx; channel_loop <=
4904 end_channel_idx; channel_loop++) {
4905 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07004906 hdd_ctxt->unsafe_channel_count++] =
4907 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08004909 NUM_CHANNELS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004910 hddLog(LOGW, FL("LTECoex unsafe ch list full"));
4911 break;
4912 }
4913 }
4914 }
4915
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304916 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 FL("number of unsafe channels is %d "),
4918 hdd_ctxt->unsafe_channel_count);
4919
4920 if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list,
4921 hdd_ctxt->unsafe_channel_count)) {
4922 hdd_err("Failed to set unsafe channel");
4923
4924 /* clear existing unsafe channel cache */
4925 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304926 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 sizeof(hdd_ctxt->unsafe_channel_list));
4928
4929 return;
4930 }
4931
4932 for (channel_loop = 0;
4933 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304934 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004935 FL("channel %d is not safe "),
4936 hdd_ctxt->unsafe_channel_list[channel_loop]);
4937 }
4938
4939 /*
4940 * If auto channel select is enabled
4941 * preferred channel is in safe channel,
4942 * re-start softap interface with safe channel.
4943 * no overlap with preferred channel and safe channel
4944 * do not re-start softap interface
4945 * stay current operating channel.
4946 */
4947 if (hdd_ctxt->unsafe_channel_count) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004948 hostapd_adapter = hdd_get_adapter(hdd_ctxt, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 if (hostapd_adapter) {
4950 if ((hostapd_adapter->sessionCtx.ap.sapConfig.
4951 acs_cfg.acs_mode) &&
4952 (!hdd_find_prefd_safe_chnl(hdd_ctxt,
4953 hostapd_adapter)))
4954 return;
4955
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304956 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004957 FL(
4958 "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d"
4959 ),
4960 hostapd_adapter->sessionCtx.ap.
4961 operatingChannel,
4962 hostapd_adapter->sessionCtx.ap.sapConfig.
4963 channel);
4964 for (channel_loop = 0;
4965 channel_loop < hdd_ctxt->unsafe_channel_count;
4966 channel_loop++) {
4967 if (((hdd_ctxt->
4968 unsafe_channel_list[channel_loop] ==
4969 hostapd_adapter->sessionCtx.ap.
4970 operatingChannel)) &&
4971 (hostapd_adapter->sessionCtx.ap.
4972 sapConfig.acs_cfg.acs_mode
4973 == true) &&
4974 !restart_sap_in_progress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304975 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 FL("Restarting SAP"));
4977 wlan_hdd_send_svc_nlink_msg
4978 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
4979 restart_sap_in_progress = 1;
4980 /*
4981 * current operating channel is un-safe
4982 * channel, restart driver
4983 */
4984 hdd_hostapd_stop(hostapd_adapter->dev);
4985 break;
4986 }
4987 }
4988 }
4989 }
4990 return;
4991}
4992
4993/**
4994 * hdd_init_channel_avoidance() - Initialize channel avoidance
4995 * @hdd_ctx: HDD global context
4996 *
4997 * Initialize the channel avoidance logic by retrieving the unsafe
4998 * channel list from the CNSS platform driver and plumbing the data
4999 * down to the lower layers. Then subscribe to subsequent channel
5000 * avoidance events.
5001 *
5002 * Return: None
5003 */
5004static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5005{
5006 uint16_t unsafe_channel_count;
5007 int index;
5008
5009 cnss_get_wlan_unsafe_channel(hdd_ctx->unsafe_channel_list,
5010 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08005011 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305013 hddLog(QDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014 hdd_ctx->unsafe_channel_count);
5015
Anurag Chouhan6d760662016-02-20 16:05:43 +05305016 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08005017 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018
5019 for (index = 0; index < unsafe_channel_count; index++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305020 hddLog(QDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 hdd_ctx->unsafe_channel_list[index]);
5022
5023 }
5024
5025 /* Plug in avoid channel notification callback */
5026 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
5027}
5028#else
5029static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5030{
5031}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005032static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033{
5034}
5035#endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */
5036
5037/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08005038 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
5039 * user space
5040 * @frame_ind: Management frame data to be informed.
5041 *
5042 * This function is used to indicate management frame to
5043 * user space
5044 *
5045 * Return: None
5046 *
5047 */
5048void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
5049{
5050 hdd_context_t *hdd_ctx = NULL;
5051 hdd_adapter_t *adapter = NULL;
5052 void *cds_context = NULL;
5053 int i;
5054
5055 /* Get the global VOSS context.*/
5056 cds_context = cds_get_global_context();
5057 if (!cds_context) {
5058 hdd_err("Global CDS context is Null");
5059 return;
5060 }
5061 /* Get the HDD context.*/
5062 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
5063
5064 if (0 != wlan_hdd_validate_context(hdd_ctx))
5065 return;
5066
5067 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
5068 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
5069 adapter =
5070 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
5071 if (adapter)
5072 break;
5073 }
5074 } else {
5075 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
5076 frame_ind->sessionId);
5077 }
5078
5079 if ((NULL != adapter) &&
5080 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
5081 __hdd_indicate_mgmt_frame(adapter,
5082 frame_ind->frame_len,
5083 frame_ind->frameBuf,
5084 frame_ind->frameType,
5085 frame_ind->rxChan,
5086 frame_ind->rxRssi);
5087 return;
5088}
5089
5090/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005091 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
5092 * @hdd_ctx: HDD context
5093 *
5094 * Disables all the dual mac features like DBS, Agile DFS etc.
5095 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305096 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005097 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305098static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099{
5100 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305101 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005102
5103 if (!hdd_ctx) {
5104 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305105 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 }
5107
5108 cfg.scan_config = 0;
5109 cfg.fw_mode_config = 0;
5110 cfg.set_dual_mac_cb =
5111 (void *)cds_soc_set_dual_mac_cfg_cb;
5112
5113 hdd_debug("Disabling all dual mac features...");
5114
5115 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305116 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
5118 return status;
5119 }
5120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305121 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122}
5123
5124/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005125 * hdd_override_ini_config - Override INI config
5126 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005128 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005129 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005130 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005131 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005132static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005134
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005135 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
5136 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5137 hdd_notice("Module enable_dfs_chan_scan set to %d",
5138 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005139 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005140 if (0 == enable_11d || 1 == enable_11d) {
5141 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5142 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005144}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005145
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005146/**
5147 * hdd_set_trace_level_for_each - Set trace level for each INI config
5148 * @hdd_ctx - HDD context
5149 *
5150 * Set trace level for each module based on INI config.
5151 *
5152 * Return: None
5153 */
5154static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5155{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305156 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
5157 hdd_ctx->config->qdf_trace_enable_wdi);
5158 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
5159 hdd_ctx->config->qdf_trace_enable_hdd);
5160 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
5161 hdd_ctx->config->qdf_trace_enable_sme);
5162 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
5163 hdd_ctx->config->qdf_trace_enable_pe);
5164 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
5165 hdd_ctx->config->qdf_trace_enable_wma);
5166 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
5167 hdd_ctx->config->qdf_trace_enable_sys);
5168 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
5169 hdd_ctx->config->qdf_trace_enable_qdf);
5170 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
5171 hdd_ctx->config->qdf_trace_enable_sap);
5172 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
5173 hdd_ctx->config->qdf_trace_enable_hdd_sap);
5174 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
5175 hdd_ctx->config->qdf_trace_enable_bmi);
5176 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
5177 hdd_ctx->config->qdf_trace_enable_cfg);
5178 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
5179 hdd_ctx->config->qdf_trace_enable_epping);
5180 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
5181 hdd_ctx->config->qdf_trace_enable_qdf_devices);
5182 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05305183 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305184 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
5185 hdd_ctx->config->qdf_trace_enable_htc);
5186 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
5187 hdd_ctx->config->qdf_trace_enable_hif);
5188 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
5189 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
5190 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
5191 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305192
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005193 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005194}
5195
5196/**
5197 * hdd_init_context - Alloc and initialize HDD context
5198 * @dev: Pointer to the underlying device
5199 * @hif_sc: HIF context
5200 *
5201 * Allocate and initialize HDD context. HDD context is allocated as part of
5202 * wiphy allocation and then context is initialized.
5203 *
5204 * Return: HDD context on success and ERR_PTR on failure
5205 */
5206hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc)
5207{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305208 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005209 int ret = 0;
5210 hdd_context_t *hdd_ctx;
5211 v_CONTEXT_t p_cds_context;
Komal Seelamc11bb222016-01-27 18:57:10 +05305212 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_sc);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005213
5214 ENTER();
5215
5216 p_cds_context = cds_get_global_context();
5217 if (p_cds_context == NULL) {
5218 hdd_alert("Failed to get CDS global context");
5219 ret = -EINVAL;
5220 goto err_out;
5221 }
5222
5223 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
5224
5225 if (hdd_ctx == NULL) {
5226 ret = -ENOMEM;
5227 goto err_out;
5228 }
5229
5230 hdd_ctx->pcds_context = p_cds_context;
5231
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305232 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005233 if (hdd_ctx->config == NULL) {
5234 hdd_alert("Failed to alloc memory for HDD config!");
5235 ret = -ENOMEM;
5236 goto err_free_hdd_context;
5237 }
5238
5239 /* Read and parse the qcom_cfg.ini file */
5240 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305241 if (QDF_STATUS_SUCCESS != status) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005242 hdd_alert("Error (status: %d) parsing INI file: %s", status,
5243 WLAN_INI_FILE);
5244 ret = -EINVAL;
5245 goto err_free_config;
5246 }
5247
5248 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
5249
5250 hdd_ctx->parent_dev = dev;
5251
5252 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5253
5254 hdd_init_ll_stats_ctx();
5255
5256 init_completion(&hdd_ctx->mc_sus_event_var);
5257 init_completion(&hdd_ctx->ready_to_suspend);
5258
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305259 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
5260 qdf_spinlock_create(&hdd_ctx->sched_scan_lock);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005261
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305262 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305263 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005264
5265 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
5266
5267 hdd_tdls_pre_init(hdd_ctx);
5268 mutex_init(&hdd_ctx->dfs_lock);
5269
Archana Ramachandrana20ef812015-11-13 16:12:13 -08005270 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
5271
Komal Seelamc11bb222016-01-27 18:57:10 +05305272 hdd_ctx->target_type = tgt_info->target_type;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005273
5274 hdd_init_offloaded_packets_ctx(hdd_ctx);
5275
Komal Seelamc11bb222016-01-27 18:57:10 +05305276 icnss_set_fw_debug_mode(hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005277
5278 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5279
5280 hdd_ctx->configuredMcastBcastFilter =
5281 hdd_ctx->config->mcastBcastFilterSetting;
5282
5283 hdd_notice("Setting configuredMcastBcastFilter: %d",
5284 hdd_ctx->config->mcastBcastFilterSetting);
5285
5286 hdd_override_ini_config(hdd_ctx);
5287
5288 ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config);
5289
5290 if (ret) {
5291 hdd_err("CFG80211 wiphy init failed: %d", ret);
5292 goto err_free_config;
5293 }
5294
5295 hdd_enable_fastpath(hdd_ctx->config, hif_sc);
5296
5297 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05305298 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005299
Anurag Chouhan6d760662016-02-20 16:05:43 +05305300 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005301 goto skip_multicast_logging;
5302
5303 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
5304
5305 ret = hdd_logging_sock_activate_svc(hdd_ctx);
5306 if (ret)
5307 goto err_free_config;
5308
5309 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305310 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005311 * levels of the code need not be set when the logger thread
5312 * is not enabled.
5313 */
5314 if (cds_is_multicast_logging())
5315 wlan_logging_set_log_level();
5316
5317skip_multicast_logging:
5318 hdd_set_trace_level_for_each(hdd_ctx);
5319
5320 return hdd_ctx;
5321
5322err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305323 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005324
5325err_free_hdd_context:
5326 wiphy_free(hdd_ctx->wiphy);
5327
5328err_out:
5329 return ERR_PTR(ret);
5330}
5331
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005332#ifdef WLAN_OPEN_P2P_INTERFACE
5333/**
5334 * hdd_open_p2p_interface - Open P2P interface
5335 * @hdd_ctx: HDD context
5336 * @rtnl_held: True if RTNL lock held
5337 *
5338 * Open P2P interface during probe. This function called to open the P2P
5339 * interface at probe along with STA interface.
5340 *
5341 * Return: 0 on success and errno on failure
5342 */
5343static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
5344{
5345 hdd_adapter_t *adapter;
5346 uint8_t *p2p_dev_addr;
5347
5348 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
5349 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305350 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005351 hdd_ctx->config->intfMacAddr[0].bytes,
5352 sizeof(tSirMacAddr));
5353
5354 /*
5355 * Generate the P2P Device Address. This consists of
5356 * the device's primary MAC address with the locally
5357 * administered bit set.
5358 */
5359 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
5360 } else {
5361 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
5362 if (p2p_dev_addr == NULL) {
5363 hdd_alert("Failed to allocate mac_address for p2p_device");
5364 return -ENOSPC;
5365 }
5366
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305367 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305368 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005369 }
5370
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005371 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005372 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08005373 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005374
5375 if (NULL == adapter) {
5376 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
5377 return -ENOSPC;
5378 }
5379
5380 return 0;
5381}
5382#else
5383static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx,
5384 bool rtnl_held)
5385{
5386 return 0;
5387}
5388#endif
5389
5390/**
5391 * hdd_open_interfaces - Open all required interfaces
5392 * hdd_ctx: HDD context
5393 * rtnl_held: True if RTNL lock is held
5394 *
5395 * Open all the interfaces like STA, P2P and OCB based on the configuration.
5396 *
5397 * Return: Primary adapter on success and PTR_ERR on failure
5398 */
5399static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
5400 bool rtnl_held)
5401{
5402 hdd_adapter_t *adapter = NULL;
5403 hdd_adapter_t *adapter_11p = NULL;
5404 int ret;
5405
5406 /* Create only 802.11p interface */
5407 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005408 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005409 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08005410 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005411
5412 if (adapter == NULL)
5413 return ERR_PTR(-ENOSPC);
5414
5415 return adapter;
5416 }
5417
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005418 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005419 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08005420 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005421
5422 if (adapter == NULL)
5423 return ERR_PTR(-ENOSPC);
5424
5425 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
5426 if (ret)
5427 goto err_close_adapter;
5428
5429 /* Open 802.11p Interface */
5430 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005431 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005432 "wlanocb%d",
5433 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08005434 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005435 if (adapter_11p == NULL) {
5436 hdd_err("Failed to open 802.11p interface");
5437 goto err_close_adapter;
5438 }
5439 }
5440
5441 return adapter;
5442
5443err_close_adapter:
5444 hdd_close_all_adapters(hdd_ctx, rtnl_held);
5445 return ERR_PTR(ret);
5446}
5447
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005448/**
5449 * hdd_update_country_code - Update country code
5450 * @hdd_ctx: HDD context
5451 * @adapter: Primary adapter context
5452 *
5453 * Update country code based on module parameter country_code at SME and wait
5454 * for the settings to take effect.
5455 *
5456 * Return: 0 on success and errno on failure
5457 */
5458static int hdd_update_country_code(hdd_context_t *hdd_ctx,
5459 hdd_adapter_t *adapter)
5460{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305461 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005462 int ret = 0;
5463 unsigned long rc;
5464
5465 if (country_code == NULL)
5466 return 0;
5467
5468 INIT_COMPLETION(adapter->change_country_code);
5469
5470 status = sme_change_country_code(hdd_ctx->hHal,
5471 wlan_hdd_change_country_code_callback,
5472 country_code, adapter,
5473 hdd_ctx->pcds_context, eSIR_TRUE,
5474 eSIR_TRUE);
5475
5476
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305477 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005478 hdd_err("SME Change Country code from module param fail ret=%d",
5479 ret);
5480 return -EINVAL;
5481 }
5482
5483 rc = wait_for_completion_timeout(&adapter->change_country_code,
5484 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
5485 if (!rc) {
5486 hdd_err("SME while setting country code timed out");
5487 ret = -ETIMEDOUT;
5488 }
5489
5490 return ret;
5491}
5492
5493/**
5494 * hdd_init_thermal_info - Initialize thermal level
5495 * @hdd_ctx: HDD context
5496 *
5497 * Initialize thermal level at SME layer and set the thermal level callback
5498 * which would be called when a configured thermal threshold is hit.
5499 *
5500 * Return: 0 on success and errno on failure
5501 */
5502static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
5503{
5504 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305505 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005506
5507 thermal_param.smeThermalMgmtEnabled =
5508 hdd_ctx->config->thermalMitigationEnable;
5509 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
5510
Poddar, Siddarth83905022016-04-16 17:56:08 -07005511 thermal_param.sme_throttle_duty_cycle_tbl[0] =
5512 hdd_ctx->config->throttle_dutycycle_level0;
5513 thermal_param.sme_throttle_duty_cycle_tbl[1] =
5514 hdd_ctx->config->throttle_dutycycle_level1;
5515 thermal_param.sme_throttle_duty_cycle_tbl[2] =
5516 hdd_ctx->config->throttle_dutycycle_level2;
5517 thermal_param.sme_throttle_duty_cycle_tbl[3] =
5518 hdd_ctx->config->throttle_dutycycle_level3;
5519
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005520 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
5521 hdd_ctx->config->thermalTempMinLevel0;
5522 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
5523 hdd_ctx->config->thermalTempMaxLevel0;
5524 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
5525 hdd_ctx->config->thermalTempMinLevel1;
5526 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
5527 hdd_ctx->config->thermalTempMaxLevel1;
5528 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
5529 hdd_ctx->config->thermalTempMinLevel2;
5530 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
5531 hdd_ctx->config->thermalTempMaxLevel2;
5532 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
5533 hdd_ctx->config->thermalTempMinLevel3;
5534 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
5535 hdd_ctx->config->thermalTempMaxLevel3;
5536
5537 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
5538
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305539 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05305540 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005541
5542 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
5543 hdd_set_thermal_level_cb);
5544
5545 return 0;
5546
5547}
5548
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005549#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5550/**
5551 * hdd_hold_rtnl_lock - Hold RTNL lock
5552 *
5553 * Hold RTNL lock
5554 *
5555 * Return: True if held and false otherwise
5556 */
5557static inline bool hdd_hold_rtnl_lock(void)
5558{
5559 rtnl_lock();
5560 return true;
5561}
5562
5563/**
5564 * hdd_release_rtnl_lock - Release RTNL lock
5565 *
5566 * Release RTNL lock
5567 *
5568 * Return: None
5569 */
5570static inline void hdd_release_rtnl_lock(void)
5571{
5572 rtnl_unlock();
5573}
5574#else
5575static inline bool hdd_hold_rtnl_lock(void) { return false; }
5576static inline void hdd_release_rtnl_lock(void) { }
5577#endif
5578
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05305579#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
5580/**
5581 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
5582 * switch without restart
5583 *
5584 * Registers callback function to change the operating channel of SAP by using
5585 * channel switch announcements instead of restarting SAP.
5586 *
5587 * Return: QDF_STATUS
5588 */
5589QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
5590{
5591 QDF_STATUS status;
5592
5593 status = cds_register_sap_restart_channel_switch_cb(
5594 (void *)hdd_sap_restart_with_channel_switch);
5595 if (!QDF_IS_STATUS_SUCCESS(status))
5596 hdd_err("restart cb registration failed");
5597
5598 return status;
5599}
5600#endif
5601
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005602/**
5603 * hdd_wlan_startup() - HDD init function
5604 * @dev: Pointer to the underlying device
5605 *
5606 * This is the driver startup code executed once a WLAN device has been detected
5607 *
5608 * Return: 0 for success, < 0 for failure
5609 */
5610int hdd_wlan_startup(struct device *dev, void *hif_sc)
5611{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305612 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005613 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005614 hdd_context_t *hdd_ctx = NULL;
5615 int ret;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005616 tSirTxPowerLimit hddtxlimit;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005617 bool rtnl_held;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005618 tSirRetStatus hal_status;
Amar Singhale4f28ee2015-10-21 14:36:56 -07005619 int ret_val;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005620
5621 ENTER();
5622
5623 if (WLAN_IS_EPPING_ENABLED(con_mode)) {
5624 ret = epping_enable(dev);
5625 EXIT();
5626 return ret;
5627 }
5628
5629 hdd_ctx = hdd_init_context(dev, hif_sc);
5630
5631 if (IS_ERR(hdd_ctx))
5632 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005633
Anurag Chouhan6d760662016-02-20 16:05:43 +05305634 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005635 ret = hdd_enable_ftm(hdd_ctx);
5636
5637 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005638 goto err_hdd_free_context;
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005639
5640 goto success;
5641 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005642
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08005643 hdd_wlan_green_ap_init(hdd_ctx);
5644
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005645 status = cds_open();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305646 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305647 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_open failed"));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005648 goto err_hdd_free_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005649 }
5650
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005651 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652
Anurag Chouhan6d760662016-02-20 16:05:43 +05305653 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654
5655 if (NULL == hdd_ctx->hHal) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305656 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HAL context is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005657 goto err_cds_close;
5658 }
5659
5660 status = cds_pre_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305661 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305662 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005663 goto err_cds_close;
5664 }
5665
5666 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
5667
Amar Singhale4f28ee2015-10-21 14:36:56 -07005668 ret_val = hdd_wiphy_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005669
Amar Singhale4f28ee2015-10-21 14:36:56 -07005670 if (ret_val) {
5671 hdd_alert("failed to initialize wiphy");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 goto err_cds_close;
5673 }
5674
5675 /*
5676 * Set 802.11p config
5677 * TODO-OCB: This has been temporarily added here to ensure this
5678 * parameter is set in CSR when we init the channel list. This should
5679 * be removed once the 5.9 GHz channels are added to the regulatory
5680 * domain.
5681 */
5682 hdd_set_dot11p_config(hdd_ctx);
5683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 /*
5685 * Note that the cds_pre_enable() sequence triggers the cfg download.
5686 * The cfg download must occur before we update the SME config
5687 * since the SME config operation must access the cfg database
5688 */
5689 status = hdd_set_sme_config(hdd_ctx);
5690
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305691 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305692 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005693 goto err_wiphy_unregister;
5694 }
5695
5696 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
5697 hdd_ctx->config->tx_chain_mask_1ss,
5698 PDEV_CMD);
5699 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305700 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005701 "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d",
5702 __func__, ret);
5703 }
5704
Amar Singhale4f28ee2015-10-21 14:36:56 -07005705 hdd_program_country_code(hdd_ctx);
5706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005707 status = hdd_set_sme_chan_list(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305708 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305709 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005710 FL("Failed to init channel list"));
5711 goto err_wiphy_unregister;
5712 }
5713
5714 /* Apply the cfg.ini to cfg.dat */
5715 if (false == hdd_update_config_dat(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305716 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005717 FL("config update failed"));
5718 goto err_wiphy_unregister;
5719 }
5720
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305721 if (QDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305722 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723 FL("can't update mac config, using MAC from ini file"));
5724 }
5725
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005726 /*
5727 * Set the MAC Address Currently this is used by HAL to add self sta.
5728 * Remove this once self sta is added as part of session open.
5729 */
5730 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
5731 hdd_ctx->config->intfMacAddr[0].bytes,
5732 sizeof(hdd_ctx->config->intfMacAddr[0]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005734 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
5735 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
5736 hal_status, hal_status);
5737 ret = -EINVAL;
5738 goto err_wiphy_unregister;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005739 }
5740
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305741 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742 goto err_wiphy_unregister;
5743
5744 /*
5745 * Start CDS which starts up the SME/MAC/HAL modules and everything
5746 * else
5747 */
5748 status = cds_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305749 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305750 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_enable failed"));
Yun Park6a46ad82016-01-04 16:48:19 -08005751 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005752 }
5753
5754 hdd_init_channel_avoidance(hdd_ctx);
5755
5756 status = hdd_post_cds_enable_config(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305757 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305758 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 FL("hdd_post_cds_enable_config failed"));
5760 goto err_cds_disable;
5761 }
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005762
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005763 cds_pkt_proto_trace_init();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005764
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005765 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005766
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005767 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005768
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005769 if (IS_ERR(adapter)) {
5770 ret = PTR_ERR(adapter);
5771 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005772 }
5773
5774 /*
5775 * target hw version/revision would only be retrieved after firmware
5776 * donwload
5777 */
5778 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
5779 &hdd_ctx->target_hw_revision,
5780 &hdd_ctx->target_hw_name);
5781
5782 /* Get the wlan hw/fw version */
5783 hdd_wlan_get_version(adapter, NULL, NULL);
5784
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005785 ret = hdd_update_country_code(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005786
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005787 if (ret)
5788 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005789
5790 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
5791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005792 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
5793 hdd_send_oem_data_rsp_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 /* FW capabilities received, Set the Dot11 mode */
5796 sme_setdef_dot11mode(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798 /* Initialize the nlink service */
5799 if (nl_srv_init() != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305800 hddLog(QDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed"));
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005801 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005802 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005804 ret = oem_activate_service(hdd_ctx);
5805 if (ret) {
5806 hdd_alert("oem_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005807 goto err_nl_srv;
5808 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005810 ret = ptt_sock_activate_svc();
5811 if (ret) {
5812 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005813 goto err_nl_srv;
5814 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005815
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005816 ret = cnss_diag_activate_service();
5817 if (ret) {
5818 hdd_alert("cnss_diag_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819 goto err_nl_srv;
5820 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005821
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005822 if (hdd_open_cesium_nl_sock() < 0) {
5823 hdd_alert("hdd_open_cesium_nl_sock failed");
5824 goto err_nl_srv;
5825 }
5826
Peng Xuf5d60c82015-10-02 17:17:03 -07005827 /*
5828 * Action frame registered in one adapter which will
5829 * applicable to all interfaces
5830 */
5831 wlan_hdd_cfg80211_register_frames(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832
5833 mutex_init(&hdd_ctx->sap_lock);
5834
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005835 hdd_release_rtnl_lock();
5836 rtnl_held = false;
5837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5839 if (ret < 0) {
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005840 hdd_err("register_netdevice_notifier failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 goto err_nl_srv;
5842 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5845 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305846 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005847#endif
5848 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305849 qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850
5851 hdd_hostapd_channel_wakelock_init(hdd_ctx);
5852
Kiran Kumar Lokerefc2803d2016-01-11 19:31:38 -08005853 if (hdd_ctx->config->fIsImpsEnabled)
5854 hdd_set_idle_ps_config(hdd_ctx, true);
5855 else
5856 hdd_set_idle_ps_config(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005857#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5858 if (hdd_ctx->config->WlanAutoShutdown != 0)
5859 if (sme_set_auto_shutdown_cb
5860 (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305861 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 hddLog(LOGE,
5863 FL(
5864 "Auto shutdown feature could not be enabled"
5865 ));
5866#endif
5867
5868#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305869 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305870 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005871 hdd_skip_acs_scan_timer_handler,
5872 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305873 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 hddLog(LOGE, FL("Failed to init ACS Skip timer"));
5875#endif
5876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005877 wlan_hdd_nan_init(hdd_ctx);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005878 status = cds_init_policy_mgr();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305879 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880 hdd_err("Policy manager initialization failed");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005881 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005882 }
5883
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005884 ret = hdd_init_thermal_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005886 if (ret) {
5887 hdd_err("Error while initializing thermal information");
5888 goto err_unreg_netdev_notifier;
5889 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005890
5891 if (0 != hdd_lro_init(hdd_ctx))
5892 hdd_err("Unable to initialize LRO in fw");
5893
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005894 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
5895 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
5896 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305897 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005898 hdd_err("Error setting txlimit in sme: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005899
5900#ifdef MSM_PLATFORM
5901 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05305902 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305903 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005904 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5905#endif
5906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005907 wlan_hdd_cfg80211_stats_ext_init(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005908
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909 sme_ext_scan_register_callback(hdd_ctx->hHal,
5910 wlan_hdd_cfg80211_extscan_callback);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005911
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05305912 status = hdd_register_for_sap_restart_with_channel_switch();
5913 if (!QDF_IS_STATUS_SUCCESS(status))
5914 /* Error already logged */
5915 goto err_unreg_netdev_notifier;
5916
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005917 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
5918 hdd_rssi_threshold_breached);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005920 hdd_cfg80211_link_layer_stats_init(hdd_ctx);
5921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
5923 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
5924 hdd_ctx->target_hw_version,
5925 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305927 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305928 qdf_list_create((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305929 qdf_spinlock_create(&hdd_ctx->hdd_scan_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305930 qdf_list_create((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931#ifdef CONFIG_CNSS
5932 cnss_init_delayed_work(&hdd_ctx->roc_req_work,
5933 wlan_hdd_roc_request_dequeue);
5934#else
5935 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5936#endif
5937
5938 /*
5939 * Register IPv6 notifier to notify if any change in IP
5940 * So that we can reconfigure the offload parameters
5941 */
5942 hdd_wlan_register_ip6_notifier(hdd_ctx);
5943
5944 /*
5945 * Register IPv4 notifier to notify if any change in IP
5946 * So that we can reconfigure the offload parameters
5947 */
5948 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5949 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5950 if (ret)
5951 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
5952 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005953 hdd_info("Registered IPv4 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005954
5955 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
5956
5957 if (hdd_ctx->config->dual_mac_feature_disable) {
5958 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305959 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960 hdd_err("Failed to disable dual mac features");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005961 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005962 }
5963 }
5964
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005965 memdump_init();
5966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967 goto success;
5968
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005969err_unreg_netdev_notifier:
5970 unregister_netdevice_notifier(&hdd_netdev_notifier);
5971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005972err_nl_srv:
5973#ifdef WLAN_KD_READY_NOTIFIER
5974 cnss_diag_notify_wlan_close();
5975 ptt_sock_deactivate_svc();
5976#endif /* WLAN_KD_READY_NOTIFIER */
5977 nl_srv_exit();
5978
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305979 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08005980 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005981 /* Proceed and complete the clean up */
5982 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005983
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08005984 hdd_close_cesium_nl_sock();
5985
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005987 hdd_release_rtnl_lock();
5988
5989 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005990
5991err_cds_disable:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005992 cds_disable(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993
Yun Park6a46ad82016-01-04 16:48:19 -08005994err_ipa_cleanup:
5995 hdd_ipa_cleanup(hdd_ctx);
5996
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005997err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005998 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005999
6000err_cds_close:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006001 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306002 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306003 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006004 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306005 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006006 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006007 cds_close(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006008
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006009err_hdd_free_context:
6010 hdd_free_context(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306011 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006013 return -EIO;
6014
6015success:
6016 EXIT();
6017 return 0;
6018}
6019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020/**
6021 * hdd_softap_sta_deauth() - handle deauth req from HDD
6022 * @adapter: Pointer to the HDD
6023 * @enable: bool value
6024 *
6025 * This to take counter measure to handle deauth req from HDD
6026 *
6027 * Return: None
6028 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306029QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030 struct tagCsrDelStaParams *pDelStaParams)
6031{
6032#ifndef WLAN_FEATURE_MBSSID
6033 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
6034#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306035 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006036
6037 ENTER();
6038
6039 hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"),
6040 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
6041
6042 /* Ignore request to deauth bcmc station */
6043 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306044 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006045
6046#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306047 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006048 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6049 pDelStaParams);
6050#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306051 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006052#endif
6053
6054 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306055 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056}
6057
6058/**
6059 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
6060 * @adapter: Pointer to the HDD
6061 *
6062 * This to take counter measure to handle deauth req from HDD
6063 *
6064 * Return: None
6065 */
6066void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
6067 uint8_t *pDestMacAddress)
6068{
6069#ifndef WLAN_FEATURE_MBSSID
6070 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
6071#endif
6072
6073 ENTER();
6074
6075 hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"),
6076 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
6077
6078 /* Ignore request to disassoc bcmc station */
6079 if (pDestMacAddress[0] & 0x1)
6080 return;
6081
6082#ifdef WLAN_FEATURE_MBSSID
6083 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6084 pDestMacAddress);
6085#else
6086 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
6087#endif
6088}
6089
6090void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
6091 bool enable)
6092{
6093#ifndef WLAN_FEATURE_MBSSID
6094 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
6095#endif
6096
6097 ENTER();
6098
6099 hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"),
6100 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
6101
6102#ifdef WLAN_FEATURE_MBSSID
6103 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6104 (bool) enable);
6105#else
6106 wlansap_set_counter_measure(p_cds_context, (bool) enable);
6107#endif
6108}
6109
6110/**
6111 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
6112 * @hdd_ctx: HDD Context
6113 *
6114 * API to find if there is any STA or P2P-Client is connected
6115 *
6116 * Return: true if connected; false otherwise
6117 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306118QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006119{
6120 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
6121}
6122
6123#ifdef WLAN_FEATURE_LPSS
6124int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
6125 hdd_adapter_t *adapter,
6126 hdd_station_ctx_t *pHddStaCtx,
6127 uint8_t is_on, uint8_t is_connected)
6128{
6129 hdd_context_t *hdd_ctx = NULL;
6130 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
6131
6132 if (!data) {
6133 hddLog(LOGE, FL("invalid data pointer"));
6134 return -EINVAL;
6135 }
6136 if (!adapter) {
6137 if (is_on) {
6138 /* no active interface */
6139 data->lpss_support = 0;
6140 data->is_on = is_on;
6141 return 0;
6142 }
6143 hddLog(LOGE, FL("invalid adapter pointer"));
6144 return -EINVAL;
6145 }
6146
6147 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelamc11bb222016-01-27 18:57:10 +05306148 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006149 data->lpss_support = 1;
6150 else
6151 data->lpss_support = 0;
6152 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
6153 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
6154 &data->numChannels);
6155 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
6156 data->is_on = is_on;
6157 data->vdev_id = adapter->sessionId;
6158 data->vdev_mode = adapter->device_mode;
6159 if (pHddStaCtx) {
6160 data->is_connected = is_connected;
6161 data->rssi = adapter->rssi;
6162 data->freq =
6163 cds_chan_to_freq(pHddStaCtx->conn_info.operationChannel);
6164 if (WLAN_SVC_MAX_SSID_LEN >=
6165 pHddStaCtx->conn_info.SSID.SSID.length) {
6166 data->ssid_len = pHddStaCtx->conn_info.SSID.SSID.length;
6167 memcpy(data->ssid,
6168 pHddStaCtx->conn_info.SSID.SSID.ssId,
6169 pHddStaCtx->conn_info.SSID.SSID.length);
6170 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05306171 if (QDF_MAC_ADDR_SIZE >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006172 sizeof(pHddStaCtx->conn_info.bssId))
6173 memcpy(data->bssid, pHddStaCtx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306174 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006175 }
6176 return 0;
6177}
6178
6179int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
6180 uint32_t fw_version,
6181 uint32_t chip_id, const char *chip_name)
6182{
6183 if (!data) {
6184 hddLog(LOGE, FL("invalid data pointer"));
6185 return -EINVAL;
6186 }
6187
6188 data->chip_id = chip_id;
6189 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
6190 if (strncmp(chip_name, "Unknown", 7))
6191 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
6192 else
6193 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
6194 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
6195 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
6196 (fw_version & 0xf0000000) >> 28,
6197 (fw_version & 0xf000000) >> 24,
6198 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
6199 return 0;
6200}
6201#endif
6202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006203/**
6204 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
6205 * @adapter: HDD adapter pointer
6206 *
6207 * This function loop through each adapter and disable roaming on each STA
6208 * device mode except the input adapter.
6209 *
6210 * Note: On the input adapter roaming is not enabled yet hence no need to
6211 * disable.
6212 *
6213 * Return: None
6214 */
6215void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
6216{
6217 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6218 hdd_adapter_t *adapterIdx = NULL;
6219 hdd_adapter_list_node_t *adapterNode = NULL;
6220 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306221 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006222
6223 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6224 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006225 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006226 cds_is_sta_active_connection_exists()) {
6227 hddLog(LOG1, FL("Connect received on STA sessionId(%d)"),
6228 adapter->sessionId);
6229 /*
6230 * Loop through adapter and disable roaming for each STA device
6231 * mode except the input adapter.
6232 */
6233 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6234
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306235 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006236 adapterIdx = adapterNode->pAdapter;
6237
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006238 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239 && adapter->sessionId != adapterIdx->sessionId) {
6240 hddLog(LOG1,
6241 FL("Disable Roaming on sessionId(%d)"),
6242 adapterIdx->sessionId);
6243 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
6244 (adapterIdx),
6245 adapterIdx->sessionId, 0);
6246 }
6247
6248 status = hdd_get_next_adapter(hdd_ctx,
6249 adapterNode,
6250 &pNext);
6251 adapterNode = pNext;
6252 }
6253 }
6254}
6255
6256/**
6257 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
6258 * @adapter: HDD adapter pointer
6259 *
6260 * This function loop through each adapter and enable roaming on each STA
6261 * device mode except the input adapter.
6262 * Note: On the input adapter no need to enable roaming because link got
6263 * disconnected on this.
6264 *
6265 * Return: None
6266 */
6267void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
6268{
6269 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6270 hdd_adapter_t *adapterIdx = NULL;
6271 hdd_adapter_list_node_t *adapterNode = NULL;
6272 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306273 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006274
6275 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6276 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006277 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006278 cds_is_sta_active_connection_exists()) {
6279 hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"),
6280 adapter->sessionId);
6281 /*
6282 * Loop through adapter and enable roaming for each STA device
6283 * mode except the input adapter.
6284 */
6285 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6286
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306287 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006288 adapterIdx = adapterNode->pAdapter;
6289
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006290 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006291 && adapter->sessionId != adapterIdx->sessionId) {
6292 hddLog(LOG1,
6293 FL("Enabling Roaming on sessionId(%d)"),
6294 adapterIdx->sessionId);
6295 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
6296 (adapterIdx),
6297 adapterIdx->sessionId,
6298 REASON_CONNECT);
6299 }
6300
6301 status = hdd_get_next_adapter(hdd_ctx,
6302 adapterNode,
6303 &pNext);
6304 adapterNode = pNext;
6305 }
6306 }
6307}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006308
6309void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
6310{
6311 struct sk_buff *skb;
6312 struct nlmsghdr *nlh;
6313 tAniMsgHdr *ani_hdr;
6314 void *nl_data = NULL;
6315 int flags = GFP_KERNEL;
6316
6317 if (in_interrupt() || irqs_disabled() || in_atomic())
6318 flags = GFP_ATOMIC;
6319
6320 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
6321
6322 if (skb == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306323 hddLog(QDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006324 return;
6325 }
6326
6327 nlh = (struct nlmsghdr *)skb->data;
6328 nlh->nlmsg_pid = 0; /* from kernel */
6329 nlh->nlmsg_flags = 0;
6330 nlh->nlmsg_seq = 0;
6331 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
6332
6333 ani_hdr = NLMSG_DATA(nlh);
6334 ani_hdr->type = type;
6335
6336 switch (type) {
6337 case WLAN_SVC_FW_CRASHED_IND:
6338 case WLAN_SVC_LTE_COEX_IND:
6339#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6340 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
6341#endif
6342 ani_hdr->length = 0;
6343 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
6344 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
6345 break;
6346 case WLAN_SVC_WLAN_STATUS_IND:
6347 case WLAN_SVC_WLAN_VERSION_IND:
6348 case WLAN_SVC_DFS_CAC_START_IND:
6349 case WLAN_SVC_DFS_CAC_END_IND:
6350 case WLAN_SVC_DFS_RADAR_DETECT_IND:
6351 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
6352 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08006353 case WLAN_SVC_WLAN_TP_TX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006354 ani_hdr->length = len;
6355 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
6356 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
6357 memcpy(nl_data, data, len);
6358 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
6359 break;
6360
6361 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306362 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006363 FL("WLAN SVC: Attempt to send unknown nlink message %d"),
6364 type);
6365 kfree_skb(skb);
6366 return;
6367 }
6368
6369 nl_srv_bcast(skb);
6370
6371 return;
6372}
6373
6374#ifdef WLAN_FEATURE_LPSS
6375void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
6376 hdd_station_ctx_t *pHddStaCtx,
6377 uint8_t is_on, uint8_t is_connected)
6378{
6379 int ret = 0;
6380 struct wlan_status_data data;
6381
Anurag Chouhan6d760662016-02-20 16:05:43 +05306382 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006383 return;
6384
6385 memset(&data, 0, sizeof(struct wlan_status_data));
6386 if (is_on)
6387 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, pHddStaCtx,
6388 is_on, is_connected);
6389 if (!ret)
6390 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND,
6391 &data,
6392 sizeof(struct wlan_status_data));
6393}
6394
6395void wlan_hdd_send_version_pkg(uint32_t fw_version,
6396 uint32_t chip_id, const char *chip_name)
6397{
6398 int ret = 0;
6399 struct wlan_version_data data;
6400#ifdef CONFIG_CNSS
6401 struct cnss_platform_cap cap;
6402
6403 ret = cnss_get_platform_cap(&cap);
6404 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306405 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006406 FL("platform capability info from CNSS not available"));
6407 return;
6408 }
6409
6410 if (!(cap.cap_flag & CNSS_HAS_UART_ACCESS))
6411 return;
6412#endif
6413
Anurag Chouhan6d760662016-02-20 16:05:43 +05306414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006415 return;
6416
6417 memset(&data, 0, sizeof(struct wlan_version_data));
6418 ret =
6419 wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
6420 chip_name);
6421 if (!ret)
6422 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND,
6423 &data,
6424 sizeof(struct wlan_version_data));
6425}
6426
6427void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
6428{
6429 hdd_adapter_t *pDataAdapter = NULL;
6430 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6431 bool scan_intf_found = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306432 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006433
6434 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306435 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006436 FL("NULL pointer for hdd_ctx"));
6437 return;
6438 }
6439
6440 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306441 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006442 pDataAdapter = adapterNode->pAdapter;
6443 if (pDataAdapter) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006444 if (pDataAdapter->device_mode == QDF_STA_MODE
6445 || pDataAdapter->device_mode == QDF_P2P_CLIENT_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006446 || pDataAdapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006447 QDF_P2P_DEVICE_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006448 scan_intf_found = true;
6449 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1,
6450 0);
6451 }
6452 }
6453 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6454 adapterNode = pNext;
6455 }
6456
6457 if (!scan_intf_found)
6458 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0);
6459}
6460#endif
6461
6462#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6463void wlan_hdd_auto_shutdown_cb(void)
6464{
6465 hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event.."));
6466 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
6467}
6468
6469void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
6470{
6471 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306472 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006473 hdd_adapter_t *adapter;
6474 bool ap_connected = false, sta_connected = false;
6475 tHalHandle hal_handle;
6476
6477 hal_handle = hdd_ctx->hHal;
6478 if (hal_handle == NULL)
6479 return;
6480
6481 if (hdd_ctx->config->WlanAutoShutdown == 0)
6482 return;
6483
6484 if (enable == false) {
6485 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306486 QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006487 hddLog(LOGE,
6488 FL("Failed to stop wlan auto shutdown timer"));
6489 }
6490 return;
6491 }
6492
6493 /* To enable shutdown timer check conncurrency */
6494 if (cds_concurrent_open_sessions_running()) {
6495 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6496
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306497 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006498 adapter = adapterNode->pAdapter;
6499 if (adapter
6500 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006501 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006502 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6503 conn_info.connState ==
6504 eConnectionState_Associated) {
6505 sta_connected = true;
6506 break;
6507 }
6508 }
6509 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006510 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006511 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
6512 bApActive == true) {
6513 ap_connected = true;
6514 break;
6515 }
6516 }
6517 status = hdd_get_next_adapter(hdd_ctx,
6518 adapterNode,
6519 &pNext);
6520 adapterNode = pNext;
6521 }
6522 }
6523
6524 if (ap_connected == true || sta_connected == true) {
6525 hddLog(LOG1,
6526 FL("CC Session active. Shutdown timer not enabled"));
6527 return;
6528 } else {
6529 if (sme_set_auto_shutdown_timer(hal_handle,
6530 hdd_ctx->config->
6531 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306532 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006533 hddLog(LOGE,
6534 FL("Failed to start wlan auto shutdown timer"));
6535 else
6536 hddLog(LOG1,
6537 FL("Auto Shutdown timer for %d seconds enabled"),
6538 hdd_ctx->config->WlanAutoShutdown);
6539
6540 }
6541}
6542#endif
6543
6544hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
6545 bool check_start_bss)
6546{
6547 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
6548 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306549 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006550 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6551
6552 con_sap_adapter = NULL;
6553
6554 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306555 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006556 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006557 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
6558 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006559 adapter != this_sap_adapter) {
6560 if (check_start_bss) {
6561 if (test_bit(SOFTAP_BSS_STARTED,
6562 &adapter->event_flags)) {
6563 con_sap_adapter = adapter;
6564 break;
6565 }
6566 } else {
6567 con_sap_adapter = adapter;
6568 break;
6569 }
6570 }
6571 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6572 adapterNode = pNext;
6573 }
6574
6575 return con_sap_adapter;
6576}
6577
6578#ifdef MSM_PLATFORM
6579void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
6580{
6581 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6582
Anurag Chouhan210db072016-02-22 18:42:15 +05306583 if (QDF_TIMER_STATE_RUNNING ==
6584 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006585 return;
6586
Anurag Chouhan210db072016-02-22 18:42:15 +05306587 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006588 hdd_ctx->config->busBandwidthComputeInterval);
6589}
6590
6591void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
6592{
6593 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306594 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006595 bool can_stop = true;
6596 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6597
Anurag Chouhan210db072016-02-22 18:42:15 +05306598 if (QDF_TIMER_STATE_RUNNING !=
6599 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006600 /* trying to stop timer, when not running is not good */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306601 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602 FL("bus band width compute timer is not running"));
6603 return;
6604 }
6605
6606 if (cds_concurrent_open_sessions_running()) {
6607 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6608
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306609 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006610 adapter = adapterNode->pAdapter;
6611 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006612 && (adapter->device_mode == QDF_STA_MODE
6613 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006614 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6615 conn_info.connState ==
6616 eConnectionState_Associated) {
6617 can_stop = false;
6618 break;
6619 }
6620 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006621 && (adapter->device_mode == QDF_SAP_MODE
6622 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006623 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
6624 true) {
6625 can_stop = false;
6626 break;
6627 }
6628 status = hdd_get_next_adapter(hdd_ctx,
6629 adapterNode,
6630 &pNext);
6631 adapterNode = pNext;
6632 }
6633 }
6634
6635 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05306636 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006637}
6638#endif
6639
6640/**
6641 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
6642 * and sta's operating channel.
6643 * @sta_adapter: Describe the first argument to foobar.
6644 * @ap_adapter: Describe the second argument to foobar.
6645 * @roam_profile: Roam profile of AP to which STA wants to connect.
6646 * @concurrent_chnl_same: If both SAP and STA channels are same then
6647 * set this flag to true else false.
6648 *
6649 * This function checks the sap's operating channel and sta's operating channel.
6650 * if both are same then it will return false else it will restart the sap in
6651 * sta's channel and return true.
6652 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306653 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006654 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306655QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006656 hdd_adapter_t *ap_adapter,
6657 tCsrRoamProfile *roam_profile,
6658 tScanResultHandle *scan_cache,
6659 bool *concurrent_chnl_same)
6660{
6661 hdd_ap_ctx_t *hdd_ap_ctx;
6662 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306663 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006664 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006665 *concurrent_chnl_same = true;
6666
6667 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6668 status =
6669 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
6670 roam_profile,
6671 scan_cache,
6672 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306673 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006674 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006675 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
6676 if (hdd_ap_ctx->operatingChannel != channel_id) {
6677 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306678 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006679 FL("channels are different"));
6680 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006681 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006682 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
6683 if (hdd_ap_ctx->operatingChannel != channel_id) {
6684 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306685 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006686 FL("channels are different"));
6687 }
6688 }
6689 } else {
6690 /*
6691 * Lets handle worst case scenario here, Scan cache lookup is
6692 * failed so we have to stop the SAP to avoid any channel
6693 * discrepancy between SAP's channel and STA's channel.
6694 * Return the status as failure so caller function could know
6695 * that scan look up is failed.
6696 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306697 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006698 FL("Finding AP from scan cache failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306699 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006700 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306701 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006702}
6703
6704#ifdef WLAN_FEATURE_MBSSID
6705/**
6706 * wlan_hdd_stop_sap() - This function stops bss of SAP.
6707 * @ap_adapter: SAP adapter
6708 *
6709 * This function will process the stopping of sap adapter.
6710 *
6711 * Return: None
6712 */
6713void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
6714{
6715 hdd_ap_ctx_t *hdd_ap_ctx;
6716 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306717 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006718 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006719
6720 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306721 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006722 FL("ap_adapter is NULL here"));
6723 return;
6724 }
6725
6726 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6727 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6728 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306729 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006730 FL("HDD context is not valid"));
6731 return;
6732 }
6733 mutex_lock(&hdd_ctx->sap_lock);
6734 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08006735 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006736 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
6737 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306738 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006739 FL("Now doing SAP STOPBSS"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306740 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306741 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006742 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05306743 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306744 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006745 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306746 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006747 mutex_unlock(&hdd_ctx->sap_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306748 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006749 FL("SAP Stop Failed"));
6750 return;
6751 }
6752 }
6753 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08006754 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006755 ap_adapter->sessionId);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306756 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006757 FL("SAP Stop Success"));
6758 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306759 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006760 FL("Can't stop ap because its not started"));
6761 }
6762 mutex_unlock(&hdd_ctx->sap_lock);
6763 return;
6764}
6765
6766/**
6767 * wlan_hdd_start_sap() - this function starts bss of SAP.
6768 * @ap_adapter: SAP adapter
6769 *
6770 * This function will process the starting of sap adapter.
6771 *
6772 * Return: None
6773 */
6774void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
6775{
6776 hdd_ap_ctx_t *hdd_ap_ctx;
6777 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306778 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006779 hdd_context_t *hdd_ctx;
6780 tsap_Config_t *sap_config;
6781
6782 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306783 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006784 FL("ap_adapter is NULL here"));
6785 return;
6786 }
6787
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006788 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07006789 hdd_err("SoftAp role has not been enabled");
6790 return;
6791 }
6792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006793 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6794 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6795 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6796 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
6797
6798 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306799 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006800 FL("HDD context is not valid"));
6801 return;
6802 }
6803 mutex_lock(&hdd_ctx->sap_lock);
6804 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
6805 goto end;
6806
6807 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
6808 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
6809 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
6810 goto end;
6811 }
6812
6813 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
6814 &hdd_ap_ctx->sapConfig,
6815 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306816 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006817 goto end;
6818
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306819 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006820 FL("Waiting for SAP to start"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306821 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006822 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306823 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306824 hddLog(QDF_TRACE_LEVEL_ERROR, FL("SAP Start failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006825 goto end;
6826 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306827 hddLog(QDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006828 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006829 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006830 ap_adapter->sessionId);
6831 hostapd_state->bCommit = true;
6832
6833end:
6834 mutex_unlock(&hdd_ctx->sap_lock);
6835 return;
6836}
6837#endif
6838
6839/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08006840 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
6841 * mac scan config
6842 * @status: Status of set antenna mode
6843 *
6844 * Callback on setting the dual mac configuration
6845 *
6846 * Return: None
6847 */
6848void wlan_hdd_soc_set_antenna_mode_cb(
6849 enum set_antenna_mode_status status)
6850{
6851 hdd_context_t *hdd_ctx;
6852
6853 hdd_info("Status: %d", status);
6854
6855 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6856 if (0 != wlan_hdd_validate_context(hdd_ctx))
6857 return;
6858
6859 /* Signal the completion of set dual mac config */
6860 complete(&hdd_ctx->set_antenna_mode_cmpl);
6861}
6862
6863/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006864 * hdd_get_fw_version() - Get FW version
6865 * @hdd_ctx: pointer to HDD context.
6866 * @major_spid: FW version - major spid.
6867 * @minor_spid: FW version - minor spid
6868 * @ssid: FW version - ssid
6869 * @crmid: FW version - crmid
6870 *
6871 * This function is called to get the firmware build version stored
6872 * as part of the HDD context
6873 *
6874 * Return: None
6875 */
6876void hdd_get_fw_version(hdd_context_t *hdd_ctx,
6877 uint32_t *major_spid, uint32_t *minor_spid,
6878 uint32_t *siid, uint32_t *crmid)
6879{
6880 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
6881 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
6882 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
6883 *crmid = hdd_ctx->target_fw_version & 0x7fff;
6884}
6885
6886#ifdef QCA_CONFIG_SMP
6887/**
6888 * wlan_hdd_get_cpu() - get cpu_index
6889 *
6890 * Return: cpu_index
6891 */
6892int wlan_hdd_get_cpu(void)
6893{
6894 int cpu_index = get_cpu();
6895 put_cpu();
6896 return cpu_index;
6897}
6898#endif
6899
6900/**
6901 * hdd_get_fwpath() - get framework path
6902 *
6903 * This function is used to get the string written by
6904 * userspace to start the wlan driver
6905 *
6906 * Return: string
6907 */
6908const char *hdd_get_fwpath(void)
6909{
6910 return fwpath.string;
6911}
6912
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006913/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006914 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006915 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006916 * This function initilizes CDS global context with the help of cds_init. This
6917 * has to be the first function called after probe to get a valid global
6918 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006919 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006920 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006921 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006922int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006923{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006924 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006925 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006926
6927#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6928 wlan_logging_sock_init_svc();
6929#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006930 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006931
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006932 if (p_cds_context == NULL) {
6933 hdd_alert("Failed to allocate CDS context");
6934 ret = -ENOMEM;
6935 goto err_out;
6936 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006937
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006938 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006939
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006940err_out:
6941 return ret;
6942}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006943
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006944/**
6945 * hdd_deinit() - Deinitialize Driver
6946 *
6947 * This function frees CDS global context with the help of cds_deinit. This
6948 * has to be the last function call in remove callback to free the global
6949 * context.
6950 */
6951void hdd_deinit(void)
6952{
6953 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006954
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006955#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6956 wlan_logging_sock_deinit_svc();
6957#endif
6958}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006959
6960#ifdef QCA_WIFI_3_0_ADRASTEA
6961#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
6962#else
6963#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
6964#endif
6965
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006966/**
6967 * __hdd_module_init - Module init helper
6968 *
6969 * Module init helper function used by both module and static driver.
6970 *
6971 * Return: 0 for success, errno on failure
6972 */
6973static int __hdd_module_init(void)
6974{
6975 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006976
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006977 pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
6978 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006979
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306980 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006981
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006982 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006983
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006984 ret = wlan_hdd_register_driver();
6985 if (ret) {
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006986 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006987 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006988 }
6989
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306990 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006991
6992 return 0;
6993out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306994 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006995 return ret;
6996}
6997
6998/**
6999 * __hdd_module_exit - Module exit helper
7000 *
7001 * Module exit helper function used by both module and static driver.
7002 */
7003static void __hdd_module_exit(void)
7004{
7005 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
7006 QWLAN_VERSIONSTR);
7007
7008 wlan_hdd_unregister_driver();
7009
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307010 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007011
7012 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007013}
7014
7015/**
7016 * hdd_module_init() - Init Function
7017 *
7018 * This is the driver entry point (invoked when module is loaded using insmod)
7019 *
7020 * Return: 0 for success, non zero for failure
7021 */
7022#ifdef MODULE
7023static int __init hdd_module_init(void)
7024{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007025 return __hdd_module_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007026}
7027#else /* #ifdef MODULE */
7028static int __init hdd_module_init(void)
7029{
7030 /* Driver initialization is delayed to fwpath_changed_handler */
7031 return 0;
7032}
7033#endif /* #ifdef MODULE */
7034
7035/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007036 * hdd_module_exit() - Exit function
7037 *
7038 * This is the driver exit point (invoked when module is unloaded using rmmod)
7039 *
7040 * Return: None
7041 */
7042static void __exit hdd_module_exit(void)
7043{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007044 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007045}
7046
7047#ifdef MODULE
7048static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
7049{
7050 return param_set_copystring(kmessage, kp);
7051}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007052#else /* #ifdef MODULE */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007053
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007054/**
7055 * kickstart_driver() - driver entry point
7056 *
7057 * This is the driver entry point
7058 * - delayed driver initialization when driver is statically linked
7059 * - invoked when module parameter fwpath is modified from userspace to signal
7060 * initializing the WLAN driver or when con_mode is modified from userspace
7061 * to signal a switch in operating mode
7062 *
7063 * Return: 0 for success, non zero for failure
7064 */
7065static int kickstart_driver(void)
7066{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007067 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007068
7069 if (!wlan_hdd_inited) {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007070 ret = __hdd_module_init();
7071 wlan_hdd_inited = ret ? 0 : 1;
7072
7073 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007074 }
7075
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007076 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007077
7078 msleep(200);
7079
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007080 ret = __hdd_module_init();
7081
7082 wlan_hdd_inited = ret ? 0 : 1;
7083
7084 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007085}
7086
7087/**
7088 * fwpath_changed_handler() - Handler Function
7089 *
7090 * Handle changes to the fwpath parameter
7091 *
7092 * Return: 0 for success, non zero for failure
7093 */
7094static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
7095{
7096 int ret;
7097
7098 ret = param_set_copystring(kmessage, kp);
7099 if (0 == ret)
7100 ret = kickstart_driver();
7101 return ret;
7102}
7103
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007104#ifdef QCA_WIFI_FTM
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007105/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007106 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007107 *
7108 * Handler function for module param con_mode when it is changed by userspace
7109 * Dynamically linked - do nothing
7110 * Statically linked - exit and init driver, as in rmmod and insmod
7111 *
7112 * Return -
7113 */
7114static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
7115{
7116 int ret;
7117
7118 ret = param_set_int(kmessage, kp);
7119 if (0 == ret)
7120 ret = kickstart_driver();
7121 return ret;
7122}
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007123#endif /* QCA_WIFI_FTM */
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007124#endif /* #ifdef MODULE */
7125
7126/**
7127 * hdd_get_conparam() - driver exit point
7128 *
7129 * This is the driver exit point (invoked when module is unloaded using rmmod)
7130 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05307131 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007132 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05307133enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007134{
Anurag Chouhan6d760662016-02-20 16:05:43 +05307135 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007136}
7137
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007138void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007139{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007140 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007141}
7142
Komal Seelamc11bb222016-01-27 18:57:10 +05307143#ifdef WLAN_FEATURE_LPSS
7144static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
7145{
7146 return hdd_ctx->config->enable_lpass_support;
7147}
7148#else
7149static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
7150{
7151 return false;
7152}
7153#endif
7154
7155/**
Komal Seelamec702b02016-02-24 18:42:16 +05307156 * hdd_update_ol_config - API to update ol configuration parameters
7157 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05307158 *
Komal Seelamc11bb222016-01-27 18:57:10 +05307159 * Return: void
7160 */
Komal Seelamec702b02016-02-24 18:42:16 +05307161static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05307162{
Komal Seelamec702b02016-02-24 18:42:16 +05307163 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307164 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05307165
Komal Seelamec702b02016-02-24 18:42:16 +05307166 if (!ol_ctx)
7167 return;
7168
7169 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
7170 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
7171 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
7172 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
7173 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
7174
7175 ol_init_ini_config(ol_ctx, &cfg);
7176}
7177
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007178#ifdef FEATURE_RUNTIME_PM
7179/**
7180 * hdd_populate_runtime_cfg() - populate runtime configuration
7181 * @hdd_ctx: hdd context
7182 * @cfg: pointer to the configuration memory being populated
7183 *
7184 * Return: void
7185 */
7186static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7187 struct hif_config_info *cfg)
7188{
7189 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
7190 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
7191}
7192#else
7193static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7194 struct hif_config_info *cfg)
7195{
7196}
7197#endif
7198
Komal Seelamec702b02016-02-24 18:42:16 +05307199/**
7200 * hdd_update_hif_config - API to update HIF configuration parameters
7201 * @hdd_ctx: HDD Context
7202 *
7203 * Return: void
7204 */
7205static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
7206{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307207 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05307208 struct hif_config_info cfg;
7209
7210 if (!scn)
7211 return;
7212
7213 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007214 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05307215 hif_init_ini_config(scn, &cfg);
7216}
7217
7218/**
7219 * hdd_update_config() - Initialize driver per module ini parameters
7220 * @hdd_ctx: HDD Context
7221 *
7222 * API is used to initialize all driver per module configuration parameters
7223 * Return: void
7224 */
7225void hdd_update_config(hdd_context_t *hdd_ctx)
7226{
7227 hdd_update_ol_config(hdd_ctx);
7228 hdd_update_hif_config(hdd_ctx);
Komal Seelamc11bb222016-01-27 18:57:10 +05307229}
7230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007231/* Register the module init/exit functions */
7232module_init(hdd_module_init);
7233module_exit(hdd_module_exit);
7234
7235MODULE_LICENSE("Dual BSD/GPL");
7236MODULE_AUTHOR("Qualcomm Atheros, Inc.");
7237MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
7238
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007239#if !defined(MODULE) && defined(QCA_WIFI_FTM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007240module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
7241 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007242#else
7243module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007244#endif
7245
7246module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
7247 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
7248
7249module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
7250
7251module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
7252
7253module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);