blob: ba20df84a53420b2583db9f6aab00205a38e6a05 [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"
58#include "cdf_types.h"
59#include "cdf_trace.h"
60
61#include <net/addrconf.h>
62#include <linux/wireless.h>
63#include <net/cfg80211.h>
64#include <linux/inetdevice.h>
65#include <net/addrconf.h>
66#include "wlan_hdd_cfg80211.h"
67#include "wlan_hdd_ext_scan.h"
68#include "wlan_hdd_p2p.h"
69#include <linux/rtnetlink.h>
70#include "sap_api.h"
71#include <linux/semaphore.h>
72#include <linux/ctype.h>
73#include <linux/compat.h>
74#ifdef MSM_PLATFORM
75#ifdef CONFIG_CNSS
76#include <soc/qcom/subsystem_restart.h>
77#endif
78#endif
79#include <wlan_hdd_hostapd.h>
80#include <wlan_hdd_softap_tx_rx.h>
81#include "cfg_api.h"
82#include "qwlan_version.h"
83#include "wma_types.h"
84#include "wlan_hdd_tdls.h"
85#ifdef FEATURE_WLAN_CH_AVOID
86#ifdef CONFIG_CNSS
87#include <net/cnss.h>
88#endif
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053089#include "cds_regdomain.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080090
91#include "wlan_hdd_ocb.h"
92
93extern int hdd_hostapd_stop(struct net_device *dev);
94#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
150static cdf_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{
192 hdd_context_t *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
193 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
319 /* Make sure that this callback corresponds to our device. */
320 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
321 return NOTIFY_DONE;
322
323 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
324 (adapter->dev != dev)) {
325 hddLog(LOGE, FL("device adapter is not matching!!!"));
326 return NOTIFY_DONE;
327 }
328
329 if (!dev->ieee80211_ptr) {
330 hddLog(LOGE, FL("ieee80211_ptr is NULL!!!"));
331 return NOTIFY_DONE;
332 }
333
334 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
335 if (NULL == hdd_ctx) {
336 hddLog(CDF_TRACE_LEVEL_FATAL, FL("HDD Context Null Pointer"));
337 CDF_ASSERT(0);
338 return NOTIFY_DONE;
339 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800340 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341 return NOTIFY_DONE;
342
343 hddLog(CDF_TRACE_LEVEL_INFO, FL("%s New Net Device State = %lu"),
344 dev->name, state);
345
346 switch (state) {
347 case NETDEV_REGISTER:
348 break;
349
350 case NETDEV_UNREGISTER:
351 break;
352
353 case NETDEV_UP:
354 sme_ch_avoid_update_req(hdd_ctx->hHal);
355 break;
356
357 case NETDEV_DOWN:
358 break;
359
360 case NETDEV_CHANGE:
361 if (true == adapter->isLinkUpSvcNeeded)
362 complete(&adapter->linkup_event_var);
363 break;
364
365 case NETDEV_GOING_DOWN:
366 if (adapter->scan_info.mScanPending != false) {
367 unsigned long rc;
368 INIT_COMPLETION(adapter->scan_info.
369 abortscan_event_var);
370 hdd_abort_mac_scan(adapter->pHddCtx,
371 adapter->sessionId,
372 eCSR_SCAN_ABORT_DEFAULT);
373 rc = wait_for_completion_timeout(
374 &adapter->scan_info.abortscan_event_var,
375 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
376 if (!rc) {
377 hddLog(LOGE,
378 FL("Timeout occurred while waiting for abortscan"));
379 }
380 } else {
381 hddLog(CDF_TRACE_LEVEL_INFO,
382 FL("Scan is not Pending from user"));
383 }
384 break;
385
386 default:
387 break;
388 }
389
390 return NOTIFY_DONE;
391}
392
393/**
394 * hdd_netdev_notifier_call() - netdev notifier callback function
395 * @nb: pointer to notifier block
396 * @state: state
397 * @ndev: ndev pointer
398 *
399 * Return: 0 on success, error number otherwise.
400 */
401static int hdd_netdev_notifier_call(struct notifier_block *nb,
402 unsigned long state,
403 void *ndev)
404{
405 int ret;
406
407 cds_ssr_protect(__func__);
408 ret = __hdd_netdev_notifier_call(nb, state, ndev);
409 cds_ssr_unprotect(__func__);
410
411 return ret;
412}
413
414struct notifier_block hdd_netdev_notifier = {
415 .notifier_call = hdd_netdev_notifier_call,
416};
417
418/* variable to hold the insmod parameters */
419static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800420
421/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530424/**
425 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
426 * @ch_width: NL channel width
427 *
428 * Converts the NL channel width to the driver's internal representation
429 *
430 * Return: Converted channel width. In case of non matching NL channel width,
431 * CH_WIDTH_MAX will be returned.
432 */
433phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
434{
435 switch (ch_width) {
436 case NL80211_CHAN_WIDTH_20_NOHT:
437 case NL80211_CHAN_WIDTH_20:
438 return CH_WIDTH_20MHZ;
439 case NL80211_CHAN_WIDTH_40:
440 return CH_WIDTH_40MHZ;
441 break;
442 case NL80211_CHAN_WIDTH_80:
443 return CH_WIDTH_80MHZ;
444 case NL80211_CHAN_WIDTH_80P80:
445 return CH_WIDTH_80P80MHZ;
446 case NL80211_CHAN_WIDTH_160:
447 return CH_WIDTH_160MHZ;
448 case NL80211_CHAN_WIDTH_5:
449 case NL80211_CHAN_WIDTH_10:
450 default:
451 hdd_err("Invalid channel width %d, setting to default",
452 ch_width);
453 return CH_WIDTH_MAX;
454 }
455}
456
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530457/* wlan_hdd_find_opclass() - Find operating class for a channel
458 * @hal: handler to HAL
459 * @channel: channel id
460 * @bw_offset: bandwidth offset
461 *
462 * Function invokes sme api to find the operating class
463 *
464 * Return: operating class
465 */
466uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
467 uint8_t bw_offset)
468{
469 uint8_t opclass = 0;
470
471 sme_get_opclass(hal, channel, bw_offset, &opclass);
472 return opclass;
473}
474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475/**
476 * hdd_cdf_trace_enable() - configure initial CDF Trace enable
477 * @moduleId: Module whose trace level is being configured
478 * @bitmask: Bitmask of log levels to be enabled
479 *
480 * Called immediately after the cfg.ini is read in order to configure
481 * the desired trace levels.
482 *
483 * Return: None
484 */
485static void hdd_cdf_trace_enable(CDF_MODULE_ID moduleId, uint32_t bitmask)
486{
487 CDF_TRACE_LEVEL level;
488
489 /*
490 * if the bitmask is the default value, then a bitmask was not
491 * specified in cfg.ini, so leave the logging level alone (it
492 * will remain at the "compiled in" default value)
493 */
494 if (CFG_CDF_TRACE_ENABLE_DEFAULT == bitmask) {
495 return;
496 }
497
498 /* a mask was specified. start by disabling all logging */
499 cdf_trace_set_value(moduleId, CDF_TRACE_LEVEL_NONE, 0);
500
501 /* now cycle through the bitmask until all "set" bits are serviced */
502 level = CDF_TRACE_LEVEL_FATAL;
503 while (0 != bitmask) {
504 if (bitmask & 1) {
505 cdf_trace_set_value(moduleId, level, 1);
506 }
507 level++;
508 bitmask >>= 1;
509 }
510}
511
512/**
513 * wlan_hdd_validate_context() - check the HDD context
514 * @hdd_ctx: HDD context pointer
515 *
516 * Return: 0 if the context is valid. Error code otherwise
517 */
518int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
519{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
521 hddLog(LOGE, FL("HDD context is Null"));
522 return -ENODEV;
523 }
524
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800525 if (cds_is_driver_recovering()) {
526 hdd_err("Recovery in Progress. State: 0x%x Ignore!!!",
527 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 return -EAGAIN;
529 }
530
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800531 if (cds_is_load_or_unload_in_progress()) {
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800532 hdd_err("Unloading/Loading in Progress. Ignore!!!: 0x%x",
533 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534 return -EAGAIN;
535 }
536 return 0;
537}
538
539void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
540{
541 hdd_adapter_t *adapter = NULL;
542 hdd_station_ctx_t *pHddStaCtx = NULL;
543 eCsrPhyMode phyMode;
544 struct hdd_config *cfg_param = NULL;
545
546 if (NULL == hdd_ctx) {
547 hddLog(CDF_TRACE_LEVEL_FATAL, FL("HDD Context is null !!"));
548 return;
549 }
550
551 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
552 if (NULL == adapter) {
553 hddLog(CDF_TRACE_LEVEL_FATAL, FL("adapter is null !!"));
554 return;
555 }
556
557 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
558
559 cfg_param = hdd_ctx->config;
560 if (NULL == cfg_param) {
561 hddLog(CDF_TRACE_LEVEL_FATAL,
562 FL("cfg_params not available !!"));
563 return;
564 }
565
566 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
567
568 if (!hdd_ctx->isVHT80Allowed) {
569 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
570 (eCSR_DOT11_MODE_11ac == phyMode) ||
571 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
572 hddLog(CDF_TRACE_LEVEL_INFO,
573 FL("Setting phymode to 11n!!"));
574 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
575 eCSR_DOT11_MODE_11n);
576 }
577 } else {
578 /*
579 * New country Supports 11ac as well resetting value back from
580 * .ini
581 */
582 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
583 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
584 dot11Mode));
585 return;
586 }
587
588 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
589 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
590 || (eCSR_CFG_DOT11_MODE_11AC ==
591 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530592 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593
594 /* need to issue a disconnect to CSR. */
595 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530596 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800597 adapter->sessionId,
598 eCSR_DISCONNECT_REASON_UNSPECIFIED);
599
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530600 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 unsigned long rc;
602
603 rc = wait_for_completion_timeout(
604 &adapter->disconnect_comp_var,
605 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
606 if (!rc)
607 hddLog(LOGE,
608 FL("failure waiting for disconnect_comp_var"));
609 }
610 }
611}
612
613/**
614 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
615 * @hdd_adapter_t Hdd adapter.
616 *
617 * This function sets the IBSS power save config parameters to WMA
618 * which will send it to firmware if FW supports IBSS power save
619 * before vdev start.
620 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530621 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622 * on failure.
623 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530624QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625{
626 int ret;
627 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
628
629 if (hdd_ctx == NULL) {
630 hddLog(CDF_TRACE_LEVEL_ERROR,
631 FL("HDD context is null"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530632 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633 }
634
635 ret = wma_cli_set_command(adapter->sessionId,
636 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
637 hdd_ctx->config->ibssATIMWinSize,
638 VDEV_CMD);
639 if (0 != ret) {
640 hddLog(CDF_TRACE_LEVEL_ERROR,
641 FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530642 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643 }
644
645 ret = wma_cli_set_command(adapter->sessionId,
646 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
647 hdd_ctx->config->isIbssPowerSaveAllowed,
648 VDEV_CMD);
649 if (0 != ret) {
650 hddLog(CDF_TRACE_LEVEL_ERROR,
651 FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"),
652 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530653 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 }
655
656 ret = wma_cli_set_command(adapter->sessionId,
657 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
658 hdd_ctx->config->
659 isIbssPowerCollapseAllowed, VDEV_CMD);
660 if (0 != ret) {
661 hddLog(CDF_TRACE_LEVEL_ERROR,
662 FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"),
663 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530664 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 }
666
667 ret = wma_cli_set_command(adapter->sessionId,
668 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
669 hdd_ctx->config->isIbssAwakeOnTxRx,
670 VDEV_CMD);
671 if (0 != ret) {
672 hddLog(CDF_TRACE_LEVEL_ERROR,
673 FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530674 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 }
676
677 ret = wma_cli_set_command(adapter->sessionId,
678 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
679 hdd_ctx->config->ibssInactivityCount,
680 VDEV_CMD);
681 if (0 != ret) {
682 hddLog(CDF_TRACE_LEVEL_ERROR,
683 FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530684 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 }
686
687 ret = wma_cli_set_command(adapter->sessionId,
688 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
689 hdd_ctx->config->ibssTxSpEndInactivityTime,
690 VDEV_CMD);
691 if (0 != ret) {
692 hddLog(CDF_TRACE_LEVEL_ERROR,
693 FL(
694 "WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d"
695 ),
696 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530697 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 }
699
700 ret = wma_cli_set_command(adapter->sessionId,
701 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
702 hdd_ctx->config->ibssPsWarmupTime,
703 VDEV_CMD);
704 if (0 != ret) {
705 hddLog(CDF_TRACE_LEVEL_ERROR,
706 FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"),
707 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530708 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800709 }
710
711 ret = wma_cli_set_command(adapter->sessionId,
712 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
713 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
714 VDEV_CMD);
715 if (0 != ret) {
716 hddLog(CDF_TRACE_LEVEL_ERROR,
717 FL(
718 "WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d"
719 ),
720 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530721 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 }
723
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530724 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725}
726
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727#define INTF_MACADDR_MASK 0x7
728
729/**
730 * hdd_update_macaddr() - update mac address
731 * @config: hdd configuration
732 * @hw_macaddr: mac address
733 *
734 * Mac address for multiple virtual interface is found as following
735 * i) The mac address of the first interface is just the actual hw mac address.
736 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
737 * define the mac address for the remaining interfaces and locally
738 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
739 * supported virtual interfaces, right now this is 0x07 (meaning 8
740 * interface).
741 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
742 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
743 *
744 * Return: None
745 */
746void hdd_update_macaddr(struct hdd_config *config,
747 struct cdf_mac_addr hw_macaddr)
748{
749 int8_t i;
750 uint8_t macaddr_b3, tmp_br3;
751
752 cdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
753 CDF_MAC_ADDR_SIZE);
754 for (i = 1; i < CDF_MAX_CONCURRENCY_PERSONA; i++) {
755 cdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
756 CDF_MAC_ADDR_SIZE);
757 macaddr_b3 = config->intfMacAddr[i].bytes[3];
758 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
759 INTF_MACADDR_MASK;
760 macaddr_b3 += tmp_br3;
761
762 /* XOR-ing bit-24 of the mac address. This will give enough
763 * mac address range before collision
764 */
765 macaddr_b3 ^= (1 << 7);
766
767 /* Set locally administered bit */
768 config->intfMacAddr[i].bytes[0] |= 0x02;
769 config->intfMacAddr[i].bytes[3] = macaddr_b3;
770 hddLog(CDF_TRACE_LEVEL_INFO, "config->intfMacAddr[%d]: "
771 MAC_ADDRESS_STR, i,
772 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
773 }
774}
775
776static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
777 struct wma_tgt_services *cfg)
778{
779 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780
781 /* Set up UAPSD */
782 config->apUapsdEnabled &= cfg->uapsd;
783
784#ifdef WLAN_FEATURE_11AC
785 /* 11AC mode support */
786 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
787 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
788 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
789#endif /* #ifdef WLAN_FEATURE_11AC */
790
791 /* ARP offload: override user setting if invalid */
792 config->fhostArpOffload &= cfg->arp_offload;
793
794#ifdef FEATURE_WLAN_SCAN_PNO
795 /* PNO offload */
796 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
797 FL("PNO Capability in f/w = %d"), cfg->pno_offload);
798 if (cfg->pno_offload)
799 config->PnoOffload = true;
800#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800801#ifdef FEATURE_WLAN_TDLS
802 config->fEnableTDLSSupport &= cfg->en_tdls;
803 config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan;
804 config->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta;
805 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
806 config->fEnableTDLSSleepSta = true;
807 } else {
808 config->fEnableTDLSSleepSta = false;
809 }
810#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811#ifdef WLAN_FEATURE_ROAM_OFFLOAD
812 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
813#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700814 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815
816}
817
818static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
819 struct wma_tgt_ht_cap *cfg)
820{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530821 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 uint32_t value, val32;
823 uint16_t val16;
824 struct hdd_config *pconfig = hdd_ctx->config;
825 tSirMacHTCapabilityInfo *phtCapInfo;
826 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
827 uint8_t enable_tx_stbc;
828
829 /* check and update RX STBC */
830 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
831 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
832
833 /* get the MPDU density */
834 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
835
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530836 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837 hddLog(CDF_TRACE_LEVEL_ERROR,
838 FL("could not get MPDU DENSITY"));
839 value = 0;
840 }
841
842 /*
843 * MPDU density:
844 * override user's setting if value is larger
845 * than the one supported by target
846 */
847 if (value > cfg->mpdu_density) {
848 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
849 cfg->mpdu_density);
850
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530851 if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852 hddLog(CDF_TRACE_LEVEL_FATAL,
853 FL("could not set MPDU DENSITY to CCM"));
854 }
855
856 /* get the HT capability info */
857 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530858 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859 hddLog(CDF_TRACE_LEVEL_ERROR,
860 FL("could not get HT capability info"));
861 return;
862 }
863 val16 = (uint16_t) val32;
864 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
865
866 /* Set the LDPC capability */
867 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
868
869 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
870 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
871
872 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
873 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
874
875 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
876 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
877
878 enable_tx_stbc = pconfig->enableTxSTBC;
879
880 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
881 pconfig->enable2x2 = 1;
882 } else {
883 pconfig->enable2x2 = 0;
884 enable_tx_stbc = 0;
885
886 /* 1x1 */
887 /* Update Rx Highest Long GI data Rate */
888 if (sme_cfg_set_int(hdd_ctx->hHal,
889 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
890 HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530891 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800892 hddLog(LOGE,
893 FL(
894 "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"
895 ));
896 }
897
898 /* Update Tx Highest Long GI data Rate */
899 if (sme_cfg_set_int
900 (hdd_ctx->hHal,
901 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
902 HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530903 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 hddLog(LOGE,
905 FL(
906 "Could not pass on HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"
907 ));
908 }
909 }
910 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
911 enable_tx_stbc = 0;
912 phtCapInfo->txSTBC = enable_tx_stbc;
913
914 val32 = val16;
915 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530916 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 hddLog(CDF_TRACE_LEVEL_FATAL,
918 FL("could not set HT capability to CCM"));
919#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
920 value = SIZE_OF_SUPPORTED_MCS_SET;
921 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530922 &value) == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 hddLog(CDF_TRACE_LEVEL_INFO, FL("Read MCS rate set"));
924
925 if (pconfig->enable2x2) {
926 for (value = 0; value < cfg->num_rf_chains; value++)
927 mcs_set[value] =
928 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
929
930 status =
931 sme_cfg_set_str(hdd_ctx->hHal,
932 WNI_CFG_SUPPORTED_MCS_SET,
933 mcs_set,
934 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530935 if (status == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936 hddLog(CDF_TRACE_LEVEL_FATAL,
937 FL("could not set MCS SET to CCM"));
938 }
939 }
940#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
941}
942
943#ifdef WLAN_FEATURE_11AC
944static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
945 struct wma_tgt_vht_cap *cfg)
946{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530947 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948 uint32_t value = 0;
949 struct hdd_config *pconfig = hdd_ctx->config;
950 struct wiphy *wiphy = hdd_ctx->wiphy;
951 struct ieee80211_supported_band *band_5g =
952 wiphy->bands[IEEE80211_BAND_5GHZ];
953
954 /* Get the current MPDU length */
955 status =
956 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
957 &value);
958
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530959 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800960 hddLog(CDF_TRACE_LEVEL_ERROR, FL("could not get MPDU LENGTH"));
961 value = 0;
962 }
963
964 /*
965 * VHT max MPDU length:
966 * override if user configured value is too high
967 * that the target cannot support
968 */
969 if (value > cfg->vht_max_mpdu) {
970 status = sme_cfg_set_int(hdd_ctx->hHal,
971 WNI_CFG_VHT_MAX_MPDU_LENGTH,
972 cfg->vht_max_mpdu);
973
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530974 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800975 hddLog(CDF_TRACE_LEVEL_FATAL,
976 FL("could not set VHT MAX MPDU LENGTH"));
977 }
978 }
979
980 /* Get the current supported chan width */
981 status = sme_cfg_get_int(hdd_ctx->hHal,
982 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
983 &value);
984
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530985 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986 hddLog(CDF_TRACE_LEVEL_ERROR,
987 FL("could not get MPDU LENGTH"));
988 value = 0;
989 }
990
991 /* Get the current RX LDPC setting */
992 status =
993 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
994 &value);
995
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530996 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997 hddLog(CDF_TRACE_LEVEL_ERROR,
998 FL("could not get VHT LDPC CODING CAP"));
999 value = 0;
1000 }
1001
1002 /* Set the LDPC capability */
1003 if (value && !cfg->vht_rx_ldpc) {
1004 status = sme_cfg_set_int(hdd_ctx->hHal,
1005 WNI_CFG_VHT_LDPC_CODING_CAP,
1006 cfg->vht_rx_ldpc);
1007
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301008 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001009 hddLog(CDF_TRACE_LEVEL_FATAL,
1010 FL("could not set VHT LDPC CODING CAP to CCM"));
1011 }
1012 }
1013
1014 /* Get current GI 80 value */
1015 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1016 &value);
1017
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301018 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019 hddLog(CDF_TRACE_LEVEL_ERROR,
1020 FL("could not get SHORT GI 80MHZ"));
1021 value = 0;
1022 }
1023
1024 /* set the Guard interval 80MHz */
1025 if (value && !cfg->vht_short_gi_80) {
1026 status = sme_cfg_set_int(hdd_ctx->hHal,
1027 WNI_CFG_VHT_SHORT_GI_80MHZ,
1028 cfg->vht_short_gi_80);
1029
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301030 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 hddLog(CDF_TRACE_LEVEL_FATAL,
1032 FL("could not set SHORT GI 80MHZ to CCM"));
1033 }
1034 }
1035
1036 /* Get current GI 160 value */
1037 status = sme_cfg_get_int(hdd_ctx->hHal,
1038 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1039 &value);
1040
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301041 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 hddLog(CDF_TRACE_LEVEL_ERROR,
1043 FL("could not get SHORT GI 80 & 160"));
1044 value = 0;
1045 }
1046
1047 /* Get VHT TX STBC cap */
1048 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1049
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301050 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001051 hddLog(CDF_TRACE_LEVEL_ERROR,
1052 FL("could not get VHT TX STBC"));
1053 value = 0;
1054 }
1055
1056 /* VHT TX STBC cap */
1057 if (value && !cfg->vht_tx_stbc) {
1058 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1059 cfg->vht_tx_stbc);
1060
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301061 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001062 hddLog(CDF_TRACE_LEVEL_FATAL,
1063 FL("could not set the VHT TX STBC to CCM"));
1064 }
1065 }
1066
1067 /* Get VHT RX STBC cap */
1068 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1069
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301070 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 hddLog(CDF_TRACE_LEVEL_ERROR,
1072 FL("could not get VHT RX STBC"));
1073 value = 0;
1074 }
1075
1076 /* VHT RX STBC cap */
1077 if (value && !cfg->vht_rx_stbc) {
1078 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1079 cfg->vht_rx_stbc);
1080
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301081 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 hddLog(CDF_TRACE_LEVEL_FATAL,
1083 FL("could not set the VHT RX STBC to CCM"));
1084 }
1085 }
1086
1087 /* Get VHT SU Beamformer cap */
1088 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1089 &value);
1090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301091 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092 hddLog(CDF_TRACE_LEVEL_ERROR,
1093 FL("could not get VHT SU BEAMFORMER CAP"));
1094 value = 0;
1095 }
1096
1097 /* set VHT SU Beamformer cap */
1098 if (value && !cfg->vht_su_bformer) {
1099 status = sme_cfg_set_int(hdd_ctx->hHal,
1100 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1101 cfg->vht_su_bformer);
1102
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301103 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001104 hddLog(CDF_TRACE_LEVEL_FATAL,
1105 FL("could not set VHT SU BEAMFORMER CAP"));
1106 }
1107 }
1108
1109 /* check and update SU BEAMFORMEE capabality */
1110 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1111 pconfig->enableTxBF = cfg->vht_su_bformee;
1112
1113 status = sme_cfg_set_int(hdd_ctx->hHal,
1114 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1115 pconfig->enableTxBF);
1116
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301117 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118 hddLog(CDF_TRACE_LEVEL_FATAL,
1119 FL("could not set VHT SU BEAMFORMEE CAP"));
1120 }
1121
1122 /* Get VHT MU Beamformer cap */
1123 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1124 &value);
1125
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301126 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001127 hddLog(CDF_TRACE_LEVEL_ERROR,
1128 FL("could not get VHT MU BEAMFORMER CAP"));
1129 value = 0;
1130 }
1131
1132 /* set VHT MU Beamformer cap */
1133 if (value && !cfg->vht_mu_bformer) {
1134 status = sme_cfg_set_int(hdd_ctx->hHal,
1135 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1136 cfg->vht_mu_bformer);
1137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301138 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139 hddLog(CDF_TRACE_LEVEL_FATAL,
1140 FL(
1141 "could not set the VHT MU BEAMFORMER CAP to CCM"
1142 ));
1143 }
1144 }
1145
1146 /* Get VHT MU Beamformee cap */
1147 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1148 &value);
1149
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301150 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 hddLog(CDF_TRACE_LEVEL_ERROR,
1152 FL("could not get VHT MU BEAMFORMEE CAP"));
1153 value = 0;
1154 }
1155
1156 /* set VHT MU Beamformee cap */
1157 if (value && !cfg->vht_mu_bformee) {
1158 status = sme_cfg_set_int(hdd_ctx->hHal,
1159 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1160 cfg->vht_mu_bformee);
1161
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301162 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001163 hddLog(CDF_TRACE_LEVEL_FATAL,
1164 FL("could not set VHT MU BEAMFORMER CAP"));
1165 }
1166 }
1167
1168 /* Get VHT MAX AMPDU Len exp */
1169 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1170 &value);
1171
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301172 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001173 hddLog(CDF_TRACE_LEVEL_ERROR,
1174 FL("could not get VHT AMPDU LEN"));
1175 value = 0;
1176 }
1177
1178 /*
1179 * VHT max AMPDU len exp:
1180 * override if user configured value is too high
1181 * that the target cannot support.
1182 * Even though Rome publish ampdu_len=7, it can
1183 * only support 4 because of some h/w bug.
1184 */
1185
1186 if (value > cfg->vht_max_ampdu_len_exp) {
1187 status = sme_cfg_set_int(hdd_ctx->hHal,
1188 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1189 cfg->vht_max_ampdu_len_exp);
1190
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301191 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 hddLog(CDF_TRACE_LEVEL_FATAL,
1193 FL("could not set the VHT AMPDU LEN EXP"));
1194 }
1195 }
1196
1197 /* Get VHT TXOP PS CAP */
1198 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1199
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301200 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201 hddLog(CDF_TRACE_LEVEL_ERROR,
1202 FL("could not get VHT TXOP PS"));
1203 value = 0;
1204 }
1205
1206 /* set VHT TXOP PS cap */
1207 if (value && !cfg->vht_txop_ps) {
1208 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1209 cfg->vht_txop_ps);
1210
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301211 if (status == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212 hddLog(CDF_TRACE_LEVEL_FATAL,
1213 FL("could not set the VHT TXOP PS"));
1214 }
1215 }
1216
1217 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1218 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1219 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1220 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1221 else
1222 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1223
1224
1225 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1226 band_5g->vht_cap.cap |=
1227 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1228 }
1229 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1230 band_5g->vht_cap.cap |=
1231 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1232 }
1233
1234 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1235 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1236
1237 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1238 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1239 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1240 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1241
1242 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1243 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1244
1245 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1246 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1247 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1248 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1249 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1250 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1251
1252 band_5g->vht_cap.cap |=
1253 (cfg->vht_max_ampdu_len_exp <<
1254 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1255
1256 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1257 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1258 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1259 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1260 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1261 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1262 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1263 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1264
1265 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1266 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1267
1268}
1269#endif /* #ifdef WLAN_FEATURE_11AC */
1270
1271void hdd_update_tgt_cfg(void *context, void *param)
1272{
1273 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1274 struct wma_tgt_cfg *cfg = param;
1275 uint8_t temp_band_cap;
1276
1277 /* first store the INI band capability */
1278 temp_band_cap = hdd_ctx->config->nBandCapability;
1279
1280 hdd_ctx->config->nBandCapability = cfg->band_cap;
1281
1282 /* now overwrite the target band capability with INI
1283 setting if INI setting is a subset */
1284
1285 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1286 (temp_band_cap != eCSR_BAND_ALL))
1287 hdd_ctx->config->nBandCapability = temp_band_cap;
1288 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1289 (temp_band_cap != eCSR_BAND_ALL) &&
1290 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
1291 hddLog(CDF_TRACE_LEVEL_WARN,
1292 FL("ini BandCapability not supported by the target"));
1293 }
1294
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001295 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001296 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1297 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1298 }
1299
1300 /* This can be extended to other configurations like ht, vht cap... */
1301
1302 if (!cdf_is_macaddr_zero(&cfg->hw_macaddr)) {
1303 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1304 } else {
1305 hddLog(CDF_TRACE_LEVEL_ERROR,
1306 FL(
1307 "Invalid MAC passed from target, using MAC from ini file"
1308 MAC_ADDRESS_STR),
1309 MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes));
1310 }
1311
1312 hdd_ctx->target_fw_version = cfg->target_fw_version;
1313
1314 hdd_ctx->max_intf_count = cfg->max_intf_count;
1315
1316#ifdef WLAN_FEATURE_LPSS
1317 hdd_ctx->lpss_support = cfg->lpss_support;
1318#endif
1319
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001320 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1323 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1324
1325 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1326
1327#ifdef WLAN_FEATURE_11AC
1328 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
1329#endif /* #ifdef WLAN_FEATURE_11AC */
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001330 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
1331 hdd_info(FL("fine_time_meas_cap: 0x%x"),
1332 hdd_ctx->config->fine_time_meas_cap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333}
1334
1335/**
1336 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1337 * @context: HDD context pointer
1338 * @param: HDD radar indication pointer
1339 *
1340 * This function is invoked when a radar in found on the
1341 * SAP current operating channel and Data Tx from netif
1342 * has to be stopped to honor the DFS regulations.
1343 * Actions: Stop the netif Tx queues,Indicate Radar present
1344 * in HDD context for future usage.
1345 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301346 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301348bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349{
1350 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1351 struct wma_dfs_radar_ind *hdd_radar_event =
1352 (struct wma_dfs_radar_ind *)param;
1353 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1354 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301355 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301357 if (!hdd_ctx || !hdd_radar_event ||
1358 hdd_ctx->config->disableDFSChSwitch)
1359 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001360
1361 if (true == hdd_radar_event->dfs_radar_status) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301362 mutex_lock(&hdd_ctx->dfs_lock);
1363 if (hdd_ctx->dfs_radar_found) {
1364 /*
1365 * Application already triggered channel switch
1366 * on current channel, so return here.
1367 */
1368 mutex_unlock(&hdd_ctx->dfs_lock);
1369 return false;
1370 }
1371
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 hdd_ctx->dfs_radar_found = true;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301373 mutex_unlock(&hdd_ctx->dfs_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374
1375 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301376 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 adapter = adapterNode->pAdapter;
1378 if (WLAN_HDD_SOFTAP == adapter->device_mode ||
1379 WLAN_HDD_P2P_GO == adapter->device_mode) {
1380 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1381 dfs_cac_block_tx = true;
1382 }
1383
1384 status = hdd_get_next_adapter(hdd_ctx,
1385 adapterNode,
1386 &pNext);
1387 adapterNode = pNext;
1388 }
1389 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301390
1391 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001393
1394/**
1395 * hdd_is_valid_mac_address() - validate MAC address
1396 * @pMacAddr: Pointer to the input MAC address
1397 *
1398 * This function validates whether the given MAC address is valid or not
1399 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1400 * where X is the hexa decimal digit character and separated by ':'
1401 * This algorithm works even if MAC address is not separated by ':'
1402 *
1403 * This code checks given input string mac contains exactly 12 hexadecimal
1404 * digits and a separator colon : appears in the input string only after
1405 * an even number of hex digits.
1406 *
1407 * Return: 1 for valid and 0 for invalid
1408 */
1409bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1410{
1411 int xdigit = 0;
1412 int separator = 0;
1413 while (*pMacAddr) {
1414 if (isxdigit(*pMacAddr)) {
1415 xdigit++;
1416 } else if (':' == *pMacAddr) {
1417 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1418 break;
1419
1420 ++separator;
1421 } else {
1422 /* Invalid MAC found */
1423 return 0;
1424 }
1425 ++pMacAddr;
1426 }
1427 return xdigit == 12 && (separator == 5 || separator == 0);
1428}
1429
1430/**
1431 * __hdd_open() - HDD Open function
1432 * @dev: Pointer to net_device structure
1433 *
1434 * This is called in response to ifconfig up
1435 *
1436 * Return: 0 for success; non-zero for failure
1437 */
1438static int __hdd_open(struct net_device *dev)
1439{
1440 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1441 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1442 int ret;
1443
1444 MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
1445 adapter->sessionId, adapter->device_mode));
1446
1447 ret = wlan_hdd_validate_context(hdd_ctx);
1448 if (0 != ret) {
1449 hddLog(LOGE, FL("HDD context is not valid"));
1450 return ret;
1451 }
1452
1453 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1454 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
1455 hddLog(LOG1, FL("Enabling Tx Queues"));
1456 /* Enable TX queues only when we are connected */
1457 wlan_hdd_netif_queue_control(adapter,
1458 WLAN_START_ALL_NETIF_QUEUE,
1459 WLAN_CONTROL_PATH);
1460 }
1461
1462 return ret;
1463}
1464
1465/**
1466 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1467 * @dev: Pointer to net_device structure
1468 *
1469 * This is called in response to ifconfig up
1470 *
1471 * Return: 0 for success; non-zero for failure
1472 */
1473int hdd_open(struct net_device *dev)
1474{
1475 int ret;
1476
1477 cds_ssr_protect(__func__);
1478 ret = __hdd_open(dev);
1479 cds_ssr_unprotect(__func__);
1480
1481 return ret;
1482}
1483
1484/**
1485 * __hdd_stop() - HDD stop function
1486 * @dev: Pointer to net_device structure
1487 *
1488 * This is called in response to ifconfig down
1489 *
1490 * Return: 0 for success; non-zero for failure
1491 */
1492static int __hdd_stop(struct net_device *dev)
1493{
1494 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1495 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1496 int ret;
1497
1498 ENTER();
1499
1500 MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
1501 adapter->sessionId, adapter->device_mode));
1502
1503 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301504 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506
1507 /* Nothing to be done if the interface is not opened */
1508 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
1509 hddLog(CDF_TRACE_LEVEL_ERROR,
1510 FL("NETDEV Interface is not OPENED"));
1511 return -ENODEV;
1512 }
1513
1514 /* Make sure the interface is marked as closed */
1515 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1516 hddLog(CDF_TRACE_LEVEL_INFO, FL("Disabling OS Tx queues"));
1517
1518 /*
1519 * Disable TX on the interface, after this hard_start_xmit() will not
1520 * be called on that interface
1521 */
1522 hddLog(LOG1, FL("Disabling queues"));
1523 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1524 WLAN_CONTROL_PATH);
1525
1526 /*
1527 * The interface is marked as down for outside world (aka kernel)
1528 * But the driver is pretty much alive inside. The driver needs to
1529 * tear down the existing connection on the netdev (session)
1530 * cleanup the data pipes and wait until the control plane is stabilized
1531 * for this interface. The call also needs to wait until the above
1532 * mentioned actions are completed before returning to the caller.
1533 * Notice that the hdd_stop_adapter is requested not to close the session
1534 * That is intentional to be able to scan if it is a STA/P2P interface
1535 */
1536 hdd_stop_adapter(hdd_ctx, adapter, false);
1537
1538 /* DeInit the adapter. This ensures datapath cleanup as well */
1539 hdd_deinit_adapter(hdd_ctx, adapter, true);
1540
1541 EXIT();
1542 return 0;
1543}
1544
1545/**
1546 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
1547 * @dev: pointer to net_device structure
1548 *
1549 * This is called in response to ifconfig down
1550 *
1551 * Return: 0 for success and error number for failure
1552 */
1553int hdd_stop(struct net_device *dev)
1554{
1555 int ret;
1556
1557 cds_ssr_protect(__func__);
1558 ret = __hdd_stop(dev);
1559 cds_ssr_unprotect(__func__);
1560
1561 return ret;
1562}
1563
1564/**
1565 * __hdd_uninit() - HDD uninit function
1566 * @dev: Pointer to net_device structure
1567 *
1568 * This is called during the netdev unregister to uninitialize all data
1569 * associated with the device
1570 *
1571 * Return: None
1572 */
1573static void __hdd_uninit(struct net_device *dev)
1574{
1575 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1576
1577 ENTER();
1578
1579 do {
1580 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1581 hddLog(LOGP, FL("Invalid magic"));
1582 break;
1583 }
1584
1585 if (NULL == adapter->pHddCtx) {
1586 hddLog(LOGP, FL("NULL hdd_ctx"));
1587 break;
1588 }
1589
1590 if (dev != adapter->dev) {
1591 hddLog(LOGP, FL("Invalid device reference"));
1592 /*
1593 * we haven't validated all cases so let this go for
1594 * now
1595 */
1596 }
1597
1598 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
1599
1600 /* after uninit our adapter structure will no longer be valid */
1601 adapter->dev = NULL;
1602 adapter->magic = 0;
1603 } while (0);
1604
1605 EXIT();
1606}
1607
1608/**
1609 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
1610 * @dev: pointer to net_device structure
1611 *
1612 * This is called during the netdev unregister to uninitialize all data
1613 * associated with the device
1614 *
1615 * Return: none
1616 */
1617static void hdd_uninit(struct net_device *dev)
1618{
1619 cds_ssr_protect(__func__);
1620 __hdd_uninit(dev);
1621 cds_ssr_unprotect(__func__);
1622}
1623
1624/**
1625 * __hdd_set_mac_address() - set the user specified mac address
1626 * @dev: Pointer to the net device.
1627 * @addr: Pointer to the sockaddr.
1628 *
1629 * This function sets the user specified mac address using
1630 * the command ifconfig wlanX hw ether <mac adress>.
1631 *
1632 * Return: 0 for success, non zero for failure
1633 */
1634static int __hdd_set_mac_address(struct net_device *dev, void *addr)
1635{
1636 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1637 hdd_context_t *hdd_ctx;
1638 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301639 QDF_STATUS cdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001640 int ret;
1641
1642 ENTER();
1643
1644 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1645 ret = wlan_hdd_validate_context(hdd_ctx);
1646 if (0 != ret)
1647 return ret;
1648
1649 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1650 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1651
1652 EXIT();
1653 return cdf_ret_status;
1654}
1655
1656/**
1657 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
1658 * function from SSR
1659 * @dev: pointer to net_device structure
1660 * @addr: Pointer to the sockaddr
1661 *
1662 * This function sets the user specified mac address using
1663 * the command ifconfig wlanX hw ether <mac adress>.
1664 *
1665 * Return: 0 for success.
1666 */
1667static int hdd_set_mac_address(struct net_device *dev, void *addr)
1668{
1669 int ret;
1670
1671 cds_ssr_protect(__func__);
1672 ret = __hdd_set_mac_address(dev, addr);
1673 cds_ssr_unprotect(__func__);
1674
1675 return ret;
1676}
1677
1678uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
1679{
1680 int i;
1681 for (i = 0; i < CDF_MAX_CONCURRENCY_PERSONA; i++) {
1682 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
1683 break;
1684 }
1685
1686 if (CDF_MAX_CONCURRENCY_PERSONA == i)
1687 return NULL;
1688
1689 hdd_ctx->config->intfAddrMask |= (1 << i);
1690 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
1691}
1692
1693void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
1694{
1695 int i;
1696 for (i = 0; i < CDF_MAX_CONCURRENCY_PERSONA; i++) {
1697 if (!memcmp(releaseAddr,
1698 &hdd_ctx->config->intfMacAddr[i].bytes[0],
1699 6)) {
1700 hdd_ctx->config->intfAddrMask &= ~(1 << i);
1701 break;
1702 }
1703 }
1704 return;
1705}
1706
1707#ifdef WLAN_FEATURE_PACKET_FILTERING
1708/**
1709 * __hdd_set_multicast_list() - set the multicast address list
1710 * @dev: Pointer to the WLAN device.
1711 * @skb: Pointer to OS packet (sk_buff).
1712 *
1713 * This funciton sets the multicast address list.
1714 *
1715 * Return: None
1716 */
1717static void __hdd_set_multicast_list(struct net_device *dev)
1718{
1719 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1720 int mc_count;
1721 int i = 0, status;
1722 struct netdev_hw_addr *ha;
1723 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1724 static const uint8_t ipv6_router_solicitation[]
1725 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
1726
Peng Xuf5d60c82015-10-02 17:17:03 -07001727 if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05301728 return;
1729
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301730 ENTER();
1731
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301733 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001734 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001735
1736 if (dev->flags & IFF_ALLMULTI) {
1737 hddLog(CDF_TRACE_LEVEL_INFO,
1738 FL("allow all multicast frames"));
1739 adapter->mc_addr_list.mc_cnt = 0;
1740 } else {
1741 mc_count = netdev_mc_count(dev);
1742 hddLog(CDF_TRACE_LEVEL_INFO,
1743 FL("mc_count = %u"), mc_count);
1744 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
1745 hddLog(CDF_TRACE_LEVEL_INFO,
1746 FL(
1747 "No free filter available; allow all multicast frames"
1748 ));
1749 adapter->mc_addr_list.mc_cnt = 0;
1750 return;
1751 }
1752
1753 adapter->mc_addr_list.mc_cnt = mc_count;
1754
1755 netdev_for_each_mc_addr(ha, dev) {
1756 if (i == mc_count)
1757 break;
1758 /*
1759 * Skip following addresses:
1760 * 1)IPv6 router solicitation address
1761 * 2)Any other address pattern if its set during
1762 * RXFILTER REMOVE driver command based on
1763 * addr_filter_pattern
1764 */
1765 if ((!memcmp(ha->addr, ipv6_router_solicitation,
1766 ETH_ALEN)) ||
1767 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
1768 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08001769 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 MAC_ADDR_ARRAY(ha->addr));
1771 adapter->mc_addr_list.mc_cnt--;
1772 continue;
1773 }
1774
1775 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
1776 ETH_ALEN);
1777 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
1778 ETH_ALEN);
1779 hddLog(CDF_TRACE_LEVEL_INFO,
1780 FL("mlist[%d] = " MAC_ADDRESS_STR), i,
1781 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
1782 i++;
1783 }
1784 }
1785 if (hdd_ctx->config->active_mode_offload) {
1786 hdd_info("enable mc filtering");
1787 wlan_hdd_set_mc_addr_list(adapter, true);
1788 } else {
1789 hdd_info("skip mc filtering enable it during cfg80211 suspend");
1790 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301791 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001792 return;
1793}
1794
1795/**
1796 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
1797 * @dev: pointer to net_device
1798 *
1799 * Return: none
1800 */
1801static void hdd_set_multicast_list(struct net_device *dev)
1802{
1803 cds_ssr_protect(__func__);
1804 __hdd_set_multicast_list(dev);
1805 cds_ssr_unprotect(__func__);
1806}
1807#endif
1808
1809/**
1810 * hdd_select_queue() - used by Linux OS to decide which queue to use first
1811 * @dev: Pointer to the WLAN device.
1812 * @skb: Pointer to OS packet (sk_buff).
1813 *
1814 * This function is registered with the Linux OS for network
1815 * core to decide which queue to use first.
1816 *
1817 * Return: ac, Queue Index/access category corresponding to UP in IP header
1818 */
1819static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
1820#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
1821 , void *accel_priv
1822#endif
1823#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1824 , select_queue_fallback_t fallback
1825#endif
1826)
1827{
1828 return hdd_wmm_select_queue(dev, skb);
1829}
1830
1831static struct net_device_ops wlan_drv_ops = {
1832 .ndo_open = hdd_open,
1833 .ndo_stop = hdd_stop,
1834 .ndo_uninit = hdd_uninit,
1835 .ndo_start_xmit = hdd_hard_start_xmit,
1836 .ndo_tx_timeout = hdd_tx_timeout,
1837 .ndo_get_stats = hdd_get_stats,
1838 .ndo_do_ioctl = hdd_ioctl,
1839 .ndo_set_mac_address = hdd_set_mac_address,
1840 .ndo_select_queue = hdd_select_queue,
1841#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001842 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843#endif
1844};
1845
1846void hdd_set_station_ops(struct net_device *pWlanDev)
1847{
1848 pWlanDev->netdev_ops = &wlan_drv_ops;
1849}
1850
1851static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
1852 tSirMacAddr macAddr,
1853 const char *name)
1854{
1855 struct net_device *pWlanDev = NULL;
1856 hdd_adapter_t *adapter = NULL;
1857 /*
1858 * cfg80211 initialization and registration....
1859 */
1860 pWlanDev =
1861 alloc_netdev_mq(sizeof(hdd_adapter_t), name,
1862#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
1863 NET_NAME_UNKNOWN,
1864#endif
1865 ether_setup,
1866 NUM_TX_QUEUES);
1867
1868 if (pWlanDev != NULL) {
1869
1870 /* Save the pointer to the net_device in the HDD adapter */
1871 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
1872
1873 cdf_mem_zero(adapter, sizeof(hdd_adapter_t));
1874
1875 adapter->dev = pWlanDev;
1876 adapter->pHddCtx = hdd_ctx;
1877 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1878
1879 init_completion(&adapter->session_open_comp_var);
1880 init_completion(&adapter->session_close_comp_var);
1881 init_completion(&adapter->disconnect_comp_var);
1882 init_completion(&adapter->linkup_event_var);
1883 init_completion(&adapter->cancel_rem_on_chan_var);
1884 init_completion(&adapter->rem_on_chan_ready_event);
1885 init_completion(&adapter->sta_authorized_event);
1886 init_completion(&adapter->offchannel_tx_event);
1887 init_completion(&adapter->tx_action_cnf_event);
1888#ifdef FEATURE_WLAN_TDLS
1889 init_completion(&adapter->tdls_add_station_comp);
1890 init_completion(&adapter->tdls_del_station_comp);
1891 init_completion(&adapter->tdls_mgmt_comp);
1892 init_completion(&adapter->tdls_link_establish_req_comp);
1893#endif
1894 init_completion(&adapter->change_country_code);
1895
1896
1897 init_completion(&adapter->scan_info.abortscan_event_var);
1898
1899 adapter->offloads_configured = false;
1900 adapter->isLinkUpSvcNeeded = false;
1901 adapter->higherDtimTransition = true;
1902 /* Init the net_device structure */
1903 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1904
1905 cdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
1906 sizeof(tSirMacAddr));
1907 cdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
1908 sizeof(tSirMacAddr));
1909 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910
1911 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
1912 pWlanDev->features |=
1913 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
1914 pWlanDev->features |= NETIF_F_RXCSUM;
1915
Dhanashri Atre83d373d2015-07-28 16:45:59 -07001916 hdd_set_tso_flags(hdd_ctx, pWlanDev);
1917
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 hdd_set_station_ops(adapter->dev);
1919
1920 pWlanDev->destructor = free_netdev;
1921 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08001922 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 adapter->wdev.wiphy = hdd_ctx->wiphy;
1924 adapter->wdev.netdev = pWlanDev;
1925 /* set pWlanDev's parent to underlying device */
1926 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
1927 hdd_wmm_init(adapter);
1928 spin_lock_init(&adapter->pause_map_lock);
1929 }
1930
1931 return adapter;
1932}
1933
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301934QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001935 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936{
1937 struct net_device *pWlanDev = adapter->dev;
1938 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
1939 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301940 /* QDF_STATUS cdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001942 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
1944 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
1945 hddLog(CDF_TRACE_LEVEL_ERROR,
1946 FL("Failed:dev_alloc_name"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301947 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 }
1949 }
1950 if (register_netdevice(pWlanDev)) {
1951 hddLog(CDF_TRACE_LEVEL_ERROR,
1952 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301953 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 }
1955 } else {
1956 if (register_netdev(pWlanDev)) {
1957 hddLog(CDF_TRACE_LEVEL_ERROR,
1958 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301959 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 }
1961 }
1962 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
1963
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301964 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965}
1966
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301967static QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968{
1969 hdd_adapter_t *adapter = pContext;
1970
1971 if (NULL == adapter) {
1972 hddLog(CDF_TRACE_LEVEL_FATAL, FL("NULL adapter"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301973 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 }
1975
1976 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1977 hddLog(CDF_TRACE_LEVEL_FATAL, FL("Invalid magic"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301978 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 }
1980
1981 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
1982
1983#if !defined (CONFIG_CNSS) && \
1984 !defined (WLAN_OPEN_SOURCE)
1985 /*
1986 * need to make sure all of our scheduled work has completed.
1987 * This callback is called from MC thread context, so it is safe to
1988 * to call below flush workqueue API from here.
1989 *
1990 * Even though this is called from MC thread context, if there is a faulty
1991 * work item in the system, that can hang this call forever. So flushing
1992 * this global work queue is not safe; and now we make sure that
1993 * individual work queues are stopped correctly. But the cancel work queue
1994 * is a GPL only API, so the proprietary version of the driver would still
1995 * rely on the global work queue flush.
1996 */
1997 flush_scheduled_work();
1998#endif
1999
2000 /*
2001 * We can be blocked while waiting for scheduled work to be
2002 * flushed, and the adapter structure can potentially be freed, in
2003 * which case the magic will have been reset. So make sure the
2004 * magic is still good, and hence the adapter structure is still
2005 * valid, before signaling completion
2006 */
2007 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2008 complete(&adapter->session_close_comp_var);
2009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302010 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011}
2012
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302013QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014{
2015 struct net_device *pWlanDev = adapter->dev;
2016 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2017 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302018 QDF_STATUS cdf_ret_status = QDF_STATUS_SUCCESS;
2019 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 uint32_t type, subType;
2021 unsigned long rc;
2022 int ret_val;
2023
2024 INIT_COMPLETION(adapter->session_open_comp_var);
2025 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
2026 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302027 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 hddLog(LOGE, FL("failed to get vdev type"));
2029 goto error_sme_open;
2030 }
2031 /* Open a SME session for future operation */
2032 cdf_ret_status =
2033 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2034 (uint8_t *) &adapter->macAddressCurrent,
2035 &adapter->sessionId, type, subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302036 if (!QDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 hddLog(LOGP,
2038 FL("sme_open_session() failed, status code %08d [x%08x]"),
2039 cdf_ret_status, cdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302040 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 goto error_sme_open;
2042 }
2043 /* Block on a completion variable. Can't wait forever though. */
2044 rc = wait_for_completion_timeout(
2045 &adapter->session_open_comp_var,
2046 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2047 if (!rc) {
2048 hddLog(LOGP,
2049 FL("Session is not opened within timeout period code %ld"),
2050 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302051 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 goto error_sme_open;
2053 }
2054
2055 /* Register wireless extensions */
2056 cdf_ret_status = hdd_register_wext(pWlanDev);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302057 if (QDF_STATUS_SUCCESS != cdf_ret_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058 hddLog(LOGP,
2059 FL("hdd_register_wext() failed, status code %08d [x%08x]"),
2060 cdf_ret_status, cdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302061 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 goto error_register_wext;
2063 }
2064 /* Set the Connection State to Not Connected */
2065 hddLog(LOG1,
2066 FL("Set HDD connState to eConnectionState_NotConnected"));
2067 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2068
2069 /* Set the default operation channel */
2070 pHddStaCtx->conn_info.operationChannel =
2071 hdd_ctx->config->OperatingChannel;
2072
2073 /* Make the default Auth Type as OPEN */
2074 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2075
2076 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302077 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 hddLog(LOGP,
2079 FL("hdd_init_tx_rx() failed, status code %08d [x%08x]"),
2080 status, status);
2081 goto error_init_txrx;
2082 }
2083
2084 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2085
2086 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302087 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002088 hddLog(LOGP,
2089 FL("hdd_wmm_adapter_init() failed, status code %08d [x%08x]"),
2090 status, status);
2091 goto error_wmm_init;
2092 }
2093
2094 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2095
2096 ret_val = wma_cli_set_command(adapter->sessionId,
2097 WMI_PDEV_PARAM_BURST_ENABLE,
2098 hdd_ctx->config->enableSifsBurst,
2099 PDEV_CMD);
2100
2101 if (0 != ret_val) {
2102 hddLog(LOGE,
2103 FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
2104 ret_val);
2105 }
2106#ifdef FEATURE_WLAN_TDLS
2107 if (0 != wlan_hdd_tdls_init(adapter)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302108 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002109 hddLog(LOGE, FL("wlan_hdd_tdls_init failed"));
2110 goto error_tdls_init;
2111 }
2112 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2113#endif
2114
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302115 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116
2117#ifdef FEATURE_WLAN_TDLS
2118error_tdls_init:
2119 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2120 hdd_wmm_adapter_close(adapter);
2121#endif
2122error_wmm_init:
2123 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2124 hdd_deinit_tx_rx(adapter);
2125error_init_txrx:
2126 hdd_unregister_wext(pWlanDev);
2127error_register_wext:
2128 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2129 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302130 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131 adapter->sessionId,
2132 hdd_sme_close_session_callback,
2133 adapter)) {
2134 unsigned long rc;
2135
2136 /*
2137 * Block on a completion variable.
2138 * Can't wait forever though.
2139 */
2140 rc = wait_for_completion_timeout(
2141 &adapter->session_close_comp_var,
2142 msecs_to_jiffies
2143 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2144 if (rc <= 0)
2145 hddLog(LOGE,
2146 FL("Session is not opened within timeout period code %ld"),
2147 rc);
2148 }
2149 }
2150error_sme_open:
2151 return status;
2152}
2153
2154void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2155{
2156 hdd_cfg80211_state_t *cfgState;
2157
2158 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2159
2160 if (NULL != cfgState->buf) {
2161 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 rc = wait_for_completion_timeout(
2163 &adapter->tx_action_cnf_event,
2164 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2165 if (!rc) {
2166 hddLog(CDF_TRACE_LEVEL_ERROR,
2167 FL("HDD Wait for Action Confirmation Failed!!"));
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302168 /*
2169 * Inform tx status as FAILURE to upper layer and free
2170 * cfgState->buf
2171 */
2172 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 }
2174 }
2175 return;
2176}
2177
2178void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2179 bool rtnl_held)
2180{
2181 ENTER();
2182 switch (adapter->device_mode) {
2183 case WLAN_HDD_INFRA_STATION:
2184 case WLAN_HDD_P2P_CLIENT:
2185 case WLAN_HDD_P2P_DEVICE:
2186 {
2187 if (test_bit
2188 (INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2189 hdd_deinit_tx_rx(adapter);
2190 clear_bit(INIT_TX_RX_SUCCESS,
2191 &adapter->event_flags);
2192 }
2193
2194 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2195 hdd_wmm_adapter_close(adapter);
2196 clear_bit(WMM_INIT_DONE,
2197 &adapter->event_flags);
2198 }
2199
2200 hdd_cleanup_actionframe(hdd_ctx, adapter);
2201 wlan_hdd_tdls_exit(adapter);
2202 break;
2203 }
2204
2205 case WLAN_HDD_SOFTAP:
2206 case WLAN_HDD_P2P_GO:
2207 {
2208
2209 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2210 hdd_wmm_adapter_close(adapter);
2211 clear_bit(WMM_INIT_DONE,
2212 &adapter->event_flags);
2213 }
2214
2215 hdd_cleanup_actionframe(hdd_ctx, adapter);
2216
2217 hdd_unregister_hostapd(adapter, rtnl_held);
2218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 break;
2220 }
2221
2222 default:
2223 break;
2224 }
2225
2226 EXIT();
2227}
2228
2229void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002230 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002231{
2232 struct net_device *pWlanDev = NULL;
2233
2234 if (adapter)
2235 pWlanDev = adapter->dev;
2236 else {
2237 hddLog(LOGE, FL("adapter is Null"));
2238 return;
2239 }
2240
2241 hdd_lro_disable(hdd_ctx, adapter);
2242 /*
2243 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2244 * the driver is almost closed and cannot handle either control
2245 * messages or data. However, unregister_netdevice() call above will
2246 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2247 * to close the active connections (basically excites control path) which
2248 * is not right. Setting this flag helps hdd_stop() to recognize that
2249 * the interface is closed and restricts any operations on that
2250 */
2251 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2252
2253 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2254 if (rtnl_held) {
2255 unregister_netdevice(pWlanDev);
2256 } else {
2257 unregister_netdev(pWlanDev);
2258 }
2259 /*
2260 * Note that the adapter is no longer valid at this point
2261 * since the memory has been reclaimed
2262 */
2263 }
2264}
2265
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302266QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267 tSirMacAddr macAddr)
2268{
2269 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2270 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302271 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302273 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002274 adapter = adapterNode->pAdapter;
2275 if (adapter
2276 && cdf_mem_compare(adapter->macAddressCurrent.bytes,
2277 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302278 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002279 }
2280 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2281 adapterNode = pNext;
2282 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302283 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284}
2285hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
2286 const char *iface_name, tSirMacAddr macAddr,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002287 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002288{
2289 hdd_adapter_t *adapter = NULL;
2290 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302291 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002292 hdd_cfg80211_state_t *cfgState;
2293 int ret;
2294
2295 hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type);
2296
2297 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
2298 /*
2299 * Max limit reached on the number of vdevs configured by the
2300 * host. Return error
2301 */
2302 hddLog(CDF_TRACE_LEVEL_ERROR,
2303 FL(
2304 "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d"
2305 ),
2306 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
2307 return NULL;
2308 }
2309
2310 if (macAddr == NULL) {
2311 /* Not received valid macAddr */
2312 hddLog(CDF_TRACE_LEVEL_ERROR,
2313 FL(
2314 "Unable to add virtual intf: Not able to get valid mac address"
2315 ));
2316 return NULL;
2317 }
2318 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302319 if (QDF_STATUS_E_FAILURE == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002320 hddLog(CDF_TRACE_LEVEL_ERROR,
2321 "Duplicate MAC addr: " MAC_ADDRESS_STR
2322 " already exists",
2323 MAC_ADDR_ARRAY(macAddr));
2324 return NULL;
2325 }
2326
2327 switch (session_type) {
2328 case WLAN_HDD_INFRA_STATION:
2329 /* Reset locally administered bit if the device mode is STA */
2330 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
2331 /* fall through */
2332 case WLAN_HDD_P2P_CLIENT:
2333 case WLAN_HDD_P2P_DEVICE:
2334 case WLAN_HDD_OCB:
2335 {
2336 adapter =
2337 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2338
2339 if (NULL == adapter) {
2340 hddLog(CDF_TRACE_LEVEL_FATAL,
2341 FL("failed to allocate adapter for session %d"),
2342 session_type);
2343 return NULL;
2344 }
2345
2346 if (WLAN_HDD_P2P_CLIENT == session_type)
2347 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348 else if (WLAN_HDD_P2P_DEVICE == session_type)
2349 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 else
2351 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2352
2353 adapter->device_mode = session_type;
2354
2355 status = hdd_init_station_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302356 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 goto err_free_netdev;
2358
2359 hdd_lro_enable(hdd_ctx, adapter);
2360
2361 /*
2362 * Workqueue which gets scheduled in IPv4 notification
2363 * callback
2364 */
2365#ifdef CONFIG_CNSS
2366 cnss_init_work(&adapter->ipv4NotifierWorkQueue,
2367 hdd_ipv4_notifier_work_queue);
2368#else
2369 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
2370 hdd_ipv4_notifier_work_queue);
2371#endif
2372
2373#ifdef WLAN_NS_OFFLOAD
2374 /*
2375 * Workqueue which gets scheduled in IPv6
2376 * notification callback.
2377 */
2378#ifdef CONFIG_CNSS
2379 cnss_init_work(&adapter->ipv6NotifierWorkQueue,
2380 hdd_ipv6_notifier_work_queue);
2381#else
2382 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
2383 hdd_ipv6_notifier_work_queue);
2384#endif
2385#endif
2386 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302387 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2389 goto err_lro_cleanup;
2390 }
2391
2392 /* Stop the Interface TX queue. */
2393 hddLog(LOG1, FL("Disabling queues"));
2394 wlan_hdd_netif_queue_control(adapter,
2395 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2396 WLAN_CONTROL_PATH);
2397
2398 hdd_register_tx_flow_control(adapter,
2399 hdd_tx_resume_timer_expired_handler,
2400 hdd_tx_resume_cb);
2401
2402 break;
2403 }
2404
2405 case WLAN_HDD_P2P_GO:
2406 case WLAN_HDD_SOFTAP:
2407 {
2408 adapter =
2409 hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
2410 (uint8_t *) iface_name);
2411 if (NULL == adapter) {
2412 hddLog(CDF_TRACE_LEVEL_FATAL,
2413 FL("failed to allocate adapter for session %d"),
2414 session_type);
2415 return NULL;
2416 }
2417
2418 adapter->wdev.iftype =
2419 (session_type ==
2420 WLAN_HDD_SOFTAP) ? NL80211_IFTYPE_AP :
2421 NL80211_IFTYPE_P2P_GO;
2422 adapter->device_mode = session_type;
2423
2424 status = hdd_init_ap_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302425 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426 goto err_free_netdev;
2427
2428 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302429 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002430 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2431 goto err_free_netdev;
2432 }
2433
2434 hddLog(LOG1, FL("Disabling queues"));
2435 wlan_hdd_netif_queue_control(adapter,
2436 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2437 WLAN_CONTROL_PATH);
2438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 break;
2440 }
2441 case WLAN_HDD_FTM:
2442 {
2443 adapter =
2444 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2445
2446 if (NULL == adapter) {
2447 hddLog(CDF_TRACE_LEVEL_FATAL,
2448 FL("failed to allocate adapter for session %d"),
2449 session_type);
2450 return NULL;
2451 }
2452
2453 /*
2454 * Assign NL80211_IFTYPE_STATION as interface type to resolve
2455 * Kernel Warning message while loading driver in FTM mode.
2456 */
2457 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2458 adapter->device_mode = session_type;
2459 status = hdd_register_interface(adapter, rtnl_held);
2460
2461 hdd_init_tx_rx(adapter);
2462
2463 /* Stop the Interface TX queue. */
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 }
2469 break;
2470 default:
2471 {
2472 hddLog(CDF_TRACE_LEVEL_FATAL,
2473 FL("Invalid session type %d"),
2474 session_type);
2475 CDF_ASSERT(0);
2476 return NULL;
2477 }
2478 }
2479
2480 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2481 mutex_init(&cfgState->remain_on_chan_ctx_lock);
2482
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302483 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 /* Add it to the hdd's session list. */
2485 pHddAdapterNode =
2486 cdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
2487 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302488 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 } else {
2490 pHddAdapterNode->pAdapter = adapter;
2491 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
2492 }
2493 }
2494
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302495 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 if (NULL != adapter) {
2497 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
2498 adapter = NULL;
2499 }
2500 if (NULL != pHddAdapterNode) {
2501 cdf_mem_free(pHddAdapterNode);
2502 }
2503 return NULL;
2504 }
2505
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302506 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002507 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508
2509 /* Initialize the WoWL service */
2510 if (!hdd_init_wowl(adapter)) {
2511 hddLog(CDF_TRACE_LEVEL_FATAL,
2512 FL("hdd_init_wowl failed"));
2513 goto err_lro_cleanup;
2514 }
2515
2516 /* Adapter successfully added. Increment the vdev count */
2517 hdd_ctx->current_intf_count++;
2518
2519 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"),
2520 hdd_ctx->current_intf_count);
2521
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002522 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 }
2524
Peng Xuf5d60c82015-10-02 17:17:03 -07002525 if ((cds_get_conparam() != CDF_GLOBAL_FTM_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 && (!hdd_ctx->config->enable2x2)) {
2527#define HDD_DTIM_1CHAIN_RX_ID 0x5
2528#define HDD_SMPS_PARAM_VALUE_S 29
2529
2530 /*
2531 * Disable DTIM 1 chain Rx when in 1x1, we are passing two value
2532 * as param_id << 29 | param_value.
2533 * Below param_value = 0(disable)
2534 */
2535 ret = wma_cli_set_command(adapter->sessionId,
2536 WMI_STA_SMPS_PARAM_CMDID,
2537 HDD_DTIM_1CHAIN_RX_ID <<
2538 HDD_SMPS_PARAM_VALUE_S,
2539 VDEV_CMD);
2540
2541 if (ret != 0) {
2542 hddLog(CDF_TRACE_LEVEL_ERROR,
2543 FL("DTIM 1 chain set failed %d"), ret);
2544 goto err_lro_cleanup;
2545 }
2546
2547 ret = wma_cli_set_command(adapter->sessionId,
2548 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2549 hdd_ctx->config->txchainmask1x1,
2550 PDEV_CMD);
2551 if (ret != 0) {
2552 hddLog(CDF_TRACE_LEVEL_ERROR,
2553 FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"),
2554 ret);
2555 goto err_lro_cleanup;
2556 }
2557 ret = wma_cli_set_command(adapter->sessionId,
2558 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2559 hdd_ctx->config->rxchainmask1x1,
2560 PDEV_CMD);
2561 if (ret != 0) {
2562 hddLog(CDF_TRACE_LEVEL_ERROR,
2563 FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"),
2564 ret);
2565 goto err_lro_cleanup;
2566 }
2567#undef HDD_DTIM_1CHAIN_RX_ID
2568#undef HDD_SMPS_PARAM_VALUE_S
2569 }
2570
Peng Xuf5d60c82015-10-02 17:17:03 -07002571 if (CDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572 ret = wma_cli_set_command(adapter->sessionId,
2573 WMI_PDEV_PARAM_HYST_EN,
2574 hdd_ctx->config->enableMemDeepSleep,
2575 PDEV_CMD);
2576
2577 if (ret != 0) {
2578 hddLog(CDF_TRACE_LEVEL_ERROR,
2579 FL("WMI_PDEV_PARAM_HYST_EN set failed %d"),
2580 ret);
2581 goto err_lro_cleanup;
2582 }
2583 }
2584
2585#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2586
2587 /* Enable FW logs based on INI configuration */
Peng Xuf5d60c82015-10-02 17:17:03 -07002588 if ((CDF_GLOBAL_FTM_MODE != cds_get_conparam()) &&
Komal Seelamc11bb222016-01-27 18:57:10 +05302589 (hdd_ctx->config->enable_fw_log)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590 uint8_t count = 0;
2591 uint32_t value = 0;
2592 uint8_t numEntries = 0;
2593 uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2594
2595 hdd_ctx->fw_log_settings.dl_type =
2596 hdd_ctx->config->enableFwLogType;
2597 ret = wma_cli_set_command(adapter->sessionId,
2598 WMI_DBGLOG_TYPE,
2599 hdd_ctx->config->enableFwLogType,
2600 DBG_CMD);
2601 if (ret != 0) {
2602 hddLog(LOGE, FL("Failed to enable FW log type ret %d"),
2603 ret);
2604 }
2605
2606 hdd_ctx->fw_log_settings.dl_loglevel =
2607 hdd_ctx->config->enableFwLogLevel;
2608 ret = wma_cli_set_command(adapter->sessionId,
2609 WMI_DBGLOG_LOG_LEVEL,
2610 hdd_ctx->config->enableFwLogLevel,
2611 DBG_CMD);
2612 if (ret != 0) {
2613 hddLog(LOGE, FL("Failed to enable FW log level ret %d"),
2614 ret);
2615 }
2616
2617 hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel,
2618 moduleLoglevel,
2619 &numEntries,
2620 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2621 while (count < numEntries) {
2622 /*
2623 * FW module log level input string looks like below:
2624 * gFwDebugModuleLoglevel=<FW Module ID>,<Log Level>,...
2625 * For example:
2626 * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6
2627 * Above input string means :
2628 * For FW module ID 1 enable log level 0
2629 * For FW module ID 2 enable log level 1
2630 * For FW module ID 3 enable log level 2
2631 * For FW module ID 4 enable log level 3
2632 * For FW module ID 5 enable log level 4
2633 * For FW module ID 6 enable log level 5
2634 * For FW module ID 7 enable log level 6
2635 */
2636
2637 /* FW expects WMI command value =
2638 * Module ID * 10 + Module Log level
2639 */
2640 value = ((moduleLoglevel[count] * 10) +
2641 moduleLoglevel[count + 1]);
2642 ret = wma_cli_set_command(adapter->sessionId,
2643 WMI_DBGLOG_MOD_LOG_LEVEL,
2644 value, DBG_CMD);
2645 if (ret != 0) {
2646 hddLog(LOGE,
2647 FL
2648 ("Failed to enable FW module log level %d ret %d"),
2649 value, ret);
2650 }
2651
2652 count += 2;
2653 }
2654 }
2655#endif
2656
2657 return adapter;
2658
2659err_lro_cleanup:
2660 hdd_lro_disable(hdd_ctx, adapter);
2661err_free_netdev:
2662 free_netdev(adapter->dev);
2663 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2664
2665 return NULL;
2666}
2667
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302668QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002669 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670{
2671 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302672 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673
2674 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302675 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 hddLog(CDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"),
2677 status);
2678 return status;
2679 }
2680
2681 while (pCurrent->pAdapter != adapter) {
2682 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302683 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 break;
2685
2686 pCurrent = pNext;
2687 }
2688 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302689 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002690 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002691 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
2692
2693 hdd_remove_adapter(hdd_ctx, adapterNode);
2694 cdf_mem_free(adapterNode);
2695 adapterNode = NULL;
2696
2697 /* Adapter removed. Decrement vdev count */
2698 if (hdd_ctx->current_intf_count != 0)
2699 hdd_ctx->current_intf_count--;
2700
2701 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302702 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302704 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705}
2706
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002707/**
2708 * hdd_close_all_adapters - Close all open adapters
2709 * @hdd_ctx: Hdd context
2710 * rtnl_held: True if RTNL lock held
2711 *
2712 * Close all open adapters.
2713 *
2714 * Return: CDF status code
2715 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302716QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717{
2718 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302719 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720
2721 ENTER();
2722
2723 do {
2724 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302725 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002726 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002727 rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728 cdf_mem_free(pHddAdapterNode);
2729 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302730 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731
2732 EXIT();
2733
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302734 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735}
2736
2737void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
2738{
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002739 struct cdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 tSirUpdateIE updateIE;
2741 switch (pHostapdAdapter->device_mode) {
2742 case WLAN_HDD_INFRA_STATION:
2743 case WLAN_HDD_P2P_CLIENT:
2744 {
2745 hdd_station_ctx_t *pHddStaCtx =
2746 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002747 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748 break;
2749 }
2750 case WLAN_HDD_SOFTAP:
2751 case WLAN_HDD_P2P_GO:
2752 case WLAN_HDD_IBSS:
2753 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002754 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755 break;
2756 }
2757 case WLAN_HDD_FTM:
2758 case WLAN_HDD_P2P_DEVICE:
2759 default:
2760 /*
2761 * wlan_hdd_reset_prob_rspies should not have been called
2762 * for these kind of devices
2763 */
2764 hddLog(LOGE,
2765 FL("Unexpected request for the current device type %d"),
2766 pHostapdAdapter->device_mode);
2767 return;
2768 }
2769
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002770 cdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002771 updateIE.smeSessionId = pHostapdAdapter->sessionId;
2772 updateIE.ieBufferlength = 0;
2773 updateIE.pAdditionIEBuffer = NULL;
2774 updateIE.append = true;
2775 updateIE.notify = false;
2776 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
2777 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302778 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
2780 }
2781}
2782
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302783QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 const bool bCloseSession)
2785{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302786 QDF_STATUS cdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
2788 union iwreq_data wrqu;
2789 tSirUpdateIE updateIE;
2790 unsigned long rc;
2791
2792 ENTER();
2793
2794 hddLog(LOG1, FL("Disabling queues"));
2795 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2796 WLAN_CONTROL_PATH);
2797 switch (adapter->device_mode) {
2798 case WLAN_HDD_INFRA_STATION:
2799 case WLAN_HDD_P2P_CLIENT:
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302800 case WLAN_HDD_IBSS:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 case WLAN_HDD_P2P_DEVICE:
2802 if (hdd_conn_is_connected(
2803 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
2804 hdd_is_connecting(
2805 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
2806 if (pWextState->roamProfile.BSSType ==
2807 eCSR_BSS_TYPE_START_IBSS)
2808 cdf_ret_status =
2809 sme_roam_disconnect(hdd_ctx->hHal,
2810 adapter->sessionId,
2811 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2812 else
2813 cdf_ret_status =
2814 sme_roam_disconnect(hdd_ctx->hHal,
2815 adapter->sessionId,
2816 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2817 /* success implies disconnect command got queued up successfully */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302818 if (cdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 rc = wait_for_completion_timeout(
2820 &adapter->disconnect_comp_var,
2821 msecs_to_jiffies
2822 (WLAN_WAIT_TIME_DISCONNECT));
2823 if (!rc) {
2824 hddLog(CDF_TRACE_LEVEL_ERROR,
2825 FL(
2826 "wait on disconnect_comp_var failed"
2827 ));
2828 }
2829 } else {
2830 hddLog(LOGE,
2831 FL(
2832 "failed to post disconnect event to SME"
2833 ));
2834 }
2835 memset(&wrqu, '\0', sizeof(wrqu));
2836 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2837 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
2838 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
2839 NULL);
2840 } else {
2841 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
2842 eCSR_SCAN_ABORT_DEFAULT);
2843 }
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302844 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002845
2846#ifdef WLAN_OPEN_SOURCE
2847 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
2848#endif
2849
2850 hdd_deregister_tx_flow_control(adapter);
2851
2852#ifdef WLAN_NS_OFFLOAD
2853#ifdef WLAN_OPEN_SOURCE
2854 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
2855#endif
2856#endif
2857
2858 /*
2859 * It is possible that the caller of this function does not
2860 * wish to close the session
2861 */
2862 if (true == bCloseSession &&
2863 test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2864 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302865 if (QDF_STATUS_SUCCESS ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2867 hdd_sme_close_session_callback,
2868 adapter)) {
2869 /*
2870 * Block on a completion variable. Can't wait
2871 * forever though.
2872 */
2873 rc = wait_for_completion_timeout(
2874 &adapter->session_close_comp_var,
2875 msecs_to_jiffies
2876 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2877 if (!rc) {
2878 hddLog(LOGE,
2879 FL(
2880 "failure waiting for session_close_comp_var"
2881 ));
2882 }
2883 }
2884 }
2885 break;
2886
2887 case WLAN_HDD_SOFTAP:
2888 case WLAN_HDD_P2P_GO:
2889 if (hdd_ctx->config->conc_custom_rule1 &&
2890 (WLAN_HDD_SOFTAP == adapter->device_mode)) {
2891 /*
2892 * Before stopping the sap adapter, lets make sure there
2893 * is no sap restart work pending.
2894 */
2895 cds_flush_work(&hdd_ctx->sap_start_work);
2896 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
2897 FL("Canceled the pending SAP restart work"));
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002898 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899 }
2900 /* Any softap specific cleanup here... */
2901 if (adapter->device_mode == WLAN_HDD_P2P_GO)
2902 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
2903
2904 hdd_deregister_tx_flow_control(adapter);
2905
2906 mutex_lock(&hdd_ctx->sap_lock);
2907 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302908 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05302909 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910
2911 /* Stop Bss. */
2912#ifdef WLAN_FEATURE_MBSSID
2913 status = wlansap_stop_bss(
2914 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
2915#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002916 status = wlansap_stop_bss(
2917 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918#endif
2919
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302920 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002921 hdd_hostapd_state_t *hostapd_state =
2922 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302923 qdf_event_reset(&hostapd_state->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 cdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302925 qdf_status =
2926 qdf_wait_single_event(&hostapd_state->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 cdf_stop_bss_event,
2928 BSS_WAIT_TIMEOUT);
2929
Anurag Chouhance0dc992016-02-16 18:18:03 +05302930 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 hddLog(LOGE,
2932 FL(
2933 "failure waiting for wlansap_stop_bss %d"
2934 ),
Anurag Chouhance0dc992016-02-16 18:18:03 +05302935 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 }
2937 } else {
2938 hddLog(LOGE, FL("failure in wlansap_stop_bss"));
2939 }
2940 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002941 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 adapter->device_mode,
2943 adapter->sessionId);
2944
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002945 cdf_copy_macaddr(&updateIE.bssid,
2946 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 updateIE.smeSessionId = adapter->sessionId;
2948 updateIE.ieBufferlength = 0;
2949 updateIE.pAdditionIEBuffer = NULL;
2950 updateIE.append = false;
2951 updateIE.notify = false;
2952 /* Probe bcn reset */
2953 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2954 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302955 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002956 hddLog(LOGE,
2957 FL(
2958 "Could not pass on PROBE_RSP_BCN data to PE"
2959 ));
2960 }
2961 /* Assoc resp reset */
2962 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2963 &updateIE,
2964 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302965 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966 hddLog(LOGE,
2967 FL(
2968 "Could not pass on ASSOC_RSP data to PE"
2969 ));
2970 }
2971 /* Reset WNI_CFG_PROBE_RSP Flags */
2972 wlan_hdd_reset_prob_rspies(adapter);
2973 kfree(adapter->sessionCtx.ap.beacon);
2974 adapter->sessionCtx.ap.beacon = NULL;
2975 }
2976 mutex_unlock(&hdd_ctx->sap_lock);
2977 break;
2978 case WLAN_HDD_OCB:
2979 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
2980 conn_info.staId[0]);
2981 break;
2982 default:
2983 break;
2984 }
2985
2986 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302987 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002988}
2989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302990QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002991{
2992 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302993 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994 hdd_adapter_t *adapter;
2995
2996 ENTER();
2997
2998 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
2999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303000 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 adapter = adapterNode->pAdapter;
3002 hdd_stop_adapter(hdd_ctx, adapter, true);
3003 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3004 adapterNode = pNext;
3005 }
3006
3007 EXIT();
3008
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303009 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010}
3011
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303012QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013{
3014 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303015 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 hdd_adapter_t *adapter;
3017
3018 ENTER();
3019
3020 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3021
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303022 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 adapter = adapterNode->pAdapter;
3024 hddLog(LOG1, FL("Disabling queues"));
3025 wlan_hdd_netif_queue_control(adapter,
3026 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3027 WLAN_CONTROL_PATH);
3028
3029 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3030
3031 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003032 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 adapter->sessionId);
3034 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3035 hdd_wmm_adapter_close(adapter);
3036 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3037 }
3038
3039 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3040 adapterNode = pNext;
3041 }
3042
3043 EXIT();
3044
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303045 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046}
3047
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303048QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049{
3050 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303051 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 hdd_adapter_t *adapter;
3053#ifndef MSM_PLATFORM
3054 struct cdf_mac_addr bcastMac = CDF_MAC_ADDR_BROADCAST_INITIALIZER;
3055#endif
3056 eConnectionState connState;
3057
3058 ENTER();
3059
3060 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3061
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303062 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003063 adapter = adapterNode->pAdapter;
3064
3065 hdd_wmm_init(adapter);
3066
3067 switch (adapter->device_mode) {
3068 case WLAN_HDD_INFRA_STATION:
3069 case WLAN_HDD_P2P_CLIENT:
3070 case WLAN_HDD_P2P_DEVICE:
3071
3072 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3073 ->conn_info.connState;
3074
3075 hdd_init_station_mode(adapter);
3076 /* Open the gates for HDD to receive Wext commands */
3077 adapter->isLinkUpSvcNeeded = false;
3078 adapter->scan_info.mScanPending = false;
3079
3080 /* Indicate disconnect event to supplicant if associated previously */
3081 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003082 eConnectionState_IbssConnected == connState ||
3083 eConnectionState_NotConnected == connState ||
3084 eConnectionState_IbssDisconnected == connState ||
3085 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003086 union iwreq_data wrqu;
3087 memset(&wrqu, '\0', sizeof(wrqu));
3088 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3089 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3090 wireless_send_event(adapter->dev, SIOCGIWAP,
3091 &wrqu, NULL);
3092 adapter->sessionCtx.station.
3093 hdd_ReassocScenario = false;
3094
3095 /* indicate disconnected event to nl80211 */
3096 cfg80211_disconnected(adapter->dev,
3097 WLAN_REASON_UNSPECIFIED,
3098 NULL, 0, GFP_KERNEL);
3099 } else if (eConnectionState_Connecting == connState) {
3100 /*
3101 * Indicate connect failure to supplicant if we were in the
3102 * process of connecting
3103 */
3104 cfg80211_connect_result(adapter->dev, NULL,
3105 NULL, 0, NULL, 0,
3106 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3107 GFP_KERNEL);
3108 }
3109
3110 hdd_register_tx_flow_control(adapter,
3111 hdd_tx_resume_timer_expired_handler,
3112 hdd_tx_resume_cb);
3113
3114 break;
3115
3116 case WLAN_HDD_SOFTAP:
3117 /* softAP can handle SSR */
3118 break;
3119
3120 case WLAN_HDD_P2P_GO:
3121#ifdef MSM_PLATFORM
3122 hddLog(CDF_TRACE_LEVEL_ERROR,
3123 FL("[SSR] send stop ap to supplicant"));
3124 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3125#else
3126 hddLog(CDF_TRACE_LEVEL_ERROR,
3127 FL("[SSR] send restart supplicant"));
3128 /* event supplicant to restart */
3129 cfg80211_del_sta(adapter->dev,
3130 (const u8 *)&bcastMac.bytes[0],
3131 GFP_KERNEL);
3132#endif
3133 break;
3134
3135 default:
3136 break;
3137 }
3138
3139 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3140 adapterNode = pNext;
3141 }
3142
3143 EXIT();
3144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303145 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146}
3147
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303148QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003149 hdd_adapter_list_node_t **padapterNode)
3150{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303151 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303153 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3154 (qdf_list_node_t **) padapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3156 return status;
3157}
3158
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303159QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 hdd_adapter_list_node_t *adapterNode,
3161 hdd_adapter_list_node_t **pNextAdapterNode)
3162{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303163 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303165 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3166 (qdf_list_node_t *) adapterNode,
3167 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168
3169 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3170 return status;
3171}
3172
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303173QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 hdd_adapter_list_node_t *adapterNode)
3175{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303176 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303178 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179 &adapterNode->node);
3180 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3181 return status;
3182}
3183
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303184QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 hdd_adapter_list_node_t **padapterNode)
3186{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303187 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303189 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3190 (qdf_list_node_t **) padapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3192 return status;
3193}
3194
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303195QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 hdd_adapter_list_node_t *adapterNode)
3197{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303198 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303200 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3201 (qdf_list_node_t *) adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3203 return status;
3204}
3205
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303206QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 hdd_adapter_list_node_t *adapterNode)
3208{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303209 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303211 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3212 (qdf_list_node_t *) adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3214 return status;
3215}
3216
3217hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3218 tSirMacAddr macAddr)
3219{
3220 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3221 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303222 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223
3224 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3225
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303226 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227 adapter = adapterNode->pAdapter;
3228
3229 if (adapter
3230 && cdf_mem_compare(adapter->macAddressCurrent.bytes,
3231 macAddr, sizeof(tSirMacAddr))) {
3232 return adapter;
3233 }
3234 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3235 adapterNode = pNext;
3236 }
3237
3238 return NULL;
3239
3240}
3241
3242hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3243 uint32_t vdev_id)
3244{
3245 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3246 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303247 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303249 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303251 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 adapter = adapterNode->pAdapter;
3253
3254 if (adapter->sessionId == vdev_id)
3255 return adapter;
3256
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303257 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003258 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3259 adapterNode = pNext;
3260 }
3261
3262 hddLog(CDF_TRACE_LEVEL_ERROR,
3263 FL("vdev_id %d does not exist with host"), vdev_id);
3264
3265 return NULL;
3266}
3267
Abhishek Singh7996eb72015-12-30 17:24:02 +05303268/**
3269 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3270 * the sessionid
3271 * @hdd_ctx: hdd context.
3272 * @sme_session_id: sme session is for the adapter to get.
3273 *
3274 * This function is used to get the adapter with provided session id
3275 *
3276 * Return: adapter pointer if found
3277 *
3278 */
3279hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3280 uint32_t sme_session_id)
3281{
3282 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3283 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303284 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303285
3286
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303287 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303288
3289 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303290 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303291 adapter = adapter_node->pAdapter;
3292
3293 if (adapter &&
3294 adapter->sessionId == sme_session_id)
3295 return adapter;
3296
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303297 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303298 hdd_get_next_adapter(hdd_ctx,
3299 adapter_node, &next);
3300 adapter_node = next;
3301 }
3302 return NULL;
3303}
3304
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003305hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, device_mode_t mode)
3306{
3307 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3308 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303309 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310
3311 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3312
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303313 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314 adapter = adapterNode->pAdapter;
3315
3316 if (adapter && (mode == adapter->device_mode))
3317 return adapter;
3318
3319 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3320 adapterNode = pNext;
3321 }
3322
3323 return NULL;
3324
3325}
3326
3327/**
3328 * hdd_get_operating_channel() - return operating channel of the device mode
3329 * @hdd_ctx: Pointer to the HDD context.
3330 * @mode: Device mode for which operating channel is required.
3331 * Suported modes:
3332 * WLAN_HDD_INFRA_STATION,
3333 * WLAN_HDD_P2P_CLIENT,
3334 * WLAN_HDD_SOFTAP,
3335 * WLAN_HDD_P2P_GO.
3336 *
3337 * This API returns the operating channel of the requested device mode
3338 *
3339 * Return: channel number. "0" id the requested device is not found OR it is
3340 * not connected.
3341 */
3342uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx, device_mode_t mode)
3343{
3344 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303345 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 hdd_adapter_t *adapter;
3347 uint8_t operatingChannel = 0;
3348
3349 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3350
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303351 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 adapter = adapterNode->pAdapter;
3353
3354 if (mode == adapter->device_mode) {
3355 switch (adapter->device_mode) {
3356 case WLAN_HDD_INFRA_STATION:
3357 case WLAN_HDD_P2P_CLIENT:
3358 if (hdd_conn_is_connected
3359 (WLAN_HDD_GET_STATION_CTX_PTR
3360 (adapter))) {
3361 operatingChannel =
3362 (WLAN_HDD_GET_STATION_CTX_PTR
3363 (adapter))->conn_info.
3364 operationChannel;
3365 }
3366 break;
3367 case WLAN_HDD_SOFTAP:
3368 case WLAN_HDD_P2P_GO:
3369 /* softap connection info */
3370 if (test_bit
3371 (SOFTAP_BSS_STARTED,
3372 &adapter->event_flags))
3373 operatingChannel =
3374 (WLAN_HDD_GET_AP_CTX_PTR
3375 (adapter))->operatingChannel;
3376 break;
3377 default:
3378 break;
3379 }
3380
3381 break; /* Found the device of interest. break the loop */
3382 }
3383
3384 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3385 adapterNode = pNext;
3386 }
3387 return operatingChannel;
3388}
3389
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303390static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391 hdd_ctx)
3392{
3393 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303394 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 hdd_adapter_t *adapter;
3396
3397 ENTER();
3398
3399 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3400
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303401 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 adapter = adapterNode->pAdapter;
3403 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3404 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3405 (adapter->device_mode == WLAN_HDD_IBSS) ||
3406 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3407 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3408 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3409 wlan_hdd_cfg80211_deregister_frames(adapter);
3410 hdd_unregister_wext(adapter->dev);
3411 }
3412 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3413 adapterNode = pNext;
3414 }
3415
3416 EXIT();
3417
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303418 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419}
3420
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303421QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422{
3423 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303424 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 hdd_adapter_t *adapter;
3426
3427 ENTER();
3428
3429 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3430
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303431 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003432 adapter = adapterNode->pAdapter;
3433 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3434 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3435 (adapter->device_mode == WLAN_HDD_IBSS) ||
3436 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3437 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3438 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3439 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3440 eCSR_SCAN_ABORT_DEFAULT);
3441 }
3442 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3443 adapterNode = pNext;
3444 }
3445
3446 EXIT();
3447
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303448 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003449}
3450
3451#ifdef WLAN_NS_OFFLOAD
3452/**
3453 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3454 * @hdd_ctx: Pointer to hdd context
3455 *
3456 * Return: None
3457 */
3458static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3459{
3460 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3461
3462 return;
3463}
3464
3465/**
3466 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3467 * @hdd_ctx: Pointer to hdd context
3468 *
3469 * Return: None
3470 */
3471static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3472{
3473 int ret;
3474
3475 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
3476 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3477 if (ret)
3478 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
3479 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003480 hdd_info("Registered IPv6 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481
3482 return;
3483}
3484#else
3485/**
3486 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3487 * @hdd_ctx: Pointer to hdd context
3488 *
3489 * Return: None
3490 */
3491static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3492{
3493}
3494/**
3495 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3496 * @hdd_ctx: Pointer to hdd context
3497 *
3498 * Return: None
3499 */
3500static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3501{
3502}
3503#endif
3504
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003505#ifdef QCA_WIFI_FTM
3506/**
3507 * hdd_disable_ftm() - Disable FTM mode
3508 * @hdd_ctx: HDD context
3509 *
3510 * Helper function to disable FTM mode.
3511 *
3512 * Return: None.
3513 */
3514static void hdd_disable_ftm(hdd_context_t *hdd_ctx)
3515{
3516 hdd_notice("Disabling FTM mode");
3517
3518 if (hdd_ftm_stop(hdd_ctx)) {
3519 hdd_alert("hdd_ftm_stop Failed!");
3520 CDF_ASSERT(0);
3521 }
3522
3523 hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED;
3524
3525 wlan_hdd_ftm_close(hdd_ctx);
3526
3527 return;
3528}
3529
3530/**
3531 * hdd_enable_ftm() - Enable FTM mode
3532 * @hdd_ctx: HDD context
3533 *
3534 * Helper function to enable FTM mode.
3535 *
3536 * Return: 0 on success and errno on failure.
3537 */
3538int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3539{
3540 int ret;
3541
3542 ret = wlan_hdd_ftm_open(hdd_ctx);
3543 if (ret) {
3544 hdd_alert("wlan_hdd_ftm_open Failed: %d", ret);
3545 goto err_out;
3546 }
3547
3548 ret = hdd_ftm_start(hdd_ctx);
3549
3550 if (ret) {
3551 hdd_alert("hdd_ftm_start Failed: %d", ret);
3552 goto err_ftm_close;
3553 }
3554
3555 ret = wiphy_register(hdd_ctx->wiphy);
3556 if (ret) {
3557 hdd_alert("wiphy register failed: %d", ret);
3558 goto err_ftm_stop;
3559 }
3560
3561 hdd_err("FTM driver loaded");
3562
3563 return 0;
3564
3565err_ftm_stop:
3566 hdd_ftm_stop(hdd_ctx);
3567err_ftm_close:
3568 wlan_hdd_ftm_close(hdd_ctx);
3569err_out:
3570 return ret;
3571
3572}
3573#else
3574int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3575{
3576 hdd_err("Driver built without FTM feature enabled!");
3577
3578 return -ENOTSUPP;
3579}
3580
3581static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { }
3582#endif
3583
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303584#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3585/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003586 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303587 * @hdd_ctx: HDD context
3588 *
3589 * Activates the logging service
3590 *
3591 * Return: Zero in case of success, negative value otherwise
3592 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003593static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303594{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003595 int ret;
3596 struct hdd_config *config = hdd_ctx->config;
3597
3598 if (!config->wlanLoggingEnable)
3599 return 0;
3600
3601 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
3602 config->wlanLoggingNumBuf);
3603 if (ret)
3604 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
3605 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303606}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003607
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303608/**
3609 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
3610 * @hdd_ctx: HDD context
3611 *
3612 * Deactivates the logging service
3613 *
3614 * Return: 0 on deactivating the logging service
3615 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003616static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303617{
3618 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
3619 return wlan_logging_sock_deactivate_svc();
3620
3621 return 0;
3622}
3623#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003624static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303625{
3626 return 0;
3627}
3628
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003629static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303630{
3631 return 0;
3632}
3633#endif
3634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003636 * hdd_free_context - Free HDD context
3637 * @hdd_ctx: HDD context to be freed.
3638 *
3639 * Free config and HDD context.
3640 *
3641 * Return: None
3642 */
3643static void hdd_free_context(hdd_context_t *hdd_ctx)
3644{
3645 if (CDF_GLOBAL_FTM_MODE != hdd_get_conparam())
3646 hdd_logging_sock_deactivate_svc(hdd_ctx);
3647
3648 cdf_mem_free(hdd_ctx->config);
3649 hdd_ctx->config = NULL;
3650
3651 wiphy_free(hdd_ctx->wiphy);
3652}
3653
3654/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655 * hdd_wlan_exit() - HDD WLAN exit function
3656 * @hdd_ctx: Pointer to the HDD Context
3657 *
3658 * This is the driver exit point (invoked during rmmod)
3659 *
3660 * Return: None
3661 */
3662void hdd_wlan_exit(hdd_context_t *hdd_ctx)
3663{
3664 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303665 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 struct wiphy *wiphy = hdd_ctx->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667
3668 ENTER();
3669
3670 hddLog(LOGE, FL("Unregister IPv6 notifier"));
3671 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3672 hddLog(LOGE, FL("Unregister IPv4 notifier"));
3673 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3674
3675 hdd_unregister_wext_all_adapters(hdd_ctx);
3676
Peng Xuf5d60c82015-10-02 17:17:03 -07003677 if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003678 hdd_disable_ftm(hdd_ctx);
3679
3680 hdd_alert("FTM driver unloaded");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 goto free_hdd_ctx;
3682 }
3683
3684 /*
3685 * Cancel any outstanding scan requests. We are about to close all
3686 * of our adapters, but an adapter structure is what SME passes back
3687 * to our callback function. Hence if there are any outstanding scan
3688 * requests then there is a race condition between when the adapter
3689 * is closed and when the callback is invoked. We try to resolve that
3690 * race condition here by canceling any outstanding scans before we
3691 * close the adapters.
3692 * Note that the scans may be cancelled in an asynchronous manner, so
3693 * ideally there needs to be some kind of synchronization. Rather than
3694 * introduce a new synchronization here, we will utilize the fact that
3695 * we are about to Request Full Power, and since that is synchronized,
3696 * the expectation is that by the time Request Full Power has completed,
3697 * all scans will be cancelled
3698 */
3699 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3700
3701#ifdef MSM_PLATFORM
3702 if (CDF_TIMER_STATE_RUNNING ==
3703 cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
3704 cdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
3705 }
3706
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303707 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003708 (cdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
3709 hddLog(CDF_TRACE_LEVEL_ERROR,
3710 FL("Cannot deallocate Bus bandwidth timer"));
3711 }
3712#endif
3713
3714#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3715 if (CDF_TIMER_STATE_RUNNING ==
3716 cdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
3717 cdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
3718 }
3719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303720 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003721 (cdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
3722 hddLog(CDF_TRACE_LEVEL_ERROR,
3723 FL("Cannot deallocate ACS Skip timer"));
3724 }
3725#endif
3726 if (CDF_TIMER_STATE_RUNNING ==
3727 cdf_mc_timer_get_current_state(
3728 &hdd_ctx->dbs_opportunistic_timer)) {
3729 cdf_mc_timer_stop(&hdd_ctx->dbs_opportunistic_timer);
3730 }
3731
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303732 if (!QDF_IS_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 (cdf_mc_timer_destroy(
3734 &hdd_ctx->dbs_opportunistic_timer))) {
3735 hdd_err("Cannot deallocate dbs opportunistic timer");
3736 }
3737
3738 /*
3739 * Powersave Offload Case
3740 * Disable Idle Power Save Mode
3741 */
3742 hdd_set_idle_ps_config(hdd_ctx, false);
3743
3744 hdd_debugfs_exit(hdd_ctx);
3745
3746 /* Unregister the Net Device Notifier */
3747 unregister_netdevice_notifier(&hdd_netdev_notifier);
3748
3749 /*
3750 * Stop all adapters, this will ensure the termination of active
3751 * connections on the interface. Make sure the cds_scheduler is
3752 * still available to handle those control messages
3753 */
3754 hdd_stop_all_adapters(hdd_ctx);
3755
3756 /* Stop all the modules */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303757 qdf_status = cds_disable(p_cds_context);
3758 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003759 hddLog(CDF_TRACE_LEVEL_FATAL,
3760 FL("Failed to stop CDS"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303761 CDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762 }
3763
3764 /*
3765 * Close the scheduler before calling cds_close to make sure no thread
3766 * is scheduled after the each module close is called i.e after all the
3767 * data structures are freed.
3768 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303769 qdf_status = cds_sched_close(p_cds_context);
3770 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771 hddLog(CDF_TRACE_LEVEL_FATAL,
3772 FL("Failed to close CDS Scheduler"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303773 CDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774 }
3775#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3776 /* Destroy the wake lock */
3777 cdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
3778#endif
3779 /* Destroy the wake lock */
3780 cdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock);
3781
3782 hdd_hostapd_channel_wakelock_deinit(hdd_ctx);
3783
3784 /*
3785 * Close CDS
3786 * This frees pMac(HAL) context. There should not be any call
3787 * that requires pMac access after this.
3788 */
3789 cds_close(p_cds_context);
3790
3791 hdd_wlan_green_ap_deinit(hdd_ctx);
3792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793#ifdef WLAN_KD_READY_NOTIFIER
3794 cnss_diag_notify_wlan_close();
3795 ptt_sock_deactivate_svc();
3796#endif /* WLAN_KD_READY_NOTIFIER */
3797 nl_srv_exit();
3798
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003799 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800
3801 hdd_ipa_cleanup(hdd_ctx);
3802
3803 /* Free up RoC request queue and flush workqueue */
3804 cds_flush_work(&hdd_ctx->roc_req_work);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303805 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
3806 qdf_list_destroy(&hdd_ctx->hdd_scan_req_q);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303808 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08003809 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 /* Proceed and complete the clean up */
3811 }
3812
3813free_hdd_ctx:
3814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815 wiphy_unregister(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003816
3817 hdd_free_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818}
3819
3820void __hdd_wlan_exit(void)
3821{
3822 hdd_context_t *hdd_ctx;
3823
3824 ENTER();
3825
3826 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
3827 if (!hdd_ctx) {
3828 hddLog(CDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context"));
3829 EXIT();
3830 return;
3831 }
3832
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003833 /* Check IPA HW Pipe shutdown */
3834 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
3835
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836#ifdef WLAN_FEATURE_LPSS
3837 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
3838#endif
3839
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003840 memdump_deinit();
3841
3842#ifdef QCA_PKT_PROTO_TRACE
3843 cds_pkt_proto_trace_close();
3844#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 /* Do all the cleanup before deregistering the driver */
3846 hdd_wlan_exit(hdd_ctx);
3847 EXIT();
3848}
3849
3850#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3851void hdd_skip_acs_scan_timer_handler(void *data)
3852{
3853 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
3854
3855 hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
3856 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
3857
3858 if (!hdd_ctx->hHal)
3859 return;
3860 sme_scan_flush_result(hdd_ctx->hHal);
3861}
3862#endif
3863
3864#ifdef QCA_HT_2040_COEX
3865/**
3866 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
3867 * @adapter: pointer to adapter
3868 * @staId: station id
3869 * @macAddrSTA: station MAC address
3870 * @channel_type: channel type
3871 *
3872 * This function notifies FW with HT20/HT40 mode
3873 *
3874 * Return: 0 if successful, error number otherwise
3875 */
3876int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
3877 struct cdf_mac_addr macAddrSTA, int channel_type)
3878{
3879 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303880 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881 hdd_context_t *hdd_ctx = NULL;
3882
3883 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3884
3885 status = wlan_hdd_validate_context(hdd_ctx);
3886 if (0 != status) {
3887 hddLog(LOGE, FL("HDD context is not valid"));
3888 return status;
3889 }
3890 if (!hdd_ctx->hHal)
3891 return -EINVAL;
3892
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303893 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303895 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 hddLog(LOGE, "Fail to send notification with ht2040 mode");
3897 return -EINVAL;
3898 }
3899
3900 return 0;
3901}
3902#endif
3903
3904/**
3905 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
3906 * @state: state
3907 *
3908 * This function notifies FW with modem power status
3909 *
3910 * Return: 0 if successful, error number otherwise
3911 */
3912int hdd_wlan_notify_modem_power_state(int state)
3913{
3914 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303915 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916 hdd_context_t *hdd_ctx;
3917
3918 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
3919 status = wlan_hdd_validate_context(hdd_ctx);
3920 if (0 != status) {
3921 hddLog(LOGE, FL("HDD context is not valid"));
3922 return status;
3923 }
3924 if (!hdd_ctx->hHal)
3925 return -EINVAL;
3926
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303927 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
3928 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 hddLog(LOGE,
3930 "Fail to send notification with modem power state %d",
3931 state);
3932 return -EINVAL;
3933 }
3934 return 0;
3935}
3936
3937/**
3938 *
3939 * hdd_post_cds_enable_config() - HDD post cds start config helper
3940 * @adapter - Pointer to the HDD
3941 *
3942 * Return: None
3943 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303944QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303946 QDF_STATUS cdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003947
3948 /*
3949 * Send ready indication to the HDD. This will kick off the MAC
3950 * into a 'running' state and should kick off an initial scan.
3951 */
3952 cdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303953 if (!QDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003954 hddLog(CDF_TRACE_LEVEL_ERROR,
3955 FL(
3956 "sme_hdd_ready_ind() failed with status code %08d [x%08x]"
3957 ),
3958 cdf_ret_status, cdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303959 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960 }
3961
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303962 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963}
3964
3965/* wake lock APIs for HDD */
3966void hdd_prevent_suspend(uint32_t reason)
3967{
3968 cdf_wake_lock_acquire(&wlan_wake_lock, reason);
3969}
3970
3971void hdd_allow_suspend(uint32_t reason)
3972{
3973 cdf_wake_lock_release(&wlan_wake_lock, reason);
3974}
3975
3976void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
3977{
3978 cdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
3979}
3980
3981/**
3982 * hdd_exchange_version_and_caps() - exchange version and capability with target
3983 * @hdd_ctx: Pointer to HDD context
3984 *
3985 * This is the HDD function to exchange version and capability information
3986 * between Host and Target
3987 *
3988 * This function gets reported version of FW.
3989 * It also finds the version of target headers used to compile the host;
3990 * It compares the above two and prints a warning if they are different;
3991 * It gets the SW and HW version string;
3992 * Finally, it exchanges capabilities between host and target i.e. host
3993 * and target exchange a msg indicating the features they support through a
3994 * bitmap
3995 *
3996 * Return: None
3997 */
3998void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
3999{
4000
4001 tSirVersionType versionCompiled;
4002 tSirVersionType versionReported;
4003 tSirVersionString versionString;
4004 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304005 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006
4007 memset(&versionCompiled, 0, sizeof(versionCompiled));
4008 memset(&versionReported, 0, sizeof(versionReported));
4009
4010 /* retrieve and display WCNSS version information */
4011 do {
4012
4013 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4014 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304015 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004016 hddLog(CDF_TRACE_LEVEL_FATAL,
4017 FL(
4018 "unable to retrieve WCNSS WLAN compiled version"
4019 ));
4020 break;
4021 }
4022
4023 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4024 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304025 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 hddLog(CDF_TRACE_LEVEL_FATAL,
4027 FL(
4028 "unable to retrieve WCNSS WLAN reported version"
4029 ));
4030 break;
4031 }
4032
4033 if ((versionCompiled.major != versionReported.major) ||
4034 (versionCompiled.minor != versionReported.minor) ||
4035 (versionCompiled.version != versionReported.version) ||
4036 (versionCompiled.revision != versionReported.revision)) {
4037 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4038 "Host expected %u.%u.%u.%u\n",
4039 WLAN_MODULE_NAME,
4040 (int)versionReported.major,
4041 (int)versionReported.minor,
4042 (int)versionReported.version,
4043 (int)versionReported.revision,
4044 (int)versionCompiled.major,
4045 (int)versionCompiled.minor,
4046 (int)versionCompiled.version,
4047 (int)versionCompiled.revision);
4048 } else {
4049 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4050 WLAN_MODULE_NAME,
4051 (int)versionReported.major,
4052 (int)versionReported.minor,
4053 (int)versionReported.version,
4054 (int)versionReported.revision);
4055 }
4056
4057 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4058 versionString,
4059 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304060 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 hddLog(CDF_TRACE_LEVEL_FATAL,
4062 FL(
4063 "unable to retrieve WCNSS software version string"
4064 ));
4065 break;
4066 }
4067
4068 pr_info("%s: WCNSS software version %s\n",
4069 WLAN_MODULE_NAME, versionString);
4070
4071 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4072 versionString,
4073 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304074 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 hddLog(CDF_TRACE_LEVEL_FATAL,
4076 FL(
4077 "unable to retrieve WCNSS hardware version string"
4078 ));
4079 break;
4080 }
4081
4082 pr_info("%s: WCNSS hardware version %s\n",
4083 WLAN_MODULE_NAME, versionString);
4084
4085 /*
4086 * 1.Check if FW version is greater than 0.1.1.0. Only then
4087 * send host-FW capability exchange message
4088 * 2.Host-FW capability exchange message is only present on
4089 * target 1.1 so send the message only if it the target is 1.1
4090 * minor numbers for different target branches:
4091 * 0 -> (1.0)Mainline Build
4092 * 1 -> (1.1)Mainline Build
4093 * 2->(1.04) Stability Build
4094 */
4095 if (((versionReported.major > 0) || (versionReported.minor > 1)
4096 || ((versionReported.minor >= 1)
4097 && (versionReported.version >= 1)))
4098 && ((versionReported.major == 1)
4099 && (versionReported.minor >= 1)))
4100 fwFeatCapsMsgSupported = 1;
4101
4102 if (fwFeatCapsMsgSupported) {
4103 /*
4104 * Indicate if IBSS heartbeat monitoring needs to be
4105 * offloaded
4106 */
4107 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4108 sme_disable_feature_capablity
4109 (IBSS_HEARTBEAT_OFFLOAD);
4110 }
4111
4112 sme_feature_caps_exchange(hdd_ctx->hHal);
4113 }
4114
4115 } while (0);
4116
4117}
4118
4119/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304120QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121{
4122 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4123 hdd_ctx->reg.cc_src);
4124}
4125
4126/**
4127 * hdd_is_5g_supported() - check if hardware supports 5GHz
4128 * @hdd_ctx: Pointer to the hdd context
4129 *
4130 * HDD function to know if hardware supports 5GHz
4131 *
4132 * Return: true if hardware supports 5GHz
4133 */
4134bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4135{
4136 /*
4137 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4138 * then hardware support 5Ghz.
4139 */
4140 return true;
4141}
4142
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304143static QDF_STATUS wlan_hdd_regulatory_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144{
4145 struct wiphy *wiphy;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304146 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147
4148 wiphy = hdd_ctx->wiphy;
4149
4150 /*
4151 * The channel information in
4152 * wiphy needs to be initialized before wiphy registration
4153 */
4154 status = cds_regulatory_init();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304155 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 hddLog(CDF_TRACE_LEVEL_FATAL,
4157 FL("cds_init_wiphy failed"));
4158 return status;
4159 }
4160
4161#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4162 wiphy->wowlan = &wowlan_support_reg_init;
4163#else
4164 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4165 WIPHY_WOWLAN_MAGIC_PKT |
4166 WIPHY_WOWLAN_DISCONNECT |
4167 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4168 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4169 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4170 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4171 WIPHY_WOWLAN_RFKILL_RELEASE;
4172
4173 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4174 WOW_MAX_FILTERS_PER_LIST);
4175 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4176 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4177#endif
4178
4179 /* registration of wiphy dev with cfg80211 */
4180 if (0 > wlan_hdd_cfg80211_register(wiphy)) {
4181 hddLog(CDF_TRACE_LEVEL_ERROR, FL("wiphy register failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304182 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 }
4184
4185 return status;
4186}
4187
4188#ifdef MSM_PLATFORM
4189void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004190 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191{
4192#ifdef CONFIG_CNSS
4193 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004194 uint64_t temp_rx = 0;
4195 uint64_t temp_tx = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004196 enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004197 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4198 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004199
Mohit Khannae71e2262015-11-10 09:37:24 -08004200
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004201 if (total > hdd_ctx->config->busBandwidthHighThreshold)
4202 next_vote_level = CNSS_BUS_WIDTH_HIGH;
4203 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
4204 next_vote_level = CNSS_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004205 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004206 next_vote_level = CNSS_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004207 else
4208 next_vote_level = CNSS_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209
Mohit Khannae71e2262015-11-10 09:37:24 -08004210 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4211 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212
4213 if (hdd_ctx->cur_vote_level != next_vote_level) {
4214 hddLog(CDF_TRACE_LEVEL_DEBUG,
4215 FL(
4216 "trigger level %d, tx_packets: %lld, rx_packets: %lld"
4217 ),
4218 next_vote_level, tx_packets, rx_packets);
4219 hdd_ctx->cur_vote_level = next_vote_level;
4220 cnss_request_bus_bandwidth(next_vote_level);
4221 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004222
4223 /* fine-tuning parameters for RX Flows */
4224 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4225
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004226 hdd_ctx->prev_rx = rx_packets;
4227 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004228 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004229 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004230 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231
Mohit Khannae71e2262015-11-10 09:37:24 -08004232 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4233 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004234
4235 if (hdd_ctx->cur_rx_level != next_rx_level) {
4236 hddLog(CDF_TRACE_LEVEL_DEBUG,
4237 FL("TCP DELACK trigger level %d, average_rx: %llu"),
4238 next_rx_level, temp_rx);
4239 hdd_ctx->cur_rx_level = next_rx_level;
4240 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
4241 &next_rx_level,
4242 sizeof(next_rx_level));
4243 }
4244
Mohit Khannae71e2262015-11-10 09:37:24 -08004245 /* fine-tuning parameters for TX Flows */
4246 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4247 hdd_ctx->prev_tx = tx_packets;
4248 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4249 next_tx_level = WLAN_SVC_TP_HIGH;
4250 else
4251 next_tx_level = WLAN_SVC_TP_LOW;
4252
4253 if (hdd_ctx->cur_tx_level != next_tx_level) {
4254 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4255 next_tx_level, temp_tx);
4256 hdd_ctx->cur_tx_level = next_tx_level;
4257 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4258 &next_tx_level,
4259 sizeof(next_tx_level));
4260 }
4261
4262 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4263 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 hdd_ctx->hdd_txrx_hist_idx++;
4265 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
4266#endif
4267}
4268
4269#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4270static void hdd_bus_bw_compute_cbk(void *priv)
4271{
4272 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4273 hdd_adapter_t *adapter = NULL;
4274 uint64_t tx_packets = 0, rx_packets = 0;
4275 uint64_t total_tx = 0, total_rx = 0;
4276 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304277 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278 bool connected = false;
4279 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4280
4281 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304282 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283 status =
4284 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4285
4286 if (adapterNode->pAdapter == NULL)
4287 continue;
4288 adapter = adapterNode->pAdapter;
4289
4290 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION ||
4291 adapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
4292 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4293 != eConnectionState_Associated) {
4294
4295 continue;
4296 }
4297
4298 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
4299 adapter->device_mode == WLAN_HDD_P2P_GO) &&
4300 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4301
4302 continue;
4303 }
4304
4305 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4306 adapter->prev_tx_packets);
4307 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4308 adapter->prev_rx_packets);
4309
4310 total_rx += adapter->stats.rx_packets;
4311 total_tx += adapter->stats.tx_packets;
4312
4313 spin_lock_bh(&hdd_ctx->bus_bw_lock);
4314 adapter->prev_tx_packets = adapter->stats.tx_packets;
4315 adapter->prev_rx_packets = adapter->stats.rx_packets;
4316 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
4317 connected = true;
4318 }
4319
4320 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
4321 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
4322 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
4323 rx_packets;
4324 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
4325 tx_packets;
4326
4327 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
4328 tx_packets += (uint64_t)ipa_tx_packets;
4329 rx_packets += (uint64_t)ipa_rx_packets;
4330
4331 if (!connected) {
4332 hddLog(CDF_TRACE_LEVEL_ERROR,
4333 FL("bus bandwidth timer running in disconnected state"));
4334 return;
4335 }
4336
4337 hdd_cnss_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
4338
4339 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
4340 hdd_ipa_uc_stat_request(adapter, 2);
4341
4342 cdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
4343 hdd_ctx->config->busBandwidthComputeInterval);
4344}
4345#endif
4346
4347/**
4348 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
4349 * @hdd_ctx: hdd context
4350 *
4351 * Return: none
4352 */
4353void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
4354{
4355 int i;
4356
4357#ifdef MSM_PLATFORM
4358 hddLog(CDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d",
4359 hdd_ctx->config->busBandwidthComputeInterval,
4360 hdd_ctx->hdd_txrx_hist_idx);
4361 hddLog(CDF_TRACE_LEVEL_ERROR,
4362 "BW High TH: %d BW Med TH: %d BW Low TH: %d",
4363 hdd_ctx->config->busBandwidthHighThreshold,
4364 hdd_ctx->config->busBandwidthMediumThreshold,
4365 hdd_ctx->config->busBandwidthLowThreshold);
4366 hddLog(CDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
4367 hdd_ctx->config->tcpDelackThresholdHigh,
4368 hdd_ctx->config->tcpDelackThresholdLow);
4369#endif
4370
Mohit Khannae71e2262015-11-10 09:37:24 -08004371 hddLog(CDF_TRACE_LEVEL_ERROR,
4372 "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 -08004373
4374 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
4375 hddLog(CDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004376 "%d: %llu, %llu, %llu, %llu, %d, %d, %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
4378 hdd_ctx->hdd_txrx_hist[i].interval_rx,
4379 hdd_ctx->hdd_txrx_hist[i].total_tx,
4380 hdd_ctx->hdd_txrx_hist[i].interval_tx,
4381 hdd_ctx->hdd_txrx_hist[i].next_vote_level,
Mohit Khannae71e2262015-11-10 09:37:24 -08004382 hdd_ctx->hdd_txrx_hist[i].next_rx_level,
4383 hdd_ctx->hdd_txrx_hist[i].next_tx_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 }
4385 return;
4386}
4387
4388/**
4389 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
4390 * @hdd_ctx: hdd context
4391 *
4392 * Return: none
4393 */
4394void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
4395{
4396 hdd_ctx->hdd_txrx_hist_idx = 0;
4397 cdf_mem_zero(hdd_ctx->hdd_txrx_hist, sizeof(hdd_ctx->hdd_txrx_hist));
4398}
4399
4400/**
4401 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
4402 * @pHddCtx: hdd context
4403 *
4404 * Return: none
4405 */
4406void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
4407{
4408
4409 hdd_adapter_t *adapter = NULL;
4410 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304411 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004412 int i;
4413
4414 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304415 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004416 adapter = adapter_node->pAdapter;
4417
4418 hddLog(CDF_TRACE_LEVEL_ERROR,
4419 "Session_id %d device mode %d current index %d",
4420 adapter->sessionId, adapter->device_mode,
4421 adapter->history_index);
4422
4423 hddLog(CDF_TRACE_LEVEL_ERROR,
4424 "Netif queue operation statistics:");
4425 hddLog(CDF_TRACE_LEVEL_ERROR,
4426 "Current pause_map value %x", adapter->pause_map);
4427 hddLog(CDF_TRACE_LEVEL_ERROR,
4428 " reason_type: pause_cnt: unpause_cnt");
4429
4430 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
4431 hddLog(CDF_TRACE_LEVEL_ERROR,
4432 "%s: %d: %d",
4433 hdd_reason_type_to_string(i),
4434 adapter->queue_oper_stats[i].pause_count,
4435 adapter->queue_oper_stats[i].unpause_count);
4436 }
4437
4438 hddLog(CDF_TRACE_LEVEL_ERROR,
4439 "Netif queue operation history:");
4440 hddLog(CDF_TRACE_LEVEL_ERROR,
4441 "index: time: action_type: reason_type: pause_map");
4442
4443 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
4444 hddLog(CDF_TRACE_LEVEL_ERROR,
4445 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05304446 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 adapter->queue_oper_history[i].time),
4448 hdd_action_type_to_string(
4449 adapter->queue_oper_history[i].netif_action),
4450 hdd_reason_type_to_string(
4451 adapter->queue_oper_history[i].netif_reason),
4452 adapter->queue_oper_history[i].pause_map);
4453 }
4454
4455 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4456 adapter_node = next;
4457 }
4458
4459
4460}
4461
4462/**
4463 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
4464 * @hdd_ctx: hdd context
4465 *
4466 * Return: none
4467 */
4468void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
4469{
4470 hdd_adapter_t *adapter = NULL;
4471 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304472 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004473
4474 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304475 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 adapter = adapter_node->pAdapter;
4477
4478 cdf_mem_zero(adapter->queue_oper_stats,
4479 sizeof(adapter->queue_oper_stats));
4480 cdf_mem_zero(adapter->queue_oper_history,
4481 sizeof(adapter->queue_oper_history));
4482
4483 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4484 adapter_node = next;
4485 }
4486}
4487
4488/**
4489 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
4490 * @halHandle: Hal handle
4491 * @pContext: Pointer to the context
4492 * @sessionId: Session ID
4493 * @scanId: Scan ID
4494 * @status: Status
4495 *
4496 * This is the callback to be executed when 11d scan is completed to flush out
4497 * the scan results
4498 *
4499 * 11d scan is done during driver load and is a passive scan on all
4500 * channels supported by the device, 11d scans may find some APs on
4501 * frequencies which are forbidden to be used in the regulatory domain
4502 * the device is operating in. If these APs are notified to the supplicant
4503 * it may try to connect to these APs, thus flush out all the scan results
4504 * which are present in SME after 11d scan is done.
4505 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304506 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304508static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 uint8_t sessionId, uint32_t scanId,
4510 eCsrScanStatus status)
4511{
4512 ENTER();
4513
4514 sme_scan_flush_result(halHandle);
4515
4516 EXIT();
4517
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304518 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519}
4520
4521#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4522/**
4523 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
4524 * @hdd_ctx: hdd global context
4525 *
4526 * Return: none
4527 */
4528static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4529{
4530 uint8_t i;
4531
4532 mutex_init(&hdd_ctx->op_ctx.op_lock);
4533 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4534 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4535 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
4536 }
4537}
4538#else
4539static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4540{
4541}
4542#endif
4543
4544#ifdef WLAN_FEATURE_FASTPATH
4545/**
4546 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
4547 * @hdd_cfg: hdd config
4548 * @context: lower layer context
4549 *
4550 * Return: none
4551 */
4552static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4553 void *context)
4554{
4555 if (hdd_cfg->fastpath_enable)
4556 hif_enable_fastpath(context);
4557}
4558#else
4559static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4560 void *context)
4561{
4562}
4563#endif
4564
4565#if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS)
4566/**
4567 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004568 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004569 * @level: thermal level
4570 *
4571 * Change IPA data path to SW path when the thermal throttle level greater
4572 * than 0, and restore the original data path when throttle level is 0
4573 *
4574 * Return: none
4575 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004576static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004578 hdd_context_t *hdd_ctx = context;
4579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 /* Change IPA to SW path when throttle level greater than 0 */
4581 if (level > THROTTLE_LEVEL_0)
4582 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
4583 else
4584 /* restore original concurrency mode */
4585 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
4586}
4587
4588/**
4589 * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel
4590 * @hdd_ctxt: hdd context pointer
4591 * @ap_adapter: hdd hostapd adapter pointer
4592 *
4593 * Try to find safe channel within preferred channel
4594 * In case auto channel selection enabled
4595 * - Preferred and safe channel should be used
4596 * - If no overlapping, preferred channel should be used
4597 *
4598 * Return: 1: found preferred safe channel
4599 * 0: could not found preferred safe channel
4600 */
4601static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt,
4602 hdd_adapter_t *ap_adapter)
4603{
4604 uint16_t safe_channels[NUM_20MHZ_RF_CHANNELS];
4605 uint16_t safe_channel_count;
4606 uint16_t unsafe_channel_count;
4607 uint8_t is_unsafe = 1;
4608 uint16_t i;
4609 uint16_t channel_loop;
4610
4611 if (!hdd_ctxt || !ap_adapter) {
4612 hdd_err("invalid context/adapter");
4613 return 0;
4614 }
4615
4616 safe_channel_count = 0;
4617 unsafe_channel_count = CDF_MIN((uint16_t)hdd_ctxt->unsafe_channel_count,
4618 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4619
4620 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
4621 is_unsafe = 0;
4622 for (channel_loop = 0;
4623 channel_loop < unsafe_channel_count; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004624 if (CDS_CHANNEL_NUM(i) ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 hdd_ctxt->unsafe_channel_list[channel_loop]) {
4626 is_unsafe = 1;
4627 break;
4628 }
4629 }
4630 if (!is_unsafe) {
4631 safe_channels[safe_channel_count] =
Amar Singhal7a1726a2015-10-14 16:28:11 -07004632 CDS_CHANNEL_NUM(i);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
4634 FL("safe channel %d"),
4635 safe_channels[safe_channel_count]);
4636 safe_channel_count++;
4637 }
4638 }
4639 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
4640 FL("perferred range %d - %d"),
4641 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
4642 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
4643 for (i = 0; i < safe_channel_count; i++) {
4644 if (safe_channels[i] >=
4645 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch
4646 && safe_channels[i] <=
4647 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch) {
4648 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
4649 FL("safe channel %d is in perferred range"),
4650 safe_channels[i]);
4651 return 1;
4652 }
4653 }
4654 return 0;
4655}
Abhishek Singh7996eb72015-12-30 17:24:02 +05304656/**
4657 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
4658 * user space
4659 * @frame_ind: Management frame data to be informed.
4660 *
4661 * This function is used to indicate management frame to
4662 * user space
4663 *
4664 * Return: None
4665 *
4666 */
4667void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
4668{
4669 hdd_context_t *hdd_ctx = NULL;
4670 hdd_adapter_t *adapter = NULL;
4671 void *cds_context = NULL;
4672 int i;
4673
4674 /* Get the global VOSS context.*/
4675 cds_context = cds_get_global_context();
4676 if (!cds_context) {
4677 hddLog(LOGE, FL("Global VOS context is Null"));
4678 return;
4679 }
4680 /* Get the HDD context.*/
4681 hdd_ctx =
4682 (hdd_context_t *)cds_get_context(CDF_MODULE_ID_HDD);
4683
4684 if (0 != wlan_hdd_validate_context(hdd_ctx))
4685 return;
4686
4687 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
4688 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4689 adapter =
4690 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
4691 if (adapter)
4692 break;
4693 }
4694 } else {
4695 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
4696 frame_ind->sessionId);
4697 }
4698
4699 if ((NULL != adapter) &&
4700 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
4701 __hdd_indicate_mgmt_frame(adapter,
4702 frame_ind->frame_len,
4703 frame_ind->frameBuf,
4704 frame_ind->frameType,
4705 frame_ind->rxChan,
4706 frame_ind->rxRssi);
4707 return;
4708}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004709
4710/**
4711 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
4712 * @adapter: HDD adapter pointer
4713 * @indParam: Channel avoid notification parameter
4714 *
4715 * Avoid channel notification from FW handler.
4716 * FW will send un-safe channel list to avoid over wrapping.
4717 * hostapd should not use notified channel
4718 *
4719 * Return: None
4720 */
4721static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
4722{
4723 hdd_adapter_t *hostapd_adapter = NULL;
4724 hdd_context_t *hdd_ctxt;
4725 tSirChAvoidIndType *ch_avoid_indi;
4726 uint8_t range_loop;
Amar Singhala297bfa2015-10-15 15:07:29 -07004727 enum channel_enum channel_loop, start_channel_idx = INVALID_RF_CHANNEL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004728 end_channel_idx = INVALID_RF_CHANNEL;
4729 uint16_t start_channel;
4730 uint16_t end_channel;
4731 v_CONTEXT_t cds_context;
4732 static int restart_sap_in_progress;
4733 tHddAvoidFreqList hdd_avoid_freq_list;
4734 uint32_t i;
4735
4736 /* Basic sanity */
4737 if (!hdd_context || !indi_param) {
4738 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Invalid arguments"));
4739 return;
4740 }
4741
4742 hdd_ctxt = (hdd_context_t *) hdd_context;
4743 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
4744 cds_context = hdd_ctxt->pcds_context;
4745
4746 /* Make unsafe channel list */
4747 hddLog(CDF_TRACE_LEVEL_INFO,
4748 FL("band count %d"),
4749 ch_avoid_indi->avoid_range_count);
4750
4751 /* generate vendor specific event */
4752 cdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
4753 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
4754 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
4755 ch_avoid_indi->avoid_freq_range[i].start_freq;
4756 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
4757 ch_avoid_indi->avoid_freq_range[i].end_freq;
4758 }
4759 hdd_avoid_freq_list.avoidFreqRangeCount =
4760 ch_avoid_indi->avoid_range_count;
4761
4762 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
4763
4764 /* clear existing unsafe channel cache */
4765 hdd_ctxt->unsafe_channel_count = 0;
4766 cdf_mem_zero(hdd_ctxt->unsafe_channel_list,
4767 sizeof(hdd_ctxt->unsafe_channel_list));
4768
4769 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
4770 range_loop++) {
4771 if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) {
4772 hddLog(LOGW, FL("LTE Coex unsafe channel list full"));
4773 break;
4774 }
4775
4776 start_channel = ieee80211_frequency_to_channel(
4777 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
4778 end_channel = ieee80211_frequency_to_channel(
4779 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
4780 hddLog(LOG1, "%s : start %d : %d, end %d : %d", __func__,
4781 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
4782 start_channel,
4783 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
4784 end_channel);
4785
4786 /* do not process frequency bands that are not mapped to
4787 * predefined channels
4788 */
4789 if (start_channel == 0 || end_channel == 0)
4790 continue;
4791
4792 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4793 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004794 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004795 ch_avoid_indi->avoid_freq_range[
4796 range_loop].start_freq) {
4797 start_channel_idx = channel_loop;
4798 break;
4799 }
4800 }
4801 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4802 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004803 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 ch_avoid_indi->avoid_freq_range[
4805 range_loop].end_freq) {
4806 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07004807 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808 ch_avoid_indi->avoid_freq_range[
4809 range_loop].end_freq)
4810 end_channel_idx--;
4811 break;
4812 }
4813 }
4814
4815 if (start_channel_idx == INVALID_RF_CHANNEL ||
4816 end_channel_idx == INVALID_RF_CHANNEL)
4817 continue;
4818
4819 for (channel_loop = start_channel_idx; channel_loop <=
4820 end_channel_idx; channel_loop++) {
4821 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07004822 hdd_ctxt->unsafe_channel_count++] =
4823 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824 if (hdd_ctxt->unsafe_channel_count >=
4825 NUM_20MHZ_RF_CHANNELS) {
4826 hddLog(LOGW, FL("LTECoex unsafe ch list full"));
4827 break;
4828 }
4829 }
4830 }
4831
4832 hddLog(CDF_TRACE_LEVEL_INFO,
4833 FL("number of unsafe channels is %d "),
4834 hdd_ctxt->unsafe_channel_count);
4835
4836 if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list,
4837 hdd_ctxt->unsafe_channel_count)) {
4838 hdd_err("Failed to set unsafe channel");
4839
4840 /* clear existing unsafe channel cache */
4841 hdd_ctxt->unsafe_channel_count = 0;
4842 cdf_mem_zero(hdd_ctxt->unsafe_channel_list,
4843 sizeof(hdd_ctxt->unsafe_channel_list));
4844
4845 return;
4846 }
4847
4848 for (channel_loop = 0;
4849 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
4850 hddLog(CDF_TRACE_LEVEL_INFO,
4851 FL("channel %d is not safe "),
4852 hdd_ctxt->unsafe_channel_list[channel_loop]);
4853 }
4854
4855 /*
4856 * If auto channel select is enabled
4857 * preferred channel is in safe channel,
4858 * re-start softap interface with safe channel.
4859 * no overlap with preferred channel and safe channel
4860 * do not re-start softap interface
4861 * stay current operating channel.
4862 */
4863 if (hdd_ctxt->unsafe_channel_count) {
4864 hostapd_adapter = hdd_get_adapter(hdd_ctxt, WLAN_HDD_SOFTAP);
4865 if (hostapd_adapter) {
4866 if ((hostapd_adapter->sessionCtx.ap.sapConfig.
4867 acs_cfg.acs_mode) &&
4868 (!hdd_find_prefd_safe_chnl(hdd_ctxt,
4869 hostapd_adapter)))
4870 return;
4871
4872 hddLog(CDF_TRACE_LEVEL_INFO,
4873 FL(
4874 "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d"
4875 ),
4876 hostapd_adapter->sessionCtx.ap.
4877 operatingChannel,
4878 hostapd_adapter->sessionCtx.ap.sapConfig.
4879 channel);
4880 for (channel_loop = 0;
4881 channel_loop < hdd_ctxt->unsafe_channel_count;
4882 channel_loop++) {
4883 if (((hdd_ctxt->
4884 unsafe_channel_list[channel_loop] ==
4885 hostapd_adapter->sessionCtx.ap.
4886 operatingChannel)) &&
4887 (hostapd_adapter->sessionCtx.ap.
4888 sapConfig.acs_cfg.acs_mode
4889 == true) &&
4890 !restart_sap_in_progress) {
4891 hddLog(CDF_TRACE_LEVEL_INFO,
4892 FL("Restarting SAP"));
4893 wlan_hdd_send_svc_nlink_msg
4894 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
4895 restart_sap_in_progress = 1;
4896 /*
4897 * current operating channel is un-safe
4898 * channel, restart driver
4899 */
4900 hdd_hostapd_stop(hostapd_adapter->dev);
4901 break;
4902 }
4903 }
4904 }
4905 }
4906 return;
4907}
4908
4909/**
4910 * hdd_init_channel_avoidance() - Initialize channel avoidance
4911 * @hdd_ctx: HDD global context
4912 *
4913 * Initialize the channel avoidance logic by retrieving the unsafe
4914 * channel list from the CNSS platform driver and plumbing the data
4915 * down to the lower layers. Then subscribe to subsequent channel
4916 * avoidance events.
4917 *
4918 * Return: None
4919 */
4920static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4921{
4922 uint16_t unsafe_channel_count;
4923 int index;
4924
4925 cnss_get_wlan_unsafe_channel(hdd_ctx->unsafe_channel_list,
4926 &(hdd_ctx->unsafe_channel_count),
4927 sizeof(uint16_t) * NUM_20MHZ_RF_CHANNELS);
4928
4929 hddLog(CDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"),
4930 hdd_ctx->unsafe_channel_count);
4931
4932 unsafe_channel_count = CDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
4933 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4934
4935 for (index = 0; index < unsafe_channel_count; index++) {
4936 hddLog(CDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"),
4937 hdd_ctx->unsafe_channel_list[index]);
4938
4939 }
4940
4941 /* Plug in avoid channel notification callback */
4942 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
4943}
4944#else
4945static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4946{
4947}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004948static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949{
4950}
4951#endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */
4952
4953/**
4954 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
4955 * @hdd_ctx: HDD context
4956 *
4957 * Disables all the dual mac features like DBS, Agile DFS etc.
4958 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304959 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004960 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304961static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962{
4963 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304964 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004965
4966 if (!hdd_ctx) {
4967 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304968 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004969 }
4970
4971 cfg.scan_config = 0;
4972 cfg.fw_mode_config = 0;
4973 cfg.set_dual_mac_cb =
4974 (void *)cds_soc_set_dual_mac_cfg_cb;
4975
4976 hdd_debug("Disabling all dual mac features...");
4977
4978 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304979 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004980 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
4981 return status;
4982 }
4983
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304984 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004985}
4986
4987/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004988 * hdd_override_ini_config - Override INI config
4989 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004991 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004992 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004993 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004994 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004995static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004996{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004998 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
4999 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5000 hdd_notice("Module enable_dfs_chan_scan set to %d",
5001 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005003 if (0 == enable_11d || 1 == enable_11d) {
5004 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5005 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005007}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005009/**
5010 * hdd_set_trace_level_for_each - Set trace level for each INI config
5011 * @hdd_ctx - HDD context
5012 *
5013 * Set trace level for each module based on INI config.
5014 *
5015 * Return: None
5016 */
5017static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5018{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005019 hdd_cdf_trace_enable(CDF_MODULE_ID_WMI,
5020 hdd_ctx->config->cdf_trace_enable_wdi);
5021 hdd_cdf_trace_enable(CDF_MODULE_ID_HDD,
5022 hdd_ctx->config->cdf_trace_enable_hdd);
5023 hdd_cdf_trace_enable(CDF_MODULE_ID_SME,
5024 hdd_ctx->config->cdf_trace_enable_sme);
5025 hdd_cdf_trace_enable(CDF_MODULE_ID_PE,
5026 hdd_ctx->config->cdf_trace_enable_pe);
5027 hdd_cdf_trace_enable(CDF_MODULE_ID_WMA,
5028 hdd_ctx->config->cdf_trace_enable_wma);
5029 hdd_cdf_trace_enable(CDF_MODULE_ID_SYS,
5030 hdd_ctx->config->cdf_trace_enable_sys);
5031 hdd_cdf_trace_enable(CDF_MODULE_ID_CDF,
5032 hdd_ctx->config->cdf_trace_enable_cdf);
5033 hdd_cdf_trace_enable(CDF_MODULE_ID_SAP,
5034 hdd_ctx->config->cdf_trace_enable_sap);
5035 hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SOFTAP,
5036 hdd_ctx->config->cdf_trace_enable_hdd_sap);
5037 hdd_cdf_trace_enable(CDF_MODULE_ID_BMI,
5038 hdd_ctx->config->cdf_trace_enable_bmi);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305039 hdd_cdf_trace_enable(CDF_MODULE_ID_CFG,
5040 hdd_ctx->config->cdf_trace_enable_cfg);
5041 hdd_cdf_trace_enable(CDF_MODULE_ID_EPPING,
5042 hdd_ctx->config->cdf_trace_enable_epping);
5043 hdd_cdf_trace_enable(CDF_MODULE_ID_CDF_DEVICE,
5044 hdd_ctx->config->cdf_trace_enable_cdf_devices);
5045 hdd_cdf_trace_enable(CDF_MODULE_ID_TXRX,
5046 hdd_ctx->config->cfd_trace_enable_txrx);
5047 hdd_cdf_trace_enable(CDF_MODULE_ID_HTC,
5048 hdd_ctx->config->cdf_trace_enable_htc);
5049 hdd_cdf_trace_enable(CDF_MODULE_ID_HIF,
5050 hdd_ctx->config->cdf_trace_enable_hif);
5051 hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SAP_DATA,
5052 hdd_ctx->config->cdf_trace_enable_hdd_sap_data);
5053 hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_DATA,
5054 hdd_ctx->config->cdf_trace_enable_hdd_data);
5055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005056 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005057}
5058
5059/**
5060 * hdd_init_context - Alloc and initialize HDD context
5061 * @dev: Pointer to the underlying device
5062 * @hif_sc: HIF context
5063 *
5064 * Allocate and initialize HDD context. HDD context is allocated as part of
5065 * wiphy allocation and then context is initialized.
5066 *
5067 * Return: HDD context on success and ERR_PTR on failure
5068 */
5069hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc)
5070{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305071 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005072 int ret = 0;
5073 hdd_context_t *hdd_ctx;
5074 v_CONTEXT_t p_cds_context;
Komal Seelamc11bb222016-01-27 18:57:10 +05305075 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_sc);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005076
5077 ENTER();
5078
5079 p_cds_context = cds_get_global_context();
5080 if (p_cds_context == NULL) {
5081 hdd_alert("Failed to get CDS global context");
5082 ret = -EINVAL;
5083 goto err_out;
5084 }
5085
5086 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
5087
5088 if (hdd_ctx == NULL) {
5089 ret = -ENOMEM;
5090 goto err_out;
5091 }
5092
5093 hdd_ctx->pcds_context = p_cds_context;
5094
5095 hdd_ctx->config = cdf_mem_malloc(sizeof(struct hdd_config));
5096 if (hdd_ctx->config == NULL) {
5097 hdd_alert("Failed to alloc memory for HDD config!");
5098 ret = -ENOMEM;
5099 goto err_free_hdd_context;
5100 }
5101
5102 /* Read and parse the qcom_cfg.ini file */
5103 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305104 if (QDF_STATUS_SUCCESS != status) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005105 hdd_alert("Error (status: %d) parsing INI file: %s", status,
5106 WLAN_INI_FILE);
5107 ret = -EINVAL;
5108 goto err_free_config;
5109 }
5110
5111 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
5112
5113 hdd_ctx->parent_dev = dev;
5114
5115 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5116
5117 hdd_init_ll_stats_ctx();
5118
5119 init_completion(&hdd_ctx->mc_sus_event_var);
5120 init_completion(&hdd_ctx->ready_to_suspend);
5121
5122 cdf_spinlock_init(&hdd_ctx->connection_status_lock);
5123 cdf_spinlock_init(&hdd_ctx->sched_scan_lock);
5124
5125 cdf_spinlock_init(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305126 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005127
5128 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
5129
5130 hdd_tdls_pre_init(hdd_ctx);
5131 mutex_init(&hdd_ctx->dfs_lock);
5132
Komal Seelamc11bb222016-01-27 18:57:10 +05305133 hdd_ctx->target_type = tgt_info->target_type;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005134
5135 hdd_init_offloaded_packets_ctx(hdd_ctx);
5136
Komal Seelamc11bb222016-01-27 18:57:10 +05305137 icnss_set_fw_debug_mode(hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005138
5139 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5140
5141 hdd_ctx->configuredMcastBcastFilter =
5142 hdd_ctx->config->mcastBcastFilterSetting;
5143
5144 hdd_notice("Setting configuredMcastBcastFilter: %d",
5145 hdd_ctx->config->mcastBcastFilterSetting);
5146
5147 hdd_override_ini_config(hdd_ctx);
5148
5149 ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config);
5150
5151 if (ret) {
5152 hdd_err("CFG80211 wiphy init failed: %d", ret);
5153 goto err_free_config;
5154 }
5155
5156 hdd_enable_fastpath(hdd_ctx->config, hif_sc);
5157
5158 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05305159 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005160
5161 if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam())
5162 goto skip_multicast_logging;
5163
5164 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
5165
5166 ret = hdd_logging_sock_activate_svc(hdd_ctx);
5167 if (ret)
5168 goto err_free_config;
5169
5170 /*
5171 * Update CDF trace levels based upon the code. The multicast
5172 * levels of the code need not be set when the logger thread
5173 * is not enabled.
5174 */
5175 if (cds_is_multicast_logging())
5176 wlan_logging_set_log_level();
5177
5178skip_multicast_logging:
5179 hdd_set_trace_level_for_each(hdd_ctx);
5180
5181 return hdd_ctx;
5182
5183err_free_config:
5184 cdf_mem_free(hdd_ctx->config);
5185
5186err_free_hdd_context:
5187 wiphy_free(hdd_ctx->wiphy);
5188
5189err_out:
5190 return ERR_PTR(ret);
5191}
5192
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005193#ifdef WLAN_OPEN_P2P_INTERFACE
5194/**
5195 * hdd_open_p2p_interface - Open P2P interface
5196 * @hdd_ctx: HDD context
5197 * @rtnl_held: True if RTNL lock held
5198 *
5199 * Open P2P interface during probe. This function called to open the P2P
5200 * interface at probe along with STA interface.
5201 *
5202 * Return: 0 on success and errno on failure
5203 */
5204static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
5205{
5206 hdd_adapter_t *adapter;
5207 uint8_t *p2p_dev_addr;
5208
5209 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
5210 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
5211 cdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
5212 hdd_ctx->config->intfMacAddr[0].bytes,
5213 sizeof(tSirMacAddr));
5214
5215 /*
5216 * Generate the P2P Device Address. This consists of
5217 * the device's primary MAC address with the locally
5218 * administered bit set.
5219 */
5220 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
5221 } else {
5222 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
5223 if (p2p_dev_addr == NULL) {
5224 hdd_alert("Failed to allocate mac_address for p2p_device");
5225 return -ENOSPC;
5226 }
5227
5228 cdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
5229 CDF_MAC_ADDR_SIZE);
5230 }
5231
5232 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5233 &hdd_ctx->p2pDeviceAddress.bytes[0],
5234 rtnl_held);
5235
5236 if (NULL == adapter) {
5237 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
5238 return -ENOSPC;
5239 }
5240
5241 return 0;
5242}
5243#else
5244static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx,
5245 bool rtnl_held)
5246{
5247 return 0;
5248}
5249#endif
5250
5251/**
5252 * hdd_open_interfaces - Open all required interfaces
5253 * hdd_ctx: HDD context
5254 * rtnl_held: True if RTNL lock is held
5255 *
5256 * Open all the interfaces like STA, P2P and OCB based on the configuration.
5257 *
5258 * Return: Primary adapter on success and PTR_ERR on failure
5259 */
5260static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
5261 bool rtnl_held)
5262{
5263 hdd_adapter_t *adapter = NULL;
5264 hdd_adapter_t *adapter_11p = NULL;
5265 int ret;
5266
5267 /* Create only 802.11p interface */
5268 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
5269 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d",
5270 wlan_hdd_get_intf_addr(hdd_ctx),
5271 rtnl_held);
5272
5273 if (adapter == NULL)
5274 return ERR_PTR(-ENOSPC);
5275
5276 return adapter;
5277 }
5278
5279 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, "wlan%d",
5280 wlan_hdd_get_intf_addr(hdd_ctx),
5281 rtnl_held);
5282
5283 if (adapter == NULL)
5284 return ERR_PTR(-ENOSPC);
5285
5286 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
5287 if (ret)
5288 goto err_close_adapter;
5289
5290 /* Open 802.11p Interface */
5291 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
5292 adapter_11p = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB,
5293 "wlanocb%d",
5294 wlan_hdd_get_intf_addr(hdd_ctx),
5295 rtnl_held);
5296 if (adapter_11p == NULL) {
5297 hdd_err("Failed to open 802.11p interface");
5298 goto err_close_adapter;
5299 }
5300 }
5301
5302 return adapter;
5303
5304err_close_adapter:
5305 hdd_close_all_adapters(hdd_ctx, rtnl_held);
5306 return ERR_PTR(ret);
5307}
5308
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005309/**
5310 * hdd_update_country_code - Update country code
5311 * @hdd_ctx: HDD context
5312 * @adapter: Primary adapter context
5313 *
5314 * Update country code based on module parameter country_code at SME and wait
5315 * for the settings to take effect.
5316 *
5317 * Return: 0 on success and errno on failure
5318 */
5319static int hdd_update_country_code(hdd_context_t *hdd_ctx,
5320 hdd_adapter_t *adapter)
5321{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305322 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005323 int ret = 0;
5324 unsigned long rc;
5325
5326 if (country_code == NULL)
5327 return 0;
5328
5329 INIT_COMPLETION(adapter->change_country_code);
5330
5331 status = sme_change_country_code(hdd_ctx->hHal,
5332 wlan_hdd_change_country_code_callback,
5333 country_code, adapter,
5334 hdd_ctx->pcds_context, eSIR_TRUE,
5335 eSIR_TRUE);
5336
5337
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305338 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005339 hdd_err("SME Change Country code from module param fail ret=%d",
5340 ret);
5341 return -EINVAL;
5342 }
5343
5344 rc = wait_for_completion_timeout(&adapter->change_country_code,
5345 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
5346 if (!rc) {
5347 hdd_err("SME while setting country code timed out");
5348 ret = -ETIMEDOUT;
5349 }
5350
5351 return ret;
5352}
5353
5354/**
5355 * hdd_init_thermal_info - Initialize thermal level
5356 * @hdd_ctx: HDD context
5357 *
5358 * Initialize thermal level at SME layer and set the thermal level callback
5359 * which would be called when a configured thermal threshold is hit.
5360 *
5361 * Return: 0 on success and errno on failure
5362 */
5363static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
5364{
5365 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305366 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005367
5368 thermal_param.smeThermalMgmtEnabled =
5369 hdd_ctx->config->thermalMitigationEnable;
5370 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
5371
5372 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
5373 hdd_ctx->config->thermalTempMinLevel0;
5374 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
5375 hdd_ctx->config->thermalTempMaxLevel0;
5376 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
5377 hdd_ctx->config->thermalTempMinLevel1;
5378 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
5379 hdd_ctx->config->thermalTempMaxLevel1;
5380 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
5381 hdd_ctx->config->thermalTempMinLevel2;
5382 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
5383 hdd_ctx->config->thermalTempMaxLevel2;
5384 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
5385 hdd_ctx->config->thermalTempMinLevel3;
5386 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
5387 hdd_ctx->config->thermalTempMaxLevel3;
5388
5389 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
5390
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305391 if (!QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005392 return cdf_status_to_os_return(status);
5393
5394 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
5395 hdd_set_thermal_level_cb);
5396
5397 return 0;
5398
5399}
5400
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005401#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5402/**
5403 * hdd_hold_rtnl_lock - Hold RTNL lock
5404 *
5405 * Hold RTNL lock
5406 *
5407 * Return: True if held and false otherwise
5408 */
5409static inline bool hdd_hold_rtnl_lock(void)
5410{
5411 rtnl_lock();
5412 return true;
5413}
5414
5415/**
5416 * hdd_release_rtnl_lock - Release RTNL lock
5417 *
5418 * Release RTNL lock
5419 *
5420 * Return: None
5421 */
5422static inline void hdd_release_rtnl_lock(void)
5423{
5424 rtnl_unlock();
5425}
5426#else
5427static inline bool hdd_hold_rtnl_lock(void) { return false; }
5428static inline void hdd_release_rtnl_lock(void) { }
5429#endif
5430
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005431/**
5432 * hdd_wlan_startup() - HDD init function
5433 * @dev: Pointer to the underlying device
5434 *
5435 * This is the driver startup code executed once a WLAN device has been detected
5436 *
5437 * Return: 0 for success, < 0 for failure
5438 */
5439int hdd_wlan_startup(struct device *dev, void *hif_sc)
5440{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305441 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005442 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005443 hdd_context_t *hdd_ctx = NULL;
5444 int ret;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005445 tSirTxPowerLimit hddtxlimit;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005446 bool rtnl_held;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005447 tSirRetStatus hal_status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005448
5449 ENTER();
5450
5451 if (WLAN_IS_EPPING_ENABLED(con_mode)) {
5452 ret = epping_enable(dev);
5453 EXIT();
5454 return ret;
5455 }
5456
5457 hdd_ctx = hdd_init_context(dev, hif_sc);
5458
5459 if (IS_ERR(hdd_ctx))
5460 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005462 if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5463 ret = hdd_enable_ftm(hdd_ctx);
5464
5465 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005466 goto err_hdd_free_context;
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005467
5468 goto success;
5469 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08005471 hdd_wlan_green_ap_init(hdd_ctx);
5472
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005473 status = cds_open();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305474 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_open failed"));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005476 goto err_hdd_free_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 }
5478
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005479 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005480
5481 hdd_ctx->hHal = cds_get_context(CDF_MODULE_ID_SME);
5482
5483 if (NULL == hdd_ctx->hHal) {
5484 hddLog(CDF_TRACE_LEVEL_FATAL, FL("HAL context is null"));
5485 goto err_cds_close;
5486 }
5487
5488 status = cds_pre_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305489 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005490 hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed"));
5491 goto err_cds_close;
5492 }
5493
5494 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
5495
5496 status = wlan_hdd_regulatory_init(hdd_ctx);
5497
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305498 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005499 hddLog(CDF_TRACE_LEVEL_FATAL,
5500 FL("Failed to init channel list"));
5501 goto err_cds_close;
5502 }
5503
5504 /*
5505 * Set 802.11p config
5506 * TODO-OCB: This has been temporarily added here to ensure this
5507 * parameter is set in CSR when we init the channel list. This should
5508 * be removed once the 5.9 GHz channels are added to the regulatory
5509 * domain.
5510 */
5511 hdd_set_dot11p_config(hdd_ctx);
5512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 /*
5514 * Note that the cds_pre_enable() sequence triggers the cfg download.
5515 * The cfg download must occur before we update the SME config
5516 * since the SME config operation must access the cfg database
5517 */
5518 status = hdd_set_sme_config(hdd_ctx);
5519
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305520 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 hddLog(CDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config"));
5522 goto err_wiphy_unregister;
5523 }
5524
5525 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
5526 hdd_ctx->config->tx_chain_mask_1ss,
5527 PDEV_CMD);
5528 if (0 != ret) {
5529 hddLog(CDF_TRACE_LEVEL_ERROR,
5530 "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d",
5531 __func__, ret);
5532 }
5533
5534 status = hdd_set_sme_chan_list(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305535 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 hddLog(CDF_TRACE_LEVEL_FATAL,
5537 FL("Failed to init channel list"));
5538 goto err_wiphy_unregister;
5539 }
5540
5541 /* Apply the cfg.ini to cfg.dat */
5542 if (false == hdd_update_config_dat(hdd_ctx)) {
5543 hddLog(CDF_TRACE_LEVEL_FATAL,
5544 FL("config update failed"));
5545 goto err_wiphy_unregister;
5546 }
5547
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305548 if (QDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005549 hddLog(CDF_TRACE_LEVEL_WARN,
5550 FL("can't update mac config, using MAC from ini file"));
5551 }
5552
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005553 /*
5554 * Set the MAC Address Currently this is used by HAL to add self sta.
5555 * Remove this once self sta is added as part of session open.
5556 */
5557 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
5558 hdd_ctx->config->intfMacAddr[0].bytes,
5559 sizeof(hdd_ctx->config->intfMacAddr[0]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005561 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
5562 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
5563 hal_status, hal_status);
5564 ret = -EINVAL;
5565 goto err_wiphy_unregister;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 }
5567
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305568 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 goto err_wiphy_unregister;
5570
5571 /*
5572 * Start CDS which starts up the SME/MAC/HAL modules and everything
5573 * else
5574 */
5575 status = cds_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305576 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577 hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_enable failed"));
Yun Park6a46ad82016-01-04 16:48:19 -08005578 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579 }
5580
5581 hdd_init_channel_avoidance(hdd_ctx);
5582
5583 status = hdd_post_cds_enable_config(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305584 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 hddLog(CDF_TRACE_LEVEL_FATAL,
5586 FL("hdd_post_cds_enable_config failed"));
5587 goto err_cds_disable;
5588 }
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 cds_pkt_proto_trace_init();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005591
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005592 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005593
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005594 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005595
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005596 if (IS_ERR(adapter)) {
5597 ret = PTR_ERR(adapter);
5598 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005599 }
5600
5601 /*
5602 * target hw version/revision would only be retrieved after firmware
5603 * donwload
5604 */
5605 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
5606 &hdd_ctx->target_hw_revision,
5607 &hdd_ctx->target_hw_name);
5608
5609 /* Get the wlan hw/fw version */
5610 hdd_wlan_get_version(adapter, NULL, NULL);
5611
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005612 ret = hdd_update_country_code(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005614 if (ret)
5615 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616
5617 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
5618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
5620 hdd_send_oem_data_rsp_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005621
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005622 status = hdd_debugfs_init(adapter);
5623
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305624 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005625 hdd_err("hdd_debugfs_init failed: %d!", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005626
5627 /* FW capabilities received, Set the Dot11 mode */
5628 sme_setdef_dot11mode(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630 /* Initialize the nlink service */
5631 if (nl_srv_init() != 0) {
5632 hddLog(CDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed"));
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005633 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005634 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005636 ret = oem_activate_service(hdd_ctx);
5637 if (ret) {
5638 hdd_alert("oem_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005639 goto err_nl_srv;
5640 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005642 ret = ptt_sock_activate_svc();
5643 if (ret) {
5644 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005645 goto err_nl_srv;
5646 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005648 ret = cnss_diag_activate_service();
5649 if (ret) {
5650 hdd_alert("cnss_diag_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005651 goto err_nl_srv;
5652 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005653
Peng Xuf5d60c82015-10-02 17:17:03 -07005654 /*
5655 * Action frame registered in one adapter which will
5656 * applicable to all interfaces
5657 */
5658 wlan_hdd_cfg80211_register_frames(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005659
5660 mutex_init(&hdd_ctx->sap_lock);
5661
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005662 hdd_release_rtnl_lock();
5663 rtnl_held = false;
5664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005665 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5666 if (ret < 0) {
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005667 hdd_err("register_netdevice_notifier failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668 goto err_nl_srv;
5669 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005671#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5672 /* Initialize the wake lcok */
5673 cdf_wake_lock_init(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5674#endif
5675 /* Initialize the wake lcok */
5676 cdf_wake_lock_init(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock");
5677
5678 hdd_hostapd_channel_wakelock_init(hdd_ctx);
5679
Kiran Kumar Lokerefc2803d2016-01-11 19:31:38 -08005680 if (hdd_ctx->config->fIsImpsEnabled)
5681 hdd_set_idle_ps_config(hdd_ctx, true);
5682 else
5683 hdd_set_idle_ps_config(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5685 if (hdd_ctx->config->WlanAutoShutdown != 0)
5686 if (sme_set_auto_shutdown_cb
5687 (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305688 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689 hddLog(LOGE,
5690 FL(
5691 "Auto shutdown feature could not be enabled"
5692 ));
5693#endif
5694
5695#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
5696 status = cdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
5697 CDF_TIMER_TYPE_SW,
5698 hdd_skip_acs_scan_timer_handler,
5699 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305700 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005701 hddLog(LOGE, FL("Failed to init ACS Skip timer"));
5702#endif
5703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704 wlan_hdd_nan_init(hdd_ctx);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005705 status = cds_init_policy_mgr();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305706 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005707 hdd_err("Policy manager initialization failed");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005708 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005709 }
5710
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005711 ret = hdd_init_thermal_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005713 if (ret) {
5714 hdd_err("Error while initializing thermal information");
5715 goto err_unreg_netdev_notifier;
5716 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005717
5718 if (0 != hdd_lro_init(hdd_ctx))
5719 hdd_err("Unable to initialize LRO in fw");
5720
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005721 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
5722 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
5723 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305724 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005725 hdd_err("Error setting txlimit in sme: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005726
5727#ifdef MSM_PLATFORM
5728 spin_lock_init(&hdd_ctx->bus_bw_lock);
5729 cdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
5730 CDF_TIMER_TYPE_SW,
5731 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5732#endif
5733
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005734 wlan_hdd_cfg80211_stats_ext_init(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005736 sme_ext_scan_register_callback(hdd_ctx->hHal,
5737 wlan_hdd_cfg80211_extscan_callback);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005738
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005739 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
5740 hdd_rssi_threshold_breached);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005741
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005742 hdd_cfg80211_link_layer_stats_init(hdd_ctx);
5743
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005744 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
5745 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
5746 hdd_ctx->target_hw_version,
5747 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005748
5749 cdf_spinlock_init(&hdd_ctx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305750 qdf_list_create((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751 cdf_spinlock_init(&hdd_ctx->hdd_scan_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305752 qdf_list_create((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753#ifdef CONFIG_CNSS
5754 cnss_init_delayed_work(&hdd_ctx->roc_req_work,
5755 wlan_hdd_roc_request_dequeue);
5756#else
5757 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5758#endif
5759
5760 /*
5761 * Register IPv6 notifier to notify if any change in IP
5762 * So that we can reconfigure the offload parameters
5763 */
5764 hdd_wlan_register_ip6_notifier(hdd_ctx);
5765
5766 /*
5767 * Register IPv4 notifier to notify if any change in IP
5768 * So that we can reconfigure the offload parameters
5769 */
5770 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5771 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5772 if (ret)
5773 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
5774 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005775 hdd_info("Registered IPv4 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005776
5777 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
5778
5779 if (hdd_ctx->config->dual_mac_feature_disable) {
5780 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305781 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005782 hdd_err("Failed to disable dual mac features");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005783 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784 }
5785 }
5786
5787 hif_enable_power_gating(hif_sc);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005788
5789 memdump_init();
5790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 goto success;
5792
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005793err_unreg_netdev_notifier:
5794 unregister_netdevice_notifier(&hdd_netdev_notifier);
5795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796err_nl_srv:
5797#ifdef WLAN_KD_READY_NOTIFIER
5798 cnss_diag_notify_wlan_close();
5799 ptt_sock_deactivate_svc();
5800#endif /* WLAN_KD_READY_NOTIFIER */
5801 nl_srv_exit();
5802
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305803 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08005804 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005805 /* Proceed and complete the clean up */
5806 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005808 hdd_debugfs_exit(hdd_ctx);
5809
5810err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005811 hdd_release_rtnl_lock();
5812
5813 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814
5815err_cds_disable:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005816 cds_disable(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817
Yun Park6a46ad82016-01-04 16:48:19 -08005818err_ipa_cleanup:
5819 hdd_ipa_cleanup(hdd_ctx);
5820
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005821err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005822 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005823
5824err_cds_close:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005825 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305826 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005827 hddLog(CDF_TRACE_LEVEL_FATAL,
5828 FL("Failed to close CDS Scheduler"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305829 CDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005831 cds_close(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005832
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005833err_hdd_free_context:
5834 hdd_free_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005835 CDF_BUG(1);
5836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005837 return -EIO;
5838
5839success:
5840 EXIT();
5841 return 0;
5842}
5843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844/**
5845 * hdd_softap_sta_deauth() - handle deauth req from HDD
5846 * @adapter: Pointer to the HDD
5847 * @enable: bool value
5848 *
5849 * This to take counter measure to handle deauth req from HDD
5850 *
5851 * Return: None
5852 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305853QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005854 struct tagCsrDelStaParams *pDelStaParams)
5855{
5856#ifndef WLAN_FEATURE_MBSSID
5857 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5858#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305859 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005860
5861 ENTER();
5862
5863 hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"),
5864 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5865
5866 /* Ignore request to deauth bcmc station */
5867 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305868 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869
5870#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305871 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005872 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5873 pDelStaParams);
5874#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305875 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876#endif
5877
5878 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305879 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880}
5881
5882/**
5883 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
5884 * @adapter: Pointer to the HDD
5885 *
5886 * This to take counter measure to handle deauth req from HDD
5887 *
5888 * Return: None
5889 */
5890void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
5891 uint8_t *pDestMacAddress)
5892{
5893#ifndef WLAN_FEATURE_MBSSID
5894 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5895#endif
5896
5897 ENTER();
5898
5899 hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"),
5900 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5901
5902 /* Ignore request to disassoc bcmc station */
5903 if (pDestMacAddress[0] & 0x1)
5904 return;
5905
5906#ifdef WLAN_FEATURE_MBSSID
5907 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5908 pDestMacAddress);
5909#else
5910 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
5911#endif
5912}
5913
5914void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
5915 bool enable)
5916{
5917#ifndef WLAN_FEATURE_MBSSID
5918 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5919#endif
5920
5921 ENTER();
5922
5923 hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"),
5924 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5925
5926#ifdef WLAN_FEATURE_MBSSID
5927 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5928 (bool) enable);
5929#else
5930 wlansap_set_counter_measure(p_cds_context, (bool) enable);
5931#endif
5932}
5933
5934/**
5935 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
5936 * @hdd_ctx: HDD Context
5937 *
5938 * API to find if there is any STA or P2P-Client is connected
5939 *
5940 * Return: true if connected; false otherwise
5941 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305942QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943{
5944 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
5945}
5946
5947#ifdef WLAN_FEATURE_LPSS
5948int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
5949 hdd_adapter_t *adapter,
5950 hdd_station_ctx_t *pHddStaCtx,
5951 uint8_t is_on, uint8_t is_connected)
5952{
5953 hdd_context_t *hdd_ctx = NULL;
5954 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
5955
5956 if (!data) {
5957 hddLog(LOGE, FL("invalid data pointer"));
5958 return -EINVAL;
5959 }
5960 if (!adapter) {
5961 if (is_on) {
5962 /* no active interface */
5963 data->lpss_support = 0;
5964 data->is_on = is_on;
5965 return 0;
5966 }
5967 hddLog(LOGE, FL("invalid adapter pointer"));
5968 return -EINVAL;
5969 }
5970
5971 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelamc11bb222016-01-27 18:57:10 +05305972 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005973 data->lpss_support = 1;
5974 else
5975 data->lpss_support = 0;
5976 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
5977 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
5978 &data->numChannels);
5979 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
5980 data->is_on = is_on;
5981 data->vdev_id = adapter->sessionId;
5982 data->vdev_mode = adapter->device_mode;
5983 if (pHddStaCtx) {
5984 data->is_connected = is_connected;
5985 data->rssi = adapter->rssi;
5986 data->freq =
5987 cds_chan_to_freq(pHddStaCtx->conn_info.operationChannel);
5988 if (WLAN_SVC_MAX_SSID_LEN >=
5989 pHddStaCtx->conn_info.SSID.SSID.length) {
5990 data->ssid_len = pHddStaCtx->conn_info.SSID.SSID.length;
5991 memcpy(data->ssid,
5992 pHddStaCtx->conn_info.SSID.SSID.ssId,
5993 pHddStaCtx->conn_info.SSID.SSID.length);
5994 }
5995 if (CDF_MAC_ADDR_SIZE >=
5996 sizeof(pHddStaCtx->conn_info.bssId))
5997 memcpy(data->bssid, pHddStaCtx->conn_info.bssId.bytes,
5998 CDF_MAC_ADDR_SIZE);
5999 }
6000 return 0;
6001}
6002
6003int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
6004 uint32_t fw_version,
6005 uint32_t chip_id, const char *chip_name)
6006{
6007 if (!data) {
6008 hddLog(LOGE, FL("invalid data pointer"));
6009 return -EINVAL;
6010 }
6011
6012 data->chip_id = chip_id;
6013 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
6014 if (strncmp(chip_name, "Unknown", 7))
6015 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
6016 else
6017 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
6018 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
6019 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
6020 (fw_version & 0xf0000000) >> 28,
6021 (fw_version & 0xf000000) >> 24,
6022 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
6023 return 0;
6024}
6025#endif
6026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006027/**
6028 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
6029 * @adapter: HDD adapter pointer
6030 *
6031 * This function loop through each adapter and disable roaming on each STA
6032 * device mode except the input adapter.
6033 *
6034 * Note: On the input adapter roaming is not enabled yet hence no need to
6035 * disable.
6036 *
6037 * Return: None
6038 */
6039void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
6040{
6041 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6042 hdd_adapter_t *adapterIdx = NULL;
6043 hdd_adapter_list_node_t *adapterNode = NULL;
6044 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306045 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046
6047 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6048 hdd_ctx->config->isRoamOffloadScanEnabled &&
6049 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6050 cds_is_sta_active_connection_exists()) {
6051 hddLog(LOG1, FL("Connect received on STA sessionId(%d)"),
6052 adapter->sessionId);
6053 /*
6054 * Loop through adapter and disable roaming for each STA device
6055 * mode except the input adapter.
6056 */
6057 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6058
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306059 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006060 adapterIdx = adapterNode->pAdapter;
6061
6062 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6063 && adapter->sessionId != adapterIdx->sessionId) {
6064 hddLog(LOG1,
6065 FL("Disable Roaming on sessionId(%d)"),
6066 adapterIdx->sessionId);
6067 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
6068 (adapterIdx),
6069 adapterIdx->sessionId, 0);
6070 }
6071
6072 status = hdd_get_next_adapter(hdd_ctx,
6073 adapterNode,
6074 &pNext);
6075 adapterNode = pNext;
6076 }
6077 }
6078}
6079
6080/**
6081 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
6082 * @adapter: HDD adapter pointer
6083 *
6084 * This function loop through each adapter and enable roaming on each STA
6085 * device mode except the input adapter.
6086 * Note: On the input adapter no need to enable roaming because link got
6087 * disconnected on this.
6088 *
6089 * Return: None
6090 */
6091void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
6092{
6093 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6094 hdd_adapter_t *adapterIdx = NULL;
6095 hdd_adapter_list_node_t *adapterNode = NULL;
6096 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306097 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098
6099 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6100 hdd_ctx->config->isRoamOffloadScanEnabled &&
6101 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6102 cds_is_sta_active_connection_exists()) {
6103 hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"),
6104 adapter->sessionId);
6105 /*
6106 * Loop through adapter and enable roaming for each STA device
6107 * mode except the input adapter.
6108 */
6109 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6110
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306111 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006112 adapterIdx = adapterNode->pAdapter;
6113
6114 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6115 && adapter->sessionId != adapterIdx->sessionId) {
6116 hddLog(LOG1,
6117 FL("Enabling Roaming on sessionId(%d)"),
6118 adapterIdx->sessionId);
6119 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
6120 (adapterIdx),
6121 adapterIdx->sessionId,
6122 REASON_CONNECT);
6123 }
6124
6125 status = hdd_get_next_adapter(hdd_ctx,
6126 adapterNode,
6127 &pNext);
6128 adapterNode = pNext;
6129 }
6130 }
6131}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006132
6133void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
6134{
6135 struct sk_buff *skb;
6136 struct nlmsghdr *nlh;
6137 tAniMsgHdr *ani_hdr;
6138 void *nl_data = NULL;
6139 int flags = GFP_KERNEL;
6140
6141 if (in_interrupt() || irqs_disabled() || in_atomic())
6142 flags = GFP_ATOMIC;
6143
6144 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
6145
6146 if (skb == NULL) {
6147 hddLog(CDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed"));
6148 return;
6149 }
6150
6151 nlh = (struct nlmsghdr *)skb->data;
6152 nlh->nlmsg_pid = 0; /* from kernel */
6153 nlh->nlmsg_flags = 0;
6154 nlh->nlmsg_seq = 0;
6155 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
6156
6157 ani_hdr = NLMSG_DATA(nlh);
6158 ani_hdr->type = type;
6159
6160 switch (type) {
6161 case WLAN_SVC_FW_CRASHED_IND:
6162 case WLAN_SVC_LTE_COEX_IND:
6163#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6164 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
6165#endif
6166 ani_hdr->length = 0;
6167 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
6168 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
6169 break;
6170 case WLAN_SVC_WLAN_STATUS_IND:
6171 case WLAN_SVC_WLAN_VERSION_IND:
6172 case WLAN_SVC_DFS_CAC_START_IND:
6173 case WLAN_SVC_DFS_CAC_END_IND:
6174 case WLAN_SVC_DFS_RADAR_DETECT_IND:
6175 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
6176 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08006177 case WLAN_SVC_WLAN_TP_TX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006178 ani_hdr->length = len;
6179 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
6180 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
6181 memcpy(nl_data, data, len);
6182 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
6183 break;
6184
6185 default:
6186 hddLog(CDF_TRACE_LEVEL_ERROR,
6187 FL("WLAN SVC: Attempt to send unknown nlink message %d"),
6188 type);
6189 kfree_skb(skb);
6190 return;
6191 }
6192
6193 nl_srv_bcast(skb);
6194
6195 return;
6196}
6197
6198#ifdef WLAN_FEATURE_LPSS
6199void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
6200 hdd_station_ctx_t *pHddStaCtx,
6201 uint8_t is_on, uint8_t is_connected)
6202{
6203 int ret = 0;
6204 struct wlan_status_data data;
6205
Peng Xuf5d60c82015-10-02 17:17:03 -07006206 if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006207 return;
6208
6209 memset(&data, 0, sizeof(struct wlan_status_data));
6210 if (is_on)
6211 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, pHddStaCtx,
6212 is_on, is_connected);
6213 if (!ret)
6214 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND,
6215 &data,
6216 sizeof(struct wlan_status_data));
6217}
6218
6219void wlan_hdd_send_version_pkg(uint32_t fw_version,
6220 uint32_t chip_id, const char *chip_name)
6221{
6222 int ret = 0;
6223 struct wlan_version_data data;
6224#ifdef CONFIG_CNSS
6225 struct cnss_platform_cap cap;
6226
6227 ret = cnss_get_platform_cap(&cap);
6228 if (ret) {
6229 hddLog(CDF_TRACE_LEVEL_ERROR,
6230 FL("platform capability info from CNSS not available"));
6231 return;
6232 }
6233
6234 if (!(cap.cap_flag & CNSS_HAS_UART_ACCESS))
6235 return;
6236#endif
6237
Peng Xuf5d60c82015-10-02 17:17:03 -07006238 if (CDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239 return;
6240
6241 memset(&data, 0, sizeof(struct wlan_version_data));
6242 ret =
6243 wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
6244 chip_name);
6245 if (!ret)
6246 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND,
6247 &data,
6248 sizeof(struct wlan_version_data));
6249}
6250
6251void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
6252{
6253 hdd_adapter_t *pDataAdapter = NULL;
6254 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6255 bool scan_intf_found = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306256 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006257
6258 if (!hdd_ctx) {
6259 hddLog(CDF_TRACE_LEVEL_ERROR,
6260 FL("NULL pointer for hdd_ctx"));
6261 return;
6262 }
6263
6264 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306265 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006266 pDataAdapter = adapterNode->pAdapter;
6267 if (pDataAdapter) {
6268 if (pDataAdapter->device_mode == WLAN_HDD_INFRA_STATION
6269 || pDataAdapter->device_mode == WLAN_HDD_P2P_CLIENT
6270 || pDataAdapter->device_mode ==
6271 WLAN_HDD_P2P_DEVICE) {
6272 scan_intf_found = true;
6273 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1,
6274 0);
6275 }
6276 }
6277 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6278 adapterNode = pNext;
6279 }
6280
6281 if (!scan_intf_found)
6282 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0);
6283}
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006284#else
6285static inline void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter,
6286 hdd_station_ctx_t *pHddStaCtx,
6287 uint8_t is_on, uint8_t is_connected)
6288{
6289 return;
6290}
6291
6292static inline void wlan_hdd_send_version_pkg(uint32_t fw_version, uint32_t
6293 chip_id, const char *chip_name)
6294{
6295 return;
6296}
6297
6298static inline void wlan_hdd_send_all_scan_intf_info(hdd_context_t *pHddCtx)
6299{
6300 return;
6301}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006302#endif
6303
6304#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6305void wlan_hdd_auto_shutdown_cb(void)
6306{
6307 hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event.."));
6308 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
6309}
6310
6311void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
6312{
6313 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306314 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006315 hdd_adapter_t *adapter;
6316 bool ap_connected = false, sta_connected = false;
6317 tHalHandle hal_handle;
6318
6319 hal_handle = hdd_ctx->hHal;
6320 if (hal_handle == NULL)
6321 return;
6322
6323 if (hdd_ctx->config->WlanAutoShutdown == 0)
6324 return;
6325
6326 if (enable == false) {
6327 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306328 QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006329 hddLog(LOGE,
6330 FL("Failed to stop wlan auto shutdown timer"));
6331 }
6332 return;
6333 }
6334
6335 /* To enable shutdown timer check conncurrency */
6336 if (cds_concurrent_open_sessions_running()) {
6337 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6338
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306339 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006340 adapter = adapterNode->pAdapter;
6341 if (adapter
6342 && adapter->device_mode ==
6343 WLAN_HDD_INFRA_STATION) {
6344 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6345 conn_info.connState ==
6346 eConnectionState_Associated) {
6347 sta_connected = true;
6348 break;
6349 }
6350 }
6351 if (adapter
6352 && adapter->device_mode == WLAN_HDD_SOFTAP) {
6353 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
6354 bApActive == true) {
6355 ap_connected = true;
6356 break;
6357 }
6358 }
6359 status = hdd_get_next_adapter(hdd_ctx,
6360 adapterNode,
6361 &pNext);
6362 adapterNode = pNext;
6363 }
6364 }
6365
6366 if (ap_connected == true || sta_connected == true) {
6367 hddLog(LOG1,
6368 FL("CC Session active. Shutdown timer not enabled"));
6369 return;
6370 } else {
6371 if (sme_set_auto_shutdown_timer(hal_handle,
6372 hdd_ctx->config->
6373 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306374 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006375 hddLog(LOGE,
6376 FL("Failed to start wlan auto shutdown timer"));
6377 else
6378 hddLog(LOG1,
6379 FL("Auto Shutdown timer for %d seconds enabled"),
6380 hdd_ctx->config->WlanAutoShutdown);
6381
6382 }
6383}
6384#endif
6385
6386hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
6387 bool check_start_bss)
6388{
6389 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
6390 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306391 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006392 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6393
6394 con_sap_adapter = NULL;
6395
6396 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306397 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006398 adapter = adapterNode->pAdapter;
6399 if (adapter && ((adapter->device_mode == WLAN_HDD_SOFTAP) ||
6400 (adapter->device_mode == WLAN_HDD_P2P_GO)) &&
6401 adapter != this_sap_adapter) {
6402 if (check_start_bss) {
6403 if (test_bit(SOFTAP_BSS_STARTED,
6404 &adapter->event_flags)) {
6405 con_sap_adapter = adapter;
6406 break;
6407 }
6408 } else {
6409 con_sap_adapter = adapter;
6410 break;
6411 }
6412 }
6413 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6414 adapterNode = pNext;
6415 }
6416
6417 return con_sap_adapter;
6418}
6419
6420#ifdef MSM_PLATFORM
6421void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
6422{
6423 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6424
6425 if (CDF_TIMER_STATE_RUNNING ==
6426 cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
6427 return;
6428
6429 cdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
6430 hdd_ctx->config->busBandwidthComputeInterval);
6431}
6432
6433void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
6434{
6435 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306436 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006437 bool can_stop = true;
6438 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6439
6440 if (CDF_TIMER_STATE_RUNNING !=
6441 cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
6442 /* trying to stop timer, when not running is not good */
6443 hddLog(CDF_TRACE_LEVEL_ERROR,
6444 FL("bus band width compute timer is not running"));
6445 return;
6446 }
6447
6448 if (cds_concurrent_open_sessions_running()) {
6449 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6450
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306451 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006452 adapter = adapterNode->pAdapter;
6453 if (adapter
6454 && (adapter->device_mode == WLAN_HDD_INFRA_STATION
6455 || adapter->device_mode == WLAN_HDD_P2P_CLIENT)
6456 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6457 conn_info.connState ==
6458 eConnectionState_Associated) {
6459 can_stop = false;
6460 break;
6461 }
6462 if (adapter
6463 && (adapter->device_mode == WLAN_HDD_SOFTAP
6464 || adapter->device_mode == WLAN_HDD_P2P_GO)
6465 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
6466 true) {
6467 can_stop = false;
6468 break;
6469 }
6470 status = hdd_get_next_adapter(hdd_ctx,
6471 adapterNode,
6472 &pNext);
6473 adapterNode = pNext;
6474 }
6475 }
6476
6477 if (can_stop == true)
6478 cdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
6479}
6480#endif
6481
6482/**
6483 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
6484 * and sta's operating channel.
6485 * @sta_adapter: Describe the first argument to foobar.
6486 * @ap_adapter: Describe the second argument to foobar.
6487 * @roam_profile: Roam profile of AP to which STA wants to connect.
6488 * @concurrent_chnl_same: If both SAP and STA channels are same then
6489 * set this flag to true else false.
6490 *
6491 * This function checks the sap's operating channel and sta's operating channel.
6492 * if both are same then it will return false else it will restart the sap in
6493 * sta's channel and return true.
6494 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306495 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006496 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306497QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006498 hdd_adapter_t *ap_adapter,
6499 tCsrRoamProfile *roam_profile,
6500 tScanResultHandle *scan_cache,
6501 bool *concurrent_chnl_same)
6502{
6503 hdd_ap_ctx_t *hdd_ap_ctx;
6504 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306505 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006506 device_mode_t device_mode = ap_adapter->device_mode;
6507 *concurrent_chnl_same = true;
6508
6509 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6510 status =
6511 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
6512 roam_profile,
6513 scan_cache,
6514 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306515 if ((QDF_STATUS_SUCCESS == status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006516 if ((WLAN_HDD_SOFTAP == device_mode) &&
6517 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
6518 if (hdd_ap_ctx->operatingChannel != channel_id) {
6519 *concurrent_chnl_same = false;
6520 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6521 FL("channels are different"));
6522 }
6523 } else if ((WLAN_HDD_P2P_GO == device_mode) &&
6524 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
6525 if (hdd_ap_ctx->operatingChannel != channel_id) {
6526 *concurrent_chnl_same = false;
6527 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6528 FL("channels are different"));
6529 }
6530 }
6531 } else {
6532 /*
6533 * Lets handle worst case scenario here, Scan cache lookup is
6534 * failed so we have to stop the SAP to avoid any channel
6535 * discrepancy between SAP's channel and STA's channel.
6536 * Return the status as failure so caller function could know
6537 * that scan look up is failed.
6538 */
6539 hddLog(CDF_TRACE_LEVEL_ERROR,
6540 FL("Finding AP from scan cache failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306541 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006542 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306543 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006544}
6545
6546#ifdef WLAN_FEATURE_MBSSID
6547/**
6548 * wlan_hdd_stop_sap() - This function stops bss of SAP.
6549 * @ap_adapter: SAP adapter
6550 *
6551 * This function will process the stopping of sap adapter.
6552 *
6553 * Return: None
6554 */
6555void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
6556{
6557 hdd_ap_ctx_t *hdd_ap_ctx;
6558 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306559 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006560 hdd_context_t *hdd_ctx;
6561#ifdef CFG80211_DEL_STA_V2
6562 struct station_del_parameters delStaParams;
6563#endif
6564
6565 if (NULL == ap_adapter) {
6566 hddLog(CDF_TRACE_LEVEL_ERROR,
6567 FL("ap_adapter is NULL here"));
6568 return;
6569 }
6570
6571 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6572 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6573 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
6574 hddLog(CDF_TRACE_LEVEL_ERROR,
6575 FL("HDD context is not valid"));
6576 return;
6577 }
6578 mutex_lock(&hdd_ctx->sap_lock);
6579 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
6580#ifdef CFG80211_DEL_STA_V2
6581 delStaParams.mac = NULL;
6582 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
6583 delStaParams.reason_code = eCsrForcedDeauthSta;
6584 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6585 ap_adapter->dev,
6586 &delStaParams);
6587#else
6588 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6589 ap_adapter->dev,
6590 NULL);
6591#endif
6592 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
6593 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6594 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
6595 FL("Now doing SAP STOPBSS"));
Anurag Chouhance0dc992016-02-16 18:18:03 +05306596 qdf_event_reset(&hostapd_state->cdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306597 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006598 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05306599 qdf_status = qdf_wait_single_event(&hostapd_state->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006600 cdf_stop_bss_event,
6601 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306602 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006603 mutex_unlock(&hdd_ctx->sap_lock);
6604 hddLog(CDF_TRACE_LEVEL_ERROR,
6605 FL("SAP Stop Failed"));
6606 return;
6607 }
6608 }
6609 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08006610 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006611 ap_adapter->sessionId);
6612 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
6613 FL("SAP Stop Success"));
6614 } else {
6615 hddLog(CDF_TRACE_LEVEL_ERROR,
6616 FL("Can't stop ap because its not started"));
6617 }
6618 mutex_unlock(&hdd_ctx->sap_lock);
6619 return;
6620}
6621
6622/**
6623 * wlan_hdd_start_sap() - this function starts bss of SAP.
6624 * @ap_adapter: SAP adapter
6625 *
6626 * This function will process the starting of sap adapter.
6627 *
6628 * Return: None
6629 */
6630void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
6631{
6632 hdd_ap_ctx_t *hdd_ap_ctx;
6633 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306634 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006635 hdd_context_t *hdd_ctx;
6636 tsap_Config_t *sap_config;
6637
6638 if (NULL == ap_adapter) {
6639 hddLog(CDF_TRACE_LEVEL_ERROR,
6640 FL("ap_adapter is NULL here"));
6641 return;
6642 }
6643
Peng Xuf5d60c82015-10-02 17:17:03 -07006644 if (WLAN_HDD_SOFTAP != ap_adapter->device_mode) {
6645 hdd_err("SoftAp role has not been enabled");
6646 return;
6647 }
6648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006649 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6650 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6651 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6652 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
6653
6654 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
6655 hddLog(CDF_TRACE_LEVEL_ERROR,
6656 FL("HDD context is not valid"));
6657 return;
6658 }
6659 mutex_lock(&hdd_ctx->sap_lock);
6660 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
6661 goto end;
6662
6663 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
6664 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
6665 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
6666 goto end;
6667 }
6668
6669 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
6670 &hdd_ap_ctx->sapConfig,
6671 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306672 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006673 goto end;
6674
6675 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
6676 FL("Waiting for SAP to start"));
Anurag Chouhance0dc992016-02-16 18:18:03 +05306677 qdf_status = qdf_wait_single_event(&hostapd_state->cdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006678 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306679 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006680 hddLog(CDF_TRACE_LEVEL_ERROR, FL("SAP Start failed"));
6681 goto end;
6682 }
6683 hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success"));
6684 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006685 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006686 ap_adapter->sessionId);
6687 hostapd_state->bCommit = true;
6688
6689end:
6690 mutex_unlock(&hdd_ctx->sap_lock);
6691 return;
6692}
6693#endif
6694
6695/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006696 * hdd_get_fw_version() - Get FW version
6697 * @hdd_ctx: pointer to HDD context.
6698 * @major_spid: FW version - major spid.
6699 * @minor_spid: FW version - minor spid
6700 * @ssid: FW version - ssid
6701 * @crmid: FW version - crmid
6702 *
6703 * This function is called to get the firmware build version stored
6704 * as part of the HDD context
6705 *
6706 * Return: None
6707 */
6708void hdd_get_fw_version(hdd_context_t *hdd_ctx,
6709 uint32_t *major_spid, uint32_t *minor_spid,
6710 uint32_t *siid, uint32_t *crmid)
6711{
6712 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
6713 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
6714 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
6715 *crmid = hdd_ctx->target_fw_version & 0x7fff;
6716}
6717
6718#ifdef QCA_CONFIG_SMP
6719/**
6720 * wlan_hdd_get_cpu() - get cpu_index
6721 *
6722 * Return: cpu_index
6723 */
6724int wlan_hdd_get_cpu(void)
6725{
6726 int cpu_index = get_cpu();
6727 put_cpu();
6728 return cpu_index;
6729}
6730#endif
6731
6732/**
6733 * hdd_get_fwpath() - get framework path
6734 *
6735 * This function is used to get the string written by
6736 * userspace to start the wlan driver
6737 *
6738 * Return: string
6739 */
6740const char *hdd_get_fwpath(void)
6741{
6742 return fwpath.string;
6743}
6744
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006745/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006746 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006747 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006748 * This function initilizes CDS global context with the help of cds_init. This
6749 * has to be the first function called after probe to get a valid global
6750 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006751 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006752 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006753 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006754int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006755{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006756 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006757 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006758
6759#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6760 wlan_logging_sock_init_svc();
6761#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006762 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006763
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006764 if (p_cds_context == NULL) {
6765 hdd_alert("Failed to allocate CDS context");
6766 ret = -ENOMEM;
6767 goto err_out;
6768 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006769
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006770 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006771
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006772err_out:
6773 return ret;
6774}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006775
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006776/**
6777 * hdd_deinit() - Deinitialize Driver
6778 *
6779 * This function frees CDS global context with the help of cds_deinit. This
6780 * has to be the last function call in remove callback to free the global
6781 * context.
6782 */
6783void hdd_deinit(void)
6784{
6785 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006786
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006787#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6788 wlan_logging_sock_deinit_svc();
6789#endif
6790}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006791
6792#ifdef QCA_WIFI_3_0_ADRASTEA
6793#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
6794#else
6795#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
6796#endif
6797
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006798/**
6799 * __hdd_module_init - Module init helper
6800 *
6801 * Module init helper function used by both module and static driver.
6802 *
6803 * Return: 0 for success, errno on failure
6804 */
6805static int __hdd_module_init(void)
6806{
6807 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006808
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006809 pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
6810 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006811
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006812 cdf_wake_lock_init(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006813
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006814 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006815
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006816 ret = wlan_hdd_register_driver();
6817 if (ret) {
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006818 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006819 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006820 }
6821
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006822 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
6823
6824 return 0;
6825out:
6826 cdf_wake_lock_destroy(&wlan_wake_lock);
6827 return ret;
6828}
6829
6830/**
6831 * __hdd_module_exit - Module exit helper
6832 *
6833 * Module exit helper function used by both module and static driver.
6834 */
6835static void __hdd_module_exit(void)
6836{
6837 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
6838 QWLAN_VERSIONSTR);
6839
6840 wlan_hdd_unregister_driver();
6841
6842 cdf_wake_lock_destroy(&wlan_wake_lock);
6843
6844 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006845}
6846
6847/**
6848 * hdd_module_init() - Init Function
6849 *
6850 * This is the driver entry point (invoked when module is loaded using insmod)
6851 *
6852 * Return: 0 for success, non zero for failure
6853 */
6854#ifdef MODULE
6855static int __init hdd_module_init(void)
6856{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006857 return __hdd_module_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006858}
6859#else /* #ifdef MODULE */
6860static int __init hdd_module_init(void)
6861{
6862 /* Driver initialization is delayed to fwpath_changed_handler */
6863 return 0;
6864}
6865#endif /* #ifdef MODULE */
6866
6867/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006868 * hdd_module_exit() - Exit function
6869 *
6870 * This is the driver exit point (invoked when module is unloaded using rmmod)
6871 *
6872 * Return: None
6873 */
6874static void __exit hdd_module_exit(void)
6875{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006876 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006877}
6878
6879#ifdef MODULE
6880static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6881{
6882 return param_set_copystring(kmessage, kp);
6883}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006884#else /* #ifdef MODULE */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006885
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006886/**
6887 * kickstart_driver() - driver entry point
6888 *
6889 * This is the driver entry point
6890 * - delayed driver initialization when driver is statically linked
6891 * - invoked when module parameter fwpath is modified from userspace to signal
6892 * initializing the WLAN driver or when con_mode is modified from userspace
6893 * to signal a switch in operating mode
6894 *
6895 * Return: 0 for success, non zero for failure
6896 */
6897static int kickstart_driver(void)
6898{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006899 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006900
6901 if (!wlan_hdd_inited) {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006902 ret = __hdd_module_init();
6903 wlan_hdd_inited = ret ? 0 : 1;
6904
6905 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006906 }
6907
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006908 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006909
6910 msleep(200);
6911
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006912 ret = __hdd_module_init();
6913
6914 wlan_hdd_inited = ret ? 0 : 1;
6915
6916 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006917}
6918
6919/**
6920 * fwpath_changed_handler() - Handler Function
6921 *
6922 * Handle changes to the fwpath parameter
6923 *
6924 * Return: 0 for success, non zero for failure
6925 */
6926static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6927{
6928 int ret;
6929
6930 ret = param_set_copystring(kmessage, kp);
6931 if (0 == ret)
6932 ret = kickstart_driver();
6933 return ret;
6934}
6935
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006936#ifdef QCA_WIFI_FTM
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006937/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006938 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006939 *
6940 * Handler function for module param con_mode when it is changed by userspace
6941 * Dynamically linked - do nothing
6942 * Statically linked - exit and init driver, as in rmmod and insmod
6943 *
6944 * Return -
6945 */
6946static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
6947{
6948 int ret;
6949
6950 ret = param_set_int(kmessage, kp);
6951 if (0 == ret)
6952 ret = kickstart_driver();
6953 return ret;
6954}
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006955#endif /* QCA_WIFI_FTM */
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006956#endif /* #ifdef MODULE */
6957
6958/**
6959 * hdd_get_conparam() - driver exit point
6960 *
6961 * This is the driver exit point (invoked when module is unloaded using rmmod)
6962 *
Peng Xuf5d60c82015-10-02 17:17:03 -07006963 * Return: enum tCDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006964 */
Peng Xuf5d60c82015-10-02 17:17:03 -07006965enum tCDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006966{
Peng Xuf5d60c82015-10-02 17:17:03 -07006967 return (enum tCDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006968}
6969
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006970void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006971{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006972 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006973}
6974
Komal Seelamc11bb222016-01-27 18:57:10 +05306975#ifdef WLAN_FEATURE_LPSS
6976static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6977{
6978 return hdd_ctx->config->enable_lpass_support;
6979}
6980#else
6981static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6982{
6983 return false;
6984}
6985#endif
6986
6987/**
Komal Seelamec702b02016-02-24 18:42:16 +05306988 * hdd_update_ol_config - API to update ol configuration parameters
6989 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05306990 *
Komal Seelamc11bb222016-01-27 18:57:10 +05306991 * Return: void
6992 */
Komal Seelamec702b02016-02-24 18:42:16 +05306993static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05306994{
Komal Seelamec702b02016-02-24 18:42:16 +05306995 struct ol_config_info cfg;
6996 struct ol_context *ol_ctx = cds_get_context(CDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05306997
Komal Seelamec702b02016-02-24 18:42:16 +05306998 if (!ol_ctx)
6999 return;
7000
7001 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
7002 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
7003 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
7004 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
7005 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
7006
7007 ol_init_ini_config(ol_ctx, &cfg);
7008}
7009
7010/**
7011 * hdd_update_hif_config - API to update HIF configuration parameters
7012 * @hdd_ctx: HDD Context
7013 *
7014 * Return: void
7015 */
7016static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
7017{
Komal Seelam3d202862016-02-24 18:43:24 +05307018 struct hif_opaque_softc *scn = cds_get_context(CDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05307019 struct hif_config_info cfg;
7020
7021 if (!scn)
7022 return;
7023
7024 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
7025 hif_init_ini_config(scn, &cfg);
7026}
7027
7028/**
7029 * hdd_update_config() - Initialize driver per module ini parameters
7030 * @hdd_ctx: HDD Context
7031 *
7032 * API is used to initialize all driver per module configuration parameters
7033 * Return: void
7034 */
7035void hdd_update_config(hdd_context_t *hdd_ctx)
7036{
7037 hdd_update_ol_config(hdd_ctx);
7038 hdd_update_hif_config(hdd_ctx);
Komal Seelamc11bb222016-01-27 18:57:10 +05307039}
7040
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007041/* Register the module init/exit functions */
7042module_init(hdd_module_init);
7043module_exit(hdd_module_exit);
7044
7045MODULE_LICENSE("Dual BSD/GPL");
7046MODULE_AUTHOR("Qualcomm Atheros, Inc.");
7047MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
7048
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007049#if !defined(MODULE) && defined(QCA_WIFI_FTM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007050module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
7051 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007052#else
7053module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007054#endif
7055
7056module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
7057 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
7058
7059module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
7060
7061module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
7062
7063module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);