blob: a9722789d7145ff57fa6e666427609546f87449f [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"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091
92#include "wlan_hdd_ocb.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080093#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094#endif /* FEATURE_WLAN_CH_AVOID */
95
96#include "wlan_hdd_nan.h"
97#include "wlan_hdd_debugfs.h"
98#include "wlan_hdd_driver_ops.h"
99#include "epping_main.h"
100#include "wlan_hdd_memdump.h"
101
102#include <wlan_hdd_ipa.h>
103#include "hif.h"
104#include "wma.h"
105#include "cds_concurrency.h"
106#include "wlan_hdd_green_ap.h"
Yuanyuan Liuedcbc302015-12-02 10:39:51 -0800107#include "platform_icnss.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530108#include "bmi.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800109
110#ifdef MODULE
111#define WLAN_MODULE_NAME module_name(THIS_MODULE)
112#else
113#define WLAN_MODULE_NAME "wlan"
114#endif
115
116#ifdef TIMER_MANAGER
117#define TIMER_MANAGER_STR " +TIMER_MANAGER"
118#else
119#define TIMER_MANAGER_STR ""
120#endif
121
122#ifdef MEMORY_DEBUG
123#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
124#else
125#define MEMORY_DEBUG_STR ""
126#endif
127
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128/* the Android framework expects this param even though we don't use it */
129#define BUF_LEN 20
130static char fwpath_buffer[BUF_LEN];
131static struct kparam_string fwpath = {
132 .string = fwpath_buffer,
133 .maxlen = BUF_LEN,
134};
135
136static char *country_code;
137static int enable_11d = -1;
138static int enable_dfs_chan_scan = -1;
139
140#ifndef MODULE
141static int wlan_hdd_inited;
142#endif
143
144/*
145 * spinlock for synchronizing asynchronous request/response
146 * (full description of use in wlan_hdd_main.h)
147 */
148DEFINE_SPINLOCK(hdd_context_lock);
149
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530150static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
152#define WOW_MAX_FILTER_LISTS 1
153#define WOW_MAX_FILTERS_PER_LIST 4
154#define WOW_MIN_PATTERN_SIZE 6
155#define WOW_MAX_PATTERN_SIZE 64
156
157#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
158static const struct wiphy_wowlan_support wowlan_support_reg_init = {
159 .flags = WIPHY_WOWLAN_ANY |
160 WIPHY_WOWLAN_MAGIC_PKT |
161 WIPHY_WOWLAN_DISCONNECT |
162 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
163 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
164 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
165 WIPHY_WOWLAN_4WAY_HANDSHAKE |
166 WIPHY_WOWLAN_RFKILL_RELEASE,
167 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
168 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
169 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
170};
171#endif
172
173/* internal function declaration */
174
175struct sock *cesium_nl_srv_sock;
176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
178void wlan_hdd_auto_shutdown_cb(void);
179#endif
180
181/**
182 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
183 * @vdev_id: vdev_id
184 * @action: action type
185 * @reason: reason type
186 *
187 * Return: none
188 */
189void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
190 enum netif_action_type action, enum netif_reason_type reason)
191{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530192 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193 hdd_adapter_t *adapter;
194
195 if (!hdd_ctx) {
196 hdd_err("hdd ctx is NULL");
197 return;
198 }
199 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
200
201 wlan_hdd_netif_queue_control(adapter, action, reason);
202 return;
203}
204
205/*
206 * Store WLAN driver version info in a global variable such that crash debugger
207 * can extract it from driver debug symbol and crashdump for post processing
208 */
209uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
210
211/**
212 * hdd_device_mode_to_string() - return string conversion of device mode
213 * @device_mode: device mode
214 *
215 * This utility function helps log string conversion of device mode.
216 *
217 * Return: string conversion of device mode, if match found;
218 * "Unknown" otherwise.
219 */
220const char *hdd_device_mode_to_string(uint8_t device_mode)
221{
222 switch (device_mode) {
223 CASE_RETURN_STRING(WLAN_HDD_INFRA_STATION);
224 CASE_RETURN_STRING(WLAN_HDD_SOFTAP);
225 CASE_RETURN_STRING(WLAN_HDD_P2P_CLIENT);
226 CASE_RETURN_STRING(WLAN_HDD_P2P_GO);
227 CASE_RETURN_STRING(WLAN_HDD_FTM);
228 CASE_RETURN_STRING(WLAN_HDD_IBSS);
229 CASE_RETURN_STRING(WLAN_HDD_P2P_DEVICE);
230 CASE_RETURN_STRING(WLAN_HDD_OCB);
231 default:
232 return "Unknown";
233 }
234}
235
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530236/**
237 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
238 * @adapter: HDD adapter
239 * @chan_number: Channel number
240 * @chan_bw: Bandwidth
241 *
242 * Checks if the given bandwidth is valid for the given channel number.
243 *
244 * Return: 0 for success, non-zero for failure
245 */
246int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
247 uint32_t chan_number,
248 phy_ch_width chan_bw)
249{
250 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
251 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
252 bool found = false;
253 tHalHandle hal;
254
255 hal = WLAN_HDD_GET_HAL_CTX(adapter);
256 if (!hal) {
257 hdd_err("Invalid HAL context");
258 return -EINVAL;
259 }
260
261 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
262 hdd_err("No valid channel list");
263 return -EOPNOTSUPP;
264 }
265
266 for (i = 0; i < len; i++) {
267 if (chan[i] == chan_number) {
268 found = true;
269 break;
270 }
271 }
272
273 if (found == false) {
274 hdd_err("Channel not in driver's valid channel list");
275 return -EOPNOTSUPP;
276 }
277
278 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
279 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
280 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
281 return -EINVAL;
282 }
283
284 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
285 if (chan_bw == CH_WIDTH_80MHZ) {
286 hdd_err("BW80 not possible in 2.4GHz band");
287 return -EINVAL;
288 }
289 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
290 (chan_bw != CH_WIDTH_MAX)) {
291 hdd_err("Only BW20 possible on channel 14");
292 return -EINVAL;
293 }
294 }
295
296 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
297 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
298 (chan_bw != CH_WIDTH_MAX)) {
299 hdd_err("Only BW20 possible on channel 165");
300 return -EINVAL;
301 }
302 }
303
304 return 0;
305}
306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800307static int __hdd_netdev_notifier_call(struct notifier_block *nb,
308 unsigned long state, void *data)
309{
310#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
311 struct netdev_notifier_info *dev_notif_info = data;
312 struct net_device *dev = dev_notif_info->dev;
313#else
314 struct net_device *dev = data;
315#endif
316 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
317 hdd_context_t *hdd_ctx;
318
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800319 ENTER_DEV(dev);
320
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321 /* Make sure that this callback corresponds to our device. */
322 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
323 return NOTIFY_DONE;
324
325 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
326 (adapter->dev != dev)) {
327 hddLog(LOGE, FL("device adapter is not matching!!!"));
328 return NOTIFY_DONE;
329 }
330
331 if (!dev->ieee80211_ptr) {
332 hddLog(LOGE, FL("ieee80211_ptr is NULL!!!"));
333 return NOTIFY_DONE;
334 }
335
336 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
337 if (NULL == hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530338 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HDD Context Null Pointer"));
339 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340 return NOTIFY_DONE;
341 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800342 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343 return NOTIFY_DONE;
344
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530345 hddLog(QDF_TRACE_LEVEL_INFO, FL("%s New Net Device State = %lu"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800346 dev->name, state);
347
348 switch (state) {
349 case NETDEV_REGISTER:
350 break;
351
352 case NETDEV_UNREGISTER:
353 break;
354
355 case NETDEV_UP:
356 sme_ch_avoid_update_req(hdd_ctx->hHal);
357 break;
358
359 case NETDEV_DOWN:
360 break;
361
362 case NETDEV_CHANGE:
363 if (true == adapter->isLinkUpSvcNeeded)
364 complete(&adapter->linkup_event_var);
365 break;
366
367 case NETDEV_GOING_DOWN:
368 if (adapter->scan_info.mScanPending != false) {
369 unsigned long rc;
370 INIT_COMPLETION(adapter->scan_info.
371 abortscan_event_var);
372 hdd_abort_mac_scan(adapter->pHddCtx,
373 adapter->sessionId,
374 eCSR_SCAN_ABORT_DEFAULT);
375 rc = wait_for_completion_timeout(
376 &adapter->scan_info.abortscan_event_var,
377 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
378 if (!rc) {
379 hddLog(LOGE,
380 FL("Timeout occurred while waiting for abortscan"));
381 }
382 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530383 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 FL("Scan is not Pending from user"));
385 }
386 break;
387
388 default:
389 break;
390 }
391
392 return NOTIFY_DONE;
393}
394
395/**
396 * hdd_netdev_notifier_call() - netdev notifier callback function
397 * @nb: pointer to notifier block
398 * @state: state
399 * @ndev: ndev pointer
400 *
401 * Return: 0 on success, error number otherwise.
402 */
403static int hdd_netdev_notifier_call(struct notifier_block *nb,
404 unsigned long state,
405 void *ndev)
406{
407 int ret;
408
409 cds_ssr_protect(__func__);
410 ret = __hdd_netdev_notifier_call(nb, state, ndev);
411 cds_ssr_unprotect(__func__);
412
413 return ret;
414}
415
416struct notifier_block hdd_netdev_notifier = {
417 .notifier_call = hdd_netdev_notifier_call,
418};
419
420/* variable to hold the insmod parameters */
421static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800422
423/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530426/**
427 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
428 * @ch_width: NL channel width
429 *
430 * Converts the NL channel width to the driver's internal representation
431 *
432 * Return: Converted channel width. In case of non matching NL channel width,
433 * CH_WIDTH_MAX will be returned.
434 */
435phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
436{
437 switch (ch_width) {
438 case NL80211_CHAN_WIDTH_20_NOHT:
439 case NL80211_CHAN_WIDTH_20:
440 return CH_WIDTH_20MHZ;
441 case NL80211_CHAN_WIDTH_40:
442 return CH_WIDTH_40MHZ;
443 break;
444 case NL80211_CHAN_WIDTH_80:
445 return CH_WIDTH_80MHZ;
446 case NL80211_CHAN_WIDTH_80P80:
447 return CH_WIDTH_80P80MHZ;
448 case NL80211_CHAN_WIDTH_160:
449 return CH_WIDTH_160MHZ;
450 case NL80211_CHAN_WIDTH_5:
451 case NL80211_CHAN_WIDTH_10:
452 default:
453 hdd_err("Invalid channel width %d, setting to default",
454 ch_width);
455 return CH_WIDTH_MAX;
456 }
457}
458
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530459/* wlan_hdd_find_opclass() - Find operating class for a channel
460 * @hal: handler to HAL
461 * @channel: channel id
462 * @bw_offset: bandwidth offset
463 *
464 * Function invokes sme api to find the operating class
465 *
466 * Return: operating class
467 */
468uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
469 uint8_t bw_offset)
470{
471 uint8_t opclass = 0;
472
473 sme_get_opclass(hal, channel, bw_offset, &opclass);
474 return opclass;
475}
476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530478 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800479 * @moduleId: Module whose trace level is being configured
480 * @bitmask: Bitmask of log levels to be enabled
481 *
482 * Called immediately after the cfg.ini is read in order to configure
483 * the desired trace levels.
484 *
485 * Return: None
486 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530487static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530489 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490
491 /*
492 * if the bitmask is the default value, then a bitmask was not
493 * specified in cfg.ini, so leave the logging level alone (it
494 * will remain at the "compiled in" default value)
495 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530496 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 return;
498 }
499
500 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530501 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502
503 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530504 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 while (0 != bitmask) {
506 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530507 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 }
509 level++;
510 bitmask >>= 1;
511 }
512}
513
514/**
515 * wlan_hdd_validate_context() - check the HDD context
516 * @hdd_ctx: HDD context pointer
517 *
518 * Return: 0 if the context is valid. Error code otherwise
519 */
520int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
521{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
523 hddLog(LOGE, FL("HDD context is Null"));
524 return -ENODEV;
525 }
526
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800527 if (cds_is_driver_recovering()) {
528 hdd_err("Recovery in Progress. State: 0x%x Ignore!!!",
529 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530 return -EAGAIN;
531 }
532
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800533 if (cds_is_load_or_unload_in_progress()) {
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800534 hdd_err("Unloading/Loading in Progress. Ignore!!!: 0x%x",
535 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536 return -EAGAIN;
537 }
538 return 0;
539}
540
541void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
542{
543 hdd_adapter_t *adapter = NULL;
544 hdd_station_ctx_t *pHddStaCtx = NULL;
545 eCsrPhyMode phyMode;
546 struct hdd_config *cfg_param = NULL;
547
548 if (NULL == hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530549 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HDD Context is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 return;
551 }
552
553 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
554 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530555 hddLog(QDF_TRACE_LEVEL_FATAL, FL("adapter is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 return;
557 }
558
559 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
560
561 cfg_param = hdd_ctx->config;
562 if (NULL == cfg_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530563 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564 FL("cfg_params not available !!"));
565 return;
566 }
567
568 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
569
570 if (!hdd_ctx->isVHT80Allowed) {
571 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
572 (eCSR_DOT11_MODE_11ac == phyMode) ||
573 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530574 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575 FL("Setting phymode to 11n!!"));
576 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
577 eCSR_DOT11_MODE_11n);
578 }
579 } else {
580 /*
581 * New country Supports 11ac as well resetting value back from
582 * .ini
583 */
584 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
585 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
586 dot11Mode));
587 return;
588 }
589
590 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
591 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
592 || (eCSR_CFG_DOT11_MODE_11AC ==
593 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530594 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595
596 /* need to issue a disconnect to CSR. */
597 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530598 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599 adapter->sessionId,
600 eCSR_DISCONNECT_REASON_UNSPECIFIED);
601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530602 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 unsigned long rc;
604
605 rc = wait_for_completion_timeout(
606 &adapter->disconnect_comp_var,
607 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
608 if (!rc)
609 hddLog(LOGE,
610 FL("failure waiting for disconnect_comp_var"));
611 }
612 }
613}
614
615/**
616 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
617 * @hdd_adapter_t Hdd adapter.
618 *
619 * This function sets the IBSS power save config parameters to WMA
620 * which will send it to firmware if FW supports IBSS power save
621 * before vdev start.
622 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530623 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 * on failure.
625 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530626QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627{
628 int ret;
629 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
630
631 if (hdd_ctx == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530632 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633 FL("HDD context is null"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530634 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 }
636
637 ret = wma_cli_set_command(adapter->sessionId,
638 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
639 hdd_ctx->config->ibssATIMWinSize,
640 VDEV_CMD);
641 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530642 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643 FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530644 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645 }
646
647 ret = wma_cli_set_command(adapter->sessionId,
648 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
649 hdd_ctx->config->isIbssPowerSaveAllowed,
650 VDEV_CMD);
651 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530652 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"),
654 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530655 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 }
657
658 ret = wma_cli_set_command(adapter->sessionId,
659 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
660 hdd_ctx->config->
661 isIbssPowerCollapseAllowed, VDEV_CMD);
662 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530663 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"),
665 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530666 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 }
668
669 ret = wma_cli_set_command(adapter->sessionId,
670 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
671 hdd_ctx->config->isIbssAwakeOnTxRx,
672 VDEV_CMD);
673 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530674 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 }
678
679 ret = wma_cli_set_command(adapter->sessionId,
680 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
681 hdd_ctx->config->ibssInactivityCount,
682 VDEV_CMD);
683 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530684 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530686 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 }
688
689 ret = wma_cli_set_command(adapter->sessionId,
690 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
691 hdd_ctx->config->ibssTxSpEndInactivityTime,
692 VDEV_CMD);
693 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530694 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 FL(
696 "WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d"
697 ),
698 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 }
701
702 ret = wma_cli_set_command(adapter->sessionId,
703 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
704 hdd_ctx->config->ibssPsWarmupTime,
705 VDEV_CMD);
706 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530707 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"),
709 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530710 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 }
712
713 ret = wma_cli_set_command(adapter->sessionId,
714 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
715 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
716 VDEV_CMD);
717 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530718 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 FL(
720 "WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d"
721 ),
722 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530723 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 }
725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530726 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727}
728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729#define INTF_MACADDR_MASK 0x7
730
731/**
732 * hdd_update_macaddr() - update mac address
733 * @config: hdd configuration
734 * @hw_macaddr: mac address
735 *
736 * Mac address for multiple virtual interface is found as following
737 * i) The mac address of the first interface is just the actual hw mac address.
738 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
739 * define the mac address for the remaining interfaces and locally
740 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
741 * supported virtual interfaces, right now this is 0x07 (meaning 8
742 * interface).
743 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
744 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
745 *
746 * Return: None
747 */
748void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530749 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800750{
751 int8_t i;
752 uint8_t macaddr_b3, tmp_br3;
753
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530754 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530755 QDF_MAC_ADDR_SIZE);
756 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530757 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530758 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 macaddr_b3 = config->intfMacAddr[i].bytes[3];
760 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
761 INTF_MACADDR_MASK;
762 macaddr_b3 += tmp_br3;
763
764 /* XOR-ing bit-24 of the mac address. This will give enough
765 * mac address range before collision
766 */
767 macaddr_b3 ^= (1 << 7);
768
769 /* Set locally administered bit */
770 config->intfMacAddr[i].bytes[0] |= 0x02;
771 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530772 hddLog(QDF_TRACE_LEVEL_INFO, "config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 MAC_ADDRESS_STR, i,
774 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
775 }
776}
777
778static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
779 struct wma_tgt_services *cfg)
780{
781 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782
783 /* Set up UAPSD */
784 config->apUapsdEnabled &= cfg->uapsd;
785
786#ifdef WLAN_FEATURE_11AC
787 /* 11AC mode support */
788 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
789 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
790 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
791#endif /* #ifdef WLAN_FEATURE_11AC */
792
793 /* ARP offload: override user setting if invalid */
794 config->fhostArpOffload &= cfg->arp_offload;
795
796#ifdef FEATURE_WLAN_SCAN_PNO
797 /* PNO offload */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530798 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 FL("PNO Capability in f/w = %d"), cfg->pno_offload);
800 if (cfg->pno_offload)
801 config->PnoOffload = true;
802#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800803#ifdef FEATURE_WLAN_TDLS
804 config->fEnableTDLSSupport &= cfg->en_tdls;
805 config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan;
806 config->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta;
807 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
808 config->fEnableTDLSSleepSta = true;
809 } else {
810 config->fEnableTDLSSleepSta = false;
811 }
812#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813#ifdef WLAN_FEATURE_ROAM_OFFLOAD
814 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
815#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700816 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817
818}
819
820static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
821 struct wma_tgt_ht_cap *cfg)
822{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530823 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824 uint32_t value, val32;
825 uint16_t val16;
826 struct hdd_config *pconfig = hdd_ctx->config;
827 tSirMacHTCapabilityInfo *phtCapInfo;
828 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
829 uint8_t enable_tx_stbc;
830
831 /* check and update RX STBC */
832 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
833 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
834
835 /* get the MPDU density */
836 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
837
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530838 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530839 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840 FL("could not get MPDU DENSITY"));
841 value = 0;
842 }
843
844 /*
845 * MPDU density:
846 * override user's setting if value is larger
847 * than the one supported by target
848 */
849 if (value > cfg->mpdu_density) {
850 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
851 cfg->mpdu_density);
852
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530853 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530854 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855 FL("could not set MPDU DENSITY to CCM"));
856 }
857
858 /* get the HT capability info */
859 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530860 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530861 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862 FL("could not get HT capability info"));
863 return;
864 }
865 val16 = (uint16_t) val32;
866 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
867
868 /* Set the LDPC capability */
869 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
870
871 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
872 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
873
874 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
875 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
876
877 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
878 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
879
880 enable_tx_stbc = pconfig->enableTxSTBC;
881
882 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
883 pconfig->enable2x2 = 1;
884 } else {
885 pconfig->enable2x2 = 0;
886 enable_tx_stbc = 0;
887
888 /* 1x1 */
889 /* Update Rx Highest Long GI data Rate */
890 if (sme_cfg_set_int(hdd_ctx->hHal,
891 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
892 HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530893 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 hddLog(LOGE,
895 FL(
896 "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"
897 ));
898 }
899
900 /* Update Tx Highest Long GI data Rate */
901 if (sme_cfg_set_int
902 (hdd_ctx->hHal,
903 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
904 HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530905 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 hddLog(LOGE,
907 FL(
908 "Could not pass on HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"
909 ));
910 }
911 }
912 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
913 enable_tx_stbc = 0;
914 phtCapInfo->txSTBC = enable_tx_stbc;
915
916 val32 = val16;
917 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530918 if (status != QDF_STATUS_SUCCESS)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530919 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920 FL("could not set HT capability to CCM"));
921#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
922 value = SIZE_OF_SUPPORTED_MCS_SET;
923 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530924 &value) == QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530925 hddLog(QDF_TRACE_LEVEL_INFO, FL("Read MCS rate set"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926
927 if (pconfig->enable2x2) {
928 for (value = 0; value < cfg->num_rf_chains; value++)
929 mcs_set[value] =
930 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
931
932 status =
933 sme_cfg_set_str(hdd_ctx->hHal,
934 WNI_CFG_SUPPORTED_MCS_SET,
935 mcs_set,
936 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530937 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530938 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 FL("could not set MCS SET to CCM"));
940 }
941 }
942#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
943}
944
945#ifdef WLAN_FEATURE_11AC
946static 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
1227 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1228 band_5g->vht_cap.cap |=
1229 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1230 }
1231 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1232 band_5g->vht_cap.cap |=
1233 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1234 }
1235
1236 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1237 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1238
1239 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1240 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1241 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1242 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1243
1244 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1245 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1246
1247 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1248 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1249 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1250 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1251 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1252 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1253
1254 band_5g->vht_cap.cap |=
1255 (cfg->vht_max_ampdu_len_exp <<
1256 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1257
1258 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1259 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1260 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1261 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1262 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1263 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1264 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1265 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1266
1267 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1268 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1269
1270}
1271#endif /* #ifdef WLAN_FEATURE_11AC */
1272
1273void hdd_update_tgt_cfg(void *context, void *param)
1274{
1275 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1276 struct wma_tgt_cfg *cfg = param;
1277 uint8_t temp_band_cap;
1278
1279 /* first store the INI band capability */
1280 temp_band_cap = hdd_ctx->config->nBandCapability;
1281
1282 hdd_ctx->config->nBandCapability = cfg->band_cap;
1283
1284 /* now overwrite the target band capability with INI
1285 setting if INI setting is a subset */
1286
1287 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1288 (temp_band_cap != eCSR_BAND_ALL))
1289 hdd_ctx->config->nBandCapability = temp_band_cap;
1290 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1291 (temp_band_cap != eCSR_BAND_ALL) &&
1292 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301293 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294 FL("ini BandCapability not supported by the target"));
1295 }
1296
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001297 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1299 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1300 }
1301
1302 /* This can be extended to other configurations like ht, vht cap... */
1303
Anurag Chouhanc5548422016-02-24 18:33:27 +05301304 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1306 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301307 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308 FL(
1309 "Invalid MAC passed from target, using MAC from ini file"
1310 MAC_ADDRESS_STR),
1311 MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes));
1312 }
1313
1314 hdd_ctx->target_fw_version = cfg->target_fw_version;
1315
1316 hdd_ctx->max_intf_count = cfg->max_intf_count;
1317
1318#ifdef WLAN_FEATURE_LPSS
1319 hdd_ctx->lpss_support = cfg->lpss_support;
1320#endif
1321
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001322 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1325 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1326
1327 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1328
1329#ifdef WLAN_FEATURE_11AC
1330 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
1331#endif /* #ifdef WLAN_FEATURE_11AC */
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001332 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001333 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001334 hdd_info(FL("fine_time_meas_cap: 0x%x"),
1335 hdd_ctx->config->fine_time_meas_cap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336}
1337
1338/**
1339 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1340 * @context: HDD context pointer
1341 * @param: HDD radar indication pointer
1342 *
1343 * This function is invoked when a radar in found on the
1344 * SAP current operating channel and Data Tx from netif
1345 * has to be stopped to honor the DFS regulations.
1346 * Actions: Stop the netif Tx queues,Indicate Radar present
1347 * in HDD context for future usage.
1348 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301349 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301351bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352{
1353 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1354 struct wma_dfs_radar_ind *hdd_radar_event =
1355 (struct wma_dfs_radar_ind *)param;
1356 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1357 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301358 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301360 if (!hdd_ctx || !hdd_radar_event ||
1361 hdd_ctx->config->disableDFSChSwitch)
1362 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001363
1364 if (true == hdd_radar_event->dfs_radar_status) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301365 mutex_lock(&hdd_ctx->dfs_lock);
1366 if (hdd_ctx->dfs_radar_found) {
1367 /*
1368 * Application already triggered channel switch
1369 * on current channel, so return here.
1370 */
1371 mutex_unlock(&hdd_ctx->dfs_lock);
1372 return false;
1373 }
1374
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 hdd_ctx->dfs_radar_found = true;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301376 mutex_unlock(&hdd_ctx->dfs_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377
1378 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301379 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 adapter = adapterNode->pAdapter;
1381 if (WLAN_HDD_SOFTAP == adapter->device_mode ||
1382 WLAN_HDD_P2P_GO == adapter->device_mode) {
1383 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1384 dfs_cac_block_tx = true;
1385 }
1386
1387 status = hdd_get_next_adapter(hdd_ctx,
1388 adapterNode,
1389 &pNext);
1390 adapterNode = pNext;
1391 }
1392 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301393
1394 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396
1397/**
1398 * hdd_is_valid_mac_address() - validate MAC address
1399 * @pMacAddr: Pointer to the input MAC address
1400 *
1401 * This function validates whether the given MAC address is valid or not
1402 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1403 * where X is the hexa decimal digit character and separated by ':'
1404 * This algorithm works even if MAC address is not separated by ':'
1405 *
1406 * This code checks given input string mac contains exactly 12 hexadecimal
1407 * digits and a separator colon : appears in the input string only after
1408 * an even number of hex digits.
1409 *
1410 * Return: 1 for valid and 0 for invalid
1411 */
1412bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1413{
1414 int xdigit = 0;
1415 int separator = 0;
1416 while (*pMacAddr) {
1417 if (isxdigit(*pMacAddr)) {
1418 xdigit++;
1419 } else if (':' == *pMacAddr) {
1420 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1421 break;
1422
1423 ++separator;
1424 } else {
1425 /* Invalid MAC found */
1426 return 0;
1427 }
1428 ++pMacAddr;
1429 }
1430 return xdigit == 12 && (separator == 5 || separator == 0);
1431}
1432
1433/**
1434 * __hdd_open() - HDD Open function
1435 * @dev: Pointer to net_device structure
1436 *
1437 * This is called in response to ifconfig up
1438 *
1439 * Return: 0 for success; non-zero for failure
1440 */
1441static int __hdd_open(struct net_device *dev)
1442{
1443 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1444 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1445 int ret;
1446
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001447 ENTER_DEV(dev);
1448
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301449 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 adapter->sessionId, adapter->device_mode));
1451
1452 ret = wlan_hdd_validate_context(hdd_ctx);
1453 if (0 != ret) {
1454 hddLog(LOGE, FL("HDD context is not valid"));
1455 return ret;
1456 }
1457
1458 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1459 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
1460 hddLog(LOG1, FL("Enabling Tx Queues"));
1461 /* Enable TX queues only when we are connected */
1462 wlan_hdd_netif_queue_control(adapter,
1463 WLAN_START_ALL_NETIF_QUEUE,
1464 WLAN_CONTROL_PATH);
1465 }
1466
1467 return ret;
1468}
1469
1470/**
1471 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1472 * @dev: Pointer to net_device structure
1473 *
1474 * This is called in response to ifconfig up
1475 *
1476 * Return: 0 for success; non-zero for failure
1477 */
1478int hdd_open(struct net_device *dev)
1479{
1480 int ret;
1481
1482 cds_ssr_protect(__func__);
1483 ret = __hdd_open(dev);
1484 cds_ssr_unprotect(__func__);
1485
1486 return ret;
1487}
1488
1489/**
1490 * __hdd_stop() - HDD stop function
1491 * @dev: Pointer to net_device structure
1492 *
1493 * This is called in response to ifconfig down
1494 *
1495 * Return: 0 for success; non-zero for failure
1496 */
1497static int __hdd_stop(struct net_device *dev)
1498{
1499 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1500 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1501 int ret;
1502
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001503 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001504
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301505 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506 adapter->sessionId, adapter->device_mode));
1507
1508 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301509 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001510 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511
1512 /* Nothing to be done if the interface is not opened */
1513 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301514 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001515 FL("NETDEV Interface is not OPENED"));
1516 return -ENODEV;
1517 }
1518
1519 /* Make sure the interface is marked as closed */
1520 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301521 hddLog(QDF_TRACE_LEVEL_INFO, FL("Disabling OS Tx queues"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001522
1523 /*
1524 * Disable TX on the interface, after this hard_start_xmit() will not
1525 * be called on that interface
1526 */
1527 hddLog(LOG1, FL("Disabling queues"));
1528 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1529 WLAN_CONTROL_PATH);
1530
1531 /*
1532 * The interface is marked as down for outside world (aka kernel)
1533 * But the driver is pretty much alive inside. The driver needs to
1534 * tear down the existing connection on the netdev (session)
1535 * cleanup the data pipes and wait until the control plane is stabilized
1536 * for this interface. The call also needs to wait until the above
1537 * mentioned actions are completed before returning to the caller.
1538 * Notice that the hdd_stop_adapter is requested not to close the session
1539 * That is intentional to be able to scan if it is a STA/P2P interface
1540 */
1541 hdd_stop_adapter(hdd_ctx, adapter, false);
1542
1543 /* DeInit the adapter. This ensures datapath cleanup as well */
1544 hdd_deinit_adapter(hdd_ctx, adapter, true);
1545
1546 EXIT();
1547 return 0;
1548}
1549
1550/**
1551 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
1552 * @dev: pointer to net_device structure
1553 *
1554 * This is called in response to ifconfig down
1555 *
1556 * Return: 0 for success and error number for failure
1557 */
1558int hdd_stop(struct net_device *dev)
1559{
1560 int ret;
1561
1562 cds_ssr_protect(__func__);
1563 ret = __hdd_stop(dev);
1564 cds_ssr_unprotect(__func__);
1565
1566 return ret;
1567}
1568
1569/**
1570 * __hdd_uninit() - HDD uninit function
1571 * @dev: Pointer to net_device structure
1572 *
1573 * This is called during the netdev unregister to uninitialize all data
1574 * associated with the device
1575 *
1576 * Return: None
1577 */
1578static void __hdd_uninit(struct net_device *dev)
1579{
1580 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1581
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001582 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583
1584 do {
1585 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1586 hddLog(LOGP, FL("Invalid magic"));
1587 break;
1588 }
1589
1590 if (NULL == adapter->pHddCtx) {
1591 hddLog(LOGP, FL("NULL hdd_ctx"));
1592 break;
1593 }
1594
1595 if (dev != adapter->dev) {
1596 hddLog(LOGP, FL("Invalid device reference"));
1597 /*
1598 * we haven't validated all cases so let this go for
1599 * now
1600 */
1601 }
1602
1603 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
1604
1605 /* after uninit our adapter structure will no longer be valid */
1606 adapter->dev = NULL;
1607 adapter->magic = 0;
1608 } while (0);
1609
1610 EXIT();
1611}
1612
1613/**
1614 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
1615 * @dev: pointer to net_device structure
1616 *
1617 * This is called during the netdev unregister to uninitialize all data
1618 * associated with the device
1619 *
1620 * Return: none
1621 */
1622static void hdd_uninit(struct net_device *dev)
1623{
1624 cds_ssr_protect(__func__);
1625 __hdd_uninit(dev);
1626 cds_ssr_unprotect(__func__);
1627}
1628
1629/**
1630 * __hdd_set_mac_address() - set the user specified mac address
1631 * @dev: Pointer to the net device.
1632 * @addr: Pointer to the sockaddr.
1633 *
1634 * This function sets the user specified mac address using
1635 * the command ifconfig wlanX hw ether <mac adress>.
1636 *
1637 * Return: 0 for success, non zero for failure
1638 */
1639static int __hdd_set_mac_address(struct net_device *dev, void *addr)
1640{
1641 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1642 hdd_context_t *hdd_ctx;
1643 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301644 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001645 int ret;
1646
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001647 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648
1649 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1650 ret = wlan_hdd_validate_context(hdd_ctx);
1651 if (0 != ret)
1652 return ret;
1653
1654 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1655 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1656
1657 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301658 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001659}
1660
1661/**
1662 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
1663 * function from SSR
1664 * @dev: pointer to net_device structure
1665 * @addr: Pointer to the sockaddr
1666 *
1667 * This function sets the user specified mac address using
1668 * the command ifconfig wlanX hw ether <mac adress>.
1669 *
1670 * Return: 0 for success.
1671 */
1672static int hdd_set_mac_address(struct net_device *dev, void *addr)
1673{
1674 int ret;
1675
1676 cds_ssr_protect(__func__);
1677 ret = __hdd_set_mac_address(dev, addr);
1678 cds_ssr_unprotect(__func__);
1679
1680 return ret;
1681}
1682
1683uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
1684{
1685 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301686 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001687 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
1688 break;
1689 }
1690
Anurag Chouhan6d760662016-02-20 16:05:43 +05301691 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001692 return NULL;
1693
1694 hdd_ctx->config->intfAddrMask |= (1 << i);
1695 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
1696}
1697
1698void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
1699{
1700 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301701 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001702 if (!memcmp(releaseAddr,
1703 &hdd_ctx->config->intfMacAddr[i].bytes[0],
1704 6)) {
1705 hdd_ctx->config->intfAddrMask &= ~(1 << i);
1706 break;
1707 }
1708 }
1709 return;
1710}
1711
1712#ifdef WLAN_FEATURE_PACKET_FILTERING
1713/**
1714 * __hdd_set_multicast_list() - set the multicast address list
1715 * @dev: Pointer to the WLAN device.
1716 * @skb: Pointer to OS packet (sk_buff).
1717 *
1718 * This funciton sets the multicast address list.
1719 *
1720 * Return: None
1721 */
1722static void __hdd_set_multicast_list(struct net_device *dev)
1723{
1724 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1725 int mc_count;
1726 int i = 0, status;
1727 struct netdev_hw_addr *ha;
1728 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1729 static const uint8_t ipv6_router_solicitation[]
1730 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
1731
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001732 ENTER_DEV(dev);
1733
Anurag Chouhan6d760662016-02-20 16:05:43 +05301734 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05301735 return;
1736
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301738 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001739 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001740
1741 if (dev->flags & IFF_ALLMULTI) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301742 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743 FL("allow all multicast frames"));
1744 adapter->mc_addr_list.mc_cnt = 0;
1745 } else {
1746 mc_count = netdev_mc_count(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301747 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748 FL("mc_count = %u"), mc_count);
1749 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301750 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001751 FL(
1752 "No free filter available; allow all multicast frames"
1753 ));
1754 adapter->mc_addr_list.mc_cnt = 0;
1755 return;
1756 }
1757
1758 adapter->mc_addr_list.mc_cnt = mc_count;
1759
1760 netdev_for_each_mc_addr(ha, dev) {
1761 if (i == mc_count)
1762 break;
1763 /*
1764 * Skip following addresses:
1765 * 1)IPv6 router solicitation address
1766 * 2)Any other address pattern if its set during
1767 * RXFILTER REMOVE driver command based on
1768 * addr_filter_pattern
1769 */
1770 if ((!memcmp(ha->addr, ipv6_router_solicitation,
1771 ETH_ALEN)) ||
1772 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
1773 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08001774 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 MAC_ADDR_ARRAY(ha->addr));
1776 adapter->mc_addr_list.mc_cnt--;
1777 continue;
1778 }
1779
1780 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
1781 ETH_ALEN);
1782 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
1783 ETH_ALEN);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301784 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001785 FL("mlist[%d] = " MAC_ADDRESS_STR), i,
1786 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
1787 i++;
1788 }
1789 }
1790 if (hdd_ctx->config->active_mode_offload) {
1791 hdd_info("enable mc filtering");
1792 wlan_hdd_set_mc_addr_list(adapter, true);
1793 } else {
1794 hdd_info("skip mc filtering enable it during cfg80211 suspend");
1795 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301796 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001797 return;
1798}
1799
1800/**
1801 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
1802 * @dev: pointer to net_device
1803 *
1804 * Return: none
1805 */
1806static void hdd_set_multicast_list(struct net_device *dev)
1807{
1808 cds_ssr_protect(__func__);
1809 __hdd_set_multicast_list(dev);
1810 cds_ssr_unprotect(__func__);
1811}
1812#endif
1813
1814/**
1815 * hdd_select_queue() - used by Linux OS to decide which queue to use first
1816 * @dev: Pointer to the WLAN device.
1817 * @skb: Pointer to OS packet (sk_buff).
1818 *
1819 * This function is registered with the Linux OS for network
1820 * core to decide which queue to use first.
1821 *
1822 * Return: ac, Queue Index/access category corresponding to UP in IP header
1823 */
1824static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
1825#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
1826 , void *accel_priv
1827#endif
1828#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1829 , select_queue_fallback_t fallback
1830#endif
1831)
1832{
1833 return hdd_wmm_select_queue(dev, skb);
1834}
1835
1836static struct net_device_ops wlan_drv_ops = {
1837 .ndo_open = hdd_open,
1838 .ndo_stop = hdd_stop,
1839 .ndo_uninit = hdd_uninit,
1840 .ndo_start_xmit = hdd_hard_start_xmit,
1841 .ndo_tx_timeout = hdd_tx_timeout,
1842 .ndo_get_stats = hdd_get_stats,
1843 .ndo_do_ioctl = hdd_ioctl,
1844 .ndo_set_mac_address = hdd_set_mac_address,
1845 .ndo_select_queue = hdd_select_queue,
1846#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848#endif
1849};
1850
1851void hdd_set_station_ops(struct net_device *pWlanDev)
1852{
1853 pWlanDev->netdev_ops = &wlan_drv_ops;
1854}
1855
1856static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
1857 tSirMacAddr macAddr,
1858 const char *name)
1859{
1860 struct net_device *pWlanDev = NULL;
1861 hdd_adapter_t *adapter = NULL;
1862 /*
1863 * cfg80211 initialization and registration....
1864 */
1865 pWlanDev =
1866 alloc_netdev_mq(sizeof(hdd_adapter_t), name,
1867#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
1868 NET_NAME_UNKNOWN,
1869#endif
1870 ether_setup,
1871 NUM_TX_QUEUES);
1872
1873 if (pWlanDev != NULL) {
1874
1875 /* Save the pointer to the net_device in the HDD adapter */
1876 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
1877
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301878 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879
1880 adapter->dev = pWlanDev;
1881 adapter->pHddCtx = hdd_ctx;
1882 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1883
1884 init_completion(&adapter->session_open_comp_var);
1885 init_completion(&adapter->session_close_comp_var);
1886 init_completion(&adapter->disconnect_comp_var);
1887 init_completion(&adapter->linkup_event_var);
1888 init_completion(&adapter->cancel_rem_on_chan_var);
1889 init_completion(&adapter->rem_on_chan_ready_event);
1890 init_completion(&adapter->sta_authorized_event);
1891 init_completion(&adapter->offchannel_tx_event);
1892 init_completion(&adapter->tx_action_cnf_event);
1893#ifdef FEATURE_WLAN_TDLS
1894 init_completion(&adapter->tdls_add_station_comp);
1895 init_completion(&adapter->tdls_del_station_comp);
1896 init_completion(&adapter->tdls_mgmt_comp);
1897 init_completion(&adapter->tdls_link_establish_req_comp);
1898#endif
1899 init_completion(&adapter->change_country_code);
1900
1901
1902 init_completion(&adapter->scan_info.abortscan_event_var);
1903
1904 adapter->offloads_configured = false;
1905 adapter->isLinkUpSvcNeeded = false;
1906 adapter->higherDtimTransition = true;
1907 /* Init the net_device structure */
1908 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1909
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301910 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301912 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 sizeof(tSirMacAddr));
1914 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001915
1916 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
1917 pWlanDev->features |=
1918 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
1919 pWlanDev->features |= NETIF_F_RXCSUM;
1920
Dhanashri Atre83d373d2015-07-28 16:45:59 -07001921 hdd_set_tso_flags(hdd_ctx, pWlanDev);
1922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 hdd_set_station_ops(adapter->dev);
1924
1925 pWlanDev->destructor = free_netdev;
1926 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08001927 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928 adapter->wdev.wiphy = hdd_ctx->wiphy;
1929 adapter->wdev.netdev = pWlanDev;
1930 /* set pWlanDev's parent to underlying device */
1931 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
1932 hdd_wmm_init(adapter);
1933 spin_lock_init(&adapter->pause_map_lock);
1934 }
1935
1936 return adapter;
1937}
1938
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301939QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001940 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941{
1942 struct net_device *pWlanDev = adapter->dev;
1943 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
1944 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301945 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001947 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
1949 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301950 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 FL("Failed:dev_alloc_name"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301952 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 }
1954 }
1955 if (register_netdevice(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301956 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301958 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959 }
1960 } else {
1961 if (register_netdev(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301962 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301964 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 }
1966 }
1967 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
1968
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301969 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970}
1971
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301972static QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973{
1974 hdd_adapter_t *adapter = pContext;
1975
1976 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301977 hddLog(QDF_TRACE_LEVEL_FATAL, FL("NULL adapter"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301978 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 }
1980
1981 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301982 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid magic"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301983 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 }
1985
1986 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
1987
1988#if !defined (CONFIG_CNSS) && \
1989 !defined (WLAN_OPEN_SOURCE)
1990 /*
1991 * need to make sure all of our scheduled work has completed.
1992 * This callback is called from MC thread context, so it is safe to
1993 * to call below flush workqueue API from here.
1994 *
1995 * Even though this is called from MC thread context, if there is a faulty
1996 * work item in the system, that can hang this call forever. So flushing
1997 * this global work queue is not safe; and now we make sure that
1998 * individual work queues are stopped correctly. But the cancel work queue
1999 * is a GPL only API, so the proprietary version of the driver would still
2000 * rely on the global work queue flush.
2001 */
2002 flush_scheduled_work();
2003#endif
2004
2005 /*
2006 * We can be blocked while waiting for scheduled work to be
2007 * flushed, and the adapter structure can potentially be freed, in
2008 * which case the magic will have been reset. So make sure the
2009 * magic is still good, and hence the adapter structure is still
2010 * valid, before signaling completion
2011 */
2012 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2013 complete(&adapter->session_close_comp_var);
2014
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302015 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016}
2017
Krunal Soni8c37e322016-02-03 16:08:37 -08002018/**
2019 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2020 * @adapter: pointer to device adapter
2021 * @type: type of interface
2022 *
2023 * This routine will check the mode of adapter and if it is required then it
2024 * will initialize the TDLS operations
2025 *
2026 * Return: QDF_STATUS
2027 */
2028#ifdef FEATURE_WLAN_TDLS
2029static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2030{
2031 if (QDF_IBSS_MODE != type) {
2032 if (0 != wlan_hdd_tdls_init(adapter)) {
2033 hddLog(LOGE, FL("wlan_hdd_tdls_init failed"));
2034 return QDF_STATUS_E_FAILURE;
2035 }
2036 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2037 }
2038 return QDF_STATUS_SUCCESS;
2039}
2040#else
2041static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2042{
2043 return QDF_STATUS_SUCCESS;
2044}
2045#endif
2046
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302047QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048{
2049 struct net_device *pWlanDev = adapter->dev;
2050 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2051 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302052 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302053 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054 uint32_t type, subType;
2055 unsigned long rc;
2056 int ret_val;
2057
2058 INIT_COMPLETION(adapter->session_open_comp_var);
2059 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
2060 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302061 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 hddLog(LOGE, FL("failed to get vdev type"));
2063 goto error_sme_open;
2064 }
2065 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302066 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002067 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2068 (uint8_t *) &adapter->macAddressCurrent,
2069 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302070 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 hddLog(LOGP,
2072 FL("sme_open_session() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302073 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302074 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 goto error_sme_open;
2076 }
2077 /* Block on a completion variable. Can't wait forever though. */
2078 rc = wait_for_completion_timeout(
2079 &adapter->session_open_comp_var,
2080 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2081 if (!rc) {
2082 hddLog(LOGP,
2083 FL("Session is not opened within timeout period code %ld"),
2084 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302085 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002086 goto error_sme_open;
2087 }
2088
2089 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302090 qdf_ret_status = hdd_register_wext(pWlanDev);
2091 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 hddLog(LOGP,
2093 FL("hdd_register_wext() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302094 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302095 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002096 goto error_register_wext;
2097 }
2098 /* Set the Connection State to Not Connected */
2099 hddLog(LOG1,
2100 FL("Set HDD connState to eConnectionState_NotConnected"));
2101 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2102
2103 /* Set the default operation channel */
2104 pHddStaCtx->conn_info.operationChannel =
2105 hdd_ctx->config->OperatingChannel;
2106
2107 /* Make the default Auth Type as OPEN */
2108 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2109
2110 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302111 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002112 hddLog(LOGP,
2113 FL("hdd_init_tx_rx() failed, status code %08d [x%08x]"),
2114 status, status);
2115 goto error_init_txrx;
2116 }
2117
2118 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2119
2120 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302121 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 hddLog(LOGP,
2123 FL("hdd_wmm_adapter_init() failed, status code %08d [x%08x]"),
2124 status, status);
2125 goto error_wmm_init;
2126 }
2127
2128 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2129
2130 ret_val = wma_cli_set_command(adapter->sessionId,
2131 WMI_PDEV_PARAM_BURST_ENABLE,
2132 hdd_ctx->config->enableSifsBurst,
2133 PDEV_CMD);
2134
2135 if (0 != ret_val) {
2136 hddLog(LOGE,
2137 FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
2138 ret_val);
2139 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002140 status = hdd_check_and_init_tdls(adapter, type);
2141 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302144 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145
2146#ifdef FEATURE_WLAN_TDLS
2147error_tdls_init:
2148 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2149 hdd_wmm_adapter_close(adapter);
2150#endif
2151error_wmm_init:
2152 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2153 hdd_deinit_tx_rx(adapter);
2154error_init_txrx:
2155 hdd_unregister_wext(pWlanDev);
2156error_register_wext:
2157 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2158 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302159 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 adapter->sessionId,
2161 hdd_sme_close_session_callback,
2162 adapter)) {
2163 unsigned long rc;
2164
2165 /*
2166 * Block on a completion variable.
2167 * Can't wait forever though.
2168 */
2169 rc = wait_for_completion_timeout(
2170 &adapter->session_close_comp_var,
2171 msecs_to_jiffies
2172 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2173 if (rc <= 0)
2174 hddLog(LOGE,
2175 FL("Session is not opened within timeout period code %ld"),
2176 rc);
2177 }
2178 }
2179error_sme_open:
2180 return status;
2181}
2182
2183void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2184{
2185 hdd_cfg80211_state_t *cfgState;
2186
2187 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2188
2189 if (NULL != cfgState->buf) {
2190 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 rc = wait_for_completion_timeout(
2192 &adapter->tx_action_cnf_event,
2193 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2194 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302195 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002196 FL("HDD Wait for Action Confirmation Failed!!"));
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302197 /*
2198 * Inform tx status as FAILURE to upper layer and free
2199 * cfgState->buf
2200 */
2201 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 }
2203 }
2204 return;
2205}
2206
2207void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2208 bool rtnl_held)
2209{
2210 ENTER();
2211 switch (adapter->device_mode) {
2212 case WLAN_HDD_INFRA_STATION:
2213 case WLAN_HDD_P2P_CLIENT:
2214 case WLAN_HDD_P2P_DEVICE:
2215 {
2216 if (test_bit
2217 (INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2218 hdd_deinit_tx_rx(adapter);
2219 clear_bit(INIT_TX_RX_SUCCESS,
2220 &adapter->event_flags);
2221 }
2222
2223 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2224 hdd_wmm_adapter_close(adapter);
2225 clear_bit(WMM_INIT_DONE,
2226 &adapter->event_flags);
2227 }
2228
2229 hdd_cleanup_actionframe(hdd_ctx, adapter);
2230 wlan_hdd_tdls_exit(adapter);
2231 break;
2232 }
2233
2234 case WLAN_HDD_SOFTAP:
2235 case WLAN_HDD_P2P_GO:
2236 {
2237
2238 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2239 hdd_wmm_adapter_close(adapter);
2240 clear_bit(WMM_INIT_DONE,
2241 &adapter->event_flags);
2242 }
2243
2244 hdd_cleanup_actionframe(hdd_ctx, adapter);
2245
2246 hdd_unregister_hostapd(adapter, rtnl_held);
2247
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002248 break;
2249 }
2250
2251 default:
2252 break;
2253 }
2254
2255 EXIT();
2256}
2257
2258void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002259 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260{
2261 struct net_device *pWlanDev = NULL;
2262
2263 if (adapter)
2264 pWlanDev = adapter->dev;
2265 else {
2266 hddLog(LOGE, FL("adapter is Null"));
2267 return;
2268 }
2269
2270 hdd_lro_disable(hdd_ctx, adapter);
Rajeev Kumardca5f812016-02-04 17:28:06 -08002271 hdd_debugfs_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 /*
2273 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2274 * the driver is almost closed and cannot handle either control
2275 * messages or data. However, unregister_netdevice() call above will
2276 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2277 * to close the active connections (basically excites control path) which
2278 * is not right. Setting this flag helps hdd_stop() to recognize that
2279 * the interface is closed and restricts any operations on that
2280 */
2281 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2282
2283 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2284 if (rtnl_held) {
2285 unregister_netdevice(pWlanDev);
2286 } else {
2287 unregister_netdev(pWlanDev);
2288 }
2289 /*
2290 * Note that the adapter is no longer valid at this point
2291 * since the memory has been reclaimed
2292 */
2293 }
2294}
2295
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302296QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 tSirMacAddr macAddr)
2298{
2299 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2300 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302301 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302303 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002304 adapter = adapterNode->pAdapter;
2305 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302306 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002307 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302308 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309 }
2310 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2311 adapterNode = pNext;
2312 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302313 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314}
2315hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
2316 const char *iface_name, tSirMacAddr macAddr,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002317 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318{
2319 hdd_adapter_t *adapter = NULL;
2320 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302321 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002322 hdd_cfg80211_state_t *cfgState;
2323 int ret;
2324
2325 hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type);
2326
2327 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
2328 /*
2329 * Max limit reached on the number of vdevs configured by the
2330 * host. Return error
2331 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302332 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 FL(
2334 "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d"
2335 ),
2336 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
2337 return NULL;
2338 }
2339
2340 if (macAddr == NULL) {
2341 /* Not received valid macAddr */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302342 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 FL(
2344 "Unable to add virtual intf: Not able to get valid mac address"
2345 ));
2346 return NULL;
2347 }
2348 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302349 if (QDF_STATUS_E_FAILURE == status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302350 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 "Duplicate MAC addr: " MAC_ADDRESS_STR
2352 " already exists",
2353 MAC_ADDR_ARRAY(macAddr));
2354 return NULL;
2355 }
2356
2357 switch (session_type) {
2358 case WLAN_HDD_INFRA_STATION:
2359 /* Reset locally administered bit if the device mode is STA */
2360 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
2361 /* fall through */
2362 case WLAN_HDD_P2P_CLIENT:
2363 case WLAN_HDD_P2P_DEVICE:
2364 case WLAN_HDD_OCB:
2365 {
2366 adapter =
2367 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2368
2369 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302370 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 FL("failed to allocate adapter for session %d"),
2372 session_type);
2373 return NULL;
2374 }
2375
2376 if (WLAN_HDD_P2P_CLIENT == session_type)
2377 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 else if (WLAN_HDD_P2P_DEVICE == session_type)
2379 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 else
2381 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2382
2383 adapter->device_mode = session_type;
2384
2385 status = hdd_init_station_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302386 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387 goto err_free_netdev;
2388
2389 hdd_lro_enable(hdd_ctx, adapter);
2390
2391 /*
2392 * Workqueue which gets scheduled in IPv4 notification
2393 * callback
2394 */
2395#ifdef CONFIG_CNSS
2396 cnss_init_work(&adapter->ipv4NotifierWorkQueue,
2397 hdd_ipv4_notifier_work_queue);
2398#else
2399 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
2400 hdd_ipv4_notifier_work_queue);
2401#endif
2402
2403#ifdef WLAN_NS_OFFLOAD
2404 /*
2405 * Workqueue which gets scheduled in IPv6
2406 * notification callback.
2407 */
2408#ifdef CONFIG_CNSS
2409 cnss_init_work(&adapter->ipv6NotifierWorkQueue,
2410 hdd_ipv6_notifier_work_queue);
2411#else
2412 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
2413 hdd_ipv6_notifier_work_queue);
2414#endif
2415#endif
2416 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302417 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2419 goto err_lro_cleanup;
2420 }
2421
2422 /* Stop the Interface TX queue. */
2423 hddLog(LOG1, FL("Disabling queues"));
2424 wlan_hdd_netif_queue_control(adapter,
2425 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2426 WLAN_CONTROL_PATH);
2427
2428 hdd_register_tx_flow_control(adapter,
2429 hdd_tx_resume_timer_expired_handler,
2430 hdd_tx_resume_cb);
2431
2432 break;
2433 }
2434
2435 case WLAN_HDD_P2P_GO:
2436 case WLAN_HDD_SOFTAP:
2437 {
2438 adapter =
2439 hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
2440 (uint8_t *) iface_name);
2441 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302442 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 FL("failed to allocate adapter for session %d"),
2444 session_type);
2445 return NULL;
2446 }
2447
2448 adapter->wdev.iftype =
2449 (session_type ==
2450 WLAN_HDD_SOFTAP) ? NL80211_IFTYPE_AP :
2451 NL80211_IFTYPE_P2P_GO;
2452 adapter->device_mode = session_type;
2453
2454 status = hdd_init_ap_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302455 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 goto err_free_netdev;
2457
2458 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302459 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2461 goto err_free_netdev;
2462 }
2463
2464 hddLog(LOG1, FL("Disabling queues"));
2465 wlan_hdd_netif_queue_control(adapter,
2466 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2467 WLAN_CONTROL_PATH);
2468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 break;
2470 }
2471 case WLAN_HDD_FTM:
2472 {
2473 adapter =
2474 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2475
2476 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302477 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 FL("failed to allocate adapter for session %d"),
2479 session_type);
2480 return NULL;
2481 }
2482
2483 /*
2484 * Assign NL80211_IFTYPE_STATION as interface type to resolve
2485 * Kernel Warning message while loading driver in FTM mode.
2486 */
2487 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2488 adapter->device_mode = session_type;
2489 status = hdd_register_interface(adapter, rtnl_held);
2490
2491 hdd_init_tx_rx(adapter);
2492
2493 /* Stop the Interface TX queue. */
2494 hddLog(LOG1, FL("Disabling queues"));
2495 wlan_hdd_netif_queue_control(adapter,
2496 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2497 WLAN_CONTROL_PATH);
2498 }
2499 break;
2500 default:
2501 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302502 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 FL("Invalid session type %d"),
2504 session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302505 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 return NULL;
2507 }
2508 }
2509
2510 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2511 mutex_init(&cfgState->remain_on_chan_ctx_lock);
2512
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302513 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 /* Add it to the hdd's session list. */
2515 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302516 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302518 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 } else {
2520 pHddAdapterNode->pAdapter = adapter;
2521 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
2522 }
2523 }
2524
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302525 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 if (NULL != adapter) {
2527 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
2528 adapter = NULL;
2529 }
2530 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302531 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 }
2533 return NULL;
2534 }
2535
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302536 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002537 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538
2539 /* Initialize the WoWL service */
2540 if (!hdd_init_wowl(adapter)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302541 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 FL("hdd_init_wowl failed"));
2543 goto err_lro_cleanup;
2544 }
2545
2546 /* Adapter successfully added. Increment the vdev count */
2547 hdd_ctx->current_intf_count++;
2548
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302549 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 hdd_ctx->current_intf_count);
2551
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002552 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 }
2554
Anurag Chouhan6d760662016-02-20 16:05:43 +05302555 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 && (!hdd_ctx->config->enable2x2)) {
2557#define HDD_DTIM_1CHAIN_RX_ID 0x5
2558#define HDD_SMPS_PARAM_VALUE_S 29
2559
2560 /*
2561 * Disable DTIM 1 chain Rx when in 1x1, we are passing two value
2562 * as param_id << 29 | param_value.
2563 * Below param_value = 0(disable)
2564 */
2565 ret = wma_cli_set_command(adapter->sessionId,
2566 WMI_STA_SMPS_PARAM_CMDID,
2567 HDD_DTIM_1CHAIN_RX_ID <<
2568 HDD_SMPS_PARAM_VALUE_S,
2569 VDEV_CMD);
2570
2571 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302572 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573 FL("DTIM 1 chain set failed %d"), ret);
2574 goto err_lro_cleanup;
2575 }
2576
2577 ret = wma_cli_set_command(adapter->sessionId,
2578 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2579 hdd_ctx->config->txchainmask1x1,
2580 PDEV_CMD);
2581 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302582 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"),
2584 ret);
2585 goto err_lro_cleanup;
2586 }
2587 ret = wma_cli_set_command(adapter->sessionId,
2588 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2589 hdd_ctx->config->rxchainmask1x1,
2590 PDEV_CMD);
2591 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302592 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"),
2594 ret);
2595 goto err_lro_cleanup;
2596 }
2597#undef HDD_DTIM_1CHAIN_RX_ID
2598#undef HDD_SMPS_PARAM_VALUE_S
2599 }
2600
Anurag Chouhan6d760662016-02-20 16:05:43 +05302601 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 ret = wma_cli_set_command(adapter->sessionId,
2603 WMI_PDEV_PARAM_HYST_EN,
2604 hdd_ctx->config->enableMemDeepSleep,
2605 PDEV_CMD);
2606
2607 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302608 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 FL("WMI_PDEV_PARAM_HYST_EN set failed %d"),
2610 ret);
2611 goto err_lro_cleanup;
2612 }
2613 }
2614
2615#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2616
2617 /* Enable FW logs based on INI configuration */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302618 if ((QDF_GLOBAL_FTM_MODE != cds_get_conparam()) &&
Komal Seelamc11bb222016-01-27 18:57:10 +05302619 (hdd_ctx->config->enable_fw_log)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 uint8_t count = 0;
2621 uint32_t value = 0;
2622 uint8_t numEntries = 0;
2623 uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2624
2625 hdd_ctx->fw_log_settings.dl_type =
2626 hdd_ctx->config->enableFwLogType;
2627 ret = wma_cli_set_command(adapter->sessionId,
2628 WMI_DBGLOG_TYPE,
2629 hdd_ctx->config->enableFwLogType,
2630 DBG_CMD);
2631 if (ret != 0) {
2632 hddLog(LOGE, FL("Failed to enable FW log type ret %d"),
2633 ret);
2634 }
2635
2636 hdd_ctx->fw_log_settings.dl_loglevel =
2637 hdd_ctx->config->enableFwLogLevel;
2638 ret = wma_cli_set_command(adapter->sessionId,
2639 WMI_DBGLOG_LOG_LEVEL,
2640 hdd_ctx->config->enableFwLogLevel,
2641 DBG_CMD);
2642 if (ret != 0) {
2643 hddLog(LOGE, FL("Failed to enable FW log level ret %d"),
2644 ret);
2645 }
2646
2647 hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel,
2648 moduleLoglevel,
2649 &numEntries,
2650 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2651 while (count < numEntries) {
2652 /*
2653 * FW module log level input string looks like below:
2654 * gFwDebugModuleLoglevel=<FW Module ID>,<Log Level>,...
2655 * For example:
2656 * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6
2657 * Above input string means :
2658 * For FW module ID 1 enable log level 0
2659 * For FW module ID 2 enable log level 1
2660 * For FW module ID 3 enable log level 2
2661 * For FW module ID 4 enable log level 3
2662 * For FW module ID 5 enable log level 4
2663 * For FW module ID 6 enable log level 5
2664 * For FW module ID 7 enable log level 6
2665 */
2666
2667 /* FW expects WMI command value =
2668 * Module ID * 10 + Module Log level
2669 */
2670 value = ((moduleLoglevel[count] * 10) +
2671 moduleLoglevel[count + 1]);
2672 ret = wma_cli_set_command(adapter->sessionId,
2673 WMI_DBGLOG_MOD_LOG_LEVEL,
2674 value, DBG_CMD);
2675 if (ret != 0) {
2676 hddLog(LOGE,
2677 FL
2678 ("Failed to enable FW module log level %d ret %d"),
2679 value, ret);
2680 }
2681
2682 count += 2;
2683 }
2684 }
2685#endif
Rajeev Kumardca5f812016-02-04 17:28:06 -08002686 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
2687 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688
2689 return adapter;
2690
2691err_lro_cleanup:
2692 hdd_lro_disable(hdd_ctx, adapter);
2693err_free_netdev:
2694 free_netdev(adapter->dev);
2695 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2696
2697 return NULL;
2698}
2699
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302700QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002701 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702{
2703 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302704 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705
2706 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302707 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302708 hddLog(QDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 status);
2710 return status;
2711 }
2712
2713 while (pCurrent->pAdapter != adapter) {
2714 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302715 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 break;
2717
2718 pCurrent = pNext;
2719 }
2720 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302721 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002722 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
2724
2725 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302726 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727 adapterNode = NULL;
2728
2729 /* Adapter removed. Decrement vdev count */
2730 if (hdd_ctx->current_intf_count != 0)
2731 hdd_ctx->current_intf_count--;
2732
2733 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302734 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302736 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737}
2738
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002739/**
2740 * hdd_close_all_adapters - Close all open adapters
2741 * @hdd_ctx: Hdd context
2742 * rtnl_held: True if RTNL lock held
2743 *
2744 * Close all open adapters.
2745 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302746 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002747 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302748QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749{
2750 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302751 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752
2753 ENTER();
2754
2755 do {
2756 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302757 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002759 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302760 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302762 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002763
2764 EXIT();
2765
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302766 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767}
2768
2769void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
2770{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302771 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 tSirUpdateIE updateIE;
2773 switch (pHostapdAdapter->device_mode) {
2774 case WLAN_HDD_INFRA_STATION:
2775 case WLAN_HDD_P2P_CLIENT:
2776 {
2777 hdd_station_ctx_t *pHddStaCtx =
2778 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002779 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 break;
2781 }
2782 case WLAN_HDD_SOFTAP:
2783 case WLAN_HDD_P2P_GO:
2784 case WLAN_HDD_IBSS:
2785 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002786 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 break;
2788 }
2789 case WLAN_HDD_FTM:
2790 case WLAN_HDD_P2P_DEVICE:
2791 default:
2792 /*
2793 * wlan_hdd_reset_prob_rspies should not have been called
2794 * for these kind of devices
2795 */
2796 hddLog(LOGE,
2797 FL("Unexpected request for the current device type %d"),
2798 pHostapdAdapter->device_mode);
2799 return;
2800 }
2801
Anurag Chouhanc5548422016-02-24 18:33:27 +05302802 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002803 updateIE.smeSessionId = pHostapdAdapter->sessionId;
2804 updateIE.ieBufferlength = 0;
2805 updateIE.pAdditionIEBuffer = NULL;
2806 updateIE.append = true;
2807 updateIE.notify = false;
2808 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
2809 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302810 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
2812 }
2813}
2814
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302815QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 const bool bCloseSession)
2817{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302818 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
2820 union iwreq_data wrqu;
2821 tSirUpdateIE updateIE;
2822 unsigned long rc;
2823
2824 ENTER();
2825
2826 hddLog(LOG1, FL("Disabling queues"));
2827 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2828 WLAN_CONTROL_PATH);
2829 switch (adapter->device_mode) {
2830 case WLAN_HDD_INFRA_STATION:
2831 case WLAN_HDD_P2P_CLIENT:
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302832 case WLAN_HDD_IBSS:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833 case WLAN_HDD_P2P_DEVICE:
2834 if (hdd_conn_is_connected(
2835 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
2836 hdd_is_connecting(
2837 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
2838 if (pWextState->roamProfile.BSSType ==
2839 eCSR_BSS_TYPE_START_IBSS)
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302840 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 sme_roam_disconnect(hdd_ctx->hHal,
2842 adapter->sessionId,
2843 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2844 else
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302845 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 sme_roam_disconnect(hdd_ctx->hHal,
2847 adapter->sessionId,
2848 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2849 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302850 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 rc = wait_for_completion_timeout(
2852 &adapter->disconnect_comp_var,
2853 msecs_to_jiffies
2854 (WLAN_WAIT_TIME_DISCONNECT));
2855 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302856 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857 FL(
2858 "wait on disconnect_comp_var failed"
2859 ));
2860 }
2861 } else {
2862 hddLog(LOGE,
2863 FL(
2864 "failed to post disconnect event to SME"
2865 ));
2866 }
2867 memset(&wrqu, '\0', sizeof(wrqu));
2868 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2869 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
2870 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
2871 NULL);
2872 } else {
2873 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
2874 eCSR_SCAN_ABORT_DEFAULT);
2875 }
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302876 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877
2878#ifdef WLAN_OPEN_SOURCE
2879 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
2880#endif
2881
2882 hdd_deregister_tx_flow_control(adapter);
2883
2884#ifdef WLAN_NS_OFFLOAD
2885#ifdef WLAN_OPEN_SOURCE
2886 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
2887#endif
2888#endif
2889
2890 /*
2891 * It is possible that the caller of this function does not
2892 * wish to close the session
2893 */
2894 if (true == bCloseSession &&
2895 test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2896 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302897 if (QDF_STATUS_SUCCESS ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2899 hdd_sme_close_session_callback,
2900 adapter)) {
2901 /*
2902 * Block on a completion variable. Can't wait
2903 * forever though.
2904 */
2905 rc = wait_for_completion_timeout(
2906 &adapter->session_close_comp_var,
2907 msecs_to_jiffies
2908 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2909 if (!rc) {
2910 hddLog(LOGE,
2911 FL(
2912 "failure waiting for session_close_comp_var"
2913 ));
2914 }
2915 }
2916 }
2917 break;
2918
2919 case WLAN_HDD_SOFTAP:
2920 case WLAN_HDD_P2P_GO:
2921 if (hdd_ctx->config->conc_custom_rule1 &&
2922 (WLAN_HDD_SOFTAP == adapter->device_mode)) {
2923 /*
2924 * Before stopping the sap adapter, lets make sure there
2925 * is no sap restart work pending.
2926 */
2927 cds_flush_work(&hdd_ctx->sap_start_work);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302928 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 FL("Canceled the pending SAP restart work"));
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002930 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 }
2932 /* Any softap specific cleanup here... */
2933 if (adapter->device_mode == WLAN_HDD_P2P_GO)
2934 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
2935
2936 hdd_deregister_tx_flow_control(adapter);
2937
2938 mutex_lock(&hdd_ctx->sap_lock);
2939 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302940 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05302941 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942
2943 /* Stop Bss. */
2944#ifdef WLAN_FEATURE_MBSSID
2945 status = wlansap_stop_bss(
2946 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
2947#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002948 status = wlansap_stop_bss(
2949 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950#endif
2951
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302952 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 hdd_hostapd_state_t *hostapd_state =
2954 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302955 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302956 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302957 qdf_status =
2958 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302959 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 BSS_WAIT_TIMEOUT);
2961
Anurag Chouhance0dc992016-02-16 18:18:03 +05302962 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 hddLog(LOGE,
2964 FL(
2965 "failure waiting for wlansap_stop_bss %d"
2966 ),
Anurag Chouhance0dc992016-02-16 18:18:03 +05302967 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 }
2969 } else {
2970 hddLog(LOGE, FL("failure in wlansap_stop_bss"));
2971 }
2972 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002973 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002974 adapter->device_mode,
2975 adapter->sessionId);
2976
Anurag Chouhanc5548422016-02-24 18:33:27 +05302977 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002978 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979 updateIE.smeSessionId = adapter->sessionId;
2980 updateIE.ieBufferlength = 0;
2981 updateIE.pAdditionIEBuffer = NULL;
2982 updateIE.append = false;
2983 updateIE.notify = false;
2984 /* Probe bcn reset */
2985 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2986 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302987 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002988 hddLog(LOGE,
2989 FL(
2990 "Could not pass on PROBE_RSP_BCN data to PE"
2991 ));
2992 }
2993 /* Assoc resp reset */
2994 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2995 &updateIE,
2996 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302997 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 hddLog(LOGE,
2999 FL(
3000 "Could not pass on ASSOC_RSP data to PE"
3001 ));
3002 }
3003 /* Reset WNI_CFG_PROBE_RSP Flags */
3004 wlan_hdd_reset_prob_rspies(adapter);
3005 kfree(adapter->sessionCtx.ap.beacon);
3006 adapter->sessionCtx.ap.beacon = NULL;
3007 }
3008 mutex_unlock(&hdd_ctx->sap_lock);
3009 break;
3010 case WLAN_HDD_OCB:
3011 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3012 conn_info.staId[0]);
3013 break;
3014 default:
3015 break;
3016 }
3017
3018 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303019 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020}
3021
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303022QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023{
3024 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303025 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003026 hdd_adapter_t *adapter;
3027
3028 ENTER();
3029
3030 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303032 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 adapter = adapterNode->pAdapter;
3034 hdd_stop_adapter(hdd_ctx, adapter, true);
3035 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3036 adapterNode = pNext;
3037 }
3038
3039 EXIT();
3040
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303041 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042}
3043
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303044QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045{
3046 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303047 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 hdd_adapter_t *adapter;
3049
3050 ENTER();
3051
3052 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3053
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303054 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 adapter = adapterNode->pAdapter;
3056 hddLog(LOG1, FL("Disabling queues"));
3057 wlan_hdd_netif_queue_control(adapter,
3058 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3059 WLAN_CONTROL_PATH);
3060
3061 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3062
3063 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003064 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 adapter->sessionId);
3066 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3067 hdd_wmm_adapter_close(adapter);
3068 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3069 }
3070
3071 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3072 adapterNode = pNext;
3073 }
3074
3075 EXIT();
3076
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303077 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078}
3079
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303080QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003081{
3082 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303083 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 hdd_adapter_t *adapter;
3085#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303086 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087#endif
3088 eConnectionState connState;
3089
3090 ENTER();
3091
3092 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3093
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303094 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003095 adapter = adapterNode->pAdapter;
3096
3097 hdd_wmm_init(adapter);
3098
3099 switch (adapter->device_mode) {
3100 case WLAN_HDD_INFRA_STATION:
3101 case WLAN_HDD_P2P_CLIENT:
3102 case WLAN_HDD_P2P_DEVICE:
3103
3104 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3105 ->conn_info.connState;
3106
3107 hdd_init_station_mode(adapter);
3108 /* Open the gates for HDD to receive Wext commands */
3109 adapter->isLinkUpSvcNeeded = false;
3110 adapter->scan_info.mScanPending = false;
3111
3112 /* Indicate disconnect event to supplicant if associated previously */
3113 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003114 eConnectionState_IbssConnected == connState ||
3115 eConnectionState_NotConnected == connState ||
3116 eConnectionState_IbssDisconnected == connState ||
3117 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118 union iwreq_data wrqu;
3119 memset(&wrqu, '\0', sizeof(wrqu));
3120 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3121 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3122 wireless_send_event(adapter->dev, SIOCGIWAP,
3123 &wrqu, NULL);
3124 adapter->sessionCtx.station.
3125 hdd_ReassocScenario = false;
3126
3127 /* indicate disconnected event to nl80211 */
3128 cfg80211_disconnected(adapter->dev,
3129 WLAN_REASON_UNSPECIFIED,
3130 NULL, 0, GFP_KERNEL);
3131 } else if (eConnectionState_Connecting == connState) {
3132 /*
3133 * Indicate connect failure to supplicant if we were in the
3134 * process of connecting
3135 */
3136 cfg80211_connect_result(adapter->dev, NULL,
3137 NULL, 0, NULL, 0,
3138 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3139 GFP_KERNEL);
3140 }
3141
3142 hdd_register_tx_flow_control(adapter,
3143 hdd_tx_resume_timer_expired_handler,
3144 hdd_tx_resume_cb);
3145
3146 break;
3147
3148 case WLAN_HDD_SOFTAP:
3149 /* softAP can handle SSR */
3150 break;
3151
3152 case WLAN_HDD_P2P_GO:
3153#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303154 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155 FL("[SSR] send stop ap to supplicant"));
3156 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3157#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303158 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 FL("[SSR] send restart supplicant"));
3160 /* event supplicant to restart */
3161 cfg80211_del_sta(adapter->dev,
3162 (const u8 *)&bcastMac.bytes[0],
3163 GFP_KERNEL);
3164#endif
3165 break;
3166
3167 default:
3168 break;
3169 }
3170
3171 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3172 adapterNode = pNext;
3173 }
3174
3175 EXIT();
3176
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303177 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178}
3179
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303180QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003181 hdd_adapter_list_node_t **padapterNode)
3182{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303183 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303184 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303185 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3186 (qdf_list_node_t **) padapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303187 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 return status;
3189}
3190
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303191QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 hdd_adapter_list_node_t *adapterNode,
3193 hdd_adapter_list_node_t **pNextAdapterNode)
3194{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303195 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303196 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303197 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3198 (qdf_list_node_t *) adapterNode,
3199 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303201 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 return status;
3203}
3204
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303205QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 hdd_adapter_list_node_t *adapterNode)
3207{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303208 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303209 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303210 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 &adapterNode->node);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303212 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213 return status;
3214}
3215
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303216QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217 hdd_adapter_list_node_t **padapterNode)
3218{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303219 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303220 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303221 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3222 (qdf_list_node_t **) padapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303223 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224 return status;
3225}
3226
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303227QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 hdd_adapter_list_node_t *adapterNode)
3229{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303230 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303231 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303232 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3233 (qdf_list_node_t *) adapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303234 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 return status;
3236}
3237
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303238QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 hdd_adapter_list_node_t *adapterNode)
3240{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303241 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303242 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303243 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3244 (qdf_list_node_t *) adapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303245 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246 return status;
3247}
3248
3249hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3250 tSirMacAddr macAddr)
3251{
3252 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3253 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303254 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255
3256 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3257
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303258 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003259 adapter = adapterNode->pAdapter;
3260
3261 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303262 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 macAddr, sizeof(tSirMacAddr))) {
3264 return adapter;
3265 }
3266 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3267 adapterNode = pNext;
3268 }
3269
3270 return NULL;
3271
3272}
3273
3274hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3275 uint32_t vdev_id)
3276{
3277 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3278 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303279 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303281 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303283 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 adapter = adapterNode->pAdapter;
3285
3286 if (adapter->sessionId == vdev_id)
3287 return adapter;
3288
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303289 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3291 adapterNode = pNext;
3292 }
3293
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303294 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 FL("vdev_id %d does not exist with host"), vdev_id);
3296
3297 return NULL;
3298}
3299
Abhishek Singh7996eb72015-12-30 17:24:02 +05303300/**
3301 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3302 * the sessionid
3303 * @hdd_ctx: hdd context.
3304 * @sme_session_id: sme session is for the adapter to get.
3305 *
3306 * This function is used to get the adapter with provided session id
3307 *
3308 * Return: adapter pointer if found
3309 *
3310 */
3311hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3312 uint32_t sme_session_id)
3313{
3314 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3315 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303316 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303317
3318
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303319 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303320
3321 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303322 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303323 adapter = adapter_node->pAdapter;
3324
3325 if (adapter &&
3326 adapter->sessionId == sme_session_id)
3327 return adapter;
3328
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303329 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303330 hdd_get_next_adapter(hdd_ctx,
3331 adapter_node, &next);
3332 adapter_node = next;
3333 }
3334 return NULL;
3335}
3336
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, device_mode_t mode)
3338{
3339 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3340 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303341 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342
3343 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3344
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303345 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 adapter = adapterNode->pAdapter;
3347
3348 if (adapter && (mode == adapter->device_mode))
3349 return adapter;
3350
3351 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3352 adapterNode = pNext;
3353 }
3354
3355 return NULL;
3356
3357}
3358
3359/**
3360 * hdd_get_operating_channel() - return operating channel of the device mode
3361 * @hdd_ctx: Pointer to the HDD context.
3362 * @mode: Device mode for which operating channel is required.
3363 * Suported modes:
3364 * WLAN_HDD_INFRA_STATION,
3365 * WLAN_HDD_P2P_CLIENT,
3366 * WLAN_HDD_SOFTAP,
3367 * WLAN_HDD_P2P_GO.
3368 *
3369 * This API returns the operating channel of the requested device mode
3370 *
3371 * Return: channel number. "0" id the requested device is not found OR it is
3372 * not connected.
3373 */
3374uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx, device_mode_t mode)
3375{
3376 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303377 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003378 hdd_adapter_t *adapter;
3379 uint8_t operatingChannel = 0;
3380
3381 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3382
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303383 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003384 adapter = adapterNode->pAdapter;
3385
3386 if (mode == adapter->device_mode) {
3387 switch (adapter->device_mode) {
3388 case WLAN_HDD_INFRA_STATION:
3389 case WLAN_HDD_P2P_CLIENT:
3390 if (hdd_conn_is_connected
3391 (WLAN_HDD_GET_STATION_CTX_PTR
3392 (adapter))) {
3393 operatingChannel =
3394 (WLAN_HDD_GET_STATION_CTX_PTR
3395 (adapter))->conn_info.
3396 operationChannel;
3397 }
3398 break;
3399 case WLAN_HDD_SOFTAP:
3400 case WLAN_HDD_P2P_GO:
3401 /* softap connection info */
3402 if (test_bit
3403 (SOFTAP_BSS_STARTED,
3404 &adapter->event_flags))
3405 operatingChannel =
3406 (WLAN_HDD_GET_AP_CTX_PTR
3407 (adapter))->operatingChannel;
3408 break;
3409 default:
3410 break;
3411 }
3412
3413 break; /* Found the device of interest. break the loop */
3414 }
3415
3416 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3417 adapterNode = pNext;
3418 }
3419 return operatingChannel;
3420}
3421
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303422static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423 hdd_ctx)
3424{
3425 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303426 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003427 hdd_adapter_t *adapter;
3428
3429 ENTER();
3430
3431 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3432
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303433 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003434 adapter = adapterNode->pAdapter;
3435 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3436 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3437 (adapter->device_mode == WLAN_HDD_IBSS) ||
3438 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3439 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3440 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3441 wlan_hdd_cfg80211_deregister_frames(adapter);
3442 hdd_unregister_wext(adapter->dev);
3443 }
3444 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3445 adapterNode = pNext;
3446 }
3447
3448 EXIT();
3449
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303450 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451}
3452
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303453QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454{
3455 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303456 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003457 hdd_adapter_t *adapter;
3458
3459 ENTER();
3460
3461 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3462
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303463 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003464 adapter = adapterNode->pAdapter;
3465 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3466 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3467 (adapter->device_mode == WLAN_HDD_IBSS) ||
3468 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3469 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3470 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3471 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3472 eCSR_SCAN_ABORT_DEFAULT);
3473 }
3474 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3475 adapterNode = pNext;
3476 }
3477
3478 EXIT();
3479
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303480 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481}
3482
3483#ifdef WLAN_NS_OFFLOAD
3484/**
3485 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3486 * @hdd_ctx: Pointer to hdd context
3487 *
3488 * Return: None
3489 */
3490static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3491{
3492 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3493
3494 return;
3495}
3496
3497/**
3498 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3499 * @hdd_ctx: Pointer to hdd context
3500 *
3501 * Return: None
3502 */
3503static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3504{
3505 int ret;
3506
3507 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
3508 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3509 if (ret)
3510 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
3511 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003512 hdd_info("Registered IPv6 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513
3514 return;
3515}
3516#else
3517/**
3518 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3519 * @hdd_ctx: Pointer to hdd context
3520 *
3521 * Return: None
3522 */
3523static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3524{
3525}
3526/**
3527 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3528 * @hdd_ctx: Pointer to hdd context
3529 *
3530 * Return: None
3531 */
3532static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3533{
3534}
3535#endif
3536
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003537#ifdef QCA_WIFI_FTM
3538/**
3539 * hdd_disable_ftm() - Disable FTM mode
3540 * @hdd_ctx: HDD context
3541 *
3542 * Helper function to disable FTM mode.
3543 *
3544 * Return: None.
3545 */
3546static void hdd_disable_ftm(hdd_context_t *hdd_ctx)
3547{
3548 hdd_notice("Disabling FTM mode");
3549
3550 if (hdd_ftm_stop(hdd_ctx)) {
3551 hdd_alert("hdd_ftm_stop Failed!");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303552 QDF_ASSERT(0);
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003553 }
3554
3555 hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED;
3556
3557 wlan_hdd_ftm_close(hdd_ctx);
3558
3559 return;
3560}
3561
3562/**
3563 * hdd_enable_ftm() - Enable FTM mode
3564 * @hdd_ctx: HDD context
3565 *
3566 * Helper function to enable FTM mode.
3567 *
3568 * Return: 0 on success and errno on failure.
3569 */
3570int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3571{
3572 int ret;
3573
3574 ret = wlan_hdd_ftm_open(hdd_ctx);
3575 if (ret) {
3576 hdd_alert("wlan_hdd_ftm_open Failed: %d", ret);
3577 goto err_out;
3578 }
3579
3580 ret = hdd_ftm_start(hdd_ctx);
3581
3582 if (ret) {
3583 hdd_alert("hdd_ftm_start Failed: %d", ret);
3584 goto err_ftm_close;
3585 }
3586
3587 ret = wiphy_register(hdd_ctx->wiphy);
3588 if (ret) {
3589 hdd_alert("wiphy register failed: %d", ret);
3590 goto err_ftm_stop;
3591 }
3592
3593 hdd_err("FTM driver loaded");
3594
3595 return 0;
3596
3597err_ftm_stop:
3598 hdd_ftm_stop(hdd_ctx);
3599err_ftm_close:
3600 wlan_hdd_ftm_close(hdd_ctx);
3601err_out:
3602 return ret;
3603
3604}
3605#else
3606int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3607{
3608 hdd_err("Driver built without FTM feature enabled!");
3609
3610 return -ENOTSUPP;
3611}
3612
3613static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { }
3614#endif
3615
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303616#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3617/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003618 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303619 * @hdd_ctx: HDD context
3620 *
3621 * Activates the logging service
3622 *
3623 * Return: Zero in case of success, negative value otherwise
3624 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003625static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303626{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003627 int ret;
3628 struct hdd_config *config = hdd_ctx->config;
3629
3630 if (!config->wlanLoggingEnable)
3631 return 0;
3632
3633 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
3634 config->wlanLoggingNumBuf);
3635 if (ret)
3636 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
3637 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303638}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003639
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303640/**
3641 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
3642 * @hdd_ctx: HDD context
3643 *
3644 * Deactivates the logging service
3645 *
3646 * Return: 0 on deactivating the logging service
3647 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003648static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303649{
3650 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
3651 return wlan_logging_sock_deactivate_svc();
3652
3653 return 0;
3654}
3655#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003656static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303657{
3658 return 0;
3659}
3660
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003661static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303662{
3663 return 0;
3664}
3665#endif
3666
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003668 * hdd_free_context - Free HDD context
3669 * @hdd_ctx: HDD context to be freed.
3670 *
3671 * Free config and HDD context.
3672 *
3673 * Return: None
3674 */
3675static void hdd_free_context(hdd_context_t *hdd_ctx)
3676{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303677 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003678 hdd_logging_sock_deactivate_svc(hdd_ctx);
3679
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303680 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003681 hdd_ctx->config = NULL;
3682
3683 wiphy_free(hdd_ctx->wiphy);
3684}
3685
3686/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003687 * hdd_wlan_exit() - HDD WLAN exit function
3688 * @hdd_ctx: Pointer to the HDD Context
3689 *
3690 * This is the driver exit point (invoked during rmmod)
3691 *
3692 * Return: None
3693 */
3694void hdd_wlan_exit(hdd_context_t *hdd_ctx)
3695{
3696 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303697 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 struct wiphy *wiphy = hdd_ctx->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003699
3700 ENTER();
3701
3702 hddLog(LOGE, FL("Unregister IPv6 notifier"));
3703 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3704 hddLog(LOGE, FL("Unregister IPv4 notifier"));
3705 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3706
3707 hdd_unregister_wext_all_adapters(hdd_ctx);
3708
Anurag Chouhan6d760662016-02-20 16:05:43 +05303709 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003710 hdd_disable_ftm(hdd_ctx);
3711
3712 hdd_alert("FTM driver unloaded");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 goto free_hdd_ctx;
3714 }
3715
3716 /*
3717 * Cancel any outstanding scan requests. We are about to close all
3718 * of our adapters, but an adapter structure is what SME passes back
3719 * to our callback function. Hence if there are any outstanding scan
3720 * requests then there is a race condition between when the adapter
3721 * is closed and when the callback is invoked. We try to resolve that
3722 * race condition here by canceling any outstanding scans before we
3723 * close the adapters.
3724 * Note that the scans may be cancelled in an asynchronous manner, so
3725 * ideally there needs to be some kind of synchronization. Rather than
3726 * introduce a new synchronization here, we will utilize the fact that
3727 * we are about to Request Full Power, and since that is synchronized,
3728 * the expectation is that by the time Request Full Power has completed,
3729 * all scans will be cancelled
3730 */
3731 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3732
3733#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05303734 if (QDF_TIMER_STATE_RUNNING ==
3735 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
3736 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 }
3738
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303739 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303740 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303741 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742 FL("Cannot deallocate Bus bandwidth timer"));
3743 }
3744#endif
3745
3746#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05303747 if (QDF_TIMER_STATE_RUNNING ==
3748 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
3749 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750 }
3751
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303752 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303753 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303754 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003755 FL("Cannot deallocate ACS Skip timer"));
3756 }
3757#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003758
3759 /*
3760 * Powersave Offload Case
3761 * Disable Idle Power Save Mode
3762 */
3763 hdd_set_idle_ps_config(hdd_ctx, false);
3764
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765 /* Unregister the Net Device Notifier */
3766 unregister_netdevice_notifier(&hdd_netdev_notifier);
3767
3768 /*
3769 * Stop all adapters, this will ensure the termination of active
3770 * connections on the interface. Make sure the cds_scheduler is
3771 * still available to handle those control messages
3772 */
3773 hdd_stop_all_adapters(hdd_ctx);
3774
3775 /* Stop all the modules */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303776 qdf_status = cds_disable(p_cds_context);
3777 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303778 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003779 FL("Failed to stop CDS"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303780 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003781 }
3782
3783 /*
3784 * Close the scheduler before calling cds_close to make sure no thread
3785 * is scheduled after the each module close is called i.e after all the
3786 * data structures are freed.
3787 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303788 qdf_status = cds_sched_close(p_cds_context);
3789 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303790 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003791 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303792 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793 }
3794#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3795 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303796 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797#endif
3798 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303799 qdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800
3801 hdd_hostapd_channel_wakelock_deinit(hdd_ctx);
3802
3803 /*
3804 * Close CDS
3805 * This frees pMac(HAL) context. There should not be any call
3806 * that requires pMac access after this.
3807 */
3808 cds_close(p_cds_context);
3809
3810 hdd_wlan_green_ap_deinit(hdd_ctx);
3811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812#ifdef WLAN_KD_READY_NOTIFIER
3813 cnss_diag_notify_wlan_close();
3814 ptt_sock_deactivate_svc();
3815#endif /* WLAN_KD_READY_NOTIFIER */
3816 nl_srv_exit();
3817
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003818 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003819
3820 hdd_ipa_cleanup(hdd_ctx);
3821
3822 /* Free up RoC request queue and flush workqueue */
3823 cds_flush_work(&hdd_ctx->roc_req_work);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303824 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
3825 qdf_list_destroy(&hdd_ctx->hdd_scan_req_q);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303827 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08003828 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003829 /* Proceed and complete the clean up */
3830 }
3831
3832free_hdd_ctx:
3833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834 wiphy_unregister(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003835
3836 hdd_free_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837}
3838
3839void __hdd_wlan_exit(void)
3840{
3841 hdd_context_t *hdd_ctx;
3842
3843 ENTER();
3844
Anurag Chouhan6d760662016-02-20 16:05:43 +05303845 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303847 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003848 EXIT();
3849 return;
3850 }
3851
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003852 /* Check IPA HW Pipe shutdown */
3853 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
3854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855#ifdef WLAN_FEATURE_LPSS
3856 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
3857#endif
3858
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003859 memdump_deinit();
3860
3861#ifdef QCA_PKT_PROTO_TRACE
3862 cds_pkt_proto_trace_close();
3863#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864 /* Do all the cleanup before deregistering the driver */
3865 hdd_wlan_exit(hdd_ctx);
3866 EXIT();
3867}
3868
3869#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3870void hdd_skip_acs_scan_timer_handler(void *data)
3871{
3872 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
3873
3874 hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
3875 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
3876
3877 if (!hdd_ctx->hHal)
3878 return;
3879 sme_scan_flush_result(hdd_ctx->hHal);
3880}
3881#endif
3882
3883#ifdef QCA_HT_2040_COEX
3884/**
3885 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
3886 * @adapter: pointer to adapter
3887 * @staId: station id
3888 * @macAddrSTA: station MAC address
3889 * @channel_type: channel type
3890 *
3891 * This function notifies FW with HT20/HT40 mode
3892 *
3893 * Return: 0 if successful, error number otherwise
3894 */
3895int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303896 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897{
3898 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303899 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003900 hdd_context_t *hdd_ctx = NULL;
3901
3902 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3903
3904 status = wlan_hdd_validate_context(hdd_ctx);
3905 if (0 != status) {
3906 hddLog(LOGE, FL("HDD context is not valid"));
3907 return status;
3908 }
3909 if (!hdd_ctx->hHal)
3910 return -EINVAL;
3911
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303912 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003913 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303914 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 hddLog(LOGE, "Fail to send notification with ht2040 mode");
3916 return -EINVAL;
3917 }
3918
3919 return 0;
3920}
3921#endif
3922
3923/**
3924 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
3925 * @state: state
3926 *
3927 * This function notifies FW with modem power status
3928 *
3929 * Return: 0 if successful, error number otherwise
3930 */
3931int hdd_wlan_notify_modem_power_state(int state)
3932{
3933 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303934 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003935 hdd_context_t *hdd_ctx;
3936
Anurag Chouhan6d760662016-02-20 16:05:43 +05303937 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938 status = wlan_hdd_validate_context(hdd_ctx);
3939 if (0 != status) {
3940 hddLog(LOGE, FL("HDD context is not valid"));
3941 return status;
3942 }
3943 if (!hdd_ctx->hHal)
3944 return -EINVAL;
3945
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303946 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
3947 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003948 hddLog(LOGE,
3949 "Fail to send notification with modem power state %d",
3950 state);
3951 return -EINVAL;
3952 }
3953 return 0;
3954}
3955
3956/**
3957 *
3958 * hdd_post_cds_enable_config() - HDD post cds start config helper
3959 * @adapter - Pointer to the HDD
3960 *
3961 * Return: None
3962 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303963QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003964{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303965 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966
3967 /*
3968 * Send ready indication to the HDD. This will kick off the MAC
3969 * into a 'running' state and should kick off an initial scan.
3970 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303971 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
3972 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303973 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003974 FL(
3975 "sme_hdd_ready_ind() failed with status code %08d [x%08x]"
3976 ),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303977 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303978 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 }
3980
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303981 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982}
3983
3984/* wake lock APIs for HDD */
3985void hdd_prevent_suspend(uint32_t reason)
3986{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303987 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988}
3989
3990void hdd_allow_suspend(uint32_t reason)
3991{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303992 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993}
3994
3995void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
3996{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303997 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998}
3999
4000/**
4001 * hdd_exchange_version_and_caps() - exchange version and capability with target
4002 * @hdd_ctx: Pointer to HDD context
4003 *
4004 * This is the HDD function to exchange version and capability information
4005 * between Host and Target
4006 *
4007 * This function gets reported version of FW.
4008 * It also finds the version of target headers used to compile the host;
4009 * It compares the above two and prints a warning if they are different;
4010 * It gets the SW and HW version string;
4011 * Finally, it exchanges capabilities between host and target i.e. host
4012 * and target exchange a msg indicating the features they support through a
4013 * bitmap
4014 *
4015 * Return: None
4016 */
4017void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4018{
4019
4020 tSirVersionType versionCompiled;
4021 tSirVersionType versionReported;
4022 tSirVersionString versionString;
4023 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304024 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025
4026 memset(&versionCompiled, 0, sizeof(versionCompiled));
4027 memset(&versionReported, 0, sizeof(versionReported));
4028
4029 /* retrieve and display WCNSS version information */
4030 do {
4031
4032 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4033 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304034 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304035 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 FL(
4037 "unable to retrieve WCNSS WLAN compiled version"
4038 ));
4039 break;
4040 }
4041
4042 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4043 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304044 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304045 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046 FL(
4047 "unable to retrieve WCNSS WLAN reported version"
4048 ));
4049 break;
4050 }
4051
4052 if ((versionCompiled.major != versionReported.major) ||
4053 (versionCompiled.minor != versionReported.minor) ||
4054 (versionCompiled.version != versionReported.version) ||
4055 (versionCompiled.revision != versionReported.revision)) {
4056 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4057 "Host expected %u.%u.%u.%u\n",
4058 WLAN_MODULE_NAME,
4059 (int)versionReported.major,
4060 (int)versionReported.minor,
4061 (int)versionReported.version,
4062 (int)versionReported.revision,
4063 (int)versionCompiled.major,
4064 (int)versionCompiled.minor,
4065 (int)versionCompiled.version,
4066 (int)versionCompiled.revision);
4067 } else {
4068 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4069 WLAN_MODULE_NAME,
4070 (int)versionReported.major,
4071 (int)versionReported.minor,
4072 (int)versionReported.version,
4073 (int)versionReported.revision);
4074 }
4075
4076 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4077 versionString,
4078 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304079 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304080 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 FL(
4082 "unable to retrieve WCNSS software version string"
4083 ));
4084 break;
4085 }
4086
4087 pr_info("%s: WCNSS software version %s\n",
4088 WLAN_MODULE_NAME, versionString);
4089
4090 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4091 versionString,
4092 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304093 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304094 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004095 FL(
4096 "unable to retrieve WCNSS hardware version string"
4097 ));
4098 break;
4099 }
4100
4101 pr_info("%s: WCNSS hardware version %s\n",
4102 WLAN_MODULE_NAME, versionString);
4103
4104 /*
4105 * 1.Check if FW version is greater than 0.1.1.0. Only then
4106 * send host-FW capability exchange message
4107 * 2.Host-FW capability exchange message is only present on
4108 * target 1.1 so send the message only if it the target is 1.1
4109 * minor numbers for different target branches:
4110 * 0 -> (1.0)Mainline Build
4111 * 1 -> (1.1)Mainline Build
4112 * 2->(1.04) Stability Build
4113 */
4114 if (((versionReported.major > 0) || (versionReported.minor > 1)
4115 || ((versionReported.minor >= 1)
4116 && (versionReported.version >= 1)))
4117 && ((versionReported.major == 1)
4118 && (versionReported.minor >= 1)))
4119 fwFeatCapsMsgSupported = 1;
4120
4121 if (fwFeatCapsMsgSupported) {
4122 /*
4123 * Indicate if IBSS heartbeat monitoring needs to be
4124 * offloaded
4125 */
4126 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4127 sme_disable_feature_capablity
4128 (IBSS_HEARTBEAT_OFFLOAD);
4129 }
4130
4131 sme_feature_caps_exchange(hdd_ctx->hHal);
4132 }
4133
4134 } while (0);
4135
4136}
4137
4138/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304139QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140{
4141 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4142 hdd_ctx->reg.cc_src);
4143}
4144
4145/**
4146 * hdd_is_5g_supported() - check if hardware supports 5GHz
4147 * @hdd_ctx: Pointer to the hdd context
4148 *
4149 * HDD function to know if hardware supports 5GHz
4150 *
4151 * Return: true if hardware supports 5GHz
4152 */
4153bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4154{
4155 /*
4156 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4157 * then hardware support 5Ghz.
4158 */
4159 return true;
4160}
4161
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304162static QDF_STATUS wlan_hdd_regulatory_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163{
4164 struct wiphy *wiphy;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304165 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004166
4167 wiphy = hdd_ctx->wiphy;
4168
4169 /*
4170 * The channel information in
4171 * wiphy needs to be initialized before wiphy registration
4172 */
4173 status = cds_regulatory_init();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304174 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304175 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176 FL("cds_init_wiphy failed"));
4177 return status;
4178 }
4179
4180#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4181 wiphy->wowlan = &wowlan_support_reg_init;
4182#else
4183 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4184 WIPHY_WOWLAN_MAGIC_PKT |
4185 WIPHY_WOWLAN_DISCONNECT |
4186 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4187 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4188 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4189 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4190 WIPHY_WOWLAN_RFKILL_RELEASE;
4191
4192 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4193 WOW_MAX_FILTERS_PER_LIST);
4194 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4195 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4196#endif
4197
4198 /* registration of wiphy dev with cfg80211 */
4199 if (0 > wlan_hdd_cfg80211_register(wiphy)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304200 hddLog(QDF_TRACE_LEVEL_ERROR, FL("wiphy register failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304201 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 }
4203
4204 return status;
4205}
4206
4207#ifdef MSM_PLATFORM
4208void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004209 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004210{
4211#ifdef CONFIG_CNSS
4212 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004213 uint64_t temp_rx = 0;
4214 uint64_t temp_tx = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215 enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004216 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4217 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218
Mohit Khannae71e2262015-11-10 09:37:24 -08004219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004220 if (total > hdd_ctx->config->busBandwidthHighThreshold)
4221 next_vote_level = CNSS_BUS_WIDTH_HIGH;
4222 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
4223 next_vote_level = CNSS_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004224 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 next_vote_level = CNSS_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004226 else
4227 next_vote_level = CNSS_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004228
Mohit Khannae71e2262015-11-10 09:37:24 -08004229 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4230 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231
4232 if (hdd_ctx->cur_vote_level != next_vote_level) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304233 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004234 FL(
4235 "trigger level %d, tx_packets: %lld, rx_packets: %lld"
4236 ),
4237 next_vote_level, tx_packets, rx_packets);
4238 hdd_ctx->cur_vote_level = next_vote_level;
4239 cnss_request_bus_bandwidth(next_vote_level);
4240 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004241
4242 /* fine-tuning parameters for RX Flows */
4243 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 hdd_ctx->prev_rx = rx_packets;
4246 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004247 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004249 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004250
Mohit Khannae71e2262015-11-10 09:37:24 -08004251 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4252 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253
4254 if (hdd_ctx->cur_rx_level != next_rx_level) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304255 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256 FL("TCP DELACK trigger level %d, average_rx: %llu"),
4257 next_rx_level, temp_rx);
4258 hdd_ctx->cur_rx_level = next_rx_level;
4259 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
4260 &next_rx_level,
4261 sizeof(next_rx_level));
4262 }
4263
Mohit Khannae71e2262015-11-10 09:37:24 -08004264 /* fine-tuning parameters for TX Flows */
4265 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4266 hdd_ctx->prev_tx = tx_packets;
4267 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4268 next_tx_level = WLAN_SVC_TP_HIGH;
4269 else
4270 next_tx_level = WLAN_SVC_TP_LOW;
4271
4272 if (hdd_ctx->cur_tx_level != next_tx_level) {
4273 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4274 next_tx_level, temp_tx);
4275 hdd_ctx->cur_tx_level = next_tx_level;
4276 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4277 &next_tx_level,
4278 sizeof(next_tx_level));
4279 }
4280
4281 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4282 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283 hdd_ctx->hdd_txrx_hist_idx++;
4284 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
4285#endif
4286}
4287
4288#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4289static void hdd_bus_bw_compute_cbk(void *priv)
4290{
4291 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4292 hdd_adapter_t *adapter = NULL;
4293 uint64_t tx_packets = 0, rx_packets = 0;
4294 uint64_t total_tx = 0, total_rx = 0;
4295 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304296 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297 bool connected = false;
4298 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4299
4300 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304301 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302 status =
4303 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4304
4305 if (adapterNode->pAdapter == NULL)
4306 continue;
4307 adapter = adapterNode->pAdapter;
4308
4309 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION ||
4310 adapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
4311 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4312 != eConnectionState_Associated) {
4313
4314 continue;
4315 }
4316
4317 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
4318 adapter->device_mode == WLAN_HDD_P2P_GO) &&
4319 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4320
4321 continue;
4322 }
4323
4324 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4325 adapter->prev_tx_packets);
4326 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4327 adapter->prev_rx_packets);
4328
4329 total_rx += adapter->stats.rx_packets;
4330 total_tx += adapter->stats.tx_packets;
4331
4332 spin_lock_bh(&hdd_ctx->bus_bw_lock);
4333 adapter->prev_tx_packets = adapter->stats.tx_packets;
4334 adapter->prev_rx_packets = adapter->stats.rx_packets;
4335 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
4336 connected = true;
4337 }
4338
4339 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
4340 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
4341 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
4342 rx_packets;
4343 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
4344 tx_packets;
4345
4346 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
4347 tx_packets += (uint64_t)ipa_tx_packets;
4348 rx_packets += (uint64_t)ipa_rx_packets;
4349
4350 if (!connected) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304351 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004352 FL("bus bandwidth timer running in disconnected state"));
4353 return;
4354 }
4355
4356 hdd_cnss_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
4357
4358 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
4359 hdd_ipa_uc_stat_request(adapter, 2);
4360
Anurag Chouhan210db072016-02-22 18:42:15 +05304361 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 hdd_ctx->config->busBandwidthComputeInterval);
4363}
4364#endif
4365
4366/**
4367 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
4368 * @hdd_ctx: hdd context
4369 *
4370 * Return: none
4371 */
4372void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
4373{
4374 int i;
4375
4376#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304377 hddLog(QDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 hdd_ctx->config->busBandwidthComputeInterval,
4379 hdd_ctx->hdd_txrx_hist_idx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304380 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381 "BW High TH: %d BW Med TH: %d BW Low TH: %d",
4382 hdd_ctx->config->busBandwidthHighThreshold,
4383 hdd_ctx->config->busBandwidthMediumThreshold,
4384 hdd_ctx->config->busBandwidthLowThreshold);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304385 hddLog(QDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386 hdd_ctx->config->tcpDelackThresholdHigh,
4387 hdd_ctx->config->tcpDelackThresholdLow);
4388#endif
4389
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304390 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004391 "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 -08004392
4393 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304394 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004395 "%d: %llu, %llu, %llu, %llu, %d, %d, %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
4397 hdd_ctx->hdd_txrx_hist[i].interval_rx,
4398 hdd_ctx->hdd_txrx_hist[i].total_tx,
4399 hdd_ctx->hdd_txrx_hist[i].interval_tx,
4400 hdd_ctx->hdd_txrx_hist[i].next_vote_level,
Mohit Khannae71e2262015-11-10 09:37:24 -08004401 hdd_ctx->hdd_txrx_hist[i].next_rx_level,
4402 hdd_ctx->hdd_txrx_hist[i].next_tx_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403 }
4404 return;
4405}
4406
4407/**
4408 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
4409 * @hdd_ctx: hdd context
4410 *
4411 * Return: none
4412 */
4413void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
4414{
4415 hdd_ctx->hdd_txrx_hist_idx = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304416 qdf_mem_zero(hdd_ctx->hdd_txrx_hist, sizeof(hdd_ctx->hdd_txrx_hist));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417}
4418
4419/**
4420 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
4421 * @pHddCtx: hdd context
4422 *
4423 * Return: none
4424 */
4425void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
4426{
4427
4428 hdd_adapter_t *adapter = NULL;
4429 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304430 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431 int i;
4432
4433 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304434 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435 adapter = adapter_node->pAdapter;
4436
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304437 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004438 "Session_id %d device mode %d current index %d",
4439 adapter->sessionId, adapter->device_mode,
4440 adapter->history_index);
4441
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304442 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443 "Netif queue operation statistics:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304444 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004445 "Current pause_map value %x", adapter->pause_map);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304446 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 " reason_type: pause_cnt: unpause_cnt");
4448
4449 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304450 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451 "%s: %d: %d",
4452 hdd_reason_type_to_string(i),
4453 adapter->queue_oper_stats[i].pause_count,
4454 adapter->queue_oper_stats[i].unpause_count);
4455 }
4456
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304457 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004458 "Netif queue operation history:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304459 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460 "index: time: action_type: reason_type: pause_map");
4461
4462 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304463 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004464 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05304465 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004466 adapter->queue_oper_history[i].time),
4467 hdd_action_type_to_string(
4468 adapter->queue_oper_history[i].netif_action),
4469 hdd_reason_type_to_string(
4470 adapter->queue_oper_history[i].netif_reason),
4471 adapter->queue_oper_history[i].pause_map);
4472 }
4473
4474 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4475 adapter_node = next;
4476 }
4477
4478
4479}
4480
4481/**
4482 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
4483 * @hdd_ctx: hdd context
4484 *
4485 * Return: none
4486 */
4487void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
4488{
4489 hdd_adapter_t *adapter = NULL;
4490 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304491 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492
4493 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304494 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495 adapter = adapter_node->pAdapter;
4496
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304497 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304499 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 sizeof(adapter->queue_oper_history));
4501
4502 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4503 adapter_node = next;
4504 }
4505}
4506
4507/**
4508 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
4509 * @halHandle: Hal handle
4510 * @pContext: Pointer to the context
4511 * @sessionId: Session ID
4512 * @scanId: Scan ID
4513 * @status: Status
4514 *
4515 * This is the callback to be executed when 11d scan is completed to flush out
4516 * the scan results
4517 *
4518 * 11d scan is done during driver load and is a passive scan on all
4519 * channels supported by the device, 11d scans may find some APs on
4520 * frequencies which are forbidden to be used in the regulatory domain
4521 * the device is operating in. If these APs are notified to the supplicant
4522 * it may try to connect to these APs, thus flush out all the scan results
4523 * which are present in SME after 11d scan is done.
4524 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304525 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304527static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 uint8_t sessionId, uint32_t scanId,
4529 eCsrScanStatus status)
4530{
4531 ENTER();
4532
4533 sme_scan_flush_result(halHandle);
4534
4535 EXIT();
4536
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304537 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538}
4539
4540#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4541/**
4542 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
4543 * @hdd_ctx: hdd global context
4544 *
4545 * Return: none
4546 */
4547static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4548{
4549 uint8_t i;
4550
4551 mutex_init(&hdd_ctx->op_ctx.op_lock);
4552 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4553 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4554 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
4555 }
4556}
4557#else
4558static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4559{
4560}
4561#endif
4562
4563#ifdef WLAN_FEATURE_FASTPATH
4564/**
4565 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
4566 * @hdd_cfg: hdd config
4567 * @context: lower layer context
4568 *
4569 * Return: none
4570 */
4571static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4572 void *context)
4573{
4574 if (hdd_cfg->fastpath_enable)
4575 hif_enable_fastpath(context);
4576}
4577#else
4578static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4579 void *context)
4580{
4581}
4582#endif
4583
4584#if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS)
4585/**
4586 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004587 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 * @level: thermal level
4589 *
4590 * Change IPA data path to SW path when the thermal throttle level greater
4591 * than 0, and restore the original data path when throttle level is 0
4592 *
4593 * Return: none
4594 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004595static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004596{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004597 hdd_context_t *hdd_ctx = context;
4598
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599 /* Change IPA to SW path when throttle level greater than 0 */
4600 if (level > THROTTLE_LEVEL_0)
4601 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
4602 else
4603 /* restore original concurrency mode */
4604 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
4605}
4606
4607/**
4608 * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel
4609 * @hdd_ctxt: hdd context pointer
4610 * @ap_adapter: hdd hostapd adapter pointer
4611 *
4612 * Try to find safe channel within preferred channel
4613 * In case auto channel selection enabled
4614 * - Preferred and safe channel should be used
4615 * - If no overlapping, preferred channel should be used
4616 *
4617 * Return: 1: found preferred safe channel
4618 * 0: could not found preferred safe channel
4619 */
4620static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt,
4621 hdd_adapter_t *ap_adapter)
4622{
4623 uint16_t safe_channels[NUM_20MHZ_RF_CHANNELS];
4624 uint16_t safe_channel_count;
4625 uint16_t unsafe_channel_count;
4626 uint8_t is_unsafe = 1;
4627 uint16_t i;
4628 uint16_t channel_loop;
4629
4630 if (!hdd_ctxt || !ap_adapter) {
4631 hdd_err("invalid context/adapter");
4632 return 0;
4633 }
4634
4635 safe_channel_count = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304636 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctxt->unsafe_channel_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4638
4639 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
4640 is_unsafe = 0;
4641 for (channel_loop = 0;
4642 channel_loop < unsafe_channel_count; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004643 if (CDS_CHANNEL_NUM(i) ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644 hdd_ctxt->unsafe_channel_list[channel_loop]) {
4645 is_unsafe = 1;
4646 break;
4647 }
4648 }
4649 if (!is_unsafe) {
4650 safe_channels[safe_channel_count] =
Amar Singhal7a1726a2015-10-14 16:28:11 -07004651 CDS_CHANNEL_NUM(i);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304652 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653 FL("safe channel %d"),
4654 safe_channels[safe_channel_count]);
4655 safe_channel_count++;
4656 }
4657 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304658 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659 FL("perferred range %d - %d"),
4660 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
4661 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
4662 for (i = 0; i < safe_channel_count; i++) {
4663 if (safe_channels[i] >=
4664 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch
4665 && safe_channels[i] <=
4666 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304667 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668 FL("safe channel %d is in perferred range"),
4669 safe_channels[i]);
4670 return 1;
4671 }
4672 }
4673 return 0;
4674}
Abhishek Singh7996eb72015-12-30 17:24:02 +05304675/**
4676 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
4677 * user space
4678 * @frame_ind: Management frame data to be informed.
4679 *
4680 * This function is used to indicate management frame to
4681 * user space
4682 *
4683 * Return: None
4684 *
4685 */
4686void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
4687{
4688 hdd_context_t *hdd_ctx = NULL;
4689 hdd_adapter_t *adapter = NULL;
4690 void *cds_context = NULL;
4691 int i;
4692
4693 /* Get the global VOSS context.*/
4694 cds_context = cds_get_global_context();
4695 if (!cds_context) {
4696 hddLog(LOGE, FL("Global VOS context is Null"));
4697 return;
4698 }
4699 /* Get the HDD context.*/
4700 hdd_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05304701 (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304702
4703 if (0 != wlan_hdd_validate_context(hdd_ctx))
4704 return;
4705
4706 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
4707 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4708 adapter =
4709 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
4710 if (adapter)
4711 break;
4712 }
4713 } else {
4714 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
4715 frame_ind->sessionId);
4716 }
4717
4718 if ((NULL != adapter) &&
4719 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
4720 __hdd_indicate_mgmt_frame(adapter,
4721 frame_ind->frame_len,
4722 frame_ind->frameBuf,
4723 frame_ind->frameType,
4724 frame_ind->rxChan,
4725 frame_ind->rxRssi);
4726 return;
4727}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004728
4729/**
4730 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
4731 * @adapter: HDD adapter pointer
4732 * @indParam: Channel avoid notification parameter
4733 *
4734 * Avoid channel notification from FW handler.
4735 * FW will send un-safe channel list to avoid over wrapping.
4736 * hostapd should not use notified channel
4737 *
4738 * Return: None
4739 */
4740static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
4741{
4742 hdd_adapter_t *hostapd_adapter = NULL;
4743 hdd_context_t *hdd_ctxt;
4744 tSirChAvoidIndType *ch_avoid_indi;
4745 uint8_t range_loop;
Amar Singhala297bfa2015-10-15 15:07:29 -07004746 enum channel_enum channel_loop, start_channel_idx = INVALID_RF_CHANNEL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004747 end_channel_idx = INVALID_RF_CHANNEL;
4748 uint16_t start_channel;
4749 uint16_t end_channel;
4750 v_CONTEXT_t cds_context;
4751 static int restart_sap_in_progress;
4752 tHddAvoidFreqList hdd_avoid_freq_list;
4753 uint32_t i;
4754
4755 /* Basic sanity */
4756 if (!hdd_context || !indi_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304757 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid arguments"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758 return;
4759 }
4760
4761 hdd_ctxt = (hdd_context_t *) hdd_context;
4762 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
4763 cds_context = hdd_ctxt->pcds_context;
4764
4765 /* Make unsafe channel list */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304766 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767 FL("band count %d"),
4768 ch_avoid_indi->avoid_range_count);
4769
4770 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304771 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004772 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
4773 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
4774 ch_avoid_indi->avoid_freq_range[i].start_freq;
4775 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
4776 ch_avoid_indi->avoid_freq_range[i].end_freq;
4777 }
4778 hdd_avoid_freq_list.avoidFreqRangeCount =
4779 ch_avoid_indi->avoid_range_count;
4780
4781 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
4782
4783 /* clear existing unsafe channel cache */
4784 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304785 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 sizeof(hdd_ctxt->unsafe_channel_list));
4787
4788 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
4789 range_loop++) {
4790 if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) {
4791 hddLog(LOGW, FL("LTE Coex unsafe channel list full"));
4792 break;
4793 }
4794
4795 start_channel = ieee80211_frequency_to_channel(
4796 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
4797 end_channel = ieee80211_frequency_to_channel(
4798 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
4799 hddLog(LOG1, "%s : start %d : %d, end %d : %d", __func__,
4800 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
4801 start_channel,
4802 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
4803 end_channel);
4804
4805 /* do not process frequency bands that are not mapped to
4806 * predefined channels
4807 */
4808 if (start_channel == 0 || end_channel == 0)
4809 continue;
4810
4811 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4812 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004813 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004814 ch_avoid_indi->avoid_freq_range[
4815 range_loop].start_freq) {
4816 start_channel_idx = channel_loop;
4817 break;
4818 }
4819 }
4820 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4821 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004822 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 ch_avoid_indi->avoid_freq_range[
4824 range_loop].end_freq) {
4825 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07004826 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004827 ch_avoid_indi->avoid_freq_range[
4828 range_loop].end_freq)
4829 end_channel_idx--;
4830 break;
4831 }
4832 }
4833
4834 if (start_channel_idx == INVALID_RF_CHANNEL ||
4835 end_channel_idx == INVALID_RF_CHANNEL)
4836 continue;
4837
4838 for (channel_loop = start_channel_idx; channel_loop <=
4839 end_channel_idx; channel_loop++) {
4840 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07004841 hdd_ctxt->unsafe_channel_count++] =
4842 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 if (hdd_ctxt->unsafe_channel_count >=
4844 NUM_20MHZ_RF_CHANNELS) {
4845 hddLog(LOGW, FL("LTECoex unsafe ch list full"));
4846 break;
4847 }
4848 }
4849 }
4850
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304851 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004852 FL("number of unsafe channels is %d "),
4853 hdd_ctxt->unsafe_channel_count);
4854
4855 if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list,
4856 hdd_ctxt->unsafe_channel_count)) {
4857 hdd_err("Failed to set unsafe channel");
4858
4859 /* clear existing unsafe channel cache */
4860 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304861 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 sizeof(hdd_ctxt->unsafe_channel_list));
4863
4864 return;
4865 }
4866
4867 for (channel_loop = 0;
4868 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304869 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 FL("channel %d is not safe "),
4871 hdd_ctxt->unsafe_channel_list[channel_loop]);
4872 }
4873
4874 /*
4875 * If auto channel select is enabled
4876 * preferred channel is in safe channel,
4877 * re-start softap interface with safe channel.
4878 * no overlap with preferred channel and safe channel
4879 * do not re-start softap interface
4880 * stay current operating channel.
4881 */
4882 if (hdd_ctxt->unsafe_channel_count) {
4883 hostapd_adapter = hdd_get_adapter(hdd_ctxt, WLAN_HDD_SOFTAP);
4884 if (hostapd_adapter) {
4885 if ((hostapd_adapter->sessionCtx.ap.sapConfig.
4886 acs_cfg.acs_mode) &&
4887 (!hdd_find_prefd_safe_chnl(hdd_ctxt,
4888 hostapd_adapter)))
4889 return;
4890
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304891 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892 FL(
4893 "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d"
4894 ),
4895 hostapd_adapter->sessionCtx.ap.
4896 operatingChannel,
4897 hostapd_adapter->sessionCtx.ap.sapConfig.
4898 channel);
4899 for (channel_loop = 0;
4900 channel_loop < hdd_ctxt->unsafe_channel_count;
4901 channel_loop++) {
4902 if (((hdd_ctxt->
4903 unsafe_channel_list[channel_loop] ==
4904 hostapd_adapter->sessionCtx.ap.
4905 operatingChannel)) &&
4906 (hostapd_adapter->sessionCtx.ap.
4907 sapConfig.acs_cfg.acs_mode
4908 == true) &&
4909 !restart_sap_in_progress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304910 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 FL("Restarting SAP"));
4912 wlan_hdd_send_svc_nlink_msg
4913 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
4914 restart_sap_in_progress = 1;
4915 /*
4916 * current operating channel is un-safe
4917 * channel, restart driver
4918 */
4919 hdd_hostapd_stop(hostapd_adapter->dev);
4920 break;
4921 }
4922 }
4923 }
4924 }
4925 return;
4926}
4927
4928/**
4929 * hdd_init_channel_avoidance() - Initialize channel avoidance
4930 * @hdd_ctx: HDD global context
4931 *
4932 * Initialize the channel avoidance logic by retrieving the unsafe
4933 * channel list from the CNSS platform driver and plumbing the data
4934 * down to the lower layers. Then subscribe to subsequent channel
4935 * avoidance events.
4936 *
4937 * Return: None
4938 */
4939static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4940{
4941 uint16_t unsafe_channel_count;
4942 int index;
4943
4944 cnss_get_wlan_unsafe_channel(hdd_ctx->unsafe_channel_list,
4945 &(hdd_ctx->unsafe_channel_count),
4946 sizeof(uint16_t) * NUM_20MHZ_RF_CHANNELS);
4947
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304948 hddLog(QDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 hdd_ctx->unsafe_channel_count);
4950
Anurag Chouhan6d760662016-02-20 16:05:43 +05304951 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4953
4954 for (index = 0; index < unsafe_channel_count; index++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304955 hddLog(QDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004956 hdd_ctx->unsafe_channel_list[index]);
4957
4958 }
4959
4960 /* Plug in avoid channel notification callback */
4961 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
4962}
4963#else
4964static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4965{
4966}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004967static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004968{
4969}
4970#endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */
4971
4972/**
4973 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
4974 * @hdd_ctx: HDD context
4975 *
4976 * Disables all the dual mac features like DBS, Agile DFS etc.
4977 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304978 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004979 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304980static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981{
4982 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304983 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984
4985 if (!hdd_ctx) {
4986 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304987 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004988 }
4989
4990 cfg.scan_config = 0;
4991 cfg.fw_mode_config = 0;
4992 cfg.set_dual_mac_cb =
4993 (void *)cds_soc_set_dual_mac_cfg_cb;
4994
4995 hdd_debug("Disabling all dual mac features...");
4996
4997 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304998 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
5000 return status;
5001 }
5002
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305003 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005004}
5005
5006/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005007 * hdd_override_ini_config - Override INI config
5008 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005010 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005012 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005014static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005015{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005016
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005017 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
5018 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5019 hdd_notice("Module enable_dfs_chan_scan set to %d",
5020 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005022 if (0 == enable_11d || 1 == enable_11d) {
5023 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5024 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005026}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005028/**
5029 * hdd_set_trace_level_for_each - Set trace level for each INI config
5030 * @hdd_ctx - HDD context
5031 *
5032 * Set trace level for each module based on INI config.
5033 *
5034 * Return: None
5035 */
5036static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5037{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305038 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
5039 hdd_ctx->config->qdf_trace_enable_wdi);
5040 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
5041 hdd_ctx->config->qdf_trace_enable_hdd);
5042 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
5043 hdd_ctx->config->qdf_trace_enable_sme);
5044 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
5045 hdd_ctx->config->qdf_trace_enable_pe);
5046 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
5047 hdd_ctx->config->qdf_trace_enable_wma);
5048 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
5049 hdd_ctx->config->qdf_trace_enable_sys);
5050 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
5051 hdd_ctx->config->qdf_trace_enable_qdf);
5052 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
5053 hdd_ctx->config->qdf_trace_enable_sap);
5054 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
5055 hdd_ctx->config->qdf_trace_enable_hdd_sap);
5056 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
5057 hdd_ctx->config->qdf_trace_enable_bmi);
5058 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
5059 hdd_ctx->config->qdf_trace_enable_cfg);
5060 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
5061 hdd_ctx->config->qdf_trace_enable_epping);
5062 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
5063 hdd_ctx->config->qdf_trace_enable_qdf_devices);
5064 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05305065 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305066 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
5067 hdd_ctx->config->qdf_trace_enable_htc);
5068 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
5069 hdd_ctx->config->qdf_trace_enable_hif);
5070 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
5071 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
5072 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
5073 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005075 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005076}
5077
5078/**
5079 * hdd_init_context - Alloc and initialize HDD context
5080 * @dev: Pointer to the underlying device
5081 * @hif_sc: HIF context
5082 *
5083 * Allocate and initialize HDD context. HDD context is allocated as part of
5084 * wiphy allocation and then context is initialized.
5085 *
5086 * Return: HDD context on success and ERR_PTR on failure
5087 */
5088hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc)
5089{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305090 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005091 int ret = 0;
5092 hdd_context_t *hdd_ctx;
5093 v_CONTEXT_t p_cds_context;
Komal Seelamc11bb222016-01-27 18:57:10 +05305094 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_sc);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005095
5096 ENTER();
5097
5098 p_cds_context = cds_get_global_context();
5099 if (p_cds_context == NULL) {
5100 hdd_alert("Failed to get CDS global context");
5101 ret = -EINVAL;
5102 goto err_out;
5103 }
5104
5105 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
5106
5107 if (hdd_ctx == NULL) {
5108 ret = -ENOMEM;
5109 goto err_out;
5110 }
5111
5112 hdd_ctx->pcds_context = p_cds_context;
5113
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305114 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005115 if (hdd_ctx->config == NULL) {
5116 hdd_alert("Failed to alloc memory for HDD config!");
5117 ret = -ENOMEM;
5118 goto err_free_hdd_context;
5119 }
5120
5121 /* Read and parse the qcom_cfg.ini file */
5122 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305123 if (QDF_STATUS_SUCCESS != status) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005124 hdd_alert("Error (status: %d) parsing INI file: %s", status,
5125 WLAN_INI_FILE);
5126 ret = -EINVAL;
5127 goto err_free_config;
5128 }
5129
5130 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
5131
5132 hdd_ctx->parent_dev = dev;
5133
5134 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5135
5136 hdd_init_ll_stats_ctx();
5137
5138 init_completion(&hdd_ctx->mc_sus_event_var);
5139 init_completion(&hdd_ctx->ready_to_suspend);
5140
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305141 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
5142 qdf_spinlock_create(&hdd_ctx->sched_scan_lock);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005143
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305144 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305145 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005146
5147 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
5148
5149 hdd_tdls_pre_init(hdd_ctx);
5150 mutex_init(&hdd_ctx->dfs_lock);
5151
Komal Seelamc11bb222016-01-27 18:57:10 +05305152 hdd_ctx->target_type = tgt_info->target_type;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005153
5154 hdd_init_offloaded_packets_ctx(hdd_ctx);
5155
Komal Seelamc11bb222016-01-27 18:57:10 +05305156 icnss_set_fw_debug_mode(hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005157
5158 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5159
5160 hdd_ctx->configuredMcastBcastFilter =
5161 hdd_ctx->config->mcastBcastFilterSetting;
5162
5163 hdd_notice("Setting configuredMcastBcastFilter: %d",
5164 hdd_ctx->config->mcastBcastFilterSetting);
5165
5166 hdd_override_ini_config(hdd_ctx);
5167
5168 ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config);
5169
5170 if (ret) {
5171 hdd_err("CFG80211 wiphy init failed: %d", ret);
5172 goto err_free_config;
5173 }
5174
5175 hdd_enable_fastpath(hdd_ctx->config, hif_sc);
5176
5177 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05305178 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005179
Anurag Chouhan6d760662016-02-20 16:05:43 +05305180 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005181 goto skip_multicast_logging;
5182
5183 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
5184
5185 ret = hdd_logging_sock_activate_svc(hdd_ctx);
5186 if (ret)
5187 goto err_free_config;
5188
5189 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305190 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005191 * levels of the code need not be set when the logger thread
5192 * is not enabled.
5193 */
5194 if (cds_is_multicast_logging())
5195 wlan_logging_set_log_level();
5196
5197skip_multicast_logging:
5198 hdd_set_trace_level_for_each(hdd_ctx);
5199
5200 return hdd_ctx;
5201
5202err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305203 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005204
5205err_free_hdd_context:
5206 wiphy_free(hdd_ctx->wiphy);
5207
5208err_out:
5209 return ERR_PTR(ret);
5210}
5211
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005212#ifdef WLAN_OPEN_P2P_INTERFACE
5213/**
5214 * hdd_open_p2p_interface - Open P2P interface
5215 * @hdd_ctx: HDD context
5216 * @rtnl_held: True if RTNL lock held
5217 *
5218 * Open P2P interface during probe. This function called to open the P2P
5219 * interface at probe along with STA interface.
5220 *
5221 * Return: 0 on success and errno on failure
5222 */
5223static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
5224{
5225 hdd_adapter_t *adapter;
5226 uint8_t *p2p_dev_addr;
5227
5228 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
5229 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305230 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005231 hdd_ctx->config->intfMacAddr[0].bytes,
5232 sizeof(tSirMacAddr));
5233
5234 /*
5235 * Generate the P2P Device Address. This consists of
5236 * the device's primary MAC address with the locally
5237 * administered bit set.
5238 */
5239 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
5240 } else {
5241 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
5242 if (p2p_dev_addr == NULL) {
5243 hdd_alert("Failed to allocate mac_address for p2p_device");
5244 return -ENOSPC;
5245 }
5246
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305247 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305248 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005249 }
5250
5251 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5252 &hdd_ctx->p2pDeviceAddress.bytes[0],
5253 rtnl_held);
5254
5255 if (NULL == adapter) {
5256 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
5257 return -ENOSPC;
5258 }
5259
5260 return 0;
5261}
5262#else
5263static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx,
5264 bool rtnl_held)
5265{
5266 return 0;
5267}
5268#endif
5269
5270/**
5271 * hdd_open_interfaces - Open all required interfaces
5272 * hdd_ctx: HDD context
5273 * rtnl_held: True if RTNL lock is held
5274 *
5275 * Open all the interfaces like STA, P2P and OCB based on the configuration.
5276 *
5277 * Return: Primary adapter on success and PTR_ERR on failure
5278 */
5279static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
5280 bool rtnl_held)
5281{
5282 hdd_adapter_t *adapter = NULL;
5283 hdd_adapter_t *adapter_11p = NULL;
5284 int ret;
5285
5286 /* Create only 802.11p interface */
5287 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
5288 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d",
5289 wlan_hdd_get_intf_addr(hdd_ctx),
5290 rtnl_held);
5291
5292 if (adapter == NULL)
5293 return ERR_PTR(-ENOSPC);
5294
5295 return adapter;
5296 }
5297
5298 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, "wlan%d",
5299 wlan_hdd_get_intf_addr(hdd_ctx),
5300 rtnl_held);
5301
5302 if (adapter == NULL)
5303 return ERR_PTR(-ENOSPC);
5304
5305 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
5306 if (ret)
5307 goto err_close_adapter;
5308
5309 /* Open 802.11p Interface */
5310 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
5311 adapter_11p = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB,
5312 "wlanocb%d",
5313 wlan_hdd_get_intf_addr(hdd_ctx),
5314 rtnl_held);
5315 if (adapter_11p == NULL) {
5316 hdd_err("Failed to open 802.11p interface");
5317 goto err_close_adapter;
5318 }
5319 }
5320
5321 return adapter;
5322
5323err_close_adapter:
5324 hdd_close_all_adapters(hdd_ctx, rtnl_held);
5325 return ERR_PTR(ret);
5326}
5327
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005328/**
5329 * hdd_update_country_code - Update country code
5330 * @hdd_ctx: HDD context
5331 * @adapter: Primary adapter context
5332 *
5333 * Update country code based on module parameter country_code at SME and wait
5334 * for the settings to take effect.
5335 *
5336 * Return: 0 on success and errno on failure
5337 */
5338static int hdd_update_country_code(hdd_context_t *hdd_ctx,
5339 hdd_adapter_t *adapter)
5340{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305341 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005342 int ret = 0;
5343 unsigned long rc;
5344
5345 if (country_code == NULL)
5346 return 0;
5347
5348 INIT_COMPLETION(adapter->change_country_code);
5349
5350 status = sme_change_country_code(hdd_ctx->hHal,
5351 wlan_hdd_change_country_code_callback,
5352 country_code, adapter,
5353 hdd_ctx->pcds_context, eSIR_TRUE,
5354 eSIR_TRUE);
5355
5356
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305357 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005358 hdd_err("SME Change Country code from module param fail ret=%d",
5359 ret);
5360 return -EINVAL;
5361 }
5362
5363 rc = wait_for_completion_timeout(&adapter->change_country_code,
5364 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
5365 if (!rc) {
5366 hdd_err("SME while setting country code timed out");
5367 ret = -ETIMEDOUT;
5368 }
5369
5370 return ret;
5371}
5372
5373/**
5374 * hdd_init_thermal_info - Initialize thermal level
5375 * @hdd_ctx: HDD context
5376 *
5377 * Initialize thermal level at SME layer and set the thermal level callback
5378 * which would be called when a configured thermal threshold is hit.
5379 *
5380 * Return: 0 on success and errno on failure
5381 */
5382static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
5383{
5384 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305385 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005386
5387 thermal_param.smeThermalMgmtEnabled =
5388 hdd_ctx->config->thermalMitigationEnable;
5389 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
5390
5391 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
5392 hdd_ctx->config->thermalTempMinLevel0;
5393 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
5394 hdd_ctx->config->thermalTempMaxLevel0;
5395 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
5396 hdd_ctx->config->thermalTempMinLevel1;
5397 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
5398 hdd_ctx->config->thermalTempMaxLevel1;
5399 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
5400 hdd_ctx->config->thermalTempMinLevel2;
5401 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
5402 hdd_ctx->config->thermalTempMaxLevel2;
5403 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
5404 hdd_ctx->config->thermalTempMinLevel3;
5405 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
5406 hdd_ctx->config->thermalTempMaxLevel3;
5407
5408 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
5409
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305410 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05305411 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005412
5413 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
5414 hdd_set_thermal_level_cb);
5415
5416 return 0;
5417
5418}
5419
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005420#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5421/**
5422 * hdd_hold_rtnl_lock - Hold RTNL lock
5423 *
5424 * Hold RTNL lock
5425 *
5426 * Return: True if held and false otherwise
5427 */
5428static inline bool hdd_hold_rtnl_lock(void)
5429{
5430 rtnl_lock();
5431 return true;
5432}
5433
5434/**
5435 * hdd_release_rtnl_lock - Release RTNL lock
5436 *
5437 * Release RTNL lock
5438 *
5439 * Return: None
5440 */
5441static inline void hdd_release_rtnl_lock(void)
5442{
5443 rtnl_unlock();
5444}
5445#else
5446static inline bool hdd_hold_rtnl_lock(void) { return false; }
5447static inline void hdd_release_rtnl_lock(void) { }
5448#endif
5449
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005450/**
5451 * hdd_wlan_startup() - HDD init function
5452 * @dev: Pointer to the underlying device
5453 *
5454 * This is the driver startup code executed once a WLAN device has been detected
5455 *
5456 * Return: 0 for success, < 0 for failure
5457 */
5458int hdd_wlan_startup(struct device *dev, void *hif_sc)
5459{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305460 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005461 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005462 hdd_context_t *hdd_ctx = NULL;
5463 int ret;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005464 tSirTxPowerLimit hddtxlimit;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005465 bool rtnl_held;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005466 tSirRetStatus hal_status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005467
5468 ENTER();
5469
5470 if (WLAN_IS_EPPING_ENABLED(con_mode)) {
5471 ret = epping_enable(dev);
5472 EXIT();
5473 return ret;
5474 }
5475
5476 hdd_ctx = hdd_init_context(dev, hif_sc);
5477
5478 if (IS_ERR(hdd_ctx))
5479 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005480
Anurag Chouhan6d760662016-02-20 16:05:43 +05305481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005482 ret = hdd_enable_ftm(hdd_ctx);
5483
5484 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005485 goto err_hdd_free_context;
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005486
5487 goto success;
5488 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08005490 hdd_wlan_green_ap_init(hdd_ctx);
5491
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005492 status = cds_open();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305493 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305494 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_open failed"));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005495 goto err_hdd_free_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 }
5497
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005498 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005499
Anurag Chouhan6d760662016-02-20 16:05:43 +05305500 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501
5502 if (NULL == hdd_ctx->hHal) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305503 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HAL context is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005504 goto err_cds_close;
5505 }
5506
5507 status = cds_pre_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305508 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305509 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005510 goto err_cds_close;
5511 }
5512
5513 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
5514
5515 status = wlan_hdd_regulatory_init(hdd_ctx);
5516
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305517 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305518 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005519 FL("Failed to init channel list"));
5520 goto err_cds_close;
5521 }
5522
5523 /*
5524 * Set 802.11p config
5525 * TODO-OCB: This has been temporarily added here to ensure this
5526 * parameter is set in CSR when we init the channel list. This should
5527 * be removed once the 5.9 GHz channels are added to the regulatory
5528 * domain.
5529 */
5530 hdd_set_dot11p_config(hdd_ctx);
5531
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532 /*
5533 * Note that the cds_pre_enable() sequence triggers the cfg download.
5534 * The cfg download must occur before we update the SME config
5535 * since the SME config operation must access the cfg database
5536 */
5537 status = hdd_set_sme_config(hdd_ctx);
5538
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305539 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305540 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541 goto err_wiphy_unregister;
5542 }
5543
5544 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
5545 hdd_ctx->config->tx_chain_mask_1ss,
5546 PDEV_CMD);
5547 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305548 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d",
5550 __func__, ret);
5551 }
5552
5553 status = hdd_set_sme_chan_list(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305554 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305555 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005556 FL("Failed to init channel list"));
5557 goto err_wiphy_unregister;
5558 }
5559
5560 /* Apply the cfg.ini to cfg.dat */
5561 if (false == hdd_update_config_dat(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305562 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005563 FL("config update failed"));
5564 goto err_wiphy_unregister;
5565 }
5566
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305567 if (QDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305568 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 FL("can't update mac config, using MAC from ini file"));
5570 }
5571
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005572 /*
5573 * Set the MAC Address Currently this is used by HAL to add self sta.
5574 * Remove this once self sta is added as part of session open.
5575 */
5576 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
5577 hdd_ctx->config->intfMacAddr[0].bytes,
5578 sizeof(hdd_ctx->config->intfMacAddr[0]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005580 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
5581 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
5582 hal_status, hal_status);
5583 ret = -EINVAL;
5584 goto err_wiphy_unregister;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 }
5586
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305587 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005588 goto err_wiphy_unregister;
5589
5590 /*
5591 * Start CDS which starts up the SME/MAC/HAL modules and everything
5592 * else
5593 */
5594 status = cds_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305595 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305596 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_enable failed"));
Yun Park6a46ad82016-01-04 16:48:19 -08005597 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 }
5599
5600 hdd_init_channel_avoidance(hdd_ctx);
5601
5602 status = hdd_post_cds_enable_config(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305603 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305604 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005605 FL("hdd_post_cds_enable_config failed"));
5606 goto err_cds_disable;
5607 }
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005608
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005609 cds_pkt_proto_trace_init();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005610
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005611 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005612
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005613 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005615 if (IS_ERR(adapter)) {
5616 ret = PTR_ERR(adapter);
5617 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005618 }
5619
5620 /*
5621 * target hw version/revision would only be retrieved after firmware
5622 * donwload
5623 */
5624 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
5625 &hdd_ctx->target_hw_revision,
5626 &hdd_ctx->target_hw_name);
5627
5628 /* Get the wlan hw/fw version */
5629 hdd_wlan_get_version(adapter, NULL, NULL);
5630
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005631 ret = hdd_update_country_code(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005633 if (ret)
5634 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635
5636 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
5637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
5639 hdd_send_oem_data_rsp_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005640
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 /* FW capabilities received, Set the Dot11 mode */
5642 sme_setdef_dot11mode(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005643
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644 /* Initialize the nlink service */
5645 if (nl_srv_init() != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305646 hddLog(QDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed"));
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005647 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005648 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005649
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005650 ret = oem_activate_service(hdd_ctx);
5651 if (ret) {
5652 hdd_alert("oem_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653 goto err_nl_srv;
5654 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005655
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005656 ret = ptt_sock_activate_svc();
5657 if (ret) {
5658 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005659 goto err_nl_srv;
5660 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005662 ret = cnss_diag_activate_service();
5663 if (ret) {
5664 hdd_alert("cnss_diag_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 goto err_nl_srv;
5666 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667
Peng Xuf5d60c82015-10-02 17:17:03 -07005668 /*
5669 * Action frame registered in one adapter which will
5670 * applicable to all interfaces
5671 */
5672 wlan_hdd_cfg80211_register_frames(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005673
5674 mutex_init(&hdd_ctx->sap_lock);
5675
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005676 hdd_release_rtnl_lock();
5677 rtnl_held = false;
5678
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005679 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5680 if (ret < 0) {
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005681 hdd_err("register_netdevice_notifier failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682 goto err_nl_srv;
5683 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005684
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005685#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5686 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305687 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005688#endif
5689 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305690 qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691
5692 hdd_hostapd_channel_wakelock_init(hdd_ctx);
5693
Kiran Kumar Lokerefc2803d2016-01-11 19:31:38 -08005694 if (hdd_ctx->config->fIsImpsEnabled)
5695 hdd_set_idle_ps_config(hdd_ctx, true);
5696 else
5697 hdd_set_idle_ps_config(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005698#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5699 if (hdd_ctx->config->WlanAutoShutdown != 0)
5700 if (sme_set_auto_shutdown_cb
5701 (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305702 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005703 hddLog(LOGE,
5704 FL(
5705 "Auto shutdown feature could not be enabled"
5706 ));
5707#endif
5708
5709#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305710 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305711 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712 hdd_skip_acs_scan_timer_handler,
5713 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305714 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005715 hddLog(LOGE, FL("Failed to init ACS Skip timer"));
5716#endif
5717
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005718 wlan_hdd_nan_init(hdd_ctx);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005719 status = cds_init_policy_mgr();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305720 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 hdd_err("Policy manager initialization failed");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005722 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723 }
5724
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005725 ret = hdd_init_thermal_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005726
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005727 if (ret) {
5728 hdd_err("Error while initializing thermal information");
5729 goto err_unreg_netdev_notifier;
5730 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005731
5732 if (0 != hdd_lro_init(hdd_ctx))
5733 hdd_err("Unable to initialize LRO in fw");
5734
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005735 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
5736 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
5737 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305738 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005739 hdd_err("Error setting txlimit in sme: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005740
5741#ifdef MSM_PLATFORM
5742 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05305743 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305744 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005745 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5746#endif
5747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005748 wlan_hdd_cfg80211_stats_ext_init(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750 sme_ext_scan_register_callback(hdd_ctx->hHal,
5751 wlan_hdd_cfg80211_extscan_callback);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005752
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
5754 hdd_rssi_threshold_breached);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005755
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005756 hdd_cfg80211_link_layer_stats_init(hdd_ctx);
5757
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005758 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
5759 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
5760 hdd_ctx->target_hw_version,
5761 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305763 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305764 qdf_list_create((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305765 qdf_spinlock_create(&hdd_ctx->hdd_scan_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305766 qdf_list_create((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767#ifdef CONFIG_CNSS
5768 cnss_init_delayed_work(&hdd_ctx->roc_req_work,
5769 wlan_hdd_roc_request_dequeue);
5770#else
5771 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5772#endif
5773
5774 /*
5775 * Register IPv6 notifier to notify if any change in IP
5776 * So that we can reconfigure the offload parameters
5777 */
5778 hdd_wlan_register_ip6_notifier(hdd_ctx);
5779
5780 /*
5781 * Register IPv4 notifier to notify if any change in IP
5782 * So that we can reconfigure the offload parameters
5783 */
5784 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5785 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5786 if (ret)
5787 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
5788 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005789 hdd_info("Registered IPv4 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790
5791 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
5792
5793 if (hdd_ctx->config->dual_mac_feature_disable) {
5794 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305795 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 hdd_err("Failed to disable dual mac features");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005797 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798 }
5799 }
5800
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005801 memdump_init();
5802
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803 goto success;
5804
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005805err_unreg_netdev_notifier:
5806 unregister_netdevice_notifier(&hdd_netdev_notifier);
5807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005808err_nl_srv:
5809#ifdef WLAN_KD_READY_NOTIFIER
5810 cnss_diag_notify_wlan_close();
5811 ptt_sock_deactivate_svc();
5812#endif /* WLAN_KD_READY_NOTIFIER */
5813 nl_srv_exit();
5814
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305815 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08005816 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817 /* Proceed and complete the clean up */
5818 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005821 hdd_release_rtnl_lock();
5822
5823 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005824
5825err_cds_disable:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005826 cds_disable(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005827
Yun Park6a46ad82016-01-04 16:48:19 -08005828err_ipa_cleanup:
5829 hdd_ipa_cleanup(hdd_ctx);
5830
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005832 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833
5834err_cds_close:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005835 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305836 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305837 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305839 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005841 cds_close(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005843err_hdd_free_context:
5844 hdd_free_context(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305845 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005846
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005847 return -EIO;
5848
5849success:
5850 EXIT();
5851 return 0;
5852}
5853
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005854/**
5855 * hdd_softap_sta_deauth() - handle deauth req from HDD
5856 * @adapter: Pointer to the HDD
5857 * @enable: bool value
5858 *
5859 * This to take counter measure to handle deauth req from HDD
5860 *
5861 * Return: None
5862 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305863QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005864 struct tagCsrDelStaParams *pDelStaParams)
5865{
5866#ifndef WLAN_FEATURE_MBSSID
5867 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5868#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305869 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870
5871 ENTER();
5872
5873 hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"),
5874 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5875
5876 /* Ignore request to deauth bcmc station */
5877 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305878 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879
5880#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305881 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005882 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5883 pDelStaParams);
5884#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305885 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005886#endif
5887
5888 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305889 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005890}
5891
5892/**
5893 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
5894 * @adapter: Pointer to the HDD
5895 *
5896 * This to take counter measure to handle deauth req from HDD
5897 *
5898 * Return: None
5899 */
5900void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
5901 uint8_t *pDestMacAddress)
5902{
5903#ifndef WLAN_FEATURE_MBSSID
5904 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5905#endif
5906
5907 ENTER();
5908
5909 hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"),
5910 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5911
5912 /* Ignore request to disassoc bcmc station */
5913 if (pDestMacAddress[0] & 0x1)
5914 return;
5915
5916#ifdef WLAN_FEATURE_MBSSID
5917 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5918 pDestMacAddress);
5919#else
5920 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
5921#endif
5922}
5923
5924void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
5925 bool enable)
5926{
5927#ifndef WLAN_FEATURE_MBSSID
5928 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5929#endif
5930
5931 ENTER();
5932
5933 hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"),
5934 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5935
5936#ifdef WLAN_FEATURE_MBSSID
5937 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5938 (bool) enable);
5939#else
5940 wlansap_set_counter_measure(p_cds_context, (bool) enable);
5941#endif
5942}
5943
5944/**
5945 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
5946 * @hdd_ctx: HDD Context
5947 *
5948 * API to find if there is any STA or P2P-Client is connected
5949 *
5950 * Return: true if connected; false otherwise
5951 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305952QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953{
5954 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
5955}
5956
5957#ifdef WLAN_FEATURE_LPSS
5958int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
5959 hdd_adapter_t *adapter,
5960 hdd_station_ctx_t *pHddStaCtx,
5961 uint8_t is_on, uint8_t is_connected)
5962{
5963 hdd_context_t *hdd_ctx = NULL;
5964 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
5965
5966 if (!data) {
5967 hddLog(LOGE, FL("invalid data pointer"));
5968 return -EINVAL;
5969 }
5970 if (!adapter) {
5971 if (is_on) {
5972 /* no active interface */
5973 data->lpss_support = 0;
5974 data->is_on = is_on;
5975 return 0;
5976 }
5977 hddLog(LOGE, FL("invalid adapter pointer"));
5978 return -EINVAL;
5979 }
5980
5981 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelamc11bb222016-01-27 18:57:10 +05305982 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005983 data->lpss_support = 1;
5984 else
5985 data->lpss_support = 0;
5986 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
5987 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
5988 &data->numChannels);
5989 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
5990 data->is_on = is_on;
5991 data->vdev_id = adapter->sessionId;
5992 data->vdev_mode = adapter->device_mode;
5993 if (pHddStaCtx) {
5994 data->is_connected = is_connected;
5995 data->rssi = adapter->rssi;
5996 data->freq =
5997 cds_chan_to_freq(pHddStaCtx->conn_info.operationChannel);
5998 if (WLAN_SVC_MAX_SSID_LEN >=
5999 pHddStaCtx->conn_info.SSID.SSID.length) {
6000 data->ssid_len = pHddStaCtx->conn_info.SSID.SSID.length;
6001 memcpy(data->ssid,
6002 pHddStaCtx->conn_info.SSID.SSID.ssId,
6003 pHddStaCtx->conn_info.SSID.SSID.length);
6004 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05306005 if (QDF_MAC_ADDR_SIZE >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006006 sizeof(pHddStaCtx->conn_info.bssId))
6007 memcpy(data->bssid, pHddStaCtx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306008 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006009 }
6010 return 0;
6011}
6012
6013int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
6014 uint32_t fw_version,
6015 uint32_t chip_id, const char *chip_name)
6016{
6017 if (!data) {
6018 hddLog(LOGE, FL("invalid data pointer"));
6019 return -EINVAL;
6020 }
6021
6022 data->chip_id = chip_id;
6023 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
6024 if (strncmp(chip_name, "Unknown", 7))
6025 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
6026 else
6027 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
6028 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
6029 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
6030 (fw_version & 0xf0000000) >> 28,
6031 (fw_version & 0xf000000) >> 24,
6032 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
6033 return 0;
6034}
6035#endif
6036
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006037/**
6038 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
6039 * @adapter: HDD adapter pointer
6040 *
6041 * This function loop through each adapter and disable roaming on each STA
6042 * device mode except the input adapter.
6043 *
6044 * Note: On the input adapter roaming is not enabled yet hence no need to
6045 * disable.
6046 *
6047 * Return: None
6048 */
6049void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
6050{
6051 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6052 hdd_adapter_t *adapterIdx = NULL;
6053 hdd_adapter_list_node_t *adapterNode = NULL;
6054 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306055 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056
6057 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6058 hdd_ctx->config->isRoamOffloadScanEnabled &&
6059 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6060 cds_is_sta_active_connection_exists()) {
6061 hddLog(LOG1, FL("Connect received on STA sessionId(%d)"),
6062 adapter->sessionId);
6063 /*
6064 * Loop through adapter and disable roaming for each STA device
6065 * mode except the input adapter.
6066 */
6067 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6068
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306069 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006070 adapterIdx = adapterNode->pAdapter;
6071
6072 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6073 && adapter->sessionId != adapterIdx->sessionId) {
6074 hddLog(LOG1,
6075 FL("Disable Roaming on sessionId(%d)"),
6076 adapterIdx->sessionId);
6077 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
6078 (adapterIdx),
6079 adapterIdx->sessionId, 0);
6080 }
6081
6082 status = hdd_get_next_adapter(hdd_ctx,
6083 adapterNode,
6084 &pNext);
6085 adapterNode = pNext;
6086 }
6087 }
6088}
6089
6090/**
6091 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
6092 * @adapter: HDD adapter pointer
6093 *
6094 * This function loop through each adapter and enable roaming on each STA
6095 * device mode except the input adapter.
6096 * Note: On the input adapter no need to enable roaming because link got
6097 * disconnected on this.
6098 *
6099 * Return: None
6100 */
6101void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
6102{
6103 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6104 hdd_adapter_t *adapterIdx = NULL;
6105 hdd_adapter_list_node_t *adapterNode = NULL;
6106 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306107 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006108
6109 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6110 hdd_ctx->config->isRoamOffloadScanEnabled &&
6111 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6112 cds_is_sta_active_connection_exists()) {
6113 hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"),
6114 adapter->sessionId);
6115 /*
6116 * Loop through adapter and enable roaming for each STA device
6117 * mode except the input adapter.
6118 */
6119 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306121 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006122 adapterIdx = adapterNode->pAdapter;
6123
6124 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6125 && adapter->sessionId != adapterIdx->sessionId) {
6126 hddLog(LOG1,
6127 FL("Enabling Roaming on sessionId(%d)"),
6128 adapterIdx->sessionId);
6129 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
6130 (adapterIdx),
6131 adapterIdx->sessionId,
6132 REASON_CONNECT);
6133 }
6134
6135 status = hdd_get_next_adapter(hdd_ctx,
6136 adapterNode,
6137 &pNext);
6138 adapterNode = pNext;
6139 }
6140 }
6141}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006142
6143void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
6144{
6145 struct sk_buff *skb;
6146 struct nlmsghdr *nlh;
6147 tAniMsgHdr *ani_hdr;
6148 void *nl_data = NULL;
6149 int flags = GFP_KERNEL;
6150
6151 if (in_interrupt() || irqs_disabled() || in_atomic())
6152 flags = GFP_ATOMIC;
6153
6154 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
6155
6156 if (skb == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306157 hddLog(QDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006158 return;
6159 }
6160
6161 nlh = (struct nlmsghdr *)skb->data;
6162 nlh->nlmsg_pid = 0; /* from kernel */
6163 nlh->nlmsg_flags = 0;
6164 nlh->nlmsg_seq = 0;
6165 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
6166
6167 ani_hdr = NLMSG_DATA(nlh);
6168 ani_hdr->type = type;
6169
6170 switch (type) {
6171 case WLAN_SVC_FW_CRASHED_IND:
6172 case WLAN_SVC_LTE_COEX_IND:
6173#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6174 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
6175#endif
6176 ani_hdr->length = 0;
6177 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
6178 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
6179 break;
6180 case WLAN_SVC_WLAN_STATUS_IND:
6181 case WLAN_SVC_WLAN_VERSION_IND:
6182 case WLAN_SVC_DFS_CAC_START_IND:
6183 case WLAN_SVC_DFS_CAC_END_IND:
6184 case WLAN_SVC_DFS_RADAR_DETECT_IND:
6185 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
6186 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08006187 case WLAN_SVC_WLAN_TP_TX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006188 ani_hdr->length = len;
6189 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
6190 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
6191 memcpy(nl_data, data, len);
6192 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
6193 break;
6194
6195 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306196 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006197 FL("WLAN SVC: Attempt to send unknown nlink message %d"),
6198 type);
6199 kfree_skb(skb);
6200 return;
6201 }
6202
6203 nl_srv_bcast(skb);
6204
6205 return;
6206}
6207
6208#ifdef WLAN_FEATURE_LPSS
6209void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
6210 hdd_station_ctx_t *pHddStaCtx,
6211 uint8_t is_on, uint8_t is_connected)
6212{
6213 int ret = 0;
6214 struct wlan_status_data data;
6215
Anurag Chouhan6d760662016-02-20 16:05:43 +05306216 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006217 return;
6218
6219 memset(&data, 0, sizeof(struct wlan_status_data));
6220 if (is_on)
6221 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, pHddStaCtx,
6222 is_on, is_connected);
6223 if (!ret)
6224 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND,
6225 &data,
6226 sizeof(struct wlan_status_data));
6227}
6228
6229void wlan_hdd_send_version_pkg(uint32_t fw_version,
6230 uint32_t chip_id, const char *chip_name)
6231{
6232 int ret = 0;
6233 struct wlan_version_data data;
6234#ifdef CONFIG_CNSS
6235 struct cnss_platform_cap cap;
6236
6237 ret = cnss_get_platform_cap(&cap);
6238 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306239 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006240 FL("platform capability info from CNSS not available"));
6241 return;
6242 }
6243
6244 if (!(cap.cap_flag & CNSS_HAS_UART_ACCESS))
6245 return;
6246#endif
6247
Anurag Chouhan6d760662016-02-20 16:05:43 +05306248 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006249 return;
6250
6251 memset(&data, 0, sizeof(struct wlan_version_data));
6252 ret =
6253 wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
6254 chip_name);
6255 if (!ret)
6256 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND,
6257 &data,
6258 sizeof(struct wlan_version_data));
6259}
6260
6261void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
6262{
6263 hdd_adapter_t *pDataAdapter = NULL;
6264 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6265 bool scan_intf_found = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306266 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267
6268 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306269 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270 FL("NULL pointer for hdd_ctx"));
6271 return;
6272 }
6273
6274 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306275 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006276 pDataAdapter = adapterNode->pAdapter;
6277 if (pDataAdapter) {
6278 if (pDataAdapter->device_mode == WLAN_HDD_INFRA_STATION
6279 || pDataAdapter->device_mode == WLAN_HDD_P2P_CLIENT
6280 || pDataAdapter->device_mode ==
6281 WLAN_HDD_P2P_DEVICE) {
6282 scan_intf_found = true;
6283 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1,
6284 0);
6285 }
6286 }
6287 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6288 adapterNode = pNext;
6289 }
6290
6291 if (!scan_intf_found)
6292 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0);
6293}
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006294#else
6295static inline void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter,
6296 hdd_station_ctx_t *pHddStaCtx,
6297 uint8_t is_on, uint8_t is_connected)
6298{
6299 return;
6300}
6301
6302static inline void wlan_hdd_send_version_pkg(uint32_t fw_version, uint32_t
6303 chip_id, const char *chip_name)
6304{
6305 return;
6306}
6307
6308static inline void wlan_hdd_send_all_scan_intf_info(hdd_context_t *pHddCtx)
6309{
6310 return;
6311}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006312#endif
6313
6314#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6315void wlan_hdd_auto_shutdown_cb(void)
6316{
6317 hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event.."));
6318 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
6319}
6320
6321void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
6322{
6323 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306324 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006325 hdd_adapter_t *adapter;
6326 bool ap_connected = false, sta_connected = false;
6327 tHalHandle hal_handle;
6328
6329 hal_handle = hdd_ctx->hHal;
6330 if (hal_handle == NULL)
6331 return;
6332
6333 if (hdd_ctx->config->WlanAutoShutdown == 0)
6334 return;
6335
6336 if (enable == false) {
6337 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306338 QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339 hddLog(LOGE,
6340 FL("Failed to stop wlan auto shutdown timer"));
6341 }
6342 return;
6343 }
6344
6345 /* To enable shutdown timer check conncurrency */
6346 if (cds_concurrent_open_sessions_running()) {
6347 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6348
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306349 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006350 adapter = adapterNode->pAdapter;
6351 if (adapter
6352 && adapter->device_mode ==
6353 WLAN_HDD_INFRA_STATION) {
6354 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6355 conn_info.connState ==
6356 eConnectionState_Associated) {
6357 sta_connected = true;
6358 break;
6359 }
6360 }
6361 if (adapter
6362 && adapter->device_mode == WLAN_HDD_SOFTAP) {
6363 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
6364 bApActive == true) {
6365 ap_connected = true;
6366 break;
6367 }
6368 }
6369 status = hdd_get_next_adapter(hdd_ctx,
6370 adapterNode,
6371 &pNext);
6372 adapterNode = pNext;
6373 }
6374 }
6375
6376 if (ap_connected == true || sta_connected == true) {
6377 hddLog(LOG1,
6378 FL("CC Session active. Shutdown timer not enabled"));
6379 return;
6380 } else {
6381 if (sme_set_auto_shutdown_timer(hal_handle,
6382 hdd_ctx->config->
6383 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306384 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006385 hddLog(LOGE,
6386 FL("Failed to start wlan auto shutdown timer"));
6387 else
6388 hddLog(LOG1,
6389 FL("Auto Shutdown timer for %d seconds enabled"),
6390 hdd_ctx->config->WlanAutoShutdown);
6391
6392 }
6393}
6394#endif
6395
6396hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
6397 bool check_start_bss)
6398{
6399 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
6400 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306401 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006402 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6403
6404 con_sap_adapter = NULL;
6405
6406 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306407 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006408 adapter = adapterNode->pAdapter;
6409 if (adapter && ((adapter->device_mode == WLAN_HDD_SOFTAP) ||
6410 (adapter->device_mode == WLAN_HDD_P2P_GO)) &&
6411 adapter != this_sap_adapter) {
6412 if (check_start_bss) {
6413 if (test_bit(SOFTAP_BSS_STARTED,
6414 &adapter->event_flags)) {
6415 con_sap_adapter = adapter;
6416 break;
6417 }
6418 } else {
6419 con_sap_adapter = adapter;
6420 break;
6421 }
6422 }
6423 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6424 adapterNode = pNext;
6425 }
6426
6427 return con_sap_adapter;
6428}
6429
6430#ifdef MSM_PLATFORM
6431void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
6432{
6433 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6434
Anurag Chouhan210db072016-02-22 18:42:15 +05306435 if (QDF_TIMER_STATE_RUNNING ==
6436 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006437 return;
6438
Anurag Chouhan210db072016-02-22 18:42:15 +05306439 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006440 hdd_ctx->config->busBandwidthComputeInterval);
6441}
6442
6443void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
6444{
6445 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306446 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006447 bool can_stop = true;
6448 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6449
Anurag Chouhan210db072016-02-22 18:42:15 +05306450 if (QDF_TIMER_STATE_RUNNING !=
6451 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006452 /* trying to stop timer, when not running is not good */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306453 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006454 FL("bus band width compute timer is not running"));
6455 return;
6456 }
6457
6458 if (cds_concurrent_open_sessions_running()) {
6459 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6460
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306461 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006462 adapter = adapterNode->pAdapter;
6463 if (adapter
6464 && (adapter->device_mode == WLAN_HDD_INFRA_STATION
6465 || adapter->device_mode == WLAN_HDD_P2P_CLIENT)
6466 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6467 conn_info.connState ==
6468 eConnectionState_Associated) {
6469 can_stop = false;
6470 break;
6471 }
6472 if (adapter
6473 && (adapter->device_mode == WLAN_HDD_SOFTAP
6474 || adapter->device_mode == WLAN_HDD_P2P_GO)
6475 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
6476 true) {
6477 can_stop = false;
6478 break;
6479 }
6480 status = hdd_get_next_adapter(hdd_ctx,
6481 adapterNode,
6482 &pNext);
6483 adapterNode = pNext;
6484 }
6485 }
6486
6487 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05306488 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006489}
6490#endif
6491
6492/**
6493 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
6494 * and sta's operating channel.
6495 * @sta_adapter: Describe the first argument to foobar.
6496 * @ap_adapter: Describe the second argument to foobar.
6497 * @roam_profile: Roam profile of AP to which STA wants to connect.
6498 * @concurrent_chnl_same: If both SAP and STA channels are same then
6499 * set this flag to true else false.
6500 *
6501 * This function checks the sap's operating channel and sta's operating channel.
6502 * if both are same then it will return false else it will restart the sap in
6503 * sta's channel and return true.
6504 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306505 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006506 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306507QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006508 hdd_adapter_t *ap_adapter,
6509 tCsrRoamProfile *roam_profile,
6510 tScanResultHandle *scan_cache,
6511 bool *concurrent_chnl_same)
6512{
6513 hdd_ap_ctx_t *hdd_ap_ctx;
6514 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306515 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006516 device_mode_t device_mode = ap_adapter->device_mode;
6517 *concurrent_chnl_same = true;
6518
6519 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6520 status =
6521 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
6522 roam_profile,
6523 scan_cache,
6524 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306525 if ((QDF_STATUS_SUCCESS == status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006526 if ((WLAN_HDD_SOFTAP == device_mode) &&
6527 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
6528 if (hdd_ap_ctx->operatingChannel != channel_id) {
6529 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306530 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006531 FL("channels are different"));
6532 }
6533 } else if ((WLAN_HDD_P2P_GO == device_mode) &&
6534 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
6535 if (hdd_ap_ctx->operatingChannel != channel_id) {
6536 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306537 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006538 FL("channels are different"));
6539 }
6540 }
6541 } else {
6542 /*
6543 * Lets handle worst case scenario here, Scan cache lookup is
6544 * failed so we have to stop the SAP to avoid any channel
6545 * discrepancy between SAP's channel and STA's channel.
6546 * Return the status as failure so caller function could know
6547 * that scan look up is failed.
6548 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306549 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006550 FL("Finding AP from scan cache failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306551 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006552 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306553 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006554}
6555
6556#ifdef WLAN_FEATURE_MBSSID
6557/**
6558 * wlan_hdd_stop_sap() - This function stops bss of SAP.
6559 * @ap_adapter: SAP adapter
6560 *
6561 * This function will process the stopping of sap adapter.
6562 *
6563 * Return: None
6564 */
6565void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
6566{
6567 hdd_ap_ctx_t *hdd_ap_ctx;
6568 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306569 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006570 hdd_context_t *hdd_ctx;
6571#ifdef CFG80211_DEL_STA_V2
6572 struct station_del_parameters delStaParams;
6573#endif
6574
6575 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306576 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006577 FL("ap_adapter is NULL here"));
6578 return;
6579 }
6580
6581 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6582 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6583 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306584 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006585 FL("HDD context is not valid"));
6586 return;
6587 }
6588 mutex_lock(&hdd_ctx->sap_lock);
6589 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
6590#ifdef CFG80211_DEL_STA_V2
6591 delStaParams.mac = NULL;
6592 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
6593 delStaParams.reason_code = eCsrForcedDeauthSta;
6594 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6595 ap_adapter->dev,
6596 &delStaParams);
6597#else
6598 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6599 ap_adapter->dev,
6600 NULL);
6601#endif
6602 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
6603 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306604 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006605 FL("Now doing SAP STOPBSS"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306606 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306607 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05306609 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306610 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006611 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306612 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006613 mutex_unlock(&hdd_ctx->sap_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306614 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006615 FL("SAP Stop Failed"));
6616 return;
6617 }
6618 }
6619 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08006620 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006621 ap_adapter->sessionId);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306622 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006623 FL("SAP Stop Success"));
6624 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306625 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006626 FL("Can't stop ap because its not started"));
6627 }
6628 mutex_unlock(&hdd_ctx->sap_lock);
6629 return;
6630}
6631
6632/**
6633 * wlan_hdd_start_sap() - this function starts bss of SAP.
6634 * @ap_adapter: SAP adapter
6635 *
6636 * This function will process the starting of sap adapter.
6637 *
6638 * Return: None
6639 */
6640void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
6641{
6642 hdd_ap_ctx_t *hdd_ap_ctx;
6643 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306644 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006645 hdd_context_t *hdd_ctx;
6646 tsap_Config_t *sap_config;
6647
6648 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306649 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006650 FL("ap_adapter is NULL here"));
6651 return;
6652 }
6653
Peng Xuf5d60c82015-10-02 17:17:03 -07006654 if (WLAN_HDD_SOFTAP != ap_adapter->device_mode) {
6655 hdd_err("SoftAp role has not been enabled");
6656 return;
6657 }
6658
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006659 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6660 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6661 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6662 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
6663
6664 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306665 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006666 FL("HDD context is not valid"));
6667 return;
6668 }
6669 mutex_lock(&hdd_ctx->sap_lock);
6670 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
6671 goto end;
6672
6673 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
6674 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
6675 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
6676 goto end;
6677 }
6678
6679 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
6680 &hdd_ap_ctx->sapConfig,
6681 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306682 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006683 goto end;
6684
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306685 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006686 FL("Waiting for SAP to start"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306687 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006688 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306689 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306690 hddLog(QDF_TRACE_LEVEL_ERROR, FL("SAP Start failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691 goto end;
6692 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306693 hddLog(QDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006694 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006695 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006696 ap_adapter->sessionId);
6697 hostapd_state->bCommit = true;
6698
6699end:
6700 mutex_unlock(&hdd_ctx->sap_lock);
6701 return;
6702}
6703#endif
6704
6705/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006706 * hdd_get_fw_version() - Get FW version
6707 * @hdd_ctx: pointer to HDD context.
6708 * @major_spid: FW version - major spid.
6709 * @minor_spid: FW version - minor spid
6710 * @ssid: FW version - ssid
6711 * @crmid: FW version - crmid
6712 *
6713 * This function is called to get the firmware build version stored
6714 * as part of the HDD context
6715 *
6716 * Return: None
6717 */
6718void hdd_get_fw_version(hdd_context_t *hdd_ctx,
6719 uint32_t *major_spid, uint32_t *minor_spid,
6720 uint32_t *siid, uint32_t *crmid)
6721{
6722 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
6723 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
6724 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
6725 *crmid = hdd_ctx->target_fw_version & 0x7fff;
6726}
6727
6728#ifdef QCA_CONFIG_SMP
6729/**
6730 * wlan_hdd_get_cpu() - get cpu_index
6731 *
6732 * Return: cpu_index
6733 */
6734int wlan_hdd_get_cpu(void)
6735{
6736 int cpu_index = get_cpu();
6737 put_cpu();
6738 return cpu_index;
6739}
6740#endif
6741
6742/**
6743 * hdd_get_fwpath() - get framework path
6744 *
6745 * This function is used to get the string written by
6746 * userspace to start the wlan driver
6747 *
6748 * Return: string
6749 */
6750const char *hdd_get_fwpath(void)
6751{
6752 return fwpath.string;
6753}
6754
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006755/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006756 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006757 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006758 * This function initilizes CDS global context with the help of cds_init. This
6759 * has to be the first function called after probe to get a valid global
6760 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006761 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006762 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006763 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006764int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006765{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006766 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006767 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006768
6769#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6770 wlan_logging_sock_init_svc();
6771#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006772 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006773
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006774 if (p_cds_context == NULL) {
6775 hdd_alert("Failed to allocate CDS context");
6776 ret = -ENOMEM;
6777 goto err_out;
6778 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006779
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006780 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006781
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006782err_out:
6783 return ret;
6784}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006785
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006786/**
6787 * hdd_deinit() - Deinitialize Driver
6788 *
6789 * This function frees CDS global context with the help of cds_deinit. This
6790 * has to be the last function call in remove callback to free the global
6791 * context.
6792 */
6793void hdd_deinit(void)
6794{
6795 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006796
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006797#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6798 wlan_logging_sock_deinit_svc();
6799#endif
6800}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006801
6802#ifdef QCA_WIFI_3_0_ADRASTEA
6803#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
6804#else
6805#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
6806#endif
6807
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006808/**
6809 * __hdd_module_init - Module init helper
6810 *
6811 * Module init helper function used by both module and static driver.
6812 *
6813 * Return: 0 for success, errno on failure
6814 */
6815static int __hdd_module_init(void)
6816{
6817 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006818
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006819 pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
6820 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006821
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306822 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006823
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006824 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006825
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006826 ret = wlan_hdd_register_driver();
6827 if (ret) {
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006828 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006829 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006830 }
6831
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306832 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006833
6834 return 0;
6835out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306836 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006837 return ret;
6838}
6839
6840/**
6841 * __hdd_module_exit - Module exit helper
6842 *
6843 * Module exit helper function used by both module and static driver.
6844 */
6845static void __hdd_module_exit(void)
6846{
6847 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
6848 QWLAN_VERSIONSTR);
6849
6850 wlan_hdd_unregister_driver();
6851
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306852 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006853
6854 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006855}
6856
6857/**
6858 * hdd_module_init() - Init Function
6859 *
6860 * This is the driver entry point (invoked when module is loaded using insmod)
6861 *
6862 * Return: 0 for success, non zero for failure
6863 */
6864#ifdef MODULE
6865static int __init hdd_module_init(void)
6866{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006867 return __hdd_module_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006868}
6869#else /* #ifdef MODULE */
6870static int __init hdd_module_init(void)
6871{
6872 /* Driver initialization is delayed to fwpath_changed_handler */
6873 return 0;
6874}
6875#endif /* #ifdef MODULE */
6876
6877/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006878 * hdd_module_exit() - Exit function
6879 *
6880 * This is the driver exit point (invoked when module is unloaded using rmmod)
6881 *
6882 * Return: None
6883 */
6884static void __exit hdd_module_exit(void)
6885{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006886 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006887}
6888
6889#ifdef MODULE
6890static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6891{
6892 return param_set_copystring(kmessage, kp);
6893}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006894#else /* #ifdef MODULE */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006895
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006896/**
6897 * kickstart_driver() - driver entry point
6898 *
6899 * This is the driver entry point
6900 * - delayed driver initialization when driver is statically linked
6901 * - invoked when module parameter fwpath is modified from userspace to signal
6902 * initializing the WLAN driver or when con_mode is modified from userspace
6903 * to signal a switch in operating mode
6904 *
6905 * Return: 0 for success, non zero for failure
6906 */
6907static int kickstart_driver(void)
6908{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006909 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006910
6911 if (!wlan_hdd_inited) {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006912 ret = __hdd_module_init();
6913 wlan_hdd_inited = ret ? 0 : 1;
6914
6915 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006916 }
6917
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006918 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006919
6920 msleep(200);
6921
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006922 ret = __hdd_module_init();
6923
6924 wlan_hdd_inited = ret ? 0 : 1;
6925
6926 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006927}
6928
6929/**
6930 * fwpath_changed_handler() - Handler Function
6931 *
6932 * Handle changes to the fwpath parameter
6933 *
6934 * Return: 0 for success, non zero for failure
6935 */
6936static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6937{
6938 int ret;
6939
6940 ret = param_set_copystring(kmessage, kp);
6941 if (0 == ret)
6942 ret = kickstart_driver();
6943 return ret;
6944}
6945
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006946#ifdef QCA_WIFI_FTM
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006947/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006948 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006949 *
6950 * Handler function for module param con_mode when it is changed by userspace
6951 * Dynamically linked - do nothing
6952 * Statically linked - exit and init driver, as in rmmod and insmod
6953 *
6954 * Return -
6955 */
6956static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
6957{
6958 int ret;
6959
6960 ret = param_set_int(kmessage, kp);
6961 if (0 == ret)
6962 ret = kickstart_driver();
6963 return ret;
6964}
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006965#endif /* QCA_WIFI_FTM */
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006966#endif /* #ifdef MODULE */
6967
6968/**
6969 * hdd_get_conparam() - driver exit point
6970 *
6971 * This is the driver exit point (invoked when module is unloaded using rmmod)
6972 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05306973 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006974 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306975enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006976{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306977 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006978}
6979
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006980void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006981{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006982 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006983}
6984
Komal Seelamc11bb222016-01-27 18:57:10 +05306985#ifdef WLAN_FEATURE_LPSS
6986static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6987{
6988 return hdd_ctx->config->enable_lpass_support;
6989}
6990#else
6991static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6992{
6993 return false;
6994}
6995#endif
6996
6997/**
Komal Seelamec702b02016-02-24 18:42:16 +05306998 * hdd_update_ol_config - API to update ol configuration parameters
6999 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05307000 *
Komal Seelamc11bb222016-01-27 18:57:10 +05307001 * Return: void
7002 */
Komal Seelamec702b02016-02-24 18:42:16 +05307003static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05307004{
Komal Seelamec702b02016-02-24 18:42:16 +05307005 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307006 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05307007
Komal Seelamec702b02016-02-24 18:42:16 +05307008 if (!ol_ctx)
7009 return;
7010
7011 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
7012 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
7013 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
7014 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
7015 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
7016
7017 ol_init_ini_config(ol_ctx, &cfg);
7018}
7019
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007020#ifdef FEATURE_RUNTIME_PM
7021/**
7022 * hdd_populate_runtime_cfg() - populate runtime configuration
7023 * @hdd_ctx: hdd context
7024 * @cfg: pointer to the configuration memory being populated
7025 *
7026 * Return: void
7027 */
7028static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7029 struct hif_config_info *cfg)
7030{
7031 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
7032 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
7033}
7034#else
7035static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7036 struct hif_config_info *cfg)
7037{
7038}
7039#endif
7040
Komal Seelamec702b02016-02-24 18:42:16 +05307041/**
7042 * hdd_update_hif_config - API to update HIF configuration parameters
7043 * @hdd_ctx: HDD Context
7044 *
7045 * Return: void
7046 */
7047static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
7048{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307049 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05307050 struct hif_config_info cfg;
7051
7052 if (!scn)
7053 return;
7054
7055 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007056 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05307057 hif_init_ini_config(scn, &cfg);
7058}
7059
7060/**
7061 * hdd_update_config() - Initialize driver per module ini parameters
7062 * @hdd_ctx: HDD Context
7063 *
7064 * API is used to initialize all driver per module configuration parameters
7065 * Return: void
7066 */
7067void hdd_update_config(hdd_context_t *hdd_ctx)
7068{
7069 hdd_update_ol_config(hdd_ctx);
7070 hdd_update_hif_config(hdd_ctx);
Komal Seelamc11bb222016-01-27 18:57:10 +05307071}
7072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007073/* Register the module init/exit functions */
7074module_init(hdd_module_init);
7075module_exit(hdd_module_exit);
7076
7077MODULE_LICENSE("Dual BSD/GPL");
7078MODULE_AUTHOR("Qualcomm Atheros, Inc.");
7079MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
7080
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007081#if !defined(MODULE) && defined(QCA_WIFI_FTM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007082module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
7083 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007084#else
7085module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007086#endif
7087
7088module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
7089 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
7090
7091module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
7092
7093module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
7094
7095module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);