blob: fefe3c2578348b284cf2f1700f7ca50e8009d310 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
3 *
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
89
90#include "wlan_hdd_ocb.h"
91
92extern int hdd_hostapd_stop(struct net_device *dev);
93#endif /* FEATURE_WLAN_CH_AVOID */
94
95#include "wlan_hdd_nan.h"
96#include "wlan_hdd_debugfs.h"
97#include "wlan_hdd_driver_ops.h"
98#include "epping_main.h"
99#include "wlan_hdd_memdump.h"
100
101#include <wlan_hdd_ipa.h>
102#include "hif.h"
103#include "wma.h"
104#include "cds_concurrency.h"
105#include "wlan_hdd_green_ap.h"
106
107#ifdef MODULE
108#define WLAN_MODULE_NAME module_name(THIS_MODULE)
109#else
110#define WLAN_MODULE_NAME "wlan"
111#endif
112
113#ifdef TIMER_MANAGER
114#define TIMER_MANAGER_STR " +TIMER_MANAGER"
115#else
116#define TIMER_MANAGER_STR ""
117#endif
118
119#ifdef MEMORY_DEBUG
120#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
121#else
122#define MEMORY_DEBUG_STR ""
123#endif
124
125#define DISABLE_KRAIT_IDLE_PS_VAL 200
126/* the Android framework expects this param even though we don't use it */
127#define BUF_LEN 20
128static char fwpath_buffer[BUF_LEN];
129static struct kparam_string fwpath = {
130 .string = fwpath_buffer,
131 .maxlen = BUF_LEN,
132};
133
134static char *country_code;
135static int enable_11d = -1;
136static int enable_dfs_chan_scan = -1;
137
138#ifndef MODULE
139static int wlan_hdd_inited;
140#endif
141
142/*
143 * spinlock for synchronizing asynchronous request/response
144 * (full description of use in wlan_hdd_main.h)
145 */
146DEFINE_SPINLOCK(hdd_context_lock);
147
148static cdf_wake_lock_t wlan_wake_lock;
149/* set when SSR is needed after unload */
150static e_hdd_ssr_required is_ssr_required = HDD_SSR_NOT_REQUIRED;
151
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
177struct completion wlan_start_comp;
178#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
179void wlan_hdd_auto_shutdown_cb(void);
180#endif
181
182/**
183 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
184 * @vdev_id: vdev_id
185 * @action: action type
186 * @reason: reason type
187 *
188 * Return: none
189 */
190void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
191 enum netif_action_type action, enum netif_reason_type reason)
192{
193 hdd_context_t *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
194 hdd_adapter_t *adapter;
195
196 if (!hdd_ctx) {
197 hdd_err("hdd ctx is NULL");
198 return;
199 }
200 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
201
202 wlan_hdd_netif_queue_control(adapter, action, reason);
203 return;
204}
205
206/*
207 * Store WLAN driver version info in a global variable such that crash debugger
208 * can extract it from driver debug symbol and crashdump for post processing
209 */
210uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
211
212/**
213 * hdd_device_mode_to_string() - return string conversion of device mode
214 * @device_mode: device mode
215 *
216 * This utility function helps log string conversion of device mode.
217 *
218 * Return: string conversion of device mode, if match found;
219 * "Unknown" otherwise.
220 */
221const char *hdd_device_mode_to_string(uint8_t device_mode)
222{
223 switch (device_mode) {
224 CASE_RETURN_STRING(WLAN_HDD_INFRA_STATION);
225 CASE_RETURN_STRING(WLAN_HDD_SOFTAP);
226 CASE_RETURN_STRING(WLAN_HDD_P2P_CLIENT);
227 CASE_RETURN_STRING(WLAN_HDD_P2P_GO);
228 CASE_RETURN_STRING(WLAN_HDD_FTM);
229 CASE_RETURN_STRING(WLAN_HDD_IBSS);
230 CASE_RETURN_STRING(WLAN_HDD_P2P_DEVICE);
231 CASE_RETURN_STRING(WLAN_HDD_OCB);
232 default:
233 return "Unknown";
234 }
235}
236
237static int __hdd_netdev_notifier_call(struct notifier_block *nb,
238 unsigned long state, void *data)
239{
240#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
241 struct netdev_notifier_info *dev_notif_info = data;
242 struct net_device *dev = dev_notif_info->dev;
243#else
244 struct net_device *dev = data;
245#endif
246 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
247 hdd_context_t *hdd_ctx;
248
249 /* Make sure that this callback corresponds to our device. */
250 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
251 return NOTIFY_DONE;
252
253 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
254 (adapter->dev != dev)) {
255 hddLog(LOGE, FL("device adapter is not matching!!!"));
256 return NOTIFY_DONE;
257 }
258
259 if (!dev->ieee80211_ptr) {
260 hddLog(LOGE, FL("ieee80211_ptr is NULL!!!"));
261 return NOTIFY_DONE;
262 }
263
264 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
265 if (NULL == hdd_ctx) {
266 hddLog(CDF_TRACE_LEVEL_FATAL, FL("HDD Context Null Pointer"));
267 CDF_ASSERT(0);
268 return NOTIFY_DONE;
269 }
270 if (hdd_ctx->isLogpInProgress)
271 return NOTIFY_DONE;
272
273 hddLog(CDF_TRACE_LEVEL_INFO, FL("%s New Net Device State = %lu"),
274 dev->name, state);
275
276 switch (state) {
277 case NETDEV_REGISTER:
278 break;
279
280 case NETDEV_UNREGISTER:
281 break;
282
283 case NETDEV_UP:
284 sme_ch_avoid_update_req(hdd_ctx->hHal);
285 break;
286
287 case NETDEV_DOWN:
288 break;
289
290 case NETDEV_CHANGE:
291 if (true == adapter->isLinkUpSvcNeeded)
292 complete(&adapter->linkup_event_var);
293 break;
294
295 case NETDEV_GOING_DOWN:
296 if (adapter->scan_info.mScanPending != false) {
297 unsigned long rc;
298 INIT_COMPLETION(adapter->scan_info.
299 abortscan_event_var);
300 hdd_abort_mac_scan(adapter->pHddCtx,
301 adapter->sessionId,
302 eCSR_SCAN_ABORT_DEFAULT);
303 rc = wait_for_completion_timeout(
304 &adapter->scan_info.abortscan_event_var,
305 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
306 if (!rc) {
307 hddLog(LOGE,
308 FL("Timeout occurred while waiting for abortscan"));
309 }
310 } else {
311 hddLog(CDF_TRACE_LEVEL_INFO,
312 FL("Scan is not Pending from user"));
313 }
314 break;
315
316 default:
317 break;
318 }
319
320 return NOTIFY_DONE;
321}
322
323/**
324 * hdd_netdev_notifier_call() - netdev notifier callback function
325 * @nb: pointer to notifier block
326 * @state: state
327 * @ndev: ndev pointer
328 *
329 * Return: 0 on success, error number otherwise.
330 */
331static int hdd_netdev_notifier_call(struct notifier_block *nb,
332 unsigned long state,
333 void *ndev)
334{
335 int ret;
336
337 cds_ssr_protect(__func__);
338 ret = __hdd_netdev_notifier_call(nb, state, ndev);
339 cds_ssr_unprotect(__func__);
340
341 return ret;
342}
343
344struct notifier_block hdd_netdev_notifier = {
345 .notifier_call = hdd_netdev_notifier_call,
346};
347
348/* variable to hold the insmod parameters */
349static int con_mode;
350#ifndef MODULE
351/*
352 * current con_mode - used only for statically linked driver
353 * con_mode is changed by userspace to indicate a mode change which will
354 * result in calling the module exit and init functions. The module
355 * exit function will clean up based on the value of con_mode prior to it
356 * being changed by userspace. So curr_con_mode records the current con_mode
357 * for exit when con_mode becomes the next mode for init
358 */
359static int curr_con_mode;
360#endif
361
362/**
363 * hdd_cdf_trace_enable() - configure initial CDF Trace enable
364 * @moduleId: Module whose trace level is being configured
365 * @bitmask: Bitmask of log levels to be enabled
366 *
367 * Called immediately after the cfg.ini is read in order to configure
368 * the desired trace levels.
369 *
370 * Return: None
371 */
372static void hdd_cdf_trace_enable(CDF_MODULE_ID moduleId, uint32_t bitmask)
373{
374 CDF_TRACE_LEVEL level;
375
376 /*
377 * if the bitmask is the default value, then a bitmask was not
378 * specified in cfg.ini, so leave the logging level alone (it
379 * will remain at the "compiled in" default value)
380 */
381 if (CFG_CDF_TRACE_ENABLE_DEFAULT == bitmask) {
382 return;
383 }
384
385 /* a mask was specified. start by disabling all logging */
386 cdf_trace_set_value(moduleId, CDF_TRACE_LEVEL_NONE, 0);
387
388 /* now cycle through the bitmask until all "set" bits are serviced */
389 level = CDF_TRACE_LEVEL_FATAL;
390 while (0 != bitmask) {
391 if (bitmask & 1) {
392 cdf_trace_set_value(moduleId, level, 1);
393 }
394 level++;
395 bitmask >>= 1;
396 }
397}
398
399/**
400 * wlan_hdd_validate_context() - check the HDD context
401 * @hdd_ctx: HDD context pointer
402 *
403 * Return: 0 if the context is valid. Error code otherwise
404 */
405int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
406{
407 ENTER();
408
409 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
410 hddLog(LOGE, FL("HDD context is Null"));
411 return -ENODEV;
412 }
413
414 if (hdd_ctx->isLogpInProgress) {
415 hddLog(LOGE, FL("LOGP in Progress. Ignore!!!"));
416 return -EAGAIN;
417 }
418
419 if ((hdd_ctx->isLoadInProgress) || (hdd_ctx->isUnloadInProgress)) {
420 hddLog(LOGE, FL("Unloading/Loading in Progress. Ignore!!!"));
421 return -EAGAIN;
422 }
423 return 0;
424}
425
426void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
427{
428 hdd_adapter_t *adapter = NULL;
429 hdd_station_ctx_t *pHddStaCtx = NULL;
430 eCsrPhyMode phyMode;
431 struct hdd_config *cfg_param = NULL;
432
433 if (NULL == hdd_ctx) {
434 hddLog(CDF_TRACE_LEVEL_FATAL, FL("HDD Context is null !!"));
435 return;
436 }
437
438 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
439 if (NULL == adapter) {
440 hddLog(CDF_TRACE_LEVEL_FATAL, FL("adapter is null !!"));
441 return;
442 }
443
444 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
445
446 cfg_param = hdd_ctx->config;
447 if (NULL == cfg_param) {
448 hddLog(CDF_TRACE_LEVEL_FATAL,
449 FL("cfg_params not available !!"));
450 return;
451 }
452
453 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
454
455 if (!hdd_ctx->isVHT80Allowed) {
456 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
457 (eCSR_DOT11_MODE_11ac == phyMode) ||
458 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
459 hddLog(CDF_TRACE_LEVEL_INFO,
460 FL("Setting phymode to 11n!!"));
461 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
462 eCSR_DOT11_MODE_11n);
463 }
464 } else {
465 /*
466 * New country Supports 11ac as well resetting value back from
467 * .ini
468 */
469 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
470 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
471 dot11Mode));
472 return;
473 }
474
475 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
476 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
477 || (eCSR_CFG_DOT11_MODE_11AC ==
478 pHddStaCtx->conn_info.dot11Mode))) {
479 CDF_STATUS cdf_status;
480
481 /* need to issue a disconnect to CSR. */
482 INIT_COMPLETION(adapter->disconnect_comp_var);
483 cdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
484 adapter->sessionId,
485 eCSR_DISCONNECT_REASON_UNSPECIFIED);
486
487 if (CDF_STATUS_SUCCESS == cdf_status) {
488 unsigned long rc;
489
490 rc = wait_for_completion_timeout(
491 &adapter->disconnect_comp_var,
492 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
493 if (!rc)
494 hddLog(LOGE,
495 FL("failure waiting for disconnect_comp_var"));
496 }
497 }
498}
499
500/**
501 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
502 * @hdd_adapter_t Hdd adapter.
503 *
504 * This function sets the IBSS power save config parameters to WMA
505 * which will send it to firmware if FW supports IBSS power save
506 * before vdev start.
507 *
508 * Return: CDF_STATUS CDF_STATUS_SUCCESS on Success and CDF_STATUS_E_FAILURE
509 * on failure.
510 */
511CDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
512{
513 int ret;
514 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
515
516 if (hdd_ctx == NULL) {
517 hddLog(CDF_TRACE_LEVEL_ERROR,
518 FL("HDD context is null"));
519 return CDF_STATUS_E_FAILURE;
520 }
521
522 ret = wma_cli_set_command(adapter->sessionId,
523 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
524 hdd_ctx->config->ibssATIMWinSize,
525 VDEV_CMD);
526 if (0 != ret) {
527 hddLog(CDF_TRACE_LEVEL_ERROR,
528 FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), ret);
529 return CDF_STATUS_E_FAILURE;
530 }
531
532 ret = wma_cli_set_command(adapter->sessionId,
533 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
534 hdd_ctx->config->isIbssPowerSaveAllowed,
535 VDEV_CMD);
536 if (0 != ret) {
537 hddLog(CDF_TRACE_LEVEL_ERROR,
538 FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"),
539 ret);
540 return CDF_STATUS_E_FAILURE;
541 }
542
543 ret = wma_cli_set_command(adapter->sessionId,
544 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
545 hdd_ctx->config->
546 isIbssPowerCollapseAllowed, VDEV_CMD);
547 if (0 != ret) {
548 hddLog(CDF_TRACE_LEVEL_ERROR,
549 FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"),
550 ret);
551 return CDF_STATUS_E_FAILURE;
552 }
553
554 ret = wma_cli_set_command(adapter->sessionId,
555 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
556 hdd_ctx->config->isIbssAwakeOnTxRx,
557 VDEV_CMD);
558 if (0 != ret) {
559 hddLog(CDF_TRACE_LEVEL_ERROR,
560 FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), ret);
561 return CDF_STATUS_E_FAILURE;
562 }
563
564 ret = wma_cli_set_command(adapter->sessionId,
565 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
566 hdd_ctx->config->ibssInactivityCount,
567 VDEV_CMD);
568 if (0 != ret) {
569 hddLog(CDF_TRACE_LEVEL_ERROR,
570 FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), ret);
571 return CDF_STATUS_E_FAILURE;
572 }
573
574 ret = wma_cli_set_command(adapter->sessionId,
575 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
576 hdd_ctx->config->ibssTxSpEndInactivityTime,
577 VDEV_CMD);
578 if (0 != ret) {
579 hddLog(CDF_TRACE_LEVEL_ERROR,
580 FL(
581 "WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d"
582 ),
583 ret);
584 return CDF_STATUS_E_FAILURE;
585 }
586
587 ret = wma_cli_set_command(adapter->sessionId,
588 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
589 hdd_ctx->config->ibssPsWarmupTime,
590 VDEV_CMD);
591 if (0 != ret) {
592 hddLog(CDF_TRACE_LEVEL_ERROR,
593 FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"),
594 ret);
595 return CDF_STATUS_E_FAILURE;
596 }
597
598 ret = wma_cli_set_command(adapter->sessionId,
599 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
600 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
601 VDEV_CMD);
602 if (0 != ret) {
603 hddLog(CDF_TRACE_LEVEL_ERROR,
604 FL(
605 "WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d"
606 ),
607 ret);
608 return CDF_STATUS_E_FAILURE;
609 }
610
611 return CDF_STATUS_SUCCESS;
612}
613
614#if defined(WLAN_FEATURE_VOWIFI_11R) ||\
615 defined(FEATURE_WLAN_ESE) ||\
616 defined(FEATURE_WLAN_LFR)
617
618#define INTF_MACADDR_MASK 0x7
619
620/**
621 * hdd_update_macaddr() - update mac address
622 * @config: hdd configuration
623 * @hw_macaddr: mac address
624 *
625 * Mac address for multiple virtual interface is found as following
626 * i) The mac address of the first interface is just the actual hw mac address.
627 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
628 * define the mac address for the remaining interfaces and locally
629 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
630 * supported virtual interfaces, right now this is 0x07 (meaning 8
631 * interface).
632 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
633 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
634 *
635 * Return: None
636 */
637void hdd_update_macaddr(struct hdd_config *config,
638 struct cdf_mac_addr hw_macaddr)
639{
640 int8_t i;
641 uint8_t macaddr_b3, tmp_br3;
642
643 cdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
644 CDF_MAC_ADDR_SIZE);
645 for (i = 1; i < CDF_MAX_CONCURRENCY_PERSONA; i++) {
646 cdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
647 CDF_MAC_ADDR_SIZE);
648 macaddr_b3 = config->intfMacAddr[i].bytes[3];
649 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
650 INTF_MACADDR_MASK;
651 macaddr_b3 += tmp_br3;
652
653 /* XOR-ing bit-24 of the mac address. This will give enough
654 * mac address range before collision
655 */
656 macaddr_b3 ^= (1 << 7);
657
658 /* Set locally administered bit */
659 config->intfMacAddr[i].bytes[0] |= 0x02;
660 config->intfMacAddr[i].bytes[3] = macaddr_b3;
661 hddLog(CDF_TRACE_LEVEL_INFO, "config->intfMacAddr[%d]: "
662 MAC_ADDRESS_STR, i,
663 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
664 }
665}
666
667static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
668 struct wma_tgt_services *cfg)
669{
670 struct hdd_config *config = hdd_ctx->config;
671 tpAniSirGlobal pMac = PMAC_STRUCT(hdd_ctx->hHal);
672
673 /* Set up UAPSD */
674 config->apUapsdEnabled &= cfg->uapsd;
675
676#ifdef WLAN_FEATURE_11AC
677 /* 11AC mode support */
678 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
679 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
680 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
681#endif /* #ifdef WLAN_FEATURE_11AC */
682
683 /* ARP offload: override user setting if invalid */
684 config->fhostArpOffload &= cfg->arp_offload;
685
686#ifdef FEATURE_WLAN_SCAN_PNO
687 /* PNO offload */
688 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
689 FL("PNO Capability in f/w = %d"), cfg->pno_offload);
690 if (cfg->pno_offload)
691 config->PnoOffload = true;
692#endif
693 pMac->lteCoexAntShare = cfg->lte_coex_ant_share;
694#ifdef FEATURE_WLAN_TDLS
695 config->fEnableTDLSSupport &= cfg->en_tdls;
696 config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan;
697 config->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta;
698 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
699 config->fEnableTDLSSleepSta = true;
700 } else {
701 config->fEnableTDLSSleepSta = false;
702 }
703#endif
704 pMac->beacon_offload = cfg->beacon_offload;
705#ifdef WLAN_FEATURE_ROAM_OFFLOAD
706 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
707#endif
708
709}
710
711static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
712 struct wma_tgt_ht_cap *cfg)
713{
714 CDF_STATUS status;
715 uint32_t value, val32;
716 uint16_t val16;
717 struct hdd_config *pconfig = hdd_ctx->config;
718 tSirMacHTCapabilityInfo *phtCapInfo;
719 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
720 uint8_t enable_tx_stbc;
721
722 /* check and update RX STBC */
723 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
724 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
725
726 /* get the MPDU density */
727 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
728
729 if (status != CDF_STATUS_SUCCESS) {
730 hddLog(CDF_TRACE_LEVEL_ERROR,
731 FL("could not get MPDU DENSITY"));
732 value = 0;
733 }
734
735 /*
736 * MPDU density:
737 * override user's setting if value is larger
738 * than the one supported by target
739 */
740 if (value > cfg->mpdu_density) {
741 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
742 cfg->mpdu_density);
743
744 if (status == CDF_STATUS_E_FAILURE)
745 hddLog(CDF_TRACE_LEVEL_FATAL,
746 FL("could not set MPDU DENSITY to CCM"));
747 }
748
749 /* get the HT capability info */
750 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
751 if (CDF_STATUS_SUCCESS != status) {
752 hddLog(CDF_TRACE_LEVEL_ERROR,
753 FL("could not get HT capability info"));
754 return;
755 }
756 val16 = (uint16_t) val32;
757 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
758
759 /* Set the LDPC capability */
760 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
761
762 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
763 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
764
765 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
766 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
767
768 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
769 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
770
771 enable_tx_stbc = pconfig->enableTxSTBC;
772
773 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
774 pconfig->enable2x2 = 1;
775 } else {
776 pconfig->enable2x2 = 0;
777 enable_tx_stbc = 0;
778
779 /* 1x1 */
780 /* Update Rx Highest Long GI data Rate */
781 if (sme_cfg_set_int(hdd_ctx->hHal,
782 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
783 HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
784 == CDF_STATUS_E_FAILURE) {
785 hddLog(LOGE,
786 FL(
787 "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"
788 ));
789 }
790
791 /* Update Tx Highest Long GI data Rate */
792 if (sme_cfg_set_int
793 (hdd_ctx->hHal,
794 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
795 HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
796 CDF_STATUS_E_FAILURE) {
797 hddLog(LOGE,
798 FL(
799 "Could not pass on HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"
800 ));
801 }
802 }
803 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
804 enable_tx_stbc = 0;
805 phtCapInfo->txSTBC = enable_tx_stbc;
806
807 val32 = val16;
808 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
809 if (status != CDF_STATUS_SUCCESS)
810 hddLog(CDF_TRACE_LEVEL_FATAL,
811 FL("could not set HT capability to CCM"));
812#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
813 value = SIZE_OF_SUPPORTED_MCS_SET;
814 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
815 &value) == CDF_STATUS_SUCCESS) {
816 hddLog(CDF_TRACE_LEVEL_INFO, FL("Read MCS rate set"));
817
818 if (pconfig->enable2x2) {
819 for (value = 0; value < cfg->num_rf_chains; value++)
820 mcs_set[value] =
821 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
822
823 status =
824 sme_cfg_set_str(hdd_ctx->hHal,
825 WNI_CFG_SUPPORTED_MCS_SET,
826 mcs_set,
827 SIZE_OF_SUPPORTED_MCS_SET);
828 if (status == CDF_STATUS_E_FAILURE)
829 hddLog(CDF_TRACE_LEVEL_FATAL,
830 FL("could not set MCS SET to CCM"));
831 }
832 }
833#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
834}
835
836#ifdef WLAN_FEATURE_11AC
837static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
838 struct wma_tgt_vht_cap *cfg)
839{
840 CDF_STATUS status;
841 uint32_t value = 0;
842 struct hdd_config *pconfig = hdd_ctx->config;
843 struct wiphy *wiphy = hdd_ctx->wiphy;
844 struct ieee80211_supported_band *band_5g =
845 wiphy->bands[IEEE80211_BAND_5GHZ];
846
847 /* Get the current MPDU length */
848 status =
849 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
850 &value);
851
852 if (status != CDF_STATUS_SUCCESS) {
853 hddLog(CDF_TRACE_LEVEL_ERROR, FL("could not get MPDU LENGTH"));
854 value = 0;
855 }
856
857 /*
858 * VHT max MPDU length:
859 * override if user configured value is too high
860 * that the target cannot support
861 */
862 if (value > cfg->vht_max_mpdu) {
863 status = sme_cfg_set_int(hdd_ctx->hHal,
864 WNI_CFG_VHT_MAX_MPDU_LENGTH,
865 cfg->vht_max_mpdu);
866
867 if (status == CDF_STATUS_E_FAILURE) {
868 hddLog(CDF_TRACE_LEVEL_FATAL,
869 FL("could not set VHT MAX MPDU LENGTH"));
870 }
871 }
872
873 /* Get the current supported chan width */
874 status = sme_cfg_get_int(hdd_ctx->hHal,
875 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
876 &value);
877
878 if (status != CDF_STATUS_SUCCESS) {
879 hddLog(CDF_TRACE_LEVEL_ERROR,
880 FL("could not get MPDU LENGTH"));
881 value = 0;
882 }
883
884 /* Get the current RX LDPC setting */
885 status =
886 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
887 &value);
888
889 if (status != CDF_STATUS_SUCCESS) {
890 hddLog(CDF_TRACE_LEVEL_ERROR,
891 FL("could not get VHT LDPC CODING CAP"));
892 value = 0;
893 }
894
895 /* Set the LDPC capability */
896 if (value && !cfg->vht_rx_ldpc) {
897 status = sme_cfg_set_int(hdd_ctx->hHal,
898 WNI_CFG_VHT_LDPC_CODING_CAP,
899 cfg->vht_rx_ldpc);
900
901 if (status == CDF_STATUS_E_FAILURE) {
902 hddLog(CDF_TRACE_LEVEL_FATAL,
903 FL("could not set VHT LDPC CODING CAP to CCM"));
904 }
905 }
906
907 /* Get current GI 80 value */
908 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
909 &value);
910
911 if (status != CDF_STATUS_SUCCESS) {
912 hddLog(CDF_TRACE_LEVEL_ERROR,
913 FL("could not get SHORT GI 80MHZ"));
914 value = 0;
915 }
916
917 /* set the Guard interval 80MHz */
918 if (value && !cfg->vht_short_gi_80) {
919 status = sme_cfg_set_int(hdd_ctx->hHal,
920 WNI_CFG_VHT_SHORT_GI_80MHZ,
921 cfg->vht_short_gi_80);
922
923 if (status == CDF_STATUS_E_FAILURE) {
924 hddLog(CDF_TRACE_LEVEL_FATAL,
925 FL("could not set SHORT GI 80MHZ to CCM"));
926 }
927 }
928
929 /* Get current GI 160 value */
930 status = sme_cfg_get_int(hdd_ctx->hHal,
931 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
932 &value);
933
934 if (status != CDF_STATUS_SUCCESS) {
935 hddLog(CDF_TRACE_LEVEL_ERROR,
936 FL("could not get SHORT GI 80 & 160"));
937 value = 0;
938 }
939
940 /* Get VHT TX STBC cap */
941 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
942
943 if (status != CDF_STATUS_SUCCESS) {
944 hddLog(CDF_TRACE_LEVEL_ERROR,
945 FL("could not get VHT TX STBC"));
946 value = 0;
947 }
948
949 /* VHT TX STBC cap */
950 if (value && !cfg->vht_tx_stbc) {
951 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
952 cfg->vht_tx_stbc);
953
954 if (status == CDF_STATUS_E_FAILURE) {
955 hddLog(CDF_TRACE_LEVEL_FATAL,
956 FL("could not set the VHT TX STBC to CCM"));
957 }
958 }
959
960 /* Get VHT RX STBC cap */
961 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
962
963 if (status != CDF_STATUS_SUCCESS) {
964 hddLog(CDF_TRACE_LEVEL_ERROR,
965 FL("could not get VHT RX STBC"));
966 value = 0;
967 }
968
969 /* VHT RX STBC cap */
970 if (value && !cfg->vht_rx_stbc) {
971 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
972 cfg->vht_rx_stbc);
973
974 if (status == CDF_STATUS_E_FAILURE) {
975 hddLog(CDF_TRACE_LEVEL_FATAL,
976 FL("could not set the VHT RX STBC to CCM"));
977 }
978 }
979
980 /* Get VHT SU Beamformer cap */
981 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
982 &value);
983
984 if (status != CDF_STATUS_SUCCESS) {
985 hddLog(CDF_TRACE_LEVEL_ERROR,
986 FL("could not get VHT SU BEAMFORMER CAP"));
987 value = 0;
988 }
989
990 /* set VHT SU Beamformer cap */
991 if (value && !cfg->vht_su_bformer) {
992 status = sme_cfg_set_int(hdd_ctx->hHal,
993 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
994 cfg->vht_su_bformer);
995
996 if (status == CDF_STATUS_E_FAILURE) {
997 hddLog(CDF_TRACE_LEVEL_FATAL,
998 FL("could not set VHT SU BEAMFORMER CAP"));
999 }
1000 }
1001
1002 /* check and update SU BEAMFORMEE capabality */
1003 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1004 pconfig->enableTxBF = cfg->vht_su_bformee;
1005
1006 status = sme_cfg_set_int(hdd_ctx->hHal,
1007 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1008 pconfig->enableTxBF);
1009
1010 if (status == CDF_STATUS_E_FAILURE) {
1011 hddLog(CDF_TRACE_LEVEL_FATAL,
1012 FL("could not set VHT SU BEAMFORMEE CAP"));
1013 }
1014
1015 /* Get VHT MU Beamformer cap */
1016 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1017 &value);
1018
1019 if (status != CDF_STATUS_SUCCESS) {
1020 hddLog(CDF_TRACE_LEVEL_ERROR,
1021 FL("could not get VHT MU BEAMFORMER CAP"));
1022 value = 0;
1023 }
1024
1025 /* set VHT MU Beamformer cap */
1026 if (value && !cfg->vht_mu_bformer) {
1027 status = sme_cfg_set_int(hdd_ctx->hHal,
1028 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1029 cfg->vht_mu_bformer);
1030
1031 if (status == CDF_STATUS_E_FAILURE) {
1032 hddLog(CDF_TRACE_LEVEL_FATAL,
1033 FL(
1034 "could not set the VHT MU BEAMFORMER CAP to CCM"
1035 ));
1036 }
1037 }
1038
1039 /* Get VHT MU Beamformee cap */
1040 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1041 &value);
1042
1043 if (status != CDF_STATUS_SUCCESS) {
1044 hddLog(CDF_TRACE_LEVEL_ERROR,
1045 FL("could not get VHT MU BEAMFORMEE CAP"));
1046 value = 0;
1047 }
1048
1049 /* set VHT MU Beamformee cap */
1050 if (value && !cfg->vht_mu_bformee) {
1051 status = sme_cfg_set_int(hdd_ctx->hHal,
1052 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1053 cfg->vht_mu_bformee);
1054
1055 if (status == CDF_STATUS_E_FAILURE) {
1056 hddLog(CDF_TRACE_LEVEL_FATAL,
1057 FL("could not set VHT MU BEAMFORMER CAP"));
1058 }
1059 }
1060
1061 /* Get VHT MAX AMPDU Len exp */
1062 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1063 &value);
1064
1065 if (status != CDF_STATUS_SUCCESS) {
1066 hddLog(CDF_TRACE_LEVEL_ERROR,
1067 FL("could not get VHT AMPDU LEN"));
1068 value = 0;
1069 }
1070
1071 /*
1072 * VHT max AMPDU len exp:
1073 * override if user configured value is too high
1074 * that the target cannot support.
1075 * Even though Rome publish ampdu_len=7, it can
1076 * only support 4 because of some h/w bug.
1077 */
1078
1079 if (value > cfg->vht_max_ampdu_len_exp) {
1080 status = sme_cfg_set_int(hdd_ctx->hHal,
1081 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1082 cfg->vht_max_ampdu_len_exp);
1083
1084 if (status == CDF_STATUS_E_FAILURE) {
1085 hddLog(CDF_TRACE_LEVEL_FATAL,
1086 FL("could not set the VHT AMPDU LEN EXP"));
1087 }
1088 }
1089
1090 /* Get VHT TXOP PS CAP */
1091 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1092
1093 if (status != CDF_STATUS_SUCCESS) {
1094 hddLog(CDF_TRACE_LEVEL_ERROR,
1095 FL("could not get VHT TXOP PS"));
1096 value = 0;
1097 }
1098
1099 /* set VHT TXOP PS cap */
1100 if (value && !cfg->vht_txop_ps) {
1101 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1102 cfg->vht_txop_ps);
1103
1104 if (status == CDF_STATUS_E_FAILURE) {
1105 hddLog(CDF_TRACE_LEVEL_FATAL,
1106 FL("could not set the VHT TXOP PS"));
1107 }
1108 }
1109
1110 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1111 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1112 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1113 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1114 else
1115 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1116
1117
1118 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1119 band_5g->vht_cap.cap |=
1120 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1121 }
1122 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1123 band_5g->vht_cap.cap |=
1124 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1125 }
1126
1127 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1128 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1129
1130 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1131 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1132 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1133 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1134
1135 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1136 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1137
1138 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1139 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1140 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1141 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1142 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1143 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1144
1145 band_5g->vht_cap.cap |=
1146 (cfg->vht_max_ampdu_len_exp <<
1147 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1148
1149 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1150 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1151 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1152 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1153 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1154 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1155 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1156 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1157
1158 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1159 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1160
1161}
1162#endif /* #ifdef WLAN_FEATURE_11AC */
1163
1164void hdd_update_tgt_cfg(void *context, void *param)
1165{
1166 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1167 struct wma_tgt_cfg *cfg = param;
1168 uint8_t temp_band_cap;
1169
1170 /* first store the INI band capability */
1171 temp_band_cap = hdd_ctx->config->nBandCapability;
1172
1173 hdd_ctx->config->nBandCapability = cfg->band_cap;
1174
1175 /* now overwrite the target band capability with INI
1176 setting if INI setting is a subset */
1177
1178 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1179 (temp_band_cap != eCSR_BAND_ALL))
1180 hdd_ctx->config->nBandCapability = temp_band_cap;
1181 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1182 (temp_band_cap != eCSR_BAND_ALL) &&
1183 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
1184 hddLog(CDF_TRACE_LEVEL_WARN,
1185 FL("ini BandCapability not supported by the target"));
1186 }
1187
1188 if (!cds_is_logp_in_progress()) {
1189 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1190 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1191 }
1192
1193 /* This can be extended to other configurations like ht, vht cap... */
1194
1195 if (!cdf_is_macaddr_zero(&cfg->hw_macaddr)) {
1196 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1197 } else {
1198 hddLog(CDF_TRACE_LEVEL_ERROR,
1199 FL(
1200 "Invalid MAC passed from target, using MAC from ini file"
1201 MAC_ADDRESS_STR),
1202 MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes));
1203 }
1204
1205 hdd_ctx->target_fw_version = cfg->target_fw_version;
1206
1207 hdd_ctx->max_intf_count = cfg->max_intf_count;
1208
1209#ifdef WLAN_FEATURE_LPSS
1210 hdd_ctx->lpss_support = cfg->lpss_support;
1211#endif
1212
1213 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1214 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1215
1216 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1217
1218#ifdef WLAN_FEATURE_11AC
1219 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
1220#endif /* #ifdef WLAN_FEATURE_11AC */
1221}
1222
1223/**
1224 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1225 * @context: HDD context pointer
1226 * @param: HDD radar indication pointer
1227 *
1228 * This function is invoked when a radar in found on the
1229 * SAP current operating channel and Data Tx from netif
1230 * has to be stopped to honor the DFS regulations.
1231 * Actions: Stop the netif Tx queues,Indicate Radar present
1232 * in HDD context for future usage.
1233 *
1234 * Return: None
1235 */
1236void hdd_dfs_indicate_radar(void *context, void *param)
1237{
1238 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1239 struct wma_dfs_radar_ind *hdd_radar_event =
1240 (struct wma_dfs_radar_ind *)param;
1241 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1242 hdd_adapter_t *adapter;
1243 CDF_STATUS status;
1244
1245 if (hdd_ctx == NULL)
1246 return;
1247
1248 if (hdd_radar_event == NULL)
1249 return;
1250
1251 if (hdd_ctx->config->disableDFSChSwitch)
1252 return;
1253
1254 if (true == hdd_radar_event->dfs_radar_status) {
1255 hdd_ctx->dfs_radar_found = true;
1256
1257 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
1258 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
1259 adapter = adapterNode->pAdapter;
1260 if (WLAN_HDD_SOFTAP == adapter->device_mode ||
1261 WLAN_HDD_P2P_GO == adapter->device_mode) {
1262 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1263 dfs_cac_block_tx = true;
1264 }
1265
1266 status = hdd_get_next_adapter(hdd_ctx,
1267 adapterNode,
1268 &pNext);
1269 adapterNode = pNext;
1270 }
1271 }
1272}
1273#endif
1274
1275/**
1276 * hdd_is_valid_mac_address() - validate MAC address
1277 * @pMacAddr: Pointer to the input MAC address
1278 *
1279 * This function validates whether the given MAC address is valid or not
1280 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1281 * where X is the hexa decimal digit character and separated by ':'
1282 * This algorithm works even if MAC address is not separated by ':'
1283 *
1284 * This code checks given input string mac contains exactly 12 hexadecimal
1285 * digits and a separator colon : appears in the input string only after
1286 * an even number of hex digits.
1287 *
1288 * Return: 1 for valid and 0 for invalid
1289 */
1290bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1291{
1292 int xdigit = 0;
1293 int separator = 0;
1294 while (*pMacAddr) {
1295 if (isxdigit(*pMacAddr)) {
1296 xdigit++;
1297 } else if (':' == *pMacAddr) {
1298 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1299 break;
1300
1301 ++separator;
1302 } else {
1303 /* Invalid MAC found */
1304 return 0;
1305 }
1306 ++pMacAddr;
1307 }
1308 return xdigit == 12 && (separator == 5 || separator == 0);
1309}
1310
1311/**
1312 * __hdd_open() - HDD Open function
1313 * @dev: Pointer to net_device structure
1314 *
1315 * This is called in response to ifconfig up
1316 *
1317 * Return: 0 for success; non-zero for failure
1318 */
1319static int __hdd_open(struct net_device *dev)
1320{
1321 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1322 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1323 int ret;
1324
1325 MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
1326 adapter->sessionId, adapter->device_mode));
1327
1328 ret = wlan_hdd_validate_context(hdd_ctx);
1329 if (0 != ret) {
1330 hddLog(LOGE, FL("HDD context is not valid"));
1331 return ret;
1332 }
1333
1334 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1335 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
1336 hddLog(LOG1, FL("Enabling Tx Queues"));
1337 /* Enable TX queues only when we are connected */
1338 wlan_hdd_netif_queue_control(adapter,
1339 WLAN_START_ALL_NETIF_QUEUE,
1340 WLAN_CONTROL_PATH);
1341 }
1342
1343 return ret;
1344}
1345
1346/**
1347 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1348 * @dev: Pointer to net_device structure
1349 *
1350 * This is called in response to ifconfig up
1351 *
1352 * Return: 0 for success; non-zero for failure
1353 */
1354int hdd_open(struct net_device *dev)
1355{
1356 int ret;
1357
1358 cds_ssr_protect(__func__);
1359 ret = __hdd_open(dev);
1360 cds_ssr_unprotect(__func__);
1361
1362 return ret;
1363}
1364
1365/**
1366 * __hdd_stop() - HDD stop function
1367 * @dev: Pointer to net_device structure
1368 *
1369 * This is called in response to ifconfig down
1370 *
1371 * Return: 0 for success; non-zero for failure
1372 */
1373static int __hdd_stop(struct net_device *dev)
1374{
1375 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1376 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1377 int ret;
1378
1379 ENTER();
1380
1381 MTRACE(cdf_trace(CDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
1382 adapter->sessionId, adapter->device_mode));
1383
1384 ret = wlan_hdd_validate_context(hdd_ctx);
1385 if (0 != ret) {
1386 hddLog(LOGE, FL("HDD context is not valid"));
1387 return ret;
1388 }
1389
1390 /* Nothing to be done if the interface is not opened */
1391 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
1392 hddLog(CDF_TRACE_LEVEL_ERROR,
1393 FL("NETDEV Interface is not OPENED"));
1394 return -ENODEV;
1395 }
1396
1397 /* Make sure the interface is marked as closed */
1398 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1399 hddLog(CDF_TRACE_LEVEL_INFO, FL("Disabling OS Tx queues"));
1400
1401 /*
1402 * Disable TX on the interface, after this hard_start_xmit() will not
1403 * be called on that interface
1404 */
1405 hddLog(LOG1, FL("Disabling queues"));
1406 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1407 WLAN_CONTROL_PATH);
1408
1409 /*
1410 * The interface is marked as down for outside world (aka kernel)
1411 * But the driver is pretty much alive inside. The driver needs to
1412 * tear down the existing connection on the netdev (session)
1413 * cleanup the data pipes and wait until the control plane is stabilized
1414 * for this interface. The call also needs to wait until the above
1415 * mentioned actions are completed before returning to the caller.
1416 * Notice that the hdd_stop_adapter is requested not to close the session
1417 * That is intentional to be able to scan if it is a STA/P2P interface
1418 */
1419 hdd_stop_adapter(hdd_ctx, adapter, false);
1420
1421 /* DeInit the adapter. This ensures datapath cleanup as well */
1422 hdd_deinit_adapter(hdd_ctx, adapter, true);
1423
1424 EXIT();
1425 return 0;
1426}
1427
1428/**
1429 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
1430 * @dev: pointer to net_device structure
1431 *
1432 * This is called in response to ifconfig down
1433 *
1434 * Return: 0 for success and error number for failure
1435 */
1436int hdd_stop(struct net_device *dev)
1437{
1438 int ret;
1439
1440 cds_ssr_protect(__func__);
1441 ret = __hdd_stop(dev);
1442 cds_ssr_unprotect(__func__);
1443
1444 return ret;
1445}
1446
1447/**
1448 * __hdd_uninit() - HDD uninit function
1449 * @dev: Pointer to net_device structure
1450 *
1451 * This is called during the netdev unregister to uninitialize all data
1452 * associated with the device
1453 *
1454 * Return: None
1455 */
1456static void __hdd_uninit(struct net_device *dev)
1457{
1458 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1459
1460 ENTER();
1461
1462 do {
1463 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1464 hddLog(LOGP, FL("Invalid magic"));
1465 break;
1466 }
1467
1468 if (NULL == adapter->pHddCtx) {
1469 hddLog(LOGP, FL("NULL hdd_ctx"));
1470 break;
1471 }
1472
1473 if (dev != adapter->dev) {
1474 hddLog(LOGP, FL("Invalid device reference"));
1475 /*
1476 * we haven't validated all cases so let this go for
1477 * now
1478 */
1479 }
1480
1481 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
1482
1483 /* after uninit our adapter structure will no longer be valid */
1484 adapter->dev = NULL;
1485 adapter->magic = 0;
1486 } while (0);
1487
1488 EXIT();
1489}
1490
1491/**
1492 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
1493 * @dev: pointer to net_device structure
1494 *
1495 * This is called during the netdev unregister to uninitialize all data
1496 * associated with the device
1497 *
1498 * Return: none
1499 */
1500static void hdd_uninit(struct net_device *dev)
1501{
1502 cds_ssr_protect(__func__);
1503 __hdd_uninit(dev);
1504 cds_ssr_unprotect(__func__);
1505}
1506
1507/**
1508 * __hdd_set_mac_address() - set the user specified mac address
1509 * @dev: Pointer to the net device.
1510 * @addr: Pointer to the sockaddr.
1511 *
1512 * This function sets the user specified mac address using
1513 * the command ifconfig wlanX hw ether <mac adress>.
1514 *
1515 * Return: 0 for success, non zero for failure
1516 */
1517static int __hdd_set_mac_address(struct net_device *dev, void *addr)
1518{
1519 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1520 hdd_context_t *hdd_ctx;
1521 struct sockaddr *psta_mac_addr = addr;
1522 CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS;
1523 int ret;
1524
1525 ENTER();
1526
1527 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1528 ret = wlan_hdd_validate_context(hdd_ctx);
1529 if (0 != ret)
1530 return ret;
1531
1532 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1533 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1534
1535 EXIT();
1536 return cdf_ret_status;
1537}
1538
1539/**
1540 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
1541 * function from SSR
1542 * @dev: pointer to net_device structure
1543 * @addr: Pointer to the sockaddr
1544 *
1545 * This function sets the user specified mac address using
1546 * the command ifconfig wlanX hw ether <mac adress>.
1547 *
1548 * Return: 0 for success.
1549 */
1550static int hdd_set_mac_address(struct net_device *dev, void *addr)
1551{
1552 int ret;
1553
1554 cds_ssr_protect(__func__);
1555 ret = __hdd_set_mac_address(dev, addr);
1556 cds_ssr_unprotect(__func__);
1557
1558 return ret;
1559}
1560
1561uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
1562{
1563 int i;
1564 for (i = 0; i < CDF_MAX_CONCURRENCY_PERSONA; i++) {
1565 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
1566 break;
1567 }
1568
1569 if (CDF_MAX_CONCURRENCY_PERSONA == i)
1570 return NULL;
1571
1572 hdd_ctx->config->intfAddrMask |= (1 << i);
1573 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
1574}
1575
1576void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
1577{
1578 int i;
1579 for (i = 0; i < CDF_MAX_CONCURRENCY_PERSONA; i++) {
1580 if (!memcmp(releaseAddr,
1581 &hdd_ctx->config->intfMacAddr[i].bytes[0],
1582 6)) {
1583 hdd_ctx->config->intfAddrMask &= ~(1 << i);
1584 break;
1585 }
1586 }
1587 return;
1588}
1589
1590#ifdef WLAN_FEATURE_PACKET_FILTERING
1591/**
1592 * __hdd_set_multicast_list() - set the multicast address list
1593 * @dev: Pointer to the WLAN device.
1594 * @skb: Pointer to OS packet (sk_buff).
1595 *
1596 * This funciton sets the multicast address list.
1597 *
1598 * Return: None
1599 */
1600static void __hdd_set_multicast_list(struct net_device *dev)
1601{
1602 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1603 int mc_count;
1604 int i = 0, status;
1605 struct netdev_hw_addr *ha;
1606 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1607 static const uint8_t ipv6_router_solicitation[]
1608 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
1609
1610 status = wlan_hdd_validate_context(hdd_ctx);
1611 if (0 != status) {
1612 hdd_err("hdd_ctx is not valid");
1613 return;
1614 }
1615
1616 if (dev->flags & IFF_ALLMULTI) {
1617 hddLog(CDF_TRACE_LEVEL_INFO,
1618 FL("allow all multicast frames"));
1619 adapter->mc_addr_list.mc_cnt = 0;
1620 } else {
1621 mc_count = netdev_mc_count(dev);
1622 hddLog(CDF_TRACE_LEVEL_INFO,
1623 FL("mc_count = %u"), mc_count);
1624 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
1625 hddLog(CDF_TRACE_LEVEL_INFO,
1626 FL(
1627 "No free filter available; allow all multicast frames"
1628 ));
1629 adapter->mc_addr_list.mc_cnt = 0;
1630 return;
1631 }
1632
1633 adapter->mc_addr_list.mc_cnt = mc_count;
1634
1635 netdev_for_each_mc_addr(ha, dev) {
1636 if (i == mc_count)
1637 break;
1638 /*
1639 * Skip following addresses:
1640 * 1)IPv6 router solicitation address
1641 * 2)Any other address pattern if its set during
1642 * RXFILTER REMOVE driver command based on
1643 * addr_filter_pattern
1644 */
1645 if ((!memcmp(ha->addr, ipv6_router_solicitation,
1646 ETH_ALEN)) ||
1647 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
1648 &adapter->addr_filter_pattern, 1)))) {
1649 hdd_err("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
1650 MAC_ADDR_ARRAY(ha->addr));
1651 adapter->mc_addr_list.mc_cnt--;
1652 continue;
1653 }
1654
1655 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
1656 ETH_ALEN);
1657 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
1658 ETH_ALEN);
1659 hddLog(CDF_TRACE_LEVEL_INFO,
1660 FL("mlist[%d] = " MAC_ADDRESS_STR), i,
1661 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
1662 i++;
1663 }
1664 }
1665 if (hdd_ctx->config->active_mode_offload) {
1666 hdd_info("enable mc filtering");
1667 wlan_hdd_set_mc_addr_list(adapter, true);
1668 } else {
1669 hdd_info("skip mc filtering enable it during cfg80211 suspend");
1670 }
1671 return;
1672}
1673
1674/**
1675 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
1676 * @dev: pointer to net_device
1677 *
1678 * Return: none
1679 */
1680static void hdd_set_multicast_list(struct net_device *dev)
1681{
1682 cds_ssr_protect(__func__);
1683 __hdd_set_multicast_list(dev);
1684 cds_ssr_unprotect(__func__);
1685}
1686#endif
1687
1688/**
1689 * hdd_select_queue() - used by Linux OS to decide which queue to use first
1690 * @dev: Pointer to the WLAN device.
1691 * @skb: Pointer to OS packet (sk_buff).
1692 *
1693 * This function is registered with the Linux OS for network
1694 * core to decide which queue to use first.
1695 *
1696 * Return: ac, Queue Index/access category corresponding to UP in IP header
1697 */
1698static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
1699#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
1700 , void *accel_priv
1701#endif
1702#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1703 , select_queue_fallback_t fallback
1704#endif
1705)
1706{
1707 return hdd_wmm_select_queue(dev, skb);
1708}
1709
1710static struct net_device_ops wlan_drv_ops = {
1711 .ndo_open = hdd_open,
1712 .ndo_stop = hdd_stop,
1713 .ndo_uninit = hdd_uninit,
1714 .ndo_start_xmit = hdd_hard_start_xmit,
1715 .ndo_tx_timeout = hdd_tx_timeout,
1716 .ndo_get_stats = hdd_get_stats,
1717 .ndo_do_ioctl = hdd_ioctl,
1718 .ndo_set_mac_address = hdd_set_mac_address,
1719 .ndo_select_queue = hdd_select_queue,
1720#ifdef WLAN_FEATURE_PACKET_FILTERING
1721#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 1, 0))
1722 .ndo_set_rx_mode = hdd_set_multicast_list,
1723#else
1724 .ndo_set_multicast_list = hdd_set_multicast_list,
1725#endif /* LINUX_VERSION_CODE */
1726#endif
1727};
1728
1729void hdd_set_station_ops(struct net_device *pWlanDev)
1730{
1731 pWlanDev->netdev_ops = &wlan_drv_ops;
1732}
1733
1734static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
1735 tSirMacAddr macAddr,
1736 const char *name)
1737{
1738 struct net_device *pWlanDev = NULL;
1739 hdd_adapter_t *adapter = NULL;
1740 /*
1741 * cfg80211 initialization and registration....
1742 */
1743 pWlanDev =
1744 alloc_netdev_mq(sizeof(hdd_adapter_t), name,
1745#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
1746 NET_NAME_UNKNOWN,
1747#endif
1748 ether_setup,
1749 NUM_TX_QUEUES);
1750
1751 if (pWlanDev != NULL) {
1752
1753 /* Save the pointer to the net_device in the HDD adapter */
1754 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
1755
1756 cdf_mem_zero(adapter, sizeof(hdd_adapter_t));
1757
1758 adapter->dev = pWlanDev;
1759 adapter->pHddCtx = hdd_ctx;
1760 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1761
1762 init_completion(&adapter->session_open_comp_var);
1763 init_completion(&adapter->session_close_comp_var);
1764 init_completion(&adapter->disconnect_comp_var);
1765 init_completion(&adapter->linkup_event_var);
1766 init_completion(&adapter->cancel_rem_on_chan_var);
1767 init_completion(&adapter->rem_on_chan_ready_event);
1768 init_completion(&adapter->sta_authorized_event);
1769 init_completion(&adapter->offchannel_tx_event);
1770 init_completion(&adapter->tx_action_cnf_event);
1771#ifdef FEATURE_WLAN_TDLS
1772 init_completion(&adapter->tdls_add_station_comp);
1773 init_completion(&adapter->tdls_del_station_comp);
1774 init_completion(&adapter->tdls_mgmt_comp);
1775 init_completion(&adapter->tdls_link_establish_req_comp);
1776#endif
1777 init_completion(&adapter->change_country_code);
1778
1779
1780 init_completion(&adapter->scan_info.abortscan_event_var);
1781
1782 adapter->offloads_configured = false;
1783 adapter->isLinkUpSvcNeeded = false;
1784 adapter->higherDtimTransition = true;
1785 /* Init the net_device structure */
1786 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1787
1788 cdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
1789 sizeof(tSirMacAddr));
1790 cdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
1791 sizeof(tSirMacAddr));
1792 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1793 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1794
1795 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
1796 pWlanDev->features |=
1797 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
1798 pWlanDev->features |= NETIF_F_RXCSUM;
1799
1800#if defined(FEATURE_TSO)
1801 if (hdd_ctx->config->tso_enable) {
1802 hddLog(CDF_TRACE_LEVEL_INFO, FL("TSO Enabled\n"));
1803 pWlanDev->features |=
1804 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
1805 NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG;
1806 }
1807#endif
1808 hdd_set_station_ops(adapter->dev);
1809
1810 pWlanDev->destructor = free_netdev;
1811 pWlanDev->ieee80211_ptr = &adapter->wdev;
1812 adapter->wdev.wiphy = hdd_ctx->wiphy;
1813 adapter->wdev.netdev = pWlanDev;
1814 /* set pWlanDev's parent to underlying device */
1815 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
1816 hdd_wmm_init(adapter);
1817 spin_lock_init(&adapter->pause_map_lock);
1818 }
1819
1820 return adapter;
1821}
1822
1823CDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
1824 uint8_t rtnl_lock_held)
1825{
1826 struct net_device *pWlanDev = adapter->dev;
1827 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
1828 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
1829 /* CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS; */
1830
1831 if (rtnl_lock_held) {
1832 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
1833 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
1834 hddLog(CDF_TRACE_LEVEL_ERROR,
1835 FL("Failed:dev_alloc_name"));
1836 return CDF_STATUS_E_FAILURE;
1837 }
1838 }
1839 if (register_netdevice(pWlanDev)) {
1840 hddLog(CDF_TRACE_LEVEL_ERROR,
1841 FL("Failed:register_netdev"));
1842 return CDF_STATUS_E_FAILURE;
1843 }
1844 } else {
1845 if (register_netdev(pWlanDev)) {
1846 hddLog(CDF_TRACE_LEVEL_ERROR,
1847 FL("Failed:register_netdev"));
1848 return CDF_STATUS_E_FAILURE;
1849 }
1850 }
1851 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
1852
1853 return CDF_STATUS_SUCCESS;
1854}
1855
1856static CDF_STATUS hdd_sme_close_session_callback(void *pContext)
1857{
1858 hdd_adapter_t *adapter = pContext;
1859
1860 if (NULL == adapter) {
1861 hddLog(CDF_TRACE_LEVEL_FATAL, FL("NULL adapter"));
1862 return CDF_STATUS_E_INVAL;
1863 }
1864
1865 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1866 hddLog(CDF_TRACE_LEVEL_FATAL, FL("Invalid magic"));
1867 return CDF_STATUS_NOT_INITIALIZED;
1868 }
1869
1870 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
1871
1872#if !defined (CONFIG_CNSS) && \
1873 !defined (WLAN_OPEN_SOURCE)
1874 /*
1875 * need to make sure all of our scheduled work has completed.
1876 * This callback is called from MC thread context, so it is safe to
1877 * to call below flush workqueue API from here.
1878 *
1879 * Even though this is called from MC thread context, if there is a faulty
1880 * work item in the system, that can hang this call forever. So flushing
1881 * this global work queue is not safe; and now we make sure that
1882 * individual work queues are stopped correctly. But the cancel work queue
1883 * is a GPL only API, so the proprietary version of the driver would still
1884 * rely on the global work queue flush.
1885 */
1886 flush_scheduled_work();
1887#endif
1888
1889 /*
1890 * We can be blocked while waiting for scheduled work to be
1891 * flushed, and the adapter structure can potentially be freed, in
1892 * which case the magic will have been reset. So make sure the
1893 * magic is still good, and hence the adapter structure is still
1894 * valid, before signaling completion
1895 */
1896 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
1897 complete(&adapter->session_close_comp_var);
1898
1899 return CDF_STATUS_SUCCESS;
1900}
1901
1902CDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
1903{
1904 struct net_device *pWlanDev = adapter->dev;
1905 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
1906 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1907 CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS;
1908 CDF_STATUS status = CDF_STATUS_E_FAILURE;
1909 uint32_t type, subType;
1910 unsigned long rc;
1911 int ret_val;
1912
1913 INIT_COMPLETION(adapter->session_open_comp_var);
1914 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
1915 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
1916 if (CDF_STATUS_SUCCESS != status) {
1917 hddLog(LOGE, FL("failed to get vdev type"));
1918 goto error_sme_open;
1919 }
1920 /* Open a SME session for future operation */
1921 cdf_ret_status =
1922 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
1923 (uint8_t *) &adapter->macAddressCurrent,
1924 &adapter->sessionId, type, subType);
1925 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
1926 hddLog(LOGP,
1927 FL("sme_open_session() failed, status code %08d [x%08x]"),
1928 cdf_ret_status, cdf_ret_status);
1929 status = CDF_STATUS_E_FAILURE;
1930 goto error_sme_open;
1931 }
1932 /* Block on a completion variable. Can't wait forever though. */
1933 rc = wait_for_completion_timeout(
1934 &adapter->session_open_comp_var,
1935 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1936 if (!rc) {
1937 hddLog(LOGP,
1938 FL("Session is not opened within timeout period code %ld"),
1939 rc);
1940 status = CDF_STATUS_E_FAILURE;
1941 goto error_sme_open;
1942 }
1943
1944 /* Register wireless extensions */
1945 cdf_ret_status = hdd_register_wext(pWlanDev);
1946 if (CDF_STATUS_SUCCESS != cdf_ret_status) {
1947 hddLog(LOGP,
1948 FL("hdd_register_wext() failed, status code %08d [x%08x]"),
1949 cdf_ret_status, cdf_ret_status);
1950 status = CDF_STATUS_E_FAILURE;
1951 goto error_register_wext;
1952 }
1953 /* Set the Connection State to Not Connected */
1954 hddLog(LOG1,
1955 FL("Set HDD connState to eConnectionState_NotConnected"));
1956 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1957
1958 /* Set the default operation channel */
1959 pHddStaCtx->conn_info.operationChannel =
1960 hdd_ctx->config->OperatingChannel;
1961
1962 /* Make the default Auth Type as OPEN */
1963 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1964
1965 status = hdd_init_tx_rx(adapter);
1966 if (CDF_STATUS_SUCCESS != status) {
1967 hddLog(LOGP,
1968 FL("hdd_init_tx_rx() failed, status code %08d [x%08x]"),
1969 status, status);
1970 goto error_init_txrx;
1971 }
1972
1973 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
1974
1975 status = hdd_wmm_adapter_init(adapter);
1976 if (CDF_STATUS_SUCCESS != status) {
1977 hddLog(LOGP,
1978 FL("hdd_wmm_adapter_init() failed, status code %08d [x%08x]"),
1979 status, status);
1980 goto error_wmm_init;
1981 }
1982
1983 set_bit(WMM_INIT_DONE, &adapter->event_flags);
1984
1985 ret_val = wma_cli_set_command(adapter->sessionId,
1986 WMI_PDEV_PARAM_BURST_ENABLE,
1987 hdd_ctx->config->enableSifsBurst,
1988 PDEV_CMD);
1989
1990 if (0 != ret_val) {
1991 hddLog(LOGE,
1992 FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
1993 ret_val);
1994 }
1995#ifdef FEATURE_WLAN_TDLS
1996 if (0 != wlan_hdd_tdls_init(adapter)) {
1997 status = CDF_STATUS_E_FAILURE;
1998 hddLog(LOGE, FL("wlan_hdd_tdls_init failed"));
1999 goto error_tdls_init;
2000 }
2001 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2002#endif
2003
2004 return CDF_STATUS_SUCCESS;
2005
2006#ifdef FEATURE_WLAN_TDLS
2007error_tdls_init:
2008 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2009 hdd_wmm_adapter_close(adapter);
2010#endif
2011error_wmm_init:
2012 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2013 hdd_deinit_tx_rx(adapter);
2014error_init_txrx:
2015 hdd_unregister_wext(pWlanDev);
2016error_register_wext:
2017 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2018 INIT_COMPLETION(adapter->session_close_comp_var);
2019 if (CDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
2020 adapter->sessionId,
2021 hdd_sme_close_session_callback,
2022 adapter)) {
2023 unsigned long rc;
2024
2025 /*
2026 * Block on a completion variable.
2027 * Can't wait forever though.
2028 */
2029 rc = wait_for_completion_timeout(
2030 &adapter->session_close_comp_var,
2031 msecs_to_jiffies
2032 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2033 if (rc <= 0)
2034 hddLog(LOGE,
2035 FL("Session is not opened within timeout period code %ld"),
2036 rc);
2037 }
2038 }
2039error_sme_open:
2040 return status;
2041}
2042
2043void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2044{
2045 hdd_cfg80211_state_t *cfgState;
2046
2047 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2048
2049 if (NULL != cfgState->buf) {
2050 unsigned long rc;
2051 INIT_COMPLETION(adapter->tx_action_cnf_event);
2052 rc = wait_for_completion_timeout(
2053 &adapter->tx_action_cnf_event,
2054 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2055 if (!rc) {
2056 hddLog(CDF_TRACE_LEVEL_ERROR,
2057 FL("HDD Wait for Action Confirmation Failed!!"));
2058 }
2059 }
2060 return;
2061}
2062
2063void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2064 bool rtnl_held)
2065{
2066 ENTER();
2067 switch (adapter->device_mode) {
2068 case WLAN_HDD_INFRA_STATION:
2069 case WLAN_HDD_P2P_CLIENT:
2070 case WLAN_HDD_P2P_DEVICE:
2071 {
2072 if (test_bit
2073 (INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2074 hdd_deinit_tx_rx(adapter);
2075 clear_bit(INIT_TX_RX_SUCCESS,
2076 &adapter->event_flags);
2077 }
2078
2079 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2080 hdd_wmm_adapter_close(adapter);
2081 clear_bit(WMM_INIT_DONE,
2082 &adapter->event_flags);
2083 }
2084
2085 hdd_cleanup_actionframe(hdd_ctx, adapter);
2086 wlan_hdd_tdls_exit(adapter);
2087 break;
2088 }
2089
2090 case WLAN_HDD_SOFTAP:
2091 case WLAN_HDD_P2P_GO:
2092 {
2093
2094 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2095 hdd_wmm_adapter_close(adapter);
2096 clear_bit(WMM_INIT_DONE,
2097 &adapter->event_flags);
2098 }
2099
2100 hdd_cleanup_actionframe(hdd_ctx, adapter);
2101
2102 hdd_unregister_hostapd(adapter, rtnl_held);
2103
2104 /* set con_mode to STA only when no SAP concurrency mode */
2105 if (!
2106 (cds_get_concurrency_mode() &
2107 (CDF_SAP_MASK | CDF_P2P_GO_MASK)))
2108 hdd_set_conparam(0);
2109
2110 break;
2111 }
2112
2113 default:
2114 break;
2115 }
2116
2117 EXIT();
2118}
2119
2120void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2121 uint8_t rtnl_held)
2122{
2123 struct net_device *pWlanDev = NULL;
2124
2125 if (adapter)
2126 pWlanDev = adapter->dev;
2127 else {
2128 hddLog(LOGE, FL("adapter is Null"));
2129 return;
2130 }
2131
2132 hdd_lro_disable(hdd_ctx, adapter);
2133 /*
2134 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2135 * the driver is almost closed and cannot handle either control
2136 * messages or data. However, unregister_netdevice() call above will
2137 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2138 * to close the active connections (basically excites control path) which
2139 * is not right. Setting this flag helps hdd_stop() to recognize that
2140 * the interface is closed and restricts any operations on that
2141 */
2142 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2143
2144 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2145 if (rtnl_held) {
2146 unregister_netdevice(pWlanDev);
2147 } else {
2148 unregister_netdev(pWlanDev);
2149 }
2150 /*
2151 * Note that the adapter is no longer valid at this point
2152 * since the memory has been reclaimed
2153 */
2154 }
2155}
2156
2157CDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
2158 tSirMacAddr macAddr)
2159{
2160 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2161 hdd_adapter_t *adapter;
2162 CDF_STATUS status;
2163 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
2164 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
2165 adapter = adapterNode->pAdapter;
2166 if (adapter
2167 && cdf_mem_compare(adapter->macAddressCurrent.bytes,
2168 macAddr, sizeof(tSirMacAddr))) {
2169 return CDF_STATUS_E_FAILURE;
2170 }
2171 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2172 adapterNode = pNext;
2173 }
2174 return CDF_STATUS_SUCCESS;
2175}
2176hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
2177 const char *iface_name, tSirMacAddr macAddr,
2178 uint8_t rtnl_held)
2179{
2180 hdd_adapter_t *adapter = NULL;
2181 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2182 CDF_STATUS status = CDF_STATUS_E_FAILURE;
2183 hdd_cfg80211_state_t *cfgState;
2184 int ret;
2185
2186 hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type);
2187
2188 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
2189 /*
2190 * Max limit reached on the number of vdevs configured by the
2191 * host. Return error
2192 */
2193 hddLog(CDF_TRACE_LEVEL_ERROR,
2194 FL(
2195 "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d"
2196 ),
2197 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
2198 return NULL;
2199 }
2200
2201 if (macAddr == NULL) {
2202 /* Not received valid macAddr */
2203 hddLog(CDF_TRACE_LEVEL_ERROR,
2204 FL(
2205 "Unable to add virtual intf: Not able to get valid mac address"
2206 ));
2207 return NULL;
2208 }
2209 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
2210 if (CDF_STATUS_E_FAILURE == status) {
2211 hddLog(CDF_TRACE_LEVEL_ERROR,
2212 "Duplicate MAC addr: " MAC_ADDRESS_STR
2213 " already exists",
2214 MAC_ADDR_ARRAY(macAddr));
2215 return NULL;
2216 }
2217
2218 switch (session_type) {
2219 case WLAN_HDD_INFRA_STATION:
2220 /* Reset locally administered bit if the device mode is STA */
2221 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
2222 /* fall through */
2223 case WLAN_HDD_P2P_CLIENT:
2224 case WLAN_HDD_P2P_DEVICE:
2225 case WLAN_HDD_OCB:
2226 {
2227 adapter =
2228 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2229
2230 if (NULL == adapter) {
2231 hddLog(CDF_TRACE_LEVEL_FATAL,
2232 FL("failed to allocate adapter for session %d"),
2233 session_type);
2234 return NULL;
2235 }
2236
2237 if (WLAN_HDD_P2P_CLIENT == session_type)
2238 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
2239#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
2240 else if (WLAN_HDD_P2P_DEVICE == session_type)
2241 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
2242#endif
2243 else
2244 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2245
2246 adapter->device_mode = session_type;
2247
2248 status = hdd_init_station_mode(adapter);
2249 if (CDF_STATUS_SUCCESS != status)
2250 goto err_free_netdev;
2251
2252 hdd_lro_enable(hdd_ctx, adapter);
2253
2254 /*
2255 * Workqueue which gets scheduled in IPv4 notification
2256 * callback
2257 */
2258#ifdef CONFIG_CNSS
2259 cnss_init_work(&adapter->ipv4NotifierWorkQueue,
2260 hdd_ipv4_notifier_work_queue);
2261#else
2262 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
2263 hdd_ipv4_notifier_work_queue);
2264#endif
2265
2266#ifdef WLAN_NS_OFFLOAD
2267 /*
2268 * Workqueue which gets scheduled in IPv6
2269 * notification callback.
2270 */
2271#ifdef CONFIG_CNSS
2272 cnss_init_work(&adapter->ipv6NotifierWorkQueue,
2273 hdd_ipv6_notifier_work_queue);
2274#else
2275 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
2276 hdd_ipv6_notifier_work_queue);
2277#endif
2278#endif
2279 status = hdd_register_interface(adapter, rtnl_held);
2280 if (CDF_STATUS_SUCCESS != status) {
2281 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2282 goto err_lro_cleanup;
2283 }
2284
2285 /* Stop the Interface TX queue. */
2286 hddLog(LOG1, FL("Disabling queues"));
2287 wlan_hdd_netif_queue_control(adapter,
2288 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2289 WLAN_CONTROL_PATH);
2290
2291 hdd_register_tx_flow_control(adapter,
2292 hdd_tx_resume_timer_expired_handler,
2293 hdd_tx_resume_cb);
2294
2295 break;
2296 }
2297
2298 case WLAN_HDD_P2P_GO:
2299 case WLAN_HDD_SOFTAP:
2300 {
2301 adapter =
2302 hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
2303 (uint8_t *) iface_name);
2304 if (NULL == adapter) {
2305 hddLog(CDF_TRACE_LEVEL_FATAL,
2306 FL("failed to allocate adapter for session %d"),
2307 session_type);
2308 return NULL;
2309 }
2310
2311 adapter->wdev.iftype =
2312 (session_type ==
2313 WLAN_HDD_SOFTAP) ? NL80211_IFTYPE_AP :
2314 NL80211_IFTYPE_P2P_GO;
2315 adapter->device_mode = session_type;
2316
2317 status = hdd_init_ap_mode(adapter);
2318 if (CDF_STATUS_SUCCESS != status)
2319 goto err_free_netdev;
2320
2321 status = hdd_register_hostapd(adapter, rtnl_held);
2322 if (CDF_STATUS_SUCCESS != status) {
2323 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2324 goto err_free_netdev;
2325 }
2326
2327 hddLog(LOG1, FL("Disabling queues"));
2328 wlan_hdd_netif_queue_control(adapter,
2329 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2330 WLAN_CONTROL_PATH);
2331
2332 hdd_set_conparam(1);
2333
2334 break;
2335 }
2336 case WLAN_HDD_FTM:
2337 {
2338 adapter =
2339 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2340
2341 if (NULL == adapter) {
2342 hddLog(CDF_TRACE_LEVEL_FATAL,
2343 FL("failed to allocate adapter for session %d"),
2344 session_type);
2345 return NULL;
2346 }
2347
2348 /*
2349 * Assign NL80211_IFTYPE_STATION as interface type to resolve
2350 * Kernel Warning message while loading driver in FTM mode.
2351 */
2352 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2353 adapter->device_mode = session_type;
2354 status = hdd_register_interface(adapter, rtnl_held);
2355
2356 hdd_init_tx_rx(adapter);
2357
2358 /* Stop the Interface TX queue. */
2359 hddLog(LOG1, FL("Disabling queues"));
2360 wlan_hdd_netif_queue_control(adapter,
2361 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2362 WLAN_CONTROL_PATH);
2363 }
2364 break;
2365 default:
2366 {
2367 hddLog(CDF_TRACE_LEVEL_FATAL,
2368 FL("Invalid session type %d"),
2369 session_type);
2370 CDF_ASSERT(0);
2371 return NULL;
2372 }
2373 }
2374
2375 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2376 mutex_init(&cfgState->remain_on_chan_ctx_lock);
2377
2378 if (CDF_STATUS_SUCCESS == status) {
2379 /* Add it to the hdd's session list. */
2380 pHddAdapterNode =
2381 cdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
2382 if (NULL == pHddAdapterNode) {
2383 status = CDF_STATUS_E_NOMEM;
2384 } else {
2385 pHddAdapterNode->pAdapter = adapter;
2386 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
2387 }
2388 }
2389
2390 if (CDF_STATUS_SUCCESS != status) {
2391 if (NULL != adapter) {
2392 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
2393 adapter = NULL;
2394 }
2395 if (NULL != pHddAdapterNode) {
2396 cdf_mem_free(pHddAdapterNode);
2397 }
2398 return NULL;
2399 }
2400
2401 if (CDF_STATUS_SUCCESS == status) {
2402 cds_set_concurrency_mode(hdd_ctx, session_type);
2403
2404 /* Initialize the WoWL service */
2405 if (!hdd_init_wowl(adapter)) {
2406 hddLog(CDF_TRACE_LEVEL_FATAL,
2407 FL("hdd_init_wowl failed"));
2408 goto err_lro_cleanup;
2409 }
2410
2411 /* Adapter successfully added. Increment the vdev count */
2412 hdd_ctx->current_intf_count++;
2413
2414 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"),
2415 hdd_ctx->current_intf_count);
2416
2417 cds_check_and_restart_sap_with_non_dfs_acs(hdd_ctx);
2418 }
2419
2420 if ((cds_get_conparam() != CDF_FTM_MODE)
2421 && (!hdd_ctx->config->enable2x2)) {
2422#define HDD_DTIM_1CHAIN_RX_ID 0x5
2423#define HDD_SMPS_PARAM_VALUE_S 29
2424
2425 /*
2426 * Disable DTIM 1 chain Rx when in 1x1, we are passing two value
2427 * as param_id << 29 | param_value.
2428 * Below param_value = 0(disable)
2429 */
2430 ret = wma_cli_set_command(adapter->sessionId,
2431 WMI_STA_SMPS_PARAM_CMDID,
2432 HDD_DTIM_1CHAIN_RX_ID <<
2433 HDD_SMPS_PARAM_VALUE_S,
2434 VDEV_CMD);
2435
2436 if (ret != 0) {
2437 hddLog(CDF_TRACE_LEVEL_ERROR,
2438 FL("DTIM 1 chain set failed %d"), ret);
2439 goto err_lro_cleanup;
2440 }
2441
2442 ret = wma_cli_set_command(adapter->sessionId,
2443 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2444 hdd_ctx->config->txchainmask1x1,
2445 PDEV_CMD);
2446 if (ret != 0) {
2447 hddLog(CDF_TRACE_LEVEL_ERROR,
2448 FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"),
2449 ret);
2450 goto err_lro_cleanup;
2451 }
2452 ret = wma_cli_set_command(adapter->sessionId,
2453 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2454 hdd_ctx->config->rxchainmask1x1,
2455 PDEV_CMD);
2456 if (ret != 0) {
2457 hddLog(CDF_TRACE_LEVEL_ERROR,
2458 FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"),
2459 ret);
2460 goto err_lro_cleanup;
2461 }
2462#undef HDD_DTIM_1CHAIN_RX_ID
2463#undef HDD_SMPS_PARAM_VALUE_S
2464 }
2465
2466 if (CDF_FTM_MODE != cds_get_conparam()) {
2467 ret = wma_cli_set_command(adapter->sessionId,
2468 WMI_PDEV_PARAM_HYST_EN,
2469 hdd_ctx->config->enableMemDeepSleep,
2470 PDEV_CMD);
2471
2472 if (ret != 0) {
2473 hddLog(CDF_TRACE_LEVEL_ERROR,
2474 FL("WMI_PDEV_PARAM_HYST_EN set failed %d"),
2475 ret);
2476 goto err_lro_cleanup;
2477 }
2478 }
2479
2480#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2481
2482 /* Enable FW logs based on INI configuration */
2483 if ((CDF_FTM_MODE != cds_get_conparam()) &&
2484 (hdd_ctx->config->enablefwlog)) {
2485 uint8_t count = 0;
2486 uint32_t value = 0;
2487 uint8_t numEntries = 0;
2488 uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2489
2490 hdd_ctx->fw_log_settings.dl_type =
2491 hdd_ctx->config->enableFwLogType;
2492 ret = wma_cli_set_command(adapter->sessionId,
2493 WMI_DBGLOG_TYPE,
2494 hdd_ctx->config->enableFwLogType,
2495 DBG_CMD);
2496 if (ret != 0) {
2497 hddLog(LOGE, FL("Failed to enable FW log type ret %d"),
2498 ret);
2499 }
2500
2501 hdd_ctx->fw_log_settings.dl_loglevel =
2502 hdd_ctx->config->enableFwLogLevel;
2503 ret = wma_cli_set_command(adapter->sessionId,
2504 WMI_DBGLOG_LOG_LEVEL,
2505 hdd_ctx->config->enableFwLogLevel,
2506 DBG_CMD);
2507 if (ret != 0) {
2508 hddLog(LOGE, FL("Failed to enable FW log level ret %d"),
2509 ret);
2510 }
2511
2512 hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel,
2513 moduleLoglevel,
2514 &numEntries,
2515 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2516 while (count < numEntries) {
2517 /*
2518 * FW module log level input string looks like below:
2519 * gFwDebugModuleLoglevel=<FW Module ID>,<Log Level>,...
2520 * For example:
2521 * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6
2522 * Above input string means :
2523 * For FW module ID 1 enable log level 0
2524 * For FW module ID 2 enable log level 1
2525 * For FW module ID 3 enable log level 2
2526 * For FW module ID 4 enable log level 3
2527 * For FW module ID 5 enable log level 4
2528 * For FW module ID 6 enable log level 5
2529 * For FW module ID 7 enable log level 6
2530 */
2531
2532 /* FW expects WMI command value =
2533 * Module ID * 10 + Module Log level
2534 */
2535 value = ((moduleLoglevel[count] * 10) +
2536 moduleLoglevel[count + 1]);
2537 ret = wma_cli_set_command(adapter->sessionId,
2538 WMI_DBGLOG_MOD_LOG_LEVEL,
2539 value, DBG_CMD);
2540 if (ret != 0) {
2541 hddLog(LOGE,
2542 FL
2543 ("Failed to enable FW module log level %d ret %d"),
2544 value, ret);
2545 }
2546
2547 count += 2;
2548 }
2549 }
2550#endif
2551
2552 return adapter;
2553
2554err_lro_cleanup:
2555 hdd_lro_disable(hdd_ctx, adapter);
2556err_free_netdev:
2557 free_netdev(adapter->dev);
2558 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2559
2560 return NULL;
2561}
2562
2563CDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2564 uint8_t rtnl_held)
2565{
2566 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
2567 CDF_STATUS status;
2568
2569 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
2570 if (CDF_STATUS_SUCCESS != status) {
2571 hddLog(CDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"),
2572 status);
2573 return status;
2574 }
2575
2576 while (pCurrent->pAdapter != adapter) {
2577 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
2578 if (CDF_STATUS_SUCCESS != status)
2579 break;
2580
2581 pCurrent = pNext;
2582 }
2583 adapterNode = pCurrent;
2584 if (CDF_STATUS_SUCCESS == status) {
2585 cds_clear_concurrency_mode(hdd_ctx, adapter->device_mode);
2586 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
2587
2588 hdd_remove_adapter(hdd_ctx, adapterNode);
2589 cdf_mem_free(adapterNode);
2590 adapterNode = NULL;
2591
2592 /* Adapter removed. Decrement vdev count */
2593 if (hdd_ctx->current_intf_count != 0)
2594 hdd_ctx->current_intf_count--;
2595
2596 /* Fw will take care incase of concurrency */
2597 return CDF_STATUS_SUCCESS;
2598 }
2599 return CDF_STATUS_E_FAILURE;
2600}
2601
2602CDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx)
2603{
2604 hdd_adapter_list_node_t *pHddAdapterNode;
2605 CDF_STATUS status;
2606
2607 ENTER();
2608
2609 do {
2610 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
2611 if (pHddAdapterNode && CDF_STATUS_SUCCESS == status) {
2612 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
2613 false);
2614 cdf_mem_free(pHddAdapterNode);
2615 }
2616 } while (NULL != pHddAdapterNode && CDF_STATUS_E_EMPTY != status);
2617
2618 EXIT();
2619
2620 return CDF_STATUS_SUCCESS;
2621}
2622
2623void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
2624{
2625 uint8_t *bssid = NULL;
2626 tSirUpdateIE updateIE;
2627 switch (pHostapdAdapter->device_mode) {
2628 case WLAN_HDD_INFRA_STATION:
2629 case WLAN_HDD_P2P_CLIENT:
2630 {
2631 hdd_station_ctx_t *pHddStaCtx =
2632 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
2633 bssid = (uint8_t *) &pHddStaCtx->conn_info.bssId;
2634 break;
2635 }
2636 case WLAN_HDD_SOFTAP:
2637 case WLAN_HDD_P2P_GO:
2638 case WLAN_HDD_IBSS:
2639 {
2640 bssid = pHostapdAdapter->macAddressCurrent.bytes;
2641 break;
2642 }
2643 case WLAN_HDD_FTM:
2644 case WLAN_HDD_P2P_DEVICE:
2645 default:
2646 /*
2647 * wlan_hdd_reset_prob_rspies should not have been called
2648 * for these kind of devices
2649 */
2650 hddLog(LOGE,
2651 FL("Unexpected request for the current device type %d"),
2652 pHostapdAdapter->device_mode);
2653 return;
2654 }
2655
2656 cdf_mem_copy(updateIE.bssid, bssid, sizeof(tSirMacAddr));
2657 updateIE.smeSessionId = pHostapdAdapter->sessionId;
2658 updateIE.ieBufferlength = 0;
2659 updateIE.pAdditionIEBuffer = NULL;
2660 updateIE.append = true;
2661 updateIE.notify = false;
2662 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
2663 &updateIE,
2664 eUPDATE_IE_PROBE_RESP) == CDF_STATUS_E_FAILURE) {
2665 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
2666 }
2667}
2668
2669CDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2670 const bool bCloseSession)
2671{
2672 CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS;
2673 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
2674 union iwreq_data wrqu;
2675 tSirUpdateIE updateIE;
2676 unsigned long rc;
2677
2678 ENTER();
2679
2680 hddLog(LOG1, FL("Disabling queues"));
2681 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2682 WLAN_CONTROL_PATH);
2683 switch (adapter->device_mode) {
2684 case WLAN_HDD_INFRA_STATION:
2685 case WLAN_HDD_P2P_CLIENT:
2686 case WLAN_HDD_P2P_DEVICE:
2687 if (hdd_conn_is_connected(
2688 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
2689 hdd_is_connecting(
2690 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
2691 if (pWextState->roamProfile.BSSType ==
2692 eCSR_BSS_TYPE_START_IBSS)
2693 cdf_ret_status =
2694 sme_roam_disconnect(hdd_ctx->hHal,
2695 adapter->sessionId,
2696 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2697 else
2698 cdf_ret_status =
2699 sme_roam_disconnect(hdd_ctx->hHal,
2700 adapter->sessionId,
2701 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2702 /* success implies disconnect command got queued up successfully */
2703 if (cdf_ret_status == CDF_STATUS_SUCCESS) {
2704 rc = wait_for_completion_timeout(
2705 &adapter->disconnect_comp_var,
2706 msecs_to_jiffies
2707 (WLAN_WAIT_TIME_DISCONNECT));
2708 if (!rc) {
2709 hddLog(CDF_TRACE_LEVEL_ERROR,
2710 FL(
2711 "wait on disconnect_comp_var failed"
2712 ));
2713 }
2714 } else {
2715 hddLog(LOGE,
2716 FL(
2717 "failed to post disconnect event to SME"
2718 ));
2719 }
2720 memset(&wrqu, '\0', sizeof(wrqu));
2721 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2722 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
2723 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
2724 NULL);
2725 } else {
2726 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
2727 eCSR_SCAN_ABORT_DEFAULT);
2728 }
2729
2730 if (adapter->device_mode != WLAN_HDD_INFRA_STATION)
2731 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
2732
2733#ifdef WLAN_OPEN_SOURCE
2734 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
2735#endif
2736
2737 hdd_deregister_tx_flow_control(adapter);
2738
2739#ifdef WLAN_NS_OFFLOAD
2740#ifdef WLAN_OPEN_SOURCE
2741 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
2742#endif
2743#endif
2744
2745 /*
2746 * It is possible that the caller of this function does not
2747 * wish to close the session
2748 */
2749 if (true == bCloseSession &&
2750 test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2751 INIT_COMPLETION(adapter->session_close_comp_var);
2752 if (CDF_STATUS_SUCCESS ==
2753 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2754 hdd_sme_close_session_callback,
2755 adapter)) {
2756 /*
2757 * Block on a completion variable. Can't wait
2758 * forever though.
2759 */
2760 rc = wait_for_completion_timeout(
2761 &adapter->session_close_comp_var,
2762 msecs_to_jiffies
2763 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2764 if (!rc) {
2765 hddLog(LOGE,
2766 FL(
2767 "failure waiting for session_close_comp_var"
2768 ));
2769 }
2770 }
2771 }
2772 break;
2773
2774 case WLAN_HDD_SOFTAP:
2775 case WLAN_HDD_P2P_GO:
2776 if (hdd_ctx->config->conc_custom_rule1 &&
2777 (WLAN_HDD_SOFTAP == adapter->device_mode)) {
2778 /*
2779 * Before stopping the sap adapter, lets make sure there
2780 * is no sap restart work pending.
2781 */
2782 cds_flush_work(&hdd_ctx->sap_start_work);
2783 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
2784 FL("Canceled the pending SAP restart work"));
2785 cds_change_sap_restart_required_status(hdd_ctx, false);
2786 }
2787 /* Any softap specific cleanup here... */
2788 if (adapter->device_mode == WLAN_HDD_P2P_GO)
2789 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
2790
2791 hdd_deregister_tx_flow_control(adapter);
2792
2793 mutex_lock(&hdd_ctx->sap_lock);
2794 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
2795 CDF_STATUS status;
2796 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2797
2798 /* Stop Bss. */
2799#ifdef WLAN_FEATURE_MBSSID
2800 status = wlansap_stop_bss(
2801 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
2802#else
2803 status = wlansap_stop_bss(hdd_ctx->pcds_context);
2804#endif
2805
2806 if (CDF_IS_STATUS_SUCCESS(status)) {
2807 hdd_hostapd_state_t *hostapd_state =
2808 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
2809 cdf_event_reset(&hostapd_state->
2810 cdf_stop_bss_event);
2811 status =
2812 cdf_wait_single_event(&hostapd_state->
2813 cdf_stop_bss_event,
2814 BSS_WAIT_TIMEOUT);
2815
2816 if (!CDF_IS_STATUS_SUCCESS(status)) {
2817 hddLog(LOGE,
2818 FL(
2819 "failure waiting for wlansap_stop_bss %d"
2820 ),
2821 status);
2822 }
2823 } else {
2824 hddLog(LOGE, FL("failure in wlansap_stop_bss"));
2825 }
2826 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
2827 cds_decr_session_set_pcl(hdd_ctx,
2828 adapter->device_mode,
2829 adapter->sessionId);
2830
2831 cdf_mem_copy(updateIE.bssid,
2832 adapter->macAddressCurrent.bytes,
2833 sizeof(tSirMacAddr));
2834 updateIE.smeSessionId = adapter->sessionId;
2835 updateIE.ieBufferlength = 0;
2836 updateIE.pAdditionIEBuffer = NULL;
2837 updateIE.append = false;
2838 updateIE.notify = false;
2839 /* Probe bcn reset */
2840 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2841 &updateIE, eUPDATE_IE_PROBE_BCN)
2842 == CDF_STATUS_E_FAILURE) {
2843 hddLog(LOGE,
2844 FL(
2845 "Could not pass on PROBE_RSP_BCN data to PE"
2846 ));
2847 }
2848 /* Assoc resp reset */
2849 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2850 &updateIE,
2851 eUPDATE_IE_ASSOC_RESP) ==
2852 CDF_STATUS_E_FAILURE) {
2853 hddLog(LOGE,
2854 FL(
2855 "Could not pass on ASSOC_RSP data to PE"
2856 ));
2857 }
2858 /* Reset WNI_CFG_PROBE_RSP Flags */
2859 wlan_hdd_reset_prob_rspies(adapter);
2860 kfree(adapter->sessionCtx.ap.beacon);
2861 adapter->sessionCtx.ap.beacon = NULL;
2862 }
2863 mutex_unlock(&hdd_ctx->sap_lock);
2864 break;
2865 case WLAN_HDD_OCB:
2866 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
2867 conn_info.staId[0]);
2868 break;
2869 default:
2870 break;
2871 }
2872
2873 EXIT();
2874 return CDF_STATUS_SUCCESS;
2875}
2876
2877CDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
2878{
2879 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2880 CDF_STATUS status;
2881 hdd_adapter_t *adapter;
2882
2883 ENTER();
2884
2885 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
2886
2887 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
2888 adapter = adapterNode->pAdapter;
2889 hdd_stop_adapter(hdd_ctx, adapter, true);
2890 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2891 adapterNode = pNext;
2892 }
2893
2894 EXIT();
2895
2896 return CDF_STATUS_SUCCESS;
2897}
2898
2899CDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
2900{
2901 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2902 CDF_STATUS status;
2903 hdd_adapter_t *adapter;
2904
2905 ENTER();
2906
2907 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
2908
2909 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
2910 adapter = adapterNode->pAdapter;
2911 hddLog(LOG1, FL("Disabling queues"));
2912 wlan_hdd_netif_queue_control(adapter,
2913 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2914 WLAN_CONTROL_PATH);
2915
2916 adapter->sessionCtx.station.hdd_ReassocScenario = false;
2917
2918 hdd_deinit_tx_rx(adapter);
2919 cds_decr_session_set_pcl(hdd_ctx,
2920 adapter->device_mode,
2921 adapter->sessionId);
2922 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2923 hdd_wmm_adapter_close(adapter);
2924 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2925 }
2926
2927 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2928 adapterNode = pNext;
2929 }
2930
2931 EXIT();
2932
2933 return CDF_STATUS_SUCCESS;
2934}
2935
2936CDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
2937{
2938 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2939 CDF_STATUS status;
2940 hdd_adapter_t *adapter;
2941#ifndef MSM_PLATFORM
2942 struct cdf_mac_addr bcastMac = CDF_MAC_ADDR_BROADCAST_INITIALIZER;
2943#endif
2944 eConnectionState connState;
2945
2946 ENTER();
2947
2948 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
2949
2950 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
2951 adapter = adapterNode->pAdapter;
2952
2953 hdd_wmm_init(adapter);
2954
2955 switch (adapter->device_mode) {
2956 case WLAN_HDD_INFRA_STATION:
2957 case WLAN_HDD_P2P_CLIENT:
2958 case WLAN_HDD_P2P_DEVICE:
2959
2960 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
2961 ->conn_info.connState;
2962
2963 hdd_init_station_mode(adapter);
2964 /* Open the gates for HDD to receive Wext commands */
2965 adapter->isLinkUpSvcNeeded = false;
2966 adapter->scan_info.mScanPending = false;
2967
2968 /* Indicate disconnect event to supplicant if associated previously */
2969 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07002970 eConnectionState_IbssConnected == connState ||
2971 eConnectionState_NotConnected == connState ||
2972 eConnectionState_IbssDisconnected == connState ||
2973 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002974 union iwreq_data wrqu;
2975 memset(&wrqu, '\0', sizeof(wrqu));
2976 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2977 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
2978 wireless_send_event(adapter->dev, SIOCGIWAP,
2979 &wrqu, NULL);
2980 adapter->sessionCtx.station.
2981 hdd_ReassocScenario = false;
2982
2983 /* indicate disconnected event to nl80211 */
2984 cfg80211_disconnected(adapter->dev,
2985 WLAN_REASON_UNSPECIFIED,
2986 NULL, 0, GFP_KERNEL);
2987 } else if (eConnectionState_Connecting == connState) {
2988 /*
2989 * Indicate connect failure to supplicant if we were in the
2990 * process of connecting
2991 */
2992 cfg80211_connect_result(adapter->dev, NULL,
2993 NULL, 0, NULL, 0,
2994 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
2995 GFP_KERNEL);
2996 }
2997
2998 hdd_register_tx_flow_control(adapter,
2999 hdd_tx_resume_timer_expired_handler,
3000 hdd_tx_resume_cb);
3001
3002 break;
3003
3004 case WLAN_HDD_SOFTAP:
3005 /* softAP can handle SSR */
3006 break;
3007
3008 case WLAN_HDD_P2P_GO:
3009#ifdef MSM_PLATFORM
3010 hddLog(CDF_TRACE_LEVEL_ERROR,
3011 FL("[SSR] send stop ap to supplicant"));
3012 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3013#else
3014 hddLog(CDF_TRACE_LEVEL_ERROR,
3015 FL("[SSR] send restart supplicant"));
3016 /* event supplicant to restart */
3017 cfg80211_del_sta(adapter->dev,
3018 (const u8 *)&bcastMac.bytes[0],
3019 GFP_KERNEL);
3020#endif
3021 break;
3022
3023 default:
3024 break;
3025 }
3026
3027 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3028 adapterNode = pNext;
3029 }
3030
3031 EXIT();
3032
3033 return CDF_STATUS_SUCCESS;
3034}
3035
3036bool hdd_is_ssr_required(void)
3037{
3038 return is_ssr_required == HDD_SSR_REQUIRED;
3039}
3040
3041/* Once SSR is disabled then it cannot be set. */
3042void hdd_set_ssr_required(e_hdd_ssr_required value)
3043{
3044 if (HDD_SSR_DISABLED == is_ssr_required)
3045 return;
3046
3047 is_ssr_required = value;
3048}
3049
3050CDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
3051 hdd_adapter_list_node_t **padapterNode)
3052{
3053 CDF_STATUS status;
3054 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
3055 status = cdf_list_peek_front(&hdd_ctx->hddAdapters,
3056 (cdf_list_node_t **) padapterNode);
3057 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3058 return status;
3059}
3060
3061CDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
3062 hdd_adapter_list_node_t *adapterNode,
3063 hdd_adapter_list_node_t **pNextAdapterNode)
3064{
3065 CDF_STATUS status;
3066 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
3067 status = cdf_list_peek_next(&hdd_ctx->hddAdapters,
3068 (cdf_list_node_t *) adapterNode,
3069 (cdf_list_node_t **) pNextAdapterNode);
3070
3071 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3072 return status;
3073}
3074
3075CDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
3076 hdd_adapter_list_node_t *adapterNode)
3077{
3078 CDF_STATUS status;
3079 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
3080 status = cdf_list_remove_node(&hdd_ctx->hddAdapters,
3081 &adapterNode->node);
3082 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3083 return status;
3084}
3085
3086CDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
3087 hdd_adapter_list_node_t **padapterNode)
3088{
3089 CDF_STATUS status;
3090 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
3091 status = cdf_list_remove_front(&hdd_ctx->hddAdapters,
3092 (cdf_list_node_t **) padapterNode);
3093 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3094 return status;
3095}
3096
3097CDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
3098 hdd_adapter_list_node_t *adapterNode)
3099{
3100 CDF_STATUS status;
3101 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
3102 status = cdf_list_insert_back(&hdd_ctx->hddAdapters,
3103 (cdf_list_node_t *) adapterNode);
3104 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3105 return status;
3106}
3107
3108CDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
3109 hdd_adapter_list_node_t *adapterNode)
3110{
3111 CDF_STATUS status;
3112 cdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
3113 status = cdf_list_insert_front(&hdd_ctx->hddAdapters,
3114 (cdf_list_node_t *) adapterNode);
3115 cdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
3116 return status;
3117}
3118
3119hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3120 tSirMacAddr macAddr)
3121{
3122 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3123 hdd_adapter_t *adapter;
3124 CDF_STATUS status;
3125
3126 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3127
3128 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
3129 adapter = adapterNode->pAdapter;
3130
3131 if (adapter
3132 && cdf_mem_compare(adapter->macAddressCurrent.bytes,
3133 macAddr, sizeof(tSirMacAddr))) {
3134 return adapter;
3135 }
3136 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3137 adapterNode = pNext;
3138 }
3139
3140 return NULL;
3141
3142}
3143
3144hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3145 uint32_t vdev_id)
3146{
3147 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3148 hdd_adapter_t *adapter;
3149 CDF_STATUS cdf_status;
3150
3151 cdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3152
3153 while ((NULL != adapterNode) && (CDF_STATUS_SUCCESS == cdf_status)) {
3154 adapter = adapterNode->pAdapter;
3155
3156 if (adapter->sessionId == vdev_id)
3157 return adapter;
3158
3159 cdf_status =
3160 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3161 adapterNode = pNext;
3162 }
3163
3164 hddLog(CDF_TRACE_LEVEL_ERROR,
3165 FL("vdev_id %d does not exist with host"), vdev_id);
3166
3167 return NULL;
3168}
3169
3170hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, device_mode_t mode)
3171{
3172 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3173 hdd_adapter_t *adapter;
3174 CDF_STATUS status;
3175
3176 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3177
3178 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
3179 adapter = adapterNode->pAdapter;
3180
3181 if (adapter && (mode == adapter->device_mode))
3182 return adapter;
3183
3184 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3185 adapterNode = pNext;
3186 }
3187
3188 return NULL;
3189
3190}
3191
3192/**
3193 * hdd_get_operating_channel() - return operating channel of the device mode
3194 * @hdd_ctx: Pointer to the HDD context.
3195 * @mode: Device mode for which operating channel is required.
3196 * Suported modes:
3197 * WLAN_HDD_INFRA_STATION,
3198 * WLAN_HDD_P2P_CLIENT,
3199 * WLAN_HDD_SOFTAP,
3200 * WLAN_HDD_P2P_GO.
3201 *
3202 * This API returns the operating channel of the requested device mode
3203 *
3204 * Return: channel number. "0" id the requested device is not found OR it is
3205 * not connected.
3206 */
3207uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx, device_mode_t mode)
3208{
3209 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3210 CDF_STATUS status;
3211 hdd_adapter_t *adapter;
3212 uint8_t operatingChannel = 0;
3213
3214 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3215
3216 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
3217 adapter = adapterNode->pAdapter;
3218
3219 if (mode == adapter->device_mode) {
3220 switch (adapter->device_mode) {
3221 case WLAN_HDD_INFRA_STATION:
3222 case WLAN_HDD_P2P_CLIENT:
3223 if (hdd_conn_is_connected
3224 (WLAN_HDD_GET_STATION_CTX_PTR
3225 (adapter))) {
3226 operatingChannel =
3227 (WLAN_HDD_GET_STATION_CTX_PTR
3228 (adapter))->conn_info.
3229 operationChannel;
3230 }
3231 break;
3232 case WLAN_HDD_SOFTAP:
3233 case WLAN_HDD_P2P_GO:
3234 /* softap connection info */
3235 if (test_bit
3236 (SOFTAP_BSS_STARTED,
3237 &adapter->event_flags))
3238 operatingChannel =
3239 (WLAN_HDD_GET_AP_CTX_PTR
3240 (adapter))->operatingChannel;
3241 break;
3242 default:
3243 break;
3244 }
3245
3246 break; /* Found the device of interest. break the loop */
3247 }
3248
3249 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3250 adapterNode = pNext;
3251 }
3252 return operatingChannel;
3253}
3254
3255static inline CDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
3256 hdd_ctx)
3257{
3258 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3259 CDF_STATUS status;
3260 hdd_adapter_t *adapter;
3261
3262 ENTER();
3263
3264 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3265
3266 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
3267 adapter = adapterNode->pAdapter;
3268 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3269 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3270 (adapter->device_mode == WLAN_HDD_IBSS) ||
3271 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3272 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3273 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3274 wlan_hdd_cfg80211_deregister_frames(adapter);
3275 hdd_unregister_wext(adapter->dev);
3276 }
3277 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3278 adapterNode = pNext;
3279 }
3280
3281 EXIT();
3282
3283 return CDF_STATUS_SUCCESS;
3284}
3285
3286CDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
3287{
3288 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3289 CDF_STATUS status;
3290 hdd_adapter_t *adapter;
3291
3292 ENTER();
3293
3294 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3295
3296 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
3297 adapter = adapterNode->pAdapter;
3298 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3299 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3300 (adapter->device_mode == WLAN_HDD_IBSS) ||
3301 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3302 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3303 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3304 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3305 eCSR_SCAN_ABORT_DEFAULT);
3306 }
3307 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3308 adapterNode = pNext;
3309 }
3310
3311 EXIT();
3312
3313 return CDF_STATUS_SUCCESS;
3314}
3315
3316#ifdef WLAN_NS_OFFLOAD
3317/**
3318 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3319 * @hdd_ctx: Pointer to hdd context
3320 *
3321 * Return: None
3322 */
3323static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3324{
3325 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3326
3327 return;
3328}
3329
3330/**
3331 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3332 * @hdd_ctx: Pointer to hdd context
3333 *
3334 * Return: None
3335 */
3336static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3337{
3338 int ret;
3339
3340 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
3341 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3342 if (ret)
3343 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
3344 else
3345 hddLog(LOGE, FL("Registered IPv6 notifier"));
3346
3347 return;
3348}
3349#else
3350/**
3351 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3352 * @hdd_ctx: Pointer to hdd context
3353 *
3354 * Return: None
3355 */
3356static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3357{
3358}
3359/**
3360 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3361 * @hdd_ctx: Pointer to hdd context
3362 *
3363 * Return: None
3364 */
3365static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3366{
3367}
3368#endif
3369
3370/**
3371 * hdd_wlan_exit() - HDD WLAN exit function
3372 * @hdd_ctx: Pointer to the HDD Context
3373 *
3374 * This is the driver exit point (invoked during rmmod)
3375 *
3376 * Return: None
3377 */
3378void hdd_wlan_exit(hdd_context_t *hdd_ctx)
3379{
3380 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
3381 CDF_STATUS cdf_status;
3382 struct wiphy *wiphy = hdd_ctx->wiphy;
3383 struct hdd_config *pConfig = hdd_ctx->config;
3384
3385 ENTER();
3386
3387 hddLog(LOGE, FL("Unregister IPv6 notifier"));
3388 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3389 hddLog(LOGE, FL("Unregister IPv4 notifier"));
3390 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3391
3392 hdd_unregister_wext_all_adapters(hdd_ctx);
3393
3394 if (CDF_FTM_MODE == hdd_get_conparam()) {
3395 hddLog(CDF_TRACE_LEVEL_INFO, FL("FTM MODE"));
3396#if defined(QCA_WIFI_FTM)
3397 if (hdd_ftm_stop(hdd_ctx)) {
3398 hddLog(CDF_TRACE_LEVEL_FATAL,
3399 FL("hdd_ftm_stop Failed"));
3400 CDF_ASSERT(0);
3401 }
3402 hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED;
3403#endif
3404 wlan_hdd_ftm_close(hdd_ctx);
3405 hddLog(CDF_TRACE_LEVEL_FATAL, FL("FTM driver unloaded"));
3406 goto free_hdd_ctx;
3407 }
3408
3409 /*
3410 * Cancel any outstanding scan requests. We are about to close all
3411 * of our adapters, but an adapter structure is what SME passes back
3412 * to our callback function. Hence if there are any outstanding scan
3413 * requests then there is a race condition between when the adapter
3414 * is closed and when the callback is invoked. We try to resolve that
3415 * race condition here by canceling any outstanding scans before we
3416 * close the adapters.
3417 * Note that the scans may be cancelled in an asynchronous manner, so
3418 * ideally there needs to be some kind of synchronization. Rather than
3419 * introduce a new synchronization here, we will utilize the fact that
3420 * we are about to Request Full Power, and since that is synchronized,
3421 * the expectation is that by the time Request Full Power has completed,
3422 * all scans will be cancelled
3423 */
3424 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3425
3426#ifdef MSM_PLATFORM
3427 if (CDF_TIMER_STATE_RUNNING ==
3428 cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
3429 cdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
3430 }
3431
3432 if (!CDF_IS_STATUS_SUCCESS
3433 (cdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
3434 hddLog(CDF_TRACE_LEVEL_ERROR,
3435 FL("Cannot deallocate Bus bandwidth timer"));
3436 }
3437#endif
3438
3439#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3440 if (CDF_TIMER_STATE_RUNNING ==
3441 cdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
3442 cdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
3443 }
3444
3445 if (!CDF_IS_STATUS_SUCCESS
3446 (cdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
3447 hddLog(CDF_TRACE_LEVEL_ERROR,
3448 FL("Cannot deallocate ACS Skip timer"));
3449 }
3450#endif
3451 if (CDF_TIMER_STATE_RUNNING ==
3452 cdf_mc_timer_get_current_state(
3453 &hdd_ctx->dbs_opportunistic_timer)) {
3454 cdf_mc_timer_stop(&hdd_ctx->dbs_opportunistic_timer);
3455 }
3456
3457 if (!CDF_IS_STATUS_SUCCESS
3458 (cdf_mc_timer_destroy(
3459 &hdd_ctx->dbs_opportunistic_timer))) {
3460 hdd_err("Cannot deallocate dbs opportunistic timer");
3461 }
3462
3463 /*
3464 * Powersave Offload Case
3465 * Disable Idle Power Save Mode
3466 */
3467 hdd_set_idle_ps_config(hdd_ctx, false);
3468
3469 hdd_debugfs_exit(hdd_ctx);
3470
3471 /* Unregister the Net Device Notifier */
3472 unregister_netdevice_notifier(&hdd_netdev_notifier);
3473
3474 /*
3475 * Stop all adapters, this will ensure the termination of active
3476 * connections on the interface. Make sure the cds_scheduler is
3477 * still available to handle those control messages
3478 */
3479 hdd_stop_all_adapters(hdd_ctx);
3480
3481 /* Stop all the modules */
3482 cdf_status = cds_disable(p_cds_context);
3483 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
3484 hddLog(CDF_TRACE_LEVEL_FATAL,
3485 FL("Failed to stop CDS"));
3486 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
3487 }
3488
3489 /*
3490 * Close the scheduler before calling cds_close to make sure no thread
3491 * is scheduled after the each module close is called i.e after all the
3492 * data structures are freed.
3493 */
3494 cdf_status = cds_sched_close(p_cds_context);
3495 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
3496 hddLog(CDF_TRACE_LEVEL_FATAL,
3497 FL("Failed to close CDS Scheduler"));
3498 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(cdf_status));
3499 }
3500#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3501 /* Destroy the wake lock */
3502 cdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
3503#endif
3504 /* Destroy the wake lock */
3505 cdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock);
3506
3507 hdd_hostapd_channel_wakelock_deinit(hdd_ctx);
3508
3509 /*
3510 * Close CDS
3511 * This frees pMac(HAL) context. There should not be any call
3512 * that requires pMac access after this.
3513 */
3514 cds_close(p_cds_context);
3515
3516 hdd_wlan_green_ap_deinit(hdd_ctx);
3517
3518#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3519 if (pConfig && pConfig->wlanLoggingEnable) {
3520 wlan_logging_sock_deactivate_svc();
3521 }
3522#endif
3523#ifdef WLAN_KD_READY_NOTIFIER
3524 cnss_diag_notify_wlan_close();
3525 ptt_sock_deactivate_svc();
3526#endif /* WLAN_KD_READY_NOTIFIER */
3527 nl_srv_exit();
3528
3529 hdd_close_all_adapters(hdd_ctx);
3530
3531 hdd_ipa_cleanup(hdd_ctx);
3532
3533 /* Free up RoC request queue and flush workqueue */
3534 cds_flush_work(&hdd_ctx->roc_req_work);
3535 cdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
3536 cdf_list_destroy(&hdd_ctx->hdd_scan_req_q);
3537
3538 if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_destroy(
3539 &hdd_ctx->hdd_conc_list_lock))) {
3540 hdd_err("Failed to destroy hdd_conc_list_lock");
3541 /* Proceed and complete the clean up */
3542 }
3543
3544free_hdd_ctx:
3545
3546 /* Free up dynamically allocated members inside HDD Adapter */
3547 if (hdd_ctx->config) {
3548 kfree(hdd_ctx->config);
3549 hdd_ctx->config = NULL;
3550 }
3551
3552 wiphy_unregister(wiphy);
3553 wiphy_free(wiphy);
3554 if (hdd_is_ssr_required()) {
3555#ifdef MSM_PLATFORM
3556#ifdef CONFIG_CNSS
3557 /*
3558 * WDI timeout had happened during unload, so SSR is needed
3559 * here
3560 */
3561 subsystem_restart("wcnss");
3562#endif
3563#endif
3564 msleep(5000);
3565 }
3566 hdd_set_ssr_required(false);
3567}
3568
3569void __hdd_wlan_exit(void)
3570{
3571 hdd_context_t *hdd_ctx;
3572
3573 ENTER();
3574
3575 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
3576 if (!hdd_ctx) {
3577 hddLog(CDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context"));
3578 EXIT();
3579 return;
3580 }
3581
3582 /* module exit should never proceed if SSR is not completed */
3583 while (hdd_ctx->isLogpInProgress) {
3584 hddLog(CDF_TRACE_LEVEL_FATAL,
3585 FL("SSR in Progress; block rmmod for 1 second!!!"));
3586 msleep(1000);
3587 }
3588
3589 hdd_ctx->isUnloadInProgress = true;
3590
3591 cds_set_load_unload_in_progress(true);
3592
3593#ifdef WLAN_FEATURE_LPSS
3594 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
3595#endif
3596
3597 /* Do all the cleanup before deregistering the driver */
3598 hdd_wlan_exit(hdd_ctx);
3599 EXIT();
3600}
3601
3602#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3603void hdd_skip_acs_scan_timer_handler(void *data)
3604{
3605 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
3606
3607 hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
3608 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
3609
3610 if (!hdd_ctx->hHal)
3611 return;
3612 sme_scan_flush_result(hdd_ctx->hHal);
3613}
3614#endif
3615
3616#ifdef QCA_HT_2040_COEX
3617/**
3618 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
3619 * @adapter: pointer to adapter
3620 * @staId: station id
3621 * @macAddrSTA: station MAC address
3622 * @channel_type: channel type
3623 *
3624 * This function notifies FW with HT20/HT40 mode
3625 *
3626 * Return: 0 if successful, error number otherwise
3627 */
3628int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
3629 struct cdf_mac_addr macAddrSTA, int channel_type)
3630{
3631 int status;
3632 CDF_STATUS cdf_status;
3633 hdd_context_t *hdd_ctx = NULL;
3634
3635 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3636
3637 status = wlan_hdd_validate_context(hdd_ctx);
3638 if (0 != status) {
3639 hddLog(LOGE, FL("HDD context is not valid"));
3640 return status;
3641 }
3642 if (!hdd_ctx->hHal)
3643 return -EINVAL;
3644
3645 cdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
3646 adapter->sessionId, channel_type);
3647 if (CDF_STATUS_SUCCESS != cdf_status) {
3648 hddLog(LOGE, "Fail to send notification with ht2040 mode");
3649 return -EINVAL;
3650 }
3651
3652 return 0;
3653}
3654#endif
3655
3656/**
3657 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
3658 * @state: state
3659 *
3660 * This function notifies FW with modem power status
3661 *
3662 * Return: 0 if successful, error number otherwise
3663 */
3664int hdd_wlan_notify_modem_power_state(int state)
3665{
3666 int status;
3667 CDF_STATUS cdf_status;
3668 hdd_context_t *hdd_ctx;
3669
3670 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
3671 status = wlan_hdd_validate_context(hdd_ctx);
3672 if (0 != status) {
3673 hddLog(LOGE, FL("HDD context is not valid"));
3674 return status;
3675 }
3676 if (!hdd_ctx->hHal)
3677 return -EINVAL;
3678
3679 cdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
3680 if (CDF_STATUS_SUCCESS != cdf_status) {
3681 hddLog(LOGE,
3682 "Fail to send notification with modem power state %d",
3683 state);
3684 return -EINVAL;
3685 }
3686 return 0;
3687}
3688
3689/**
3690 *
3691 * hdd_post_cds_enable_config() - HDD post cds start config helper
3692 * @adapter - Pointer to the HDD
3693 *
3694 * Return: None
3695 */
3696CDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
3697{
3698 CDF_STATUS cdf_ret_status;
3699
3700 /*
3701 * Send ready indication to the HDD. This will kick off the MAC
3702 * into a 'running' state and should kick off an initial scan.
3703 */
3704 cdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
3705 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
3706 hddLog(CDF_TRACE_LEVEL_ERROR,
3707 FL(
3708 "sme_hdd_ready_ind() failed with status code %08d [x%08x]"
3709 ),
3710 cdf_ret_status, cdf_ret_status);
3711 return CDF_STATUS_E_FAILURE;
3712 }
3713
3714 return CDF_STATUS_SUCCESS;
3715}
3716
3717/* wake lock APIs for HDD */
3718void hdd_prevent_suspend(uint32_t reason)
3719{
3720 cdf_wake_lock_acquire(&wlan_wake_lock, reason);
3721}
3722
3723void hdd_allow_suspend(uint32_t reason)
3724{
3725 cdf_wake_lock_release(&wlan_wake_lock, reason);
3726}
3727
3728void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
3729{
3730 cdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
3731}
3732
3733/**
3734 * hdd_exchange_version_and_caps() - exchange version and capability with target
3735 * @hdd_ctx: Pointer to HDD context
3736 *
3737 * This is the HDD function to exchange version and capability information
3738 * between Host and Target
3739 *
3740 * This function gets reported version of FW.
3741 * It also finds the version of target headers used to compile the host;
3742 * It compares the above two and prints a warning if they are different;
3743 * It gets the SW and HW version string;
3744 * Finally, it exchanges capabilities between host and target i.e. host
3745 * and target exchange a msg indicating the features they support through a
3746 * bitmap
3747 *
3748 * Return: None
3749 */
3750void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
3751{
3752
3753 tSirVersionType versionCompiled;
3754 tSirVersionType versionReported;
3755 tSirVersionString versionString;
3756 uint8_t fwFeatCapsMsgSupported = 0;
3757 CDF_STATUS vstatus;
3758
3759 memset(&versionCompiled, 0, sizeof(versionCompiled));
3760 memset(&versionReported, 0, sizeof(versionReported));
3761
3762 /* retrieve and display WCNSS version information */
3763 do {
3764
3765 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
3766 &versionCompiled);
3767 if (!CDF_IS_STATUS_SUCCESS(vstatus)) {
3768 hddLog(CDF_TRACE_LEVEL_FATAL,
3769 FL(
3770 "unable to retrieve WCNSS WLAN compiled version"
3771 ));
3772 break;
3773 }
3774
3775 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
3776 &versionReported);
3777 if (!CDF_IS_STATUS_SUCCESS(vstatus)) {
3778 hddLog(CDF_TRACE_LEVEL_FATAL,
3779 FL(
3780 "unable to retrieve WCNSS WLAN reported version"
3781 ));
3782 break;
3783 }
3784
3785 if ((versionCompiled.major != versionReported.major) ||
3786 (versionCompiled.minor != versionReported.minor) ||
3787 (versionCompiled.version != versionReported.version) ||
3788 (versionCompiled.revision != versionReported.revision)) {
3789 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3790 "Host expected %u.%u.%u.%u\n",
3791 WLAN_MODULE_NAME,
3792 (int)versionReported.major,
3793 (int)versionReported.minor,
3794 (int)versionReported.version,
3795 (int)versionReported.revision,
3796 (int)versionCompiled.major,
3797 (int)versionCompiled.minor,
3798 (int)versionCompiled.version,
3799 (int)versionCompiled.revision);
3800 } else {
3801 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3802 WLAN_MODULE_NAME,
3803 (int)versionReported.major,
3804 (int)versionReported.minor,
3805 (int)versionReported.version,
3806 (int)versionReported.revision);
3807 }
3808
3809 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
3810 versionString,
3811 sizeof(versionString));
3812 if (!CDF_IS_STATUS_SUCCESS(vstatus)) {
3813 hddLog(CDF_TRACE_LEVEL_FATAL,
3814 FL(
3815 "unable to retrieve WCNSS software version string"
3816 ));
3817 break;
3818 }
3819
3820 pr_info("%s: WCNSS software version %s\n",
3821 WLAN_MODULE_NAME, versionString);
3822
3823 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
3824 versionString,
3825 sizeof(versionString));
3826 if (!CDF_IS_STATUS_SUCCESS(vstatus)) {
3827 hddLog(CDF_TRACE_LEVEL_FATAL,
3828 FL(
3829 "unable to retrieve WCNSS hardware version string"
3830 ));
3831 break;
3832 }
3833
3834 pr_info("%s: WCNSS hardware version %s\n",
3835 WLAN_MODULE_NAME, versionString);
3836
3837 /*
3838 * 1.Check if FW version is greater than 0.1.1.0. Only then
3839 * send host-FW capability exchange message
3840 * 2.Host-FW capability exchange message is only present on
3841 * target 1.1 so send the message only if it the target is 1.1
3842 * minor numbers for different target branches:
3843 * 0 -> (1.0)Mainline Build
3844 * 1 -> (1.1)Mainline Build
3845 * 2->(1.04) Stability Build
3846 */
3847 if (((versionReported.major > 0) || (versionReported.minor > 1)
3848 || ((versionReported.minor >= 1)
3849 && (versionReported.version >= 1)))
3850 && ((versionReported.major == 1)
3851 && (versionReported.minor >= 1)))
3852 fwFeatCapsMsgSupported = 1;
3853
3854 if (fwFeatCapsMsgSupported) {
3855 /*
3856 * Indicate if IBSS heartbeat monitoring needs to be
3857 * offloaded
3858 */
3859 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
3860 sme_disable_feature_capablity
3861 (IBSS_HEARTBEAT_OFFLOAD);
3862 }
3863
3864 sme_feature_caps_exchange(hdd_ctx->hHal);
3865 }
3866
3867 } while (0);
3868
3869}
3870
3871/* Initialize channel list in sme based on the country code */
3872CDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
3873{
3874 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
3875 hdd_ctx->reg.cc_src);
3876}
3877
3878/**
3879 * hdd_is_5g_supported() - check if hardware supports 5GHz
3880 * @hdd_ctx: Pointer to the hdd context
3881 *
3882 * HDD function to know if hardware supports 5GHz
3883 *
3884 * Return: true if hardware supports 5GHz
3885 */
3886bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
3887{
3888 /*
3889 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
3890 * then hardware support 5Ghz.
3891 */
3892 return true;
3893}
3894
3895static CDF_STATUS wlan_hdd_regulatory_init(hdd_context_t *hdd_ctx)
3896{
3897 struct wiphy *wiphy;
3898 CDF_STATUS status = CDF_STATUS_SUCCESS;
3899
3900 wiphy = hdd_ctx->wiphy;
3901
3902 /*
3903 * The channel information in
3904 * wiphy needs to be initialized before wiphy registration
3905 */
3906 status = cds_regulatory_init();
3907 if (!CDF_IS_STATUS_SUCCESS(status)) {
3908 hddLog(CDF_TRACE_LEVEL_FATAL,
3909 FL("cds_init_wiphy failed"));
3910 return status;
3911 }
3912
3913#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
3914 wiphy->wowlan = &wowlan_support_reg_init;
3915#else
3916 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
3917 WIPHY_WOWLAN_MAGIC_PKT |
3918 WIPHY_WOWLAN_DISCONNECT |
3919 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
3920 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
3921 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
3922 WIPHY_WOWLAN_4WAY_HANDSHAKE |
3923 WIPHY_WOWLAN_RFKILL_RELEASE;
3924
3925 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
3926 WOW_MAX_FILTERS_PER_LIST);
3927 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
3928 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
3929#endif
3930
3931 /* registration of wiphy dev with cfg80211 */
3932 if (0 > wlan_hdd_cfg80211_register(wiphy)) {
3933 hddLog(CDF_TRACE_LEVEL_ERROR, FL("wiphy register failed"));
3934 status = CDF_STATUS_E_FAILURE;
3935 }
3936
3937 return status;
3938}
3939
3940#ifdef MSM_PLATFORM
3941void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx,
3942 uint64_t tx_packets, uint64_t rx_packets)
3943{
3944#ifdef CONFIG_CNSS
3945 uint64_t total = tx_packets + rx_packets;
3946 enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE;
3947
3948 uint64_t temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
3949 enum cnss_bus_width_type next_rx_level = CNSS_BUS_WIDTH_NONE;
3950 if (total > hdd_ctx->config->busBandwidthHighThreshold)
3951 next_vote_level = CNSS_BUS_WIDTH_HIGH;
3952 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
3953 next_vote_level = CNSS_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07003954 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955 next_vote_level = CNSS_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07003956 else
3957 next_vote_level = CNSS_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958
3959 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level
3960 = next_vote_level;
3961
3962 if (hdd_ctx->cur_vote_level != next_vote_level) {
3963 hddLog(CDF_TRACE_LEVEL_DEBUG,
3964 FL(
3965 "trigger level %d, tx_packets: %lld, rx_packets: %lld"
3966 ),
3967 next_vote_level, tx_packets, rx_packets);
3968 hdd_ctx->cur_vote_level = next_vote_level;
3969 cnss_request_bus_bandwidth(next_vote_level);
3970 }
3971 hdd_ctx->prev_rx = rx_packets;
3972 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
3973 next_rx_level = CNSS_BUS_WIDTH_HIGH;
3974 else
3975 next_rx_level = CNSS_BUS_WIDTH_LOW;
3976
3977 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level
3978 = next_rx_level;
3979
3980 if (hdd_ctx->cur_rx_level != next_rx_level) {
3981 hddLog(CDF_TRACE_LEVEL_DEBUG,
3982 FL("TCP DELACK trigger level %d, average_rx: %llu"),
3983 next_rx_level, temp_rx);
3984 hdd_ctx->cur_rx_level = next_rx_level;
3985 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
3986 &next_rx_level,
3987 sizeof(next_rx_level));
3988 }
3989
3990 hdd_ctx->hdd_txrx_hist_idx++;
3991 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
3992#endif
3993}
3994
3995#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
3996static void hdd_bus_bw_compute_cbk(void *priv)
3997{
3998 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
3999 hdd_adapter_t *adapter = NULL;
4000 uint64_t tx_packets = 0, rx_packets = 0;
4001 uint64_t total_tx = 0, total_rx = 0;
4002 hdd_adapter_list_node_t *adapterNode = NULL;
4003 CDF_STATUS status = 0;
4004 bool connected = false;
4005 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4006
4007 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4008 NULL != adapterNode && CDF_STATUS_SUCCESS == status;
4009 status =
4010 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4011
4012 if (adapterNode->pAdapter == NULL)
4013 continue;
4014 adapter = adapterNode->pAdapter;
4015
4016 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION ||
4017 adapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
4018 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4019 != eConnectionState_Associated) {
4020
4021 continue;
4022 }
4023
4024 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
4025 adapter->device_mode == WLAN_HDD_P2P_GO) &&
4026 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4027
4028 continue;
4029 }
4030
4031 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4032 adapter->prev_tx_packets);
4033 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4034 adapter->prev_rx_packets);
4035
4036 total_rx += adapter->stats.rx_packets;
4037 total_tx += adapter->stats.tx_packets;
4038
4039 spin_lock_bh(&hdd_ctx->bus_bw_lock);
4040 adapter->prev_tx_packets = adapter->stats.tx_packets;
4041 adapter->prev_rx_packets = adapter->stats.rx_packets;
4042 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
4043 connected = true;
4044 }
4045
4046 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
4047 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
4048 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
4049 rx_packets;
4050 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
4051 tx_packets;
4052
4053 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
4054 tx_packets += (uint64_t)ipa_tx_packets;
4055 rx_packets += (uint64_t)ipa_rx_packets;
4056
4057 if (!connected) {
4058 hddLog(CDF_TRACE_LEVEL_ERROR,
4059 FL("bus bandwidth timer running in disconnected state"));
4060 return;
4061 }
4062
4063 hdd_cnss_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
4064
4065 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
4066 hdd_ipa_uc_stat_request(adapter, 2);
4067
4068 cdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
4069 hdd_ctx->config->busBandwidthComputeInterval);
4070}
4071#endif
4072
4073/**
4074 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
4075 * @hdd_ctx: hdd context
4076 *
4077 * Return: none
4078 */
4079void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
4080{
4081 int i;
4082
4083#ifdef MSM_PLATFORM
4084 hddLog(CDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d",
4085 hdd_ctx->config->busBandwidthComputeInterval,
4086 hdd_ctx->hdd_txrx_hist_idx);
4087 hddLog(CDF_TRACE_LEVEL_ERROR,
4088 "BW High TH: %d BW Med TH: %d BW Low TH: %d",
4089 hdd_ctx->config->busBandwidthHighThreshold,
4090 hdd_ctx->config->busBandwidthMediumThreshold,
4091 hdd_ctx->config->busBandwidthLowThreshold);
4092 hddLog(CDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
4093 hdd_ctx->config->tcpDelackThresholdHigh,
4094 hdd_ctx->config->tcpDelackThresholdLow);
4095#endif
4096
4097 hddLog(CDF_TRACE_LEVEL_ERROR, "index, total_rx, interval_rx,"
4098 "total_tx, interval_tx, next_vote_level, next_rx_level");
4099
4100 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
4101 hddLog(CDF_TRACE_LEVEL_ERROR,
4102 "%d: %llu, %llu, %llu, %llu, %d, %d",
4103 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
4104 hdd_ctx->hdd_txrx_hist[i].interval_rx,
4105 hdd_ctx->hdd_txrx_hist[i].total_tx,
4106 hdd_ctx->hdd_txrx_hist[i].interval_tx,
4107 hdd_ctx->hdd_txrx_hist[i].next_vote_level,
4108 hdd_ctx->hdd_txrx_hist[i].next_rx_level);
4109 }
4110 return;
4111}
4112
4113/**
4114 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
4115 * @hdd_ctx: hdd context
4116 *
4117 * Return: none
4118 */
4119void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
4120{
4121 hdd_ctx->hdd_txrx_hist_idx = 0;
4122 cdf_mem_zero(hdd_ctx->hdd_txrx_hist, sizeof(hdd_ctx->hdd_txrx_hist));
4123}
4124
4125/**
4126 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
4127 * @pHddCtx: hdd context
4128 *
4129 * Return: none
4130 */
4131void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
4132{
4133
4134 hdd_adapter_t *adapter = NULL;
4135 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4136 CDF_STATUS status;
4137 int i;
4138
4139 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4140 while (NULL != adapter_node && CDF_STATUS_SUCCESS == status) {
4141 adapter = adapter_node->pAdapter;
4142
4143 hddLog(CDF_TRACE_LEVEL_ERROR,
4144 "Session_id %d device mode %d current index %d",
4145 adapter->sessionId, adapter->device_mode,
4146 adapter->history_index);
4147
4148 hddLog(CDF_TRACE_LEVEL_ERROR,
4149 "Netif queue operation statistics:");
4150 hddLog(CDF_TRACE_LEVEL_ERROR,
4151 "Current pause_map value %x", adapter->pause_map);
4152 hddLog(CDF_TRACE_LEVEL_ERROR,
4153 " reason_type: pause_cnt: unpause_cnt");
4154
4155 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
4156 hddLog(CDF_TRACE_LEVEL_ERROR,
4157 "%s: %d: %d",
4158 hdd_reason_type_to_string(i),
4159 adapter->queue_oper_stats[i].pause_count,
4160 adapter->queue_oper_stats[i].unpause_count);
4161 }
4162
4163 hddLog(CDF_TRACE_LEVEL_ERROR,
4164 "Netif queue operation history:");
4165 hddLog(CDF_TRACE_LEVEL_ERROR,
4166 "index: time: action_type: reason_type: pause_map");
4167
4168 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
4169 hddLog(CDF_TRACE_LEVEL_ERROR,
4170 "%d: %u: %s: %s: %x",
4171 i, cdf_system_ticks_to_msecs(
4172 adapter->queue_oper_history[i].time),
4173 hdd_action_type_to_string(
4174 adapter->queue_oper_history[i].netif_action),
4175 hdd_reason_type_to_string(
4176 adapter->queue_oper_history[i].netif_reason),
4177 adapter->queue_oper_history[i].pause_map);
4178 }
4179
4180 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4181 adapter_node = next;
4182 }
4183
4184
4185}
4186
4187/**
4188 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
4189 * @hdd_ctx: hdd context
4190 *
4191 * Return: none
4192 */
4193void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
4194{
4195 hdd_adapter_t *adapter = NULL;
4196 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4197 CDF_STATUS status;
4198
4199 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
4200 while (NULL != adapter_node && CDF_STATUS_SUCCESS == status) {
4201 adapter = adapter_node->pAdapter;
4202
4203 cdf_mem_zero(adapter->queue_oper_stats,
4204 sizeof(adapter->queue_oper_stats));
4205 cdf_mem_zero(adapter->queue_oper_history,
4206 sizeof(adapter->queue_oper_history));
4207
4208 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4209 adapter_node = next;
4210 }
4211}
4212
4213/**
4214 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
4215 * @halHandle: Hal handle
4216 * @pContext: Pointer to the context
4217 * @sessionId: Session ID
4218 * @scanId: Scan ID
4219 * @status: Status
4220 *
4221 * This is the callback to be executed when 11d scan is completed to flush out
4222 * the scan results
4223 *
4224 * 11d scan is done during driver load and is a passive scan on all
4225 * channels supported by the device, 11d scans may find some APs on
4226 * frequencies which are forbidden to be used in the regulatory domain
4227 * the device is operating in. If these APs are notified to the supplicant
4228 * it may try to connect to these APs, thus flush out all the scan results
4229 * which are present in SME after 11d scan is done.
4230 *
4231 * Return: CDF_STATUS_SUCCESS
4232 */
4233static CDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
4234 uint8_t sessionId, uint32_t scanId,
4235 eCsrScanStatus status)
4236{
4237 ENTER();
4238
4239 sme_scan_flush_result(halHandle);
4240
4241 EXIT();
4242
4243 return CDF_STATUS_SUCCESS;
4244}
4245
4246#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4247/**
4248 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
4249 * @hdd_ctx: hdd global context
4250 *
4251 * Return: none
4252 */
4253static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4254{
4255 uint8_t i;
4256
4257 mutex_init(&hdd_ctx->op_ctx.op_lock);
4258 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4259 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4260 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
4261 }
4262}
4263#else
4264static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4265{
4266}
4267#endif
4268
4269#ifdef WLAN_FEATURE_FASTPATH
4270/**
4271 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
4272 * @hdd_cfg: hdd config
4273 * @context: lower layer context
4274 *
4275 * Return: none
4276 */
4277static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4278 void *context)
4279{
4280 if (hdd_cfg->fastpath_enable)
4281 hif_enable_fastpath(context);
4282}
4283#else
4284static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4285 void *context)
4286{
4287}
4288#endif
4289
4290#if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS)
4291/**
4292 * hdd_set_thermal_level_cb() - set thermal level callback function
4293 * @hdd_ctxt: hdd context pointer
4294 * @level: thermal level
4295 *
4296 * Change IPA data path to SW path when the thermal throttle level greater
4297 * than 0, and restore the original data path when throttle level is 0
4298 *
4299 * Return: none
4300 */
4301static void hdd_set_thermal_level_cb(hdd_context_t *hdd_ctx, u_int8_t level)
4302{
4303 /* Change IPA to SW path when throttle level greater than 0 */
4304 if (level > THROTTLE_LEVEL_0)
4305 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
4306 else
4307 /* restore original concurrency mode */
4308 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
4309}
4310
4311/**
4312 * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel
4313 * @hdd_ctxt: hdd context pointer
4314 * @ap_adapter: hdd hostapd adapter pointer
4315 *
4316 * Try to find safe channel within preferred channel
4317 * In case auto channel selection enabled
4318 * - Preferred and safe channel should be used
4319 * - If no overlapping, preferred channel should be used
4320 *
4321 * Return: 1: found preferred safe channel
4322 * 0: could not found preferred safe channel
4323 */
4324static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt,
4325 hdd_adapter_t *ap_adapter)
4326{
4327 uint16_t safe_channels[NUM_20MHZ_RF_CHANNELS];
4328 uint16_t safe_channel_count;
4329 uint16_t unsafe_channel_count;
4330 uint8_t is_unsafe = 1;
4331 uint16_t i;
4332 uint16_t channel_loop;
4333
4334 if (!hdd_ctxt || !ap_adapter) {
4335 hdd_err("invalid context/adapter");
4336 return 0;
4337 }
4338
4339 safe_channel_count = 0;
4340 unsafe_channel_count = CDF_MIN((uint16_t)hdd_ctxt->unsafe_channel_count,
4341 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4342
4343 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
4344 is_unsafe = 0;
4345 for (channel_loop = 0;
4346 channel_loop < unsafe_channel_count; channel_loop++) {
4347 if (rf_channels[i].channelNum ==
4348 hdd_ctxt->unsafe_channel_list[channel_loop]) {
4349 is_unsafe = 1;
4350 break;
4351 }
4352 }
4353 if (!is_unsafe) {
4354 safe_channels[safe_channel_count] =
4355 rf_channels[i].channelNum;
4356 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
4357 FL("safe channel %d"),
4358 safe_channels[safe_channel_count]);
4359 safe_channel_count++;
4360 }
4361 }
4362 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
4363 FL("perferred range %d - %d"),
4364 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
4365 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
4366 for (i = 0; i < safe_channel_count; i++) {
4367 if (safe_channels[i] >=
4368 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch
4369 && safe_channels[i] <=
4370 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch) {
4371 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
4372 FL("safe channel %d is in perferred range"),
4373 safe_channels[i]);
4374 return 1;
4375 }
4376 }
4377 return 0;
4378}
4379
4380/**
4381 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
4382 * @adapter: HDD adapter pointer
4383 * @indParam: Channel avoid notification parameter
4384 *
4385 * Avoid channel notification from FW handler.
4386 * FW will send un-safe channel list to avoid over wrapping.
4387 * hostapd should not use notified channel
4388 *
4389 * Return: None
4390 */
4391static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
4392{
4393 hdd_adapter_t *hostapd_adapter = NULL;
4394 hdd_context_t *hdd_ctxt;
4395 tSirChAvoidIndType *ch_avoid_indi;
4396 uint8_t range_loop;
4397 eRfChannels channel_loop, start_channel_idx = INVALID_RF_CHANNEL,
4398 end_channel_idx = INVALID_RF_CHANNEL;
4399 uint16_t start_channel;
4400 uint16_t end_channel;
4401 v_CONTEXT_t cds_context;
4402 static int restart_sap_in_progress;
4403 tHddAvoidFreqList hdd_avoid_freq_list;
4404 uint32_t i;
4405
4406 /* Basic sanity */
4407 if (!hdd_context || !indi_param) {
4408 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Invalid arguments"));
4409 return;
4410 }
4411
4412 hdd_ctxt = (hdd_context_t *) hdd_context;
4413 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
4414 cds_context = hdd_ctxt->pcds_context;
4415
4416 /* Make unsafe channel list */
4417 hddLog(CDF_TRACE_LEVEL_INFO,
4418 FL("band count %d"),
4419 ch_avoid_indi->avoid_range_count);
4420
4421 /* generate vendor specific event */
4422 cdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
4423 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
4424 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
4425 ch_avoid_indi->avoid_freq_range[i].start_freq;
4426 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
4427 ch_avoid_indi->avoid_freq_range[i].end_freq;
4428 }
4429 hdd_avoid_freq_list.avoidFreqRangeCount =
4430 ch_avoid_indi->avoid_range_count;
4431
4432 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
4433
4434 /* clear existing unsafe channel cache */
4435 hdd_ctxt->unsafe_channel_count = 0;
4436 cdf_mem_zero(hdd_ctxt->unsafe_channel_list,
4437 sizeof(hdd_ctxt->unsafe_channel_list));
4438
4439 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
4440 range_loop++) {
4441 if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) {
4442 hddLog(LOGW, FL("LTE Coex unsafe channel list full"));
4443 break;
4444 }
4445
4446 start_channel = ieee80211_frequency_to_channel(
4447 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
4448 end_channel = ieee80211_frequency_to_channel(
4449 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
4450 hddLog(LOG1, "%s : start %d : %d, end %d : %d", __func__,
4451 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
4452 start_channel,
4453 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
4454 end_channel);
4455
4456 /* do not process frequency bands that are not mapped to
4457 * predefined channels
4458 */
4459 if (start_channel == 0 || end_channel == 0)
4460 continue;
4461
4462 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4463 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
4464 if (rf_channels[channel_loop].targetFreq >=
4465 ch_avoid_indi->avoid_freq_range[
4466 range_loop].start_freq) {
4467 start_channel_idx = channel_loop;
4468 break;
4469 }
4470 }
4471 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4472 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
4473 if (rf_channels[channel_loop].targetFreq >=
4474 ch_avoid_indi->avoid_freq_range[
4475 range_loop].end_freq) {
4476 end_channel_idx = channel_loop;
4477 if (rf_channels[channel_loop].targetFreq >
4478 ch_avoid_indi->avoid_freq_range[
4479 range_loop].end_freq)
4480 end_channel_idx--;
4481 break;
4482 }
4483 }
4484
4485 if (start_channel_idx == INVALID_RF_CHANNEL ||
4486 end_channel_idx == INVALID_RF_CHANNEL)
4487 continue;
4488
4489 for (channel_loop = start_channel_idx; channel_loop <=
4490 end_channel_idx; channel_loop++) {
4491 hdd_ctxt->unsafe_channel_list[
4492 hdd_ctxt->unsafe_channel_count++] =
4493 rf_channels[channel_loop].channelNum;
4494 if (hdd_ctxt->unsafe_channel_count >=
4495 NUM_20MHZ_RF_CHANNELS) {
4496 hddLog(LOGW, FL("LTECoex unsafe ch list full"));
4497 break;
4498 }
4499 }
4500 }
4501
4502 hddLog(CDF_TRACE_LEVEL_INFO,
4503 FL("number of unsafe channels is %d "),
4504 hdd_ctxt->unsafe_channel_count);
4505
4506 if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list,
4507 hdd_ctxt->unsafe_channel_count)) {
4508 hdd_err("Failed to set unsafe channel");
4509
4510 /* clear existing unsafe channel cache */
4511 hdd_ctxt->unsafe_channel_count = 0;
4512 cdf_mem_zero(hdd_ctxt->unsafe_channel_list,
4513 sizeof(hdd_ctxt->unsafe_channel_list));
4514
4515 return;
4516 }
4517
4518 for (channel_loop = 0;
4519 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
4520 hddLog(CDF_TRACE_LEVEL_INFO,
4521 FL("channel %d is not safe "),
4522 hdd_ctxt->unsafe_channel_list[channel_loop]);
4523 }
4524
4525 /*
4526 * If auto channel select is enabled
4527 * preferred channel is in safe channel,
4528 * re-start softap interface with safe channel.
4529 * no overlap with preferred channel and safe channel
4530 * do not re-start softap interface
4531 * stay current operating channel.
4532 */
4533 if (hdd_ctxt->unsafe_channel_count) {
4534 hostapd_adapter = hdd_get_adapter(hdd_ctxt, WLAN_HDD_SOFTAP);
4535 if (hostapd_adapter) {
4536 if ((hostapd_adapter->sessionCtx.ap.sapConfig.
4537 acs_cfg.acs_mode) &&
4538 (!hdd_find_prefd_safe_chnl(hdd_ctxt,
4539 hostapd_adapter)))
4540 return;
4541
4542 hddLog(CDF_TRACE_LEVEL_INFO,
4543 FL(
4544 "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d"
4545 ),
4546 hostapd_adapter->sessionCtx.ap.
4547 operatingChannel,
4548 hostapd_adapter->sessionCtx.ap.sapConfig.
4549 channel);
4550 for (channel_loop = 0;
4551 channel_loop < hdd_ctxt->unsafe_channel_count;
4552 channel_loop++) {
4553 if (((hdd_ctxt->
4554 unsafe_channel_list[channel_loop] ==
4555 hostapd_adapter->sessionCtx.ap.
4556 operatingChannel)) &&
4557 (hostapd_adapter->sessionCtx.ap.
4558 sapConfig.acs_cfg.acs_mode
4559 == true) &&
4560 !restart_sap_in_progress) {
4561 hddLog(CDF_TRACE_LEVEL_INFO,
4562 FL("Restarting SAP"));
4563 wlan_hdd_send_svc_nlink_msg
4564 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
4565 restart_sap_in_progress = 1;
4566 /*
4567 * current operating channel is un-safe
4568 * channel, restart driver
4569 */
4570 hdd_hostapd_stop(hostapd_adapter->dev);
4571 break;
4572 }
4573 }
4574 }
4575 }
4576 return;
4577}
4578
4579/**
4580 * hdd_init_channel_avoidance() - Initialize channel avoidance
4581 * @hdd_ctx: HDD global context
4582 *
4583 * Initialize the channel avoidance logic by retrieving the unsafe
4584 * channel list from the CNSS platform driver and plumbing the data
4585 * down to the lower layers. Then subscribe to subsequent channel
4586 * avoidance events.
4587 *
4588 * Return: None
4589 */
4590static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4591{
4592 uint16_t unsafe_channel_count;
4593 int index;
4594
4595 cnss_get_wlan_unsafe_channel(hdd_ctx->unsafe_channel_list,
4596 &(hdd_ctx->unsafe_channel_count),
4597 sizeof(uint16_t) * NUM_20MHZ_RF_CHANNELS);
4598
4599 hddLog(CDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"),
4600 hdd_ctx->unsafe_channel_count);
4601
4602 unsafe_channel_count = CDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
4603 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4604
4605 for (index = 0; index < unsafe_channel_count; index++) {
4606 hddLog(CDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"),
4607 hdd_ctx->unsafe_channel_list[index]);
4608
4609 }
4610
4611 /* Plug in avoid channel notification callback */
4612 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
4613}
4614#else
4615static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4616{
4617}
4618static void hdd_set_thermal_level_cb(hdd_context_t *hdd_ctx, u_int8_t level)
4619{
4620}
4621#endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */
4622
4623/**
4624 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
4625 * @hdd_ctx: HDD context
4626 *
4627 * Disables all the dual mac features like DBS, Agile DFS etc.
4628 *
4629 * Return: CDF_STATUS_SUCCESS on success
4630 */
4631static CDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
4632{
4633 struct sir_dual_mac_config cfg;
4634 CDF_STATUS status;
4635
4636 if (!hdd_ctx) {
4637 hdd_err("HDD context is NULL");
4638 return CDF_STATUS_E_FAILURE;
4639 }
4640
4641 cfg.scan_config = 0;
4642 cfg.fw_mode_config = 0;
4643 cfg.set_dual_mac_cb =
4644 (void *)cds_soc_set_dual_mac_cfg_cb;
4645
4646 hdd_debug("Disabling all dual mac features...");
4647
4648 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
4649 if (status != CDF_STATUS_SUCCESS) {
4650 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
4651 return status;
4652 }
4653
4654 return CDF_STATUS_SUCCESS;
4655}
4656
4657/**
4658 * hdd_wlan_startup() - HDD init function
4659 * @dev: Pointer to the underlying device
4660 *
4661 * This is the driver startup code executed once a WLAN device has been detected
4662 *
4663 * Return: 0 for success, < 0 for failure
4664 */
4665int hdd_wlan_startup(struct device *dev, void *hif_sc)
4666{
4667 CDF_STATUS status;
4668 hdd_adapter_t *adapter = NULL;
4669#ifdef WLAN_OPEN_P2P_INTERFACE
4670 hdd_adapter_t *pP2adapter = NULL;
4671#endif
4672 hdd_context_t *hdd_ctx = NULL;
4673 v_CONTEXT_t p_cds_context = NULL;
4674 int ret;
4675 int i;
4676 struct wiphy *wiphy;
4677 unsigned long rc;
4678 tSmeThermalParams thermalParam;
4679 tSirTxPowerLimit *hddtxlimit;
4680 uint8_t rtnl_lock_enable;
4681 uint8_t reg_netdev_notifier_done = false;
4682 hdd_adapter_t *dot11_adapter = NULL;
4683
4684 ENTER();
4685
4686 if (WLAN_IS_EPPING_ENABLED(con_mode)) {
4687 ret = epping_enable(dev);
4688 EXIT();
4689 return ret;
4690 }
4691
4692 /* cfg80211: wiphy allocation */
4693 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
4694
4695 if (wiphy == NULL) {
4696 hddLog(CDF_TRACE_LEVEL_ERROR, FL("cfg80211 init failed"));
4697 return -EIO;
4698 }
4699
4700 hdd_ctx = wiphy_priv(wiphy);
4701
4702 /* Initialize the adapter context to zeros. */
4703 cdf_mem_zero(hdd_ctx, sizeof(hdd_context_t));
4704
4705 hdd_ctx->wiphy = wiphy;
4706 hdd_ctx->isLoadInProgress = true;
4707 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
4708 cds_set_wakelock_logging(false);
4709
4710 cds_set_load_unload_in_progress(true);
4711
4712 /* Get cds context here bcoz cds_open requires it */
4713 p_cds_context = cds_get_global_context();
4714
4715 if (p_cds_context == NULL) {
4716 hddLog(CDF_TRACE_LEVEL_FATAL,
4717 FL("Failed cds_get_global_context"));
4718 goto err_free_hdd_context;
4719 }
4720 /* Save the Global CDS context in adapter context for future. */
4721 hdd_ctx->pcds_context = p_cds_context;
4722
4723 /* Save the adapter context in global context for future. */
4724 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
4725
4726 hdd_ctx->parent_dev = dev;
4727
4728 hdd_init_ll_stats_ctx();
4729
4730 init_completion(&hdd_ctx->mc_sus_event_var);
4731 init_completion(&hdd_ctx->ready_to_suspend);
4732
4733 spin_lock_init(&hdd_ctx->schedScan_lock);
4734
4735 cdf_spinlock_init(&hdd_ctx->hdd_adapter_lock);
4736 cdf_list_init(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
4737
4738 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
4739
4740#ifdef FEATURE_WLAN_TDLS
4741 /*
4742 * tdls_lock is initialized before an hdd_open_adapter ( which is
4743 * invoked by other instances also) to protect the concurrent
4744 * access for the Adapters by TDLS module.
4745 */
4746 mutex_init(&hdd_ctx->tdls_lock);
4747#endif
4748
4749 /* store target type and target version info in hdd ctx */
4750 hdd_ctx->target_type = ((struct ol_softc *)hif_sc)->target_type;
4751 hdd_init_offloaded_packets_ctx(hdd_ctx);
4752 /* Load all config first as TL config is needed during cds_open */
4753 hdd_ctx->config =
4754 (struct hdd_config *) kmalloc(sizeof(struct hdd_config), GFP_KERNEL);
4755 if (hdd_ctx->config == NULL) {
4756 hddLog(CDF_TRACE_LEVEL_FATAL,
4757 FL("Failed kmalloc struct hdd_config"));
4758 goto err_config;
4759 }
4760
4761 cdf_mem_zero(hdd_ctx->config, sizeof(struct hdd_config));
4762
4763 /* Read and parse the qcom_cfg.ini file */
4764 status = hdd_parse_config_ini(hdd_ctx);
4765 if (CDF_STATUS_SUCCESS != status) {
4766 hddLog(CDF_TRACE_LEVEL_FATAL, FL("error parsing %s"),
4767 WLAN_INI_FILE);
4768 goto err_config;
4769 }
4770
4771 hdd_ctx->current_intf_count = 0;
4772 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
4773
4774 /*
4775 * INI has been read, initialise the configuredMcastBcastFilter with
4776 * INI value as this will serve as the default value
4777 */
4778 hdd_ctx->configuredMcastBcastFilter =
4779 hdd_ctx->config->mcastBcastFilterSetting;
4780 hddLog(CDF_TRACE_LEVEL_INFO,
4781 FL("Setting configuredMcastBcastFilter: %d"),
4782 hdd_ctx->config->mcastBcastFilterSetting);
4783
4784 if (false == hdd_is_5g_supported(hdd_ctx)) {
4785 /* 5Ghz is not supported. */
4786 if (1 != hdd_ctx->config->nBandCapability) {
4787 hddLog(CDF_TRACE_LEVEL_INFO,
4788 FL(
4789 "Setting hdd_ctx->config->nBandCapability = 1"
4790 ));
4791 hdd_ctx->config->nBandCapability = 1;
4792 }
4793 }
4794
4795 /*
4796 * cfg80211: Initialization ...
4797 */
4798 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, hdd_ctx->config)) {
4799 hddLog(LOGE,
4800 FL("wlan_hdd_cfg80211_init return failure"));
4801 goto err_config;
4802 }
4803
4804 hdd_enable_fastpath(hdd_ctx->config, hif_sc);
4805 /*
4806 * Initialize struct for saving f/w log setting will be used
4807 * after ssr
4808 */
4809 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enablefwlog;
4810 hdd_ctx->fw_log_settings.dl_type = 0;
4811 hdd_ctx->fw_log_settings.dl_report = 0;
4812 hdd_ctx->fw_log_settings.dl_loglevel = 0;
4813 hdd_ctx->fw_log_settings.index = 0;
4814 for (i = 0; i < MAX_MOD_LOGLEVEL; i++) {
4815 hdd_ctx->fw_log_settings.dl_mod_loglevel[i] = 0;
4816 }
4817 /* Update CDF trace levels based upon the cfg.ini */
4818 hdd_cdf_trace_enable(CDF_MODULE_ID_WMI,
4819 hdd_ctx->config->cdf_trace_enable_wdi);
4820 hdd_cdf_trace_enable(CDF_MODULE_ID_HDD,
4821 hdd_ctx->config->cdf_trace_enable_hdd);
4822 hdd_cdf_trace_enable(CDF_MODULE_ID_SME,
4823 hdd_ctx->config->cdf_trace_enable_sme);
4824 hdd_cdf_trace_enable(CDF_MODULE_ID_PE,
4825 hdd_ctx->config->cdf_trace_enable_pe);
4826 hdd_cdf_trace_enable(CDF_MODULE_ID_WMA,
4827 hdd_ctx->config->cdf_trace_enable_wma);
4828 hdd_cdf_trace_enable(CDF_MODULE_ID_SYS,
4829 hdd_ctx->config->cdf_trace_enable_sys);
4830 hdd_cdf_trace_enable(CDF_MODULE_ID_CDF,
4831 hdd_ctx->config->cdf_trace_enable_cdf);
4832 hdd_cdf_trace_enable(CDF_MODULE_ID_SAP,
4833 hdd_ctx->config->cdf_trace_enable_sap);
4834 hdd_cdf_trace_enable(CDF_MODULE_ID_HDD_SOFTAP,
4835 hdd_ctx->config->cdf_trace_enable_hdd_sap);
4836 hdd_cdf_trace_enable(CDF_MODULE_ID_BMI,
4837 hdd_ctx->config->cdf_trace_enable_bmi);
4838 hdd_cfg_print(hdd_ctx);
4839
4840 if (CDF_FTM_MODE == hdd_get_conparam())
4841 goto ftm_processing;
4842
4843 hdd_ctx->isLogpInProgress = false;
4844 cds_set_logp_in_progress(false);
4845
4846 cds_set_connection_in_progress(hdd_ctx, false);
4847
4848 status = cds_open(&p_cds_context, 0);
4849 if (!CDF_IS_STATUS_SUCCESS(status)) {
4850 hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_open failed"));
4851 goto err_cds_open;
4852 }
4853
4854 wlan_hdd_update_wiphy(wiphy, hdd_ctx->config);
4855
4856 hdd_ctx->hHal = cds_get_context(CDF_MODULE_ID_SME);
4857
4858 if (NULL == hdd_ctx->hHal) {
4859 hddLog(CDF_TRACE_LEVEL_FATAL, FL("HAL context is null"));
4860 goto err_cds_close;
4861 }
4862
4863 status = cds_pre_enable(hdd_ctx->pcds_context);
4864 if (!CDF_IS_STATUS_SUCCESS(status)) {
4865 hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed"));
4866 goto err_cds_close;
4867 }
4868
4869 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
4870
4871 status = wlan_hdd_regulatory_init(hdd_ctx);
4872
4873 if (status != CDF_STATUS_SUCCESS) {
4874 hddLog(CDF_TRACE_LEVEL_FATAL,
4875 FL("Failed to init channel list"));
4876 goto err_cds_close;
4877 }
4878
4879 /*
4880 * Set 802.11p config
4881 * TODO-OCB: This has been temporarily added here to ensure this
4882 * parameter is set in CSR when we init the channel list. This should
4883 * be removed once the 5.9 GHz channels are added to the regulatory
4884 * domain.
4885 */
4886 hdd_set_dot11p_config(hdd_ctx);
4887
4888 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
4889 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
4890 hddLog(CDF_TRACE_LEVEL_INFO,
4891 FL("module enable_dfs_chan_scan set to %d"),
4892 enable_dfs_chan_scan);
4893 }
4894 if (0 == enable_11d || 1 == enable_11d) {
4895 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
4896 hddLog(CDF_TRACE_LEVEL_INFO, FL("module enable_11d set to %d"),
4897 enable_11d);
4898 }
4899
4900 /*
4901 * Note that the cds_pre_enable() sequence triggers the cfg download.
4902 * The cfg download must occur before we update the SME config
4903 * since the SME config operation must access the cfg database
4904 */
4905 status = hdd_set_sme_config(hdd_ctx);
4906
4907 if (CDF_STATUS_SUCCESS != status) {
4908 hddLog(CDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config"));
4909 goto err_wiphy_unregister;
4910 }
4911
4912 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
4913 hdd_ctx->config->tx_chain_mask_1ss,
4914 PDEV_CMD);
4915 if (0 != ret) {
4916 hddLog(CDF_TRACE_LEVEL_ERROR,
4917 "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d",
4918 __func__, ret);
4919 }
4920
4921 status = hdd_set_sme_chan_list(hdd_ctx);
4922 if (status != CDF_STATUS_SUCCESS) {
4923 hddLog(CDF_TRACE_LEVEL_FATAL,
4924 FL("Failed to init channel list"));
4925 goto err_wiphy_unregister;
4926 }
4927
4928 /* Apply the cfg.ini to cfg.dat */
4929 if (false == hdd_update_config_dat(hdd_ctx)) {
4930 hddLog(CDF_TRACE_LEVEL_FATAL,
4931 FL("config update failed"));
4932 goto err_wiphy_unregister;
4933 }
4934
4935 if (CDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) {
4936 hddLog(CDF_TRACE_LEVEL_WARN,
4937 FL("can't update mac config, using MAC from ini file"));
4938 }
4939
4940 {
4941 CDF_STATUS cdf_ret_status;
4942 /*
4943 * Set the MAC Address Currently this is used by HAL to
4944 * add self sta. Remove this once self sta is added as
4945 * part of session open.
4946 */
4947 cdf_ret_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
4948 (uint8_t *) &hdd_ctx->config->
4949 intfMacAddr[0],
4950 sizeof(hdd_ctx->config->
4951 intfMacAddr[0]));
4952
4953 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
4954 hddLog(CDF_TRACE_LEVEL_ERROR,
4955 FL(
4956 "Failed to set MAC Address. HALStatus is %08d [x%08x]"
4957 ),
4958 cdf_ret_status, cdf_ret_status);
4959 goto err_wiphy_unregister;
4960 }
4961 }
4962
4963 if (hdd_ipa_init(hdd_ctx) == CDF_STATUS_E_FAILURE)
4964 goto err_wiphy_unregister;
4965
4966 /*
4967 * Start CDS which starts up the SME/MAC/HAL modules and everything
4968 * else
4969 */
4970 status = cds_enable(hdd_ctx->pcds_context);
4971 if (!CDF_IS_STATUS_SUCCESS(status)) {
4972 hddLog(CDF_TRACE_LEVEL_FATAL, FL("cds_enable failed"));
4973 goto err_wiphy_unregister;
4974 }
4975
4976 hdd_init_channel_avoidance(hdd_ctx);
4977
4978 status = hdd_post_cds_enable_config(hdd_ctx);
4979 if (!CDF_IS_STATUS_SUCCESS(status)) {
4980 hddLog(CDF_TRACE_LEVEL_FATAL,
4981 FL("hdd_post_cds_enable_config failed"));
4982 goto err_cds_disable;
4983 }
4984#ifdef QCA_PKT_PROTO_TRACE
4985 cds_pkt_proto_trace_init();
4986#endif /* QCA_PKT_PROTO_TRACE */
4987
4988ftm_processing:
4989 if (CDF_FTM_MODE == hdd_get_conparam()) {
4990 if (CDF_STATUS_SUCCESS != wlan_hdd_ftm_open(hdd_ctx)) {
4991 hddLog(CDF_TRACE_LEVEL_FATAL,
4992 FL("wlan_hdd_ftm_open Failed"));
4993 goto err_config;
4994 }
4995#if defined(QCA_WIFI_FTM)
4996 if (hdd_ftm_start(hdd_ctx)) {
4997 hddLog(CDF_TRACE_LEVEL_FATAL,
4998 FL("hdd_ftm_start Failed"));
4999 goto err_free_ftm_open;
5000 }
5001#endif
5002 /* registration of wiphy dev with cfg80211 */
5003 if (0 > wlan_hdd_cfg80211_register(wiphy)) {
5004 hddLog(LOGE, FL("wiphy register failed"));
5005 goto err_free_ftm_open;
5006 }
5007
5008 cds_set_load_unload_in_progress(false);
5009 hdd_ctx->isLoadInProgress = false;
5010 hddLog(LOGE, FL("FTM driver loaded"));
5011 complete(&wlan_start_comp);
5012 return CDF_STATUS_SUCCESS;
5013 }
5014#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5015 rtnl_lock();
5016 rtnl_lock_enable = true;
5017#else
5018 rtnl_lock_enable = false;
5019#endif
5020
5021 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE)
5022 /* Create only 802.11p interface */
5023 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d",
5024 wlan_hdd_get_intf_addr(hdd_ctx),
5025 rtnl_lock_enable);
5026 else
5027 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION,
5028 "wlan%d",
5029 wlan_hdd_get_intf_addr(hdd_ctx),
5030 rtnl_lock_enable);
5031
5032#ifdef WLAN_OPEN_P2P_INTERFACE
5033 /* Open P2P device interface */
5034 if (adapter != NULL) {
5035 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
5036 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
5037 cdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
5038 hdd_ctx->config->intfMacAddr[0].bytes,
5039 sizeof(tSirMacAddr));
5040
5041 /*
5042 * Generate the P2P Device Address. This consists of
5043 * the device's primary MAC address with the locally
5044 * administered bit set.
5045 */
5046 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
5047 } else {
5048 uint8_t *p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
5049 if (p2p_dev_addr != NULL) {
5050 cdf_mem_copy(&hdd_ctx->p2pDeviceAddress.
5051 bytes[0], p2p_dev_addr,
5052 CDF_MAC_ADDR_SIZE);
5053 } else {
5054 hddLog(CDF_TRACE_LEVEL_FATAL,
5055 FL(
5056 "Failed to allocate mac_address for p2p_device"
5057 ));
5058 goto err_close_adapter;
5059 }
5060 }
5061
5062 pP2adapter =
5063 hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5064 &hdd_ctx->p2pDeviceAddress.bytes[0],
5065 rtnl_lock_enable);
5066
5067 if (NULL == pP2adapter) {
5068 hddLog(CDF_TRACE_LEVEL_FATAL,
5069 FL(
5070 "Failed to do hdd_open_adapter for P2P Device Interface"
5071 ));
5072 goto err_close_adapter;
5073 }
5074 }
5075#endif
5076
5077 if (adapter == NULL) {
5078 hddLog(CDF_TRACE_LEVEL_ERROR, FL("hdd_open_adapter failed"));
5079 goto err_close_adapter;
5080 }
5081
5082 /* Open 802.11p Interface */
5083 if (adapter != NULL) {
5084 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
5085 dot11_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB,
5086 "wlanocb%d",
5087 wlan_hdd_get_intf_addr(hdd_ctx),
5088 rtnl_lock_enable);
5089 if (dot11_adapter == NULL) {
5090 hddLog(LOGE,
5091 FL("failed to open 802.11p Interface"));
5092 goto err_close_adapter;
5093 }
5094 }
5095 }
5096
5097 /*
5098 * target hw version/revision would only be retrieved after firmware
5099 * donwload
5100 */
5101 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
5102 &hdd_ctx->target_hw_revision,
5103 &hdd_ctx->target_hw_name);
5104
5105 /* Get the wlan hw/fw version */
5106 hdd_wlan_get_version(adapter, NULL, NULL);
5107
5108 /* pass target_fw_version to HIF layer */
5109 hif_set_fw_info(hif_sc, hdd_ctx->target_fw_version);
5110
5111 if (country_code) {
5112 CDF_STATUS ret;
5113
5114 INIT_COMPLETION(adapter->change_country_code);
5115
5116 ret = sme_change_country_code(hdd_ctx->hHal,
5117 wlan_hdd_change_country_code_callback,
5118 country_code, adapter,
5119 hdd_ctx->pcds_context, eSIR_TRUE,
5120 eSIR_TRUE);
5121 if (CDF_STATUS_SUCCESS == ret) {
5122 rc = wait_for_completion_timeout(
5123 &adapter->change_country_code,
5124 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
5125 if (!rc) {
5126 hddLog(LOGE,
5127 FL("SME while setting country code timed out"));
5128 }
5129 } else {
5130 hddLog(CDF_TRACE_LEVEL_ERROR,
5131 FL(
5132 "SME Change Country code from module param fail ret=%d"
5133 ),
5134 ret);
5135 ret = -EINVAL;
5136 }
5137 }
5138
5139 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
5140
5141#ifdef FEATURE_OEM_DATA_SUPPORT
5142 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
5143 hdd_send_oem_data_rsp_msg);
5144#endif
5145
5146 /* Open debugfs interface */
5147 if (CDF_STATUS_SUCCESS != hdd_debugfs_init(adapter)) {
5148 hddLog(CDF_TRACE_LEVEL_ERROR,
5149 FL("hdd_debugfs_init failed!"));
5150 }
5151
5152 /* FW capabilities received, Set the Dot11 mode */
5153 sme_setdef_dot11mode(hdd_ctx->hHal);
5154#if !defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5155 /* register net device notifier for device change notification */
5156 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5157
5158 if (ret < 0) {
5159 hddLog(CDF_TRACE_LEVEL_ERROR,
5160 FL("register_netdevice_notifier failed"));
5161 goto err_free_power_on_lock;
5162 }
5163 reg_netdev_notifier_done = true;
5164#endif
5165 /* Initialize the nlink service */
5166 if (nl_srv_init() != 0) {
5167 hddLog(CDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed"));
5168 goto err_reg_netdev;
5169 }
5170#ifdef WLAN_KD_READY_NOTIFIER
5171 hdd_ctx->kd_nl_init = 1;
5172#endif /* WLAN_KD_READY_NOTIFIER */
5173
5174#ifdef FEATURE_OEM_DATA_SUPPORT
5175 /* Initialize the OEM service */
5176 if (oem_activate_service(hdd_ctx) != 0) {
5177 hddLog(CDF_TRACE_LEVEL_FATAL,
5178 FL("oem_activate_service failed"));
5179 goto err_nl_srv;
5180 }
5181#endif
5182
5183#ifdef PTT_SOCK_SVC_ENABLE
5184 /* Initialize the PTT service */
5185 if (ptt_sock_activate_svc() != 0) {
5186 hddLog(CDF_TRACE_LEVEL_FATAL,
5187 FL("ptt_sock_activate_svc failed"));
5188 goto err_nl_srv;
5189 }
5190#endif
5191
5192 /* Initialize the CNSS-DIAG service */
5193 if (cnss_diag_activate_service() < 0) {
5194 hddLog(CDF_TRACE_LEVEL_FATAL,
5195 FL("cnss_diag_activate_service failed"));
5196 goto err_nl_srv;
5197 }
5198#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
5199 if (hdd_ctx->config->wlanLoggingEnable) {
5200 if (wlan_logging_sock_activate_svc
5201 (hdd_ctx->config->wlanLoggingFEToConsole,
5202 hdd_ctx->config->wlanLoggingNumBuf)) {
5203 hddLog(CDF_TRACE_LEVEL_ERROR,
5204 FL("wlan_logging_sock_activate_svc failed"));
5205 goto err_nl_srv;
5206 }
5207 }
5208#endif
5209 if (cds_is_multicast_logging())
5210 wlan_logging_set_log_level();
5211
5212 if (CDF_SAP_MODE != hdd_get_conparam()) {
5213 /*
5214 * Action frame registered in one adapter which will
5215 * applicable to all interfaces
5216 */
5217 wlan_hdd_cfg80211_register_frames(adapter);
5218 }
5219
5220 mutex_init(&hdd_ctx->sap_lock);
5221
5222 hdd_ctx->isLoadInProgress = false;
5223
5224#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5225 if (rtnl_lock_enable == true) {
5226 rtnl_lock_enable = false;
5227 rtnl_unlock();
5228 }
5229 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5230 if (ret < 0) {
5231 hddLog(CDF_TRACE_LEVEL_ERROR,
5232 FL("register_netdevice_notifier failed"));
5233 goto err_nl_srv;
5234 }
5235 reg_netdev_notifier_done = true;
5236#endif
5237#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5238 /* Initialize the wake lcok */
5239 cdf_wake_lock_init(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
5240#endif
5241 /* Initialize the wake lcok */
5242 cdf_wake_lock_init(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock");
5243
5244 hdd_hostapd_channel_wakelock_init(hdd_ctx);
5245
5246 cds_set_load_unload_in_progress(false);
5247
5248 hdd_set_idle_ps_config(hdd_ctx, true);
5249#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5250 if (hdd_ctx->config->WlanAutoShutdown != 0)
5251 if (sme_set_auto_shutdown_cb
5252 (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb)
5253 != CDF_STATUS_SUCCESS)
5254 hddLog(LOGE,
5255 FL(
5256 "Auto shutdown feature could not be enabled"
5257 ));
5258#endif
5259
5260#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
5261 status = cdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
5262 CDF_TIMER_TYPE_SW,
5263 hdd_skip_acs_scan_timer_handler,
5264 (void *)hdd_ctx);
5265 if (!CDF_IS_STATUS_SUCCESS(status))
5266 hddLog(LOGE, FL("Failed to init ACS Skip timer"));
5267#endif
5268
5269 hdd_wlan_green_ap_init(hdd_ctx);
5270 wlan_hdd_nan_init(hdd_ctx);
5271 status = cds_init_policy_mgr(hdd_ctx);
5272 if (!CDF_IS_STATUS_SUCCESS(status)) {
5273 hdd_err("Policy manager initialization failed");
5274 goto err_nl_srv;
5275 }
5276
5277 /* Thermal Mitigation */
5278 thermalParam.smeThermalMgmtEnabled =
5279 hdd_ctx->config->thermalMitigationEnable;
5280 thermalParam.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
5281
5282 thermalParam.smeThermalLevels[0].smeMinTempThreshold =
5283 hdd_ctx->config->thermalTempMinLevel0;
5284 thermalParam.smeThermalLevels[0].smeMaxTempThreshold =
5285 hdd_ctx->config->thermalTempMaxLevel0;
5286 thermalParam.smeThermalLevels[1].smeMinTempThreshold =
5287 hdd_ctx->config->thermalTempMinLevel1;
5288 thermalParam.smeThermalLevels[1].smeMaxTempThreshold =
5289 hdd_ctx->config->thermalTempMaxLevel1;
5290 thermalParam.smeThermalLevels[2].smeMinTempThreshold =
5291 hdd_ctx->config->thermalTempMinLevel2;
5292 thermalParam.smeThermalLevels[2].smeMaxTempThreshold =
5293 hdd_ctx->config->thermalTempMaxLevel2;
5294 thermalParam.smeThermalLevels[3].smeMinTempThreshold =
5295 hdd_ctx->config->thermalTempMinLevel3;
5296 thermalParam.smeThermalLevels[3].smeMaxTempThreshold =
5297 hdd_ctx->config->thermalTempMaxLevel3;
5298
5299 if (0 != hdd_lro_init(hdd_ctx))
5300 hdd_err("Unable to initialize LRO in fw");
5301
5302 if (CDF_STATUS_SUCCESS !=
5303 sme_init_thermal_info(hdd_ctx->hHal, thermalParam)) {
5304 hddLog(CDF_TRACE_LEVEL_ERROR,
5305 FL("Error while initializing thermal information"));
5306 }
5307
5308 /* Plug in set thermal level callback */
5309 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
5310 (sme_set_thermal_level_callback)hdd_set_thermal_level_cb);
5311
5312 /* SAR power limit */
5313 hddtxlimit = cdf_mem_malloc(sizeof(tSirTxPowerLimit));
5314 if (!hddtxlimit) {
5315 hddLog(CDF_TRACE_LEVEL_ERROR,
5316 FL("Memory allocation for TxPowerLimit failed!"));
5317 goto err_nl_srv;
5318 }
5319 hddtxlimit->txPower2g = hdd_ctx->config->TxPower2g;
5320 hddtxlimit->txPower5g = hdd_ctx->config->TxPower5g;
5321
5322 if (CDF_STATUS_SUCCESS != sme_txpower_limit(hdd_ctx->hHal, hddtxlimit))
5323 hddLog(CDF_TRACE_LEVEL_ERROR,
5324 FL("Error setting txlimit in sme"));
5325
5326#ifdef MSM_PLATFORM
5327 spin_lock_init(&hdd_ctx->bus_bw_lock);
5328 cdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
5329 CDF_TIMER_TYPE_SW,
5330 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5331#endif
5332
5333#ifdef WLAN_FEATURE_STATS_EXT
5334 wlan_hdd_cfg80211_stats_ext_init(hdd_ctx);
5335#endif
5336#ifdef FEATURE_WLAN_EXTSCAN
5337 sme_ext_scan_register_callback(hdd_ctx->hHal,
5338 wlan_hdd_cfg80211_extscan_callback);
5339#endif /* FEATURE_WLAN_EXTSCAN */
5340 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
5341 hdd_rssi_threshold_breached);
5342#ifdef WLAN_FEATURE_LINK_LAYER_STATS
5343 wlan_hdd_cfg80211_link_layer_stats_init(hdd_ctx);
5344#endif
5345
5346#ifdef WLAN_FEATURE_LPSS
5347 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
5348 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
5349 hdd_ctx->target_hw_version,
5350 hdd_ctx->target_hw_name);
5351#endif
5352
5353 cdf_spinlock_init(&hdd_ctx->hdd_roc_req_q_lock);
5354 cdf_list_init((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY);
5355 cdf_spinlock_init(&hdd_ctx->hdd_scan_req_q_lock);
5356 cdf_list_init((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX);
5357#ifdef CONFIG_CNSS
5358 cnss_init_delayed_work(&hdd_ctx->roc_req_work,
5359 wlan_hdd_roc_request_dequeue);
5360#else
5361 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5362#endif
5363
5364 /*
5365 * Register IPv6 notifier to notify if any change in IP
5366 * So that we can reconfigure the offload parameters
5367 */
5368 hdd_wlan_register_ip6_notifier(hdd_ctx);
5369
5370 /*
5371 * Register IPv4 notifier to notify if any change in IP
5372 * So that we can reconfigure the offload parameters
5373 */
5374 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5375 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5376 if (ret)
5377 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
5378 else
5379 hddLog(LOGE, FL("Registered IPv4 notifier"));
5380
5381 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
5382
5383 if (hdd_ctx->config->dual_mac_feature_disable) {
5384 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
5385 if (status != CDF_STATUS_SUCCESS) {
5386 hdd_err("Failed to disable dual mac features");
5387 goto err_nl_srv;
5388 }
5389 }
5390
5391 hif_enable_power_gating(hif_sc);
5392
5393 complete(&wlan_start_comp);
5394 goto success;
5395
5396err_nl_srv:
5397#ifdef WLAN_KD_READY_NOTIFIER
5398 cnss_diag_notify_wlan_close();
5399 ptt_sock_deactivate_svc();
5400#endif /* WLAN_KD_READY_NOTIFIER */
5401 nl_srv_exit();
5402
5403 if (!CDF_IS_STATUS_SUCCESS
5404 (cdf_mutex_destroy(&hdd_ctx->hdd_conc_list_lock))) {
5405 hdd_err("Failed to destroy hdd_conc_list_lock");
5406 /* Proceed and complete the clean up */
5407 }
5408err_reg_netdev:
5409 if (rtnl_lock_enable == true) {
5410 rtnl_lock_enable = false;
5411 rtnl_unlock();
5412 }
5413 if (reg_netdev_notifier_done == true) {
5414 unregister_netdevice_notifier(&hdd_netdev_notifier);
5415 reg_netdev_notifier_done = false;
5416 }
5417#if !defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5418err_free_power_on_lock:
5419#endif
5420 hdd_debugfs_exit(hdd_ctx);
5421
5422err_close_adapter:
5423#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5424 if (rtnl_lock_enable == true) {
5425 rtnl_lock_enable = false;
5426 rtnl_unlock();
5427 }
5428#endif
5429 hdd_close_all_adapters(hdd_ctx);
5430
5431err_cds_disable:
5432 cds_disable(p_cds_context);
5433
5434err_wiphy_unregister:
5435 wiphy_unregister(wiphy);
5436
5437err_cds_close:
5438 status = cds_sched_close(p_cds_context);
5439 if (!CDF_IS_STATUS_SUCCESS(status)) {
5440 hddLog(CDF_TRACE_LEVEL_FATAL,
5441 FL("Failed to close CDS Scheduler"));
5442 CDF_ASSERT(CDF_IS_STATUS_SUCCESS(status));
5443 }
5444 cds_close(p_cds_context);
5445
5446err_cds_open:
5447
5448 if (CDF_FTM_MODE == hdd_get_conparam()) {
5449#if defined(QCA_WIFI_FTM)
5450err_free_ftm_open:
5451 wlan_hdd_ftm_close(hdd_ctx);
5452#endif
5453 }
5454
5455err_config:
5456 kfree(hdd_ctx->config);
5457 hdd_ctx->config = NULL;
5458
5459err_free_hdd_context:
5460 /* wiphy_free() will free the HDD context so remove global reference */
5461 if (p_cds_context)
5462 ((cds_context_type *) (p_cds_context))->pHDDContext = NULL;
5463
5464 wiphy_free(wiphy);
5465 /* kfree(wdev) ; */
5466 CDF_BUG(1);
5467
5468 if (hdd_is_ssr_required()) {
5469#ifdef MSM_PLATFORM
5470#ifdef CONFIG_CNSS
5471 /*
5472 * WDI timeout had happened during load, so SSR is needed
5473 * here
5474 */
5475 subsystem_restart("wcnss");
5476#endif
5477#endif
5478 msleep(5000);
5479 }
5480 hdd_set_ssr_required(false);
5481
5482 return -EIO;
5483
5484success:
5485 EXIT();
5486 return 0;
5487}
5488
5489/*
5490 * In BMI Phase we are only sending small chunk (256 bytes) of the FW image at
5491 * a time, and wait for the completion interrupt to start the next transfer.
5492 * During this phase, the KRAIT is entering IDLE/StandAlone(SA) Power Save(PS).
5493 * The delay incurred for resuming from IDLE/SA PS is huge during driver load.
5494 * So prevent APPS IDLE/SA PS durint driver load for reducing interrupt latency.
5495 */
5496
5497#ifdef CONFIG_CNSS
5498static inline void hdd_request_pm_qos(int val)
5499{
5500 cnss_request_pm_qos(val);
5501}
5502
5503static inline void hdd_remove_pm_qos(void)
5504{
5505 cnss_remove_pm_qos();
5506}
5507#else
5508static inline void hdd_request_pm_qos(int val)
5509{
5510}
5511
5512static inline void hdd_remove_pm_qos(void)
5513{
5514}
5515#endif
5516
5517/**
5518 * hdd_driver_init() - Core Driver Init Function
5519 *
5520 * This is the driver entry point - called in different timeline depending
5521 * on whether the driver is statically or dynamically linked
5522 *
5523 * Return: 0 for success, non zero for failure
5524 */
5525static int hdd_driver_init(void)
5526{
5527 CDF_STATUS status;
5528 v_CONTEXT_t p_cds_context = NULL;
5529 int ret_status = 0;
5530 unsigned long rc;
5531
5532#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
5533 wlan_logging_sock_init_svc();
5534#endif
5535
5536 ENTER();
5537
5538 cdf_wake_lock_init(&wlan_wake_lock, "wlan");
5539 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
5540 /*
5541 * The Krait is going to Idle/Stand Alone Power Save
5542 * more aggressively which is resulting in the longer driver load time.
5543 * The Fix is to not allow Krait to enter Idle Power Save during driver
5544 * load.
5545 */
5546 hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL);
5547 cds_ssr_protect_init();
5548
5549 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
5550 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
5551
5552 do {
5553 cdf_mc_timer_manager_init();
5554 cdf_mem_init();
5555 /* Allocate CDS global context */
5556 status = cds_alloc_global_context(&p_cds_context);
5557
5558 if (!CDF_IS_STATUS_SUCCESS(status)) {
5559 hddLog(CDF_TRACE_LEVEL_FATAL,
5560 FL("Failed to preOpen CDS"));
5561 ret_status = -1;
5562 break;
5563 }
5564
5565 hdd_trace_init();
5566
5567#ifndef MODULE
5568 /*
5569 * For statically linked driver, call hdd_set_conparam to update
5570 * curr_con_mode
5571 */
5572 hdd_set_conparam((uint32_t) con_mode);
5573#endif
5574
5575#ifdef QCA_WIFI_3_0_ADRASTEA
5576#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
5577#else
5578#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
5579#endif
5580
5581 init_completion(&wlan_start_comp);
5582 ret_status = wlan_hdd_register_driver();
5583 if (!ret_status) {
5584 rc = wait_for_completion_timeout(
5585 &wlan_start_comp,
5586 msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
5587 if (!rc) {
5588 hddLog(LOGP,
5589 FL("timed-out waiting for wlan_hdd_register_driver"));
5590 ret_status = -1;
5591 } else
5592 ret_status = 0;
5593 }
5594
5595 hdd_remove_pm_qos();
5596 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
5597
5598 if (ret_status) {
5599 hddLog(LOGP, FL("WLAN Driver Initialization failed"));
5600 wlan_hdd_unregister_driver();
5601 cds_free_global_context(&p_cds_context);
5602 ret_status = -ENODEV;
5603 break;
5604 } else {
5605 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5606 memdump_init();
5607 return 0;
5608 }
5609
5610 } while (0);
5611
5612 if (0 != ret_status) {
5613 cdf_mc_timer_exit();
5614 cdf_mem_exit();
5615 cdf_wake_lock_destroy(&wlan_wake_lock);
5616
5617#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
5618 wlan_logging_sock_deinit_svc();
5619#endif
5620 memdump_deinit();
5621 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
5622 } else {
5623 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
5624 }
5625
5626 EXIT();
5627
5628 return ret_status;
5629}
5630
5631/**
5632 * hdd_module_init() - Init Function
5633 *
5634 * This is the driver entry point (invoked when module is loaded using insmod)
5635 *
5636 * Return: 0 for success, non zero for failure
5637 */
5638#ifdef MODULE
5639static int __init hdd_module_init(void)
5640{
5641 return hdd_driver_init();
5642}
5643#else /* #ifdef MODULE */
5644static int __init hdd_module_init(void)
5645{
5646 /* Driver initialization is delayed to fwpath_changed_handler */
5647 return 0;
5648}
5649#endif /* #ifdef MODULE */
5650
5651/**
5652 * hdd_driver_exit() - Exit function
5653 *
5654 * This is the driver exit point (invoked when module is unloaded using rmmod
5655 * or con_mode was changed by userspace)
5656 *
5657 * Return: None
5658 */
5659static void hdd_driver_exit(void)
5660{
5661 hdd_context_t *hdd_ctx = NULL;
5662 int retry = 0;
5663
5664 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME,
5665 QWLAN_VERSIONSTR);
5666
5667 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
5668 if (!hdd_ctx) {
5669 hddLog(CDF_TRACE_LEVEL_FATAL,
5670 FL("module exit called before probe"));
5671 } else {
5672#ifdef QCA_PKT_PROTO_TRACE
5673 cds_pkt_proto_trace_close();
5674#endif /* QCA_PKT_PROTO_TRACE */
5675 while (hdd_ctx->isLogpInProgress ||
5676 cds_is_logp_in_progress()) {
5677 hddLog(CDF_TRACE_LEVEL_FATAL,
5678 FL(
5679 "SSR in Progress; block rmmod for 1 second!!!"
5680 ));
5681 msleep(1000);
5682
5683 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
5684 hddLog(CDF_TRACE_LEVEL_FATAL,
5685 FL("SSR never completed, fatal error"));
5686 CDF_BUG(0);
5687 }
5688 }
5689
5690 rtnl_lock();
5691 hdd_ctx->isUnloadInProgress = true;
5692 cds_set_load_unload_in_progress(true);
5693 rtnl_unlock();
5694 }
5695
5696 cds_wait_for_work_thread_completion(__func__);
5697 memdump_deinit();
5698
5699 wlan_hdd_unregister_driver();
5700 return;
5701}
5702
5703/**
5704 * hdd_module_exit() - Exit function
5705 *
5706 * This is the driver exit point (invoked when module is unloaded using rmmod)
5707 *
5708 * Return: None
5709 */
5710static void __exit hdd_module_exit(void)
5711{
5712 hdd_driver_exit();
5713}
5714
5715#ifdef MODULE
5716static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
5717{
5718 return param_set_copystring(kmessage, kp);
5719}
5720
5721#if !defined(QCA_WIFI_FTM)
5722static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
5723{
5724 return param_set_int(kmessage, kp);
5725}
5726#endif
5727#else /* #ifdef MODULE */
5728/**
5729 * kickstart_driver() - driver entry point
5730 *
5731 * This is the driver entry point
5732 * - delayed driver initialization when driver is statically linked
5733 * - invoked when module parameter fwpath is modified from userspace to signal
5734 * initializing the WLAN driver or when con_mode is modified from userspace
5735 * to signal a switch in operating mode
5736 *
5737 * Return: 0 for success, non zero for failure
5738 */
5739static int kickstart_driver(void)
5740{
5741 int ret_status;
5742
5743 if (!wlan_hdd_inited) {
5744 ret_status = hdd_driver_init();
5745 wlan_hdd_inited = ret_status ? 0 : 1;
5746 return ret_status;
5747 }
5748
5749 hdd_driver_exit();
5750
5751 msleep(200);
5752
5753 ret_status = hdd_driver_init();
5754 wlan_hdd_inited = ret_status ? 0 : 1;
5755 return ret_status;
5756}
5757
5758/**
5759 * fwpath_changed_handler() - Handler Function
5760 *
5761 * Handle changes to the fwpath parameter
5762 *
5763 * Return: 0 for success, non zero for failure
5764 */
5765static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
5766{
5767 int ret;
5768
5769 ret = param_set_copystring(kmessage, kp);
5770 if (0 == ret)
5771 ret = kickstart_driver();
5772 return ret;
5773}
5774
5775#if !defined(QCA_WIFI_FTM)
5776/**
5777 * con_mode_handler() - handls module param con_mode change
5778 *
5779 * Handler function for module param con_mode when it is changed by userspace
5780 * Dynamically linked - do nothing
5781 * Statically linked - exit and init driver, as in rmmod and insmod
5782 *
5783 * Return -
5784 */
5785static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
5786{
5787 int ret;
5788
5789 ret = param_set_int(kmessage, kp);
5790 if (0 == ret)
5791 ret = kickstart_driver();
5792 return ret;
5793}
5794#endif
5795#endif /* #ifdef MODULE */
5796
5797/**
5798 * hdd_get_conparam() - driver exit point
5799 *
5800 * This is the driver exit point (invoked when module is unloaded using rmmod)
5801 *
5802 * Return: tCDF_CON_MODE
5803 */
5804tCDF_CON_MODE hdd_get_conparam(void)
5805{
5806#ifdef MODULE
5807 return (tCDF_CON_MODE) con_mode;
5808#else
5809 return (tCDF_CON_MODE) curr_con_mode;
5810#endif
5811}
5812
5813void hdd_set_conparam(uint32_t newParam)
5814{
5815 con_mode = newParam;
5816#ifndef MODULE
5817 curr_con_mode = con_mode;
5818#endif
5819}
5820
5821/**
5822 * hdd_softap_sta_deauth() - handle deauth req from HDD
5823 * @adapter: Pointer to the HDD
5824 * @enable: bool value
5825 *
5826 * This to take counter measure to handle deauth req from HDD
5827 *
5828 * Return: None
5829 */
5830CDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
5831 struct tagCsrDelStaParams *pDelStaParams)
5832{
5833#ifndef WLAN_FEATURE_MBSSID
5834 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5835#endif
5836 CDF_STATUS cdf_status = CDF_STATUS_E_FAULT;
5837
5838 ENTER();
5839
5840 hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"),
5841 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5842
5843 /* Ignore request to deauth bcmc station */
5844 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
5845 return cdf_status;
5846
5847#ifdef WLAN_FEATURE_MBSSID
5848 cdf_status =
5849 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5850 pDelStaParams);
5851#else
5852 cdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
5853#endif
5854
5855 EXIT();
5856 return cdf_status;
5857}
5858
5859/**
5860 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
5861 * @adapter: Pointer to the HDD
5862 *
5863 * This to take counter measure to handle deauth req from HDD
5864 *
5865 * Return: None
5866 */
5867void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
5868 uint8_t *pDestMacAddress)
5869{
5870#ifndef WLAN_FEATURE_MBSSID
5871 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5872#endif
5873
5874 ENTER();
5875
5876 hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"),
5877 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5878
5879 /* Ignore request to disassoc bcmc station */
5880 if (pDestMacAddress[0] & 0x1)
5881 return;
5882
5883#ifdef WLAN_FEATURE_MBSSID
5884 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5885 pDestMacAddress);
5886#else
5887 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
5888#endif
5889}
5890
5891void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
5892 bool enable)
5893{
5894#ifndef WLAN_FEATURE_MBSSID
5895 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5896#endif
5897
5898 ENTER();
5899
5900 hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"),
5901 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5902
5903#ifdef WLAN_FEATURE_MBSSID
5904 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5905 (bool) enable);
5906#else
5907 wlansap_set_counter_measure(p_cds_context, (bool) enable);
5908#endif
5909}
5910
5911/**
5912 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
5913 * @hdd_ctx: HDD Context
5914 *
5915 * API to find if there is any STA or P2P-Client is connected
5916 *
5917 * Return: true if connected; false otherwise
5918 */
5919CDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
5920{
5921 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
5922}
5923
5924#ifdef WLAN_FEATURE_LPSS
5925int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
5926 hdd_adapter_t *adapter,
5927 hdd_station_ctx_t *pHddStaCtx,
5928 uint8_t is_on, uint8_t is_connected)
5929{
5930 hdd_context_t *hdd_ctx = NULL;
5931 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
5932
5933 if (!data) {
5934 hddLog(LOGE, FL("invalid data pointer"));
5935 return -EINVAL;
5936 }
5937 if (!adapter) {
5938 if (is_on) {
5939 /* no active interface */
5940 data->lpss_support = 0;
5941 data->is_on = is_on;
5942 return 0;
5943 }
5944 hddLog(LOGE, FL("invalid adapter pointer"));
5945 return -EINVAL;
5946 }
5947
5948 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5949 if (hdd_ctx->lpss_support && hdd_ctx->config->enablelpasssupport)
5950 data->lpss_support = 1;
5951 else
5952 data->lpss_support = 0;
5953 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
5954 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
5955 &data->numChannels);
5956 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
5957 data->is_on = is_on;
5958 data->vdev_id = adapter->sessionId;
5959 data->vdev_mode = adapter->device_mode;
5960 if (pHddStaCtx) {
5961 data->is_connected = is_connected;
5962 data->rssi = adapter->rssi;
5963 data->freq =
5964 cds_chan_to_freq(pHddStaCtx->conn_info.operationChannel);
5965 if (WLAN_SVC_MAX_SSID_LEN >=
5966 pHddStaCtx->conn_info.SSID.SSID.length) {
5967 data->ssid_len = pHddStaCtx->conn_info.SSID.SSID.length;
5968 memcpy(data->ssid,
5969 pHddStaCtx->conn_info.SSID.SSID.ssId,
5970 pHddStaCtx->conn_info.SSID.SSID.length);
5971 }
5972 if (CDF_MAC_ADDR_SIZE >=
5973 sizeof(pHddStaCtx->conn_info.bssId))
5974 memcpy(data->bssid, pHddStaCtx->conn_info.bssId.bytes,
5975 CDF_MAC_ADDR_SIZE);
5976 }
5977 return 0;
5978}
5979
5980int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
5981 uint32_t fw_version,
5982 uint32_t chip_id, const char *chip_name)
5983{
5984 if (!data) {
5985 hddLog(LOGE, FL("invalid data pointer"));
5986 return -EINVAL;
5987 }
5988
5989 data->chip_id = chip_id;
5990 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
5991 if (strncmp(chip_name, "Unknown", 7))
5992 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
5993 else
5994 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
5995 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
5996 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
5997 (fw_version & 0xf0000000) >> 28,
5998 (fw_version & 0xf000000) >> 24,
5999 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
6000 return 0;
6001}
6002#endif
6003
6004#if defined(FEATURE_WLAN_LFR)
6005/**
6006 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
6007 * @adapter: HDD adapter pointer
6008 *
6009 * This function loop through each adapter and disable roaming on each STA
6010 * device mode except the input adapter.
6011 *
6012 * Note: On the input adapter roaming is not enabled yet hence no need to
6013 * disable.
6014 *
6015 * Return: None
6016 */
6017void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
6018{
6019 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6020 hdd_adapter_t *adapterIdx = NULL;
6021 hdd_adapter_list_node_t *adapterNode = NULL;
6022 hdd_adapter_list_node_t *pNext = NULL;
6023 CDF_STATUS status;
6024
6025 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6026 hdd_ctx->config->isRoamOffloadScanEnabled &&
6027 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6028 cds_is_sta_active_connection_exists()) {
6029 hddLog(LOG1, FL("Connect received on STA sessionId(%d)"),
6030 adapter->sessionId);
6031 /*
6032 * Loop through adapter and disable roaming for each STA device
6033 * mode except the input adapter.
6034 */
6035 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6036
6037 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
6038 adapterIdx = adapterNode->pAdapter;
6039
6040 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6041 && adapter->sessionId != adapterIdx->sessionId) {
6042 hddLog(LOG1,
6043 FL("Disable Roaming on sessionId(%d)"),
6044 adapterIdx->sessionId);
6045 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
6046 (adapterIdx),
6047 adapterIdx->sessionId, 0);
6048 }
6049
6050 status = hdd_get_next_adapter(hdd_ctx,
6051 adapterNode,
6052 &pNext);
6053 adapterNode = pNext;
6054 }
6055 }
6056}
6057
6058/**
6059 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
6060 * @adapter: HDD adapter pointer
6061 *
6062 * This function loop through each adapter and enable roaming on each STA
6063 * device mode except the input adapter.
6064 * Note: On the input adapter no need to enable roaming because link got
6065 * disconnected on this.
6066 *
6067 * Return: None
6068 */
6069void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
6070{
6071 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6072 hdd_adapter_t *adapterIdx = NULL;
6073 hdd_adapter_list_node_t *adapterNode = NULL;
6074 hdd_adapter_list_node_t *pNext = NULL;
6075 CDF_STATUS status;
6076
6077 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6078 hdd_ctx->config->isRoamOffloadScanEnabled &&
6079 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6080 cds_is_sta_active_connection_exists()) {
6081 hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"),
6082 adapter->sessionId);
6083 /*
6084 * Loop through adapter and enable roaming for each STA device
6085 * mode except the input adapter.
6086 */
6087 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6088
6089 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
6090 adapterIdx = adapterNode->pAdapter;
6091
6092 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6093 && adapter->sessionId != adapterIdx->sessionId) {
6094 hddLog(LOG1,
6095 FL("Enabling Roaming on sessionId(%d)"),
6096 adapterIdx->sessionId);
6097 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
6098 (adapterIdx),
6099 adapterIdx->sessionId,
6100 REASON_CONNECT);
6101 }
6102
6103 status = hdd_get_next_adapter(hdd_ctx,
6104 adapterNode,
6105 &pNext);
6106 adapterNode = pNext;
6107 }
6108 }
6109}
6110#endif
6111
6112void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
6113{
6114 struct sk_buff *skb;
6115 struct nlmsghdr *nlh;
6116 tAniMsgHdr *ani_hdr;
6117 void *nl_data = NULL;
6118 int flags = GFP_KERNEL;
6119
6120 if (in_interrupt() || irqs_disabled() || in_atomic())
6121 flags = GFP_ATOMIC;
6122
6123 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
6124
6125 if (skb == NULL) {
6126 hddLog(CDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed"));
6127 return;
6128 }
6129
6130 nlh = (struct nlmsghdr *)skb->data;
6131 nlh->nlmsg_pid = 0; /* from kernel */
6132 nlh->nlmsg_flags = 0;
6133 nlh->nlmsg_seq = 0;
6134 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
6135
6136 ani_hdr = NLMSG_DATA(nlh);
6137 ani_hdr->type = type;
6138
6139 switch (type) {
6140 case WLAN_SVC_FW_CRASHED_IND:
6141 case WLAN_SVC_LTE_COEX_IND:
6142#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6143 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
6144#endif
6145 ani_hdr->length = 0;
6146 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
6147 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
6148 break;
6149 case WLAN_SVC_WLAN_STATUS_IND:
6150 case WLAN_SVC_WLAN_VERSION_IND:
6151 case WLAN_SVC_DFS_CAC_START_IND:
6152 case WLAN_SVC_DFS_CAC_END_IND:
6153 case WLAN_SVC_DFS_RADAR_DETECT_IND:
6154 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
6155 case WLAN_SVC_WLAN_TP_IND:
6156 ani_hdr->length = len;
6157 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
6158 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
6159 memcpy(nl_data, data, len);
6160 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
6161 break;
6162
6163 default:
6164 hddLog(CDF_TRACE_LEVEL_ERROR,
6165 FL("WLAN SVC: Attempt to send unknown nlink message %d"),
6166 type);
6167 kfree_skb(skb);
6168 return;
6169 }
6170
6171 nl_srv_bcast(skb);
6172
6173 return;
6174}
6175
6176#ifdef WLAN_FEATURE_LPSS
6177void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
6178 hdd_station_ctx_t *pHddStaCtx,
6179 uint8_t is_on, uint8_t is_connected)
6180{
6181 int ret = 0;
6182 struct wlan_status_data data;
6183
6184 if (CDF_FTM_MODE == hdd_get_conparam())
6185 return;
6186
6187 memset(&data, 0, sizeof(struct wlan_status_data));
6188 if (is_on)
6189 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, pHddStaCtx,
6190 is_on, is_connected);
6191 if (!ret)
6192 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND,
6193 &data,
6194 sizeof(struct wlan_status_data));
6195}
6196
6197void wlan_hdd_send_version_pkg(uint32_t fw_version,
6198 uint32_t chip_id, const char *chip_name)
6199{
6200 int ret = 0;
6201 struct wlan_version_data data;
6202#ifdef CONFIG_CNSS
6203 struct cnss_platform_cap cap;
6204
6205 ret = cnss_get_platform_cap(&cap);
6206 if (ret) {
6207 hddLog(CDF_TRACE_LEVEL_ERROR,
6208 FL("platform capability info from CNSS not available"));
6209 return;
6210 }
6211
6212 if (!(cap.cap_flag & CNSS_HAS_UART_ACCESS))
6213 return;
6214#endif
6215
6216 if (CDF_FTM_MODE == hdd_get_conparam())
6217 return;
6218
6219 memset(&data, 0, sizeof(struct wlan_version_data));
6220 ret =
6221 wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
6222 chip_name);
6223 if (!ret)
6224 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND,
6225 &data,
6226 sizeof(struct wlan_version_data));
6227}
6228
6229void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
6230{
6231 hdd_adapter_t *pDataAdapter = NULL;
6232 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6233 bool scan_intf_found = false;
6234 CDF_STATUS status;
6235
6236 if (!hdd_ctx) {
6237 hddLog(CDF_TRACE_LEVEL_ERROR,
6238 FL("NULL pointer for hdd_ctx"));
6239 return;
6240 }
6241
6242 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6243 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
6244 pDataAdapter = adapterNode->pAdapter;
6245 if (pDataAdapter) {
6246 if (pDataAdapter->device_mode == WLAN_HDD_INFRA_STATION
6247 || pDataAdapter->device_mode == WLAN_HDD_P2P_CLIENT
6248 || pDataAdapter->device_mode ==
6249 WLAN_HDD_P2P_DEVICE) {
6250 scan_intf_found = true;
6251 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1,
6252 0);
6253 }
6254 }
6255 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6256 adapterNode = pNext;
6257 }
6258
6259 if (!scan_intf_found)
6260 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0);
6261}
6262#endif
6263
6264#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6265void wlan_hdd_auto_shutdown_cb(void)
6266{
6267 hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event.."));
6268 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
6269}
6270
6271void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
6272{
6273 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6274 CDF_STATUS status;
6275 hdd_adapter_t *adapter;
6276 bool ap_connected = false, sta_connected = false;
6277 tHalHandle hal_handle;
6278
6279 hal_handle = hdd_ctx->hHal;
6280 if (hal_handle == NULL)
6281 return;
6282
6283 if (hdd_ctx->config->WlanAutoShutdown == 0)
6284 return;
6285
6286 if (enable == false) {
6287 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
6288 CDF_STATUS_SUCCESS) {
6289 hddLog(LOGE,
6290 FL("Failed to stop wlan auto shutdown timer"));
6291 }
6292 return;
6293 }
6294
6295 /* To enable shutdown timer check conncurrency */
6296 if (cds_concurrent_open_sessions_running()) {
6297 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6298
6299 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
6300 adapter = adapterNode->pAdapter;
6301 if (adapter
6302 && adapter->device_mode ==
6303 WLAN_HDD_INFRA_STATION) {
6304 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6305 conn_info.connState ==
6306 eConnectionState_Associated) {
6307 sta_connected = true;
6308 break;
6309 }
6310 }
6311 if (adapter
6312 && adapter->device_mode == WLAN_HDD_SOFTAP) {
6313 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
6314 bApActive == true) {
6315 ap_connected = true;
6316 break;
6317 }
6318 }
6319 status = hdd_get_next_adapter(hdd_ctx,
6320 adapterNode,
6321 &pNext);
6322 adapterNode = pNext;
6323 }
6324 }
6325
6326 if (ap_connected == true || sta_connected == true) {
6327 hddLog(LOG1,
6328 FL("CC Session active. Shutdown timer not enabled"));
6329 return;
6330 } else {
6331 if (sme_set_auto_shutdown_timer(hal_handle,
6332 hdd_ctx->config->
6333 WlanAutoShutdown)
6334 != CDF_STATUS_SUCCESS)
6335 hddLog(LOGE,
6336 FL("Failed to start wlan auto shutdown timer"));
6337 else
6338 hddLog(LOG1,
6339 FL("Auto Shutdown timer for %d seconds enabled"),
6340 hdd_ctx->config->WlanAutoShutdown);
6341
6342 }
6343}
6344#endif
6345
6346hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
6347 bool check_start_bss)
6348{
6349 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
6350 hdd_adapter_t *adapter, *con_sap_adapter;
6351 CDF_STATUS status = CDF_STATUS_SUCCESS;
6352 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6353
6354 con_sap_adapter = NULL;
6355
6356 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6357 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
6358 adapter = adapterNode->pAdapter;
6359 if (adapter && ((adapter->device_mode == WLAN_HDD_SOFTAP) ||
6360 (adapter->device_mode == WLAN_HDD_P2P_GO)) &&
6361 adapter != this_sap_adapter) {
6362 if (check_start_bss) {
6363 if (test_bit(SOFTAP_BSS_STARTED,
6364 &adapter->event_flags)) {
6365 con_sap_adapter = adapter;
6366 break;
6367 }
6368 } else {
6369 con_sap_adapter = adapter;
6370 break;
6371 }
6372 }
6373 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6374 adapterNode = pNext;
6375 }
6376
6377 return con_sap_adapter;
6378}
6379
6380#ifdef MSM_PLATFORM
6381void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
6382{
6383 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6384
6385 if (CDF_TIMER_STATE_RUNNING ==
6386 cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
6387 return;
6388
6389 cdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
6390 hdd_ctx->config->busBandwidthComputeInterval);
6391}
6392
6393void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
6394{
6395 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6396 CDF_STATUS status;
6397 bool can_stop = true;
6398 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6399
6400 if (CDF_TIMER_STATE_RUNNING !=
6401 cdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
6402 /* trying to stop timer, when not running is not good */
6403 hddLog(CDF_TRACE_LEVEL_ERROR,
6404 FL("bus band width compute timer is not running"));
6405 return;
6406 }
6407
6408 if (cds_concurrent_open_sessions_running()) {
6409 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6410
6411 while (NULL != adapterNode && CDF_STATUS_SUCCESS == status) {
6412 adapter = adapterNode->pAdapter;
6413 if (adapter
6414 && (adapter->device_mode == WLAN_HDD_INFRA_STATION
6415 || adapter->device_mode == WLAN_HDD_P2P_CLIENT)
6416 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6417 conn_info.connState ==
6418 eConnectionState_Associated) {
6419 can_stop = false;
6420 break;
6421 }
6422 if (adapter
6423 && (adapter->device_mode == WLAN_HDD_SOFTAP
6424 || adapter->device_mode == WLAN_HDD_P2P_GO)
6425 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
6426 true) {
6427 can_stop = false;
6428 break;
6429 }
6430 status = hdd_get_next_adapter(hdd_ctx,
6431 adapterNode,
6432 &pNext);
6433 adapterNode = pNext;
6434 }
6435 }
6436
6437 if (can_stop == true)
6438 cdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
6439}
6440#endif
6441
6442/**
6443 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
6444 * and sta's operating channel.
6445 * @sta_adapter: Describe the first argument to foobar.
6446 * @ap_adapter: Describe the second argument to foobar.
6447 * @roam_profile: Roam profile of AP to which STA wants to connect.
6448 * @concurrent_chnl_same: If both SAP and STA channels are same then
6449 * set this flag to true else false.
6450 *
6451 * This function checks the sap's operating channel and sta's operating channel.
6452 * if both are same then it will return false else it will restart the sap in
6453 * sta's channel and return true.
6454 *
6455 * Return: CDF_STATUS_SUCCESS or CDF_STATUS_E_FAILURE.
6456 */
6457CDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
6458 hdd_adapter_t *ap_adapter,
6459 tCsrRoamProfile *roam_profile,
6460 tScanResultHandle *scan_cache,
6461 bool *concurrent_chnl_same)
6462{
6463 hdd_ap_ctx_t *hdd_ap_ctx;
6464 uint8_t channel_id;
6465 CDF_STATUS status;
6466 device_mode_t device_mode = ap_adapter->device_mode;
6467 *concurrent_chnl_same = true;
6468
6469 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6470 status =
6471 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
6472 roam_profile,
6473 scan_cache,
6474 &channel_id);
6475 if ((CDF_STATUS_SUCCESS == status)) {
6476 if ((WLAN_HDD_SOFTAP == device_mode) &&
6477 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
6478 if (hdd_ap_ctx->operatingChannel != channel_id) {
6479 *concurrent_chnl_same = false;
6480 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6481 FL("channels are different"));
6482 }
6483 } else if ((WLAN_HDD_P2P_GO == device_mode) &&
6484 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
6485 if (hdd_ap_ctx->operatingChannel != channel_id) {
6486 *concurrent_chnl_same = false;
6487 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6488 FL("channels are different"));
6489 }
6490 }
6491 } else {
6492 /*
6493 * Lets handle worst case scenario here, Scan cache lookup is
6494 * failed so we have to stop the SAP to avoid any channel
6495 * discrepancy between SAP's channel and STA's channel.
6496 * Return the status as failure so caller function could know
6497 * that scan look up is failed.
6498 */
6499 hddLog(CDF_TRACE_LEVEL_ERROR,
6500 FL("Finding AP from scan cache failed"));
6501 return CDF_STATUS_E_FAILURE;
6502 }
6503 return CDF_STATUS_SUCCESS;
6504}
6505
6506#ifdef WLAN_FEATURE_MBSSID
6507/**
6508 * wlan_hdd_stop_sap() - This function stops bss of SAP.
6509 * @ap_adapter: SAP adapter
6510 *
6511 * This function will process the stopping of sap adapter.
6512 *
6513 * Return: None
6514 */
6515void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
6516{
6517 hdd_ap_ctx_t *hdd_ap_ctx;
6518 hdd_hostapd_state_t *hostapd_state;
6519 CDF_STATUS cdf_status;
6520 hdd_context_t *hdd_ctx;
6521#ifdef CFG80211_DEL_STA_V2
6522 struct station_del_parameters delStaParams;
6523#endif
6524
6525 if (NULL == ap_adapter) {
6526 hddLog(CDF_TRACE_LEVEL_ERROR,
6527 FL("ap_adapter is NULL here"));
6528 return;
6529 }
6530
6531 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6532 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6533 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
6534 hddLog(CDF_TRACE_LEVEL_ERROR,
6535 FL("HDD context is not valid"));
6536 return;
6537 }
6538 mutex_lock(&hdd_ctx->sap_lock);
6539 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
6540#ifdef CFG80211_DEL_STA_V2
6541 delStaParams.mac = NULL;
6542 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
6543 delStaParams.reason_code = eCsrForcedDeauthSta;
6544 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6545 ap_adapter->dev,
6546 &delStaParams);
6547#else
6548 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6549 ap_adapter->dev,
6550 NULL);
6551#endif
6552 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
6553 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6554 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
6555 FL("Now doing SAP STOPBSS"));
6556 cdf_event_reset(&hostapd_state->cdf_stop_bss_event);
6557 if (CDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
6558 sapContext)) {
6559 cdf_status = cdf_wait_single_event(&hostapd_state->
6560 cdf_stop_bss_event,
6561 BSS_WAIT_TIMEOUT);
6562 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
6563 mutex_unlock(&hdd_ctx->sap_lock);
6564 hddLog(CDF_TRACE_LEVEL_ERROR,
6565 FL("SAP Stop Failed"));
6566 return;
6567 }
6568 }
6569 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
6570 cds_decr_session_set_pcl(hdd_ctx,
6571 ap_adapter->device_mode,
6572 ap_adapter->sessionId);
6573 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
6574 FL("SAP Stop Success"));
6575 } else {
6576 hddLog(CDF_TRACE_LEVEL_ERROR,
6577 FL("Can't stop ap because its not started"));
6578 }
6579 mutex_unlock(&hdd_ctx->sap_lock);
6580 return;
6581}
6582
6583/**
6584 * wlan_hdd_start_sap() - this function starts bss of SAP.
6585 * @ap_adapter: SAP adapter
6586 *
6587 * This function will process the starting of sap adapter.
6588 *
6589 * Return: None
6590 */
6591void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
6592{
6593 hdd_ap_ctx_t *hdd_ap_ctx;
6594 hdd_hostapd_state_t *hostapd_state;
6595 CDF_STATUS cdf_status;
6596 hdd_context_t *hdd_ctx;
6597 tsap_Config_t *sap_config;
6598
6599 if (NULL == ap_adapter) {
6600 hddLog(CDF_TRACE_LEVEL_ERROR,
6601 FL("ap_adapter is NULL here"));
6602 return;
6603 }
6604
6605 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6606 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6607 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6608 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
6609
6610 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
6611 hddLog(CDF_TRACE_LEVEL_ERROR,
6612 FL("HDD context is not valid"));
6613 return;
6614 }
6615 mutex_lock(&hdd_ctx->sap_lock);
6616 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
6617 goto end;
6618
6619 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
6620 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
6621 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
6622 goto end;
6623 }
6624
6625 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
6626 &hdd_ap_ctx->sapConfig,
6627 ap_adapter->dev)
6628 != CDF_STATUS_SUCCESS)
6629 goto end;
6630
6631 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
6632 FL("Waiting for SAP to start"));
6633 cdf_status = cdf_wait_single_event(&hostapd_state->cdf_event,
6634 BSS_WAIT_TIMEOUT);
6635 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
6636 hddLog(CDF_TRACE_LEVEL_ERROR, FL("SAP Start failed"));
6637 goto end;
6638 }
6639 hddLog(CDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success"));
6640 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
6641 cds_incr_active_session(hdd_ctx, ap_adapter->device_mode,
6642 ap_adapter->sessionId);
6643 hostapd_state->bCommit = true;
6644
6645end:
6646 mutex_unlock(&hdd_ctx->sap_lock);
6647 return;
6648}
6649#endif
6650
6651/**
6652 * hdd_wlan_get_wake_lock_ptr(): get HDD's wake lock pointer
6653 *
6654 * This function returns the wake lock pointer to the caller
6655 *
6656 * Return: cdf_wake_lock_t
6657 */
6658cdf_wake_lock_t *hdd_wlan_get_wake_lock_ptr(void)
6659{
6660 return &wlan_wake_lock;
6661}
6662
6663/**
6664 * hdd_get_fw_version() - Get FW version
6665 * @hdd_ctx: pointer to HDD context.
6666 * @major_spid: FW version - major spid.
6667 * @minor_spid: FW version - minor spid
6668 * @ssid: FW version - ssid
6669 * @crmid: FW version - crmid
6670 *
6671 * This function is called to get the firmware build version stored
6672 * as part of the HDD context
6673 *
6674 * Return: None
6675 */
6676void hdd_get_fw_version(hdd_context_t *hdd_ctx,
6677 uint32_t *major_spid, uint32_t *minor_spid,
6678 uint32_t *siid, uint32_t *crmid)
6679{
6680 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
6681 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
6682 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
6683 *crmid = hdd_ctx->target_fw_version & 0x7fff;
6684}
6685
6686#ifdef QCA_CONFIG_SMP
6687/**
6688 * wlan_hdd_get_cpu() - get cpu_index
6689 *
6690 * Return: cpu_index
6691 */
6692int wlan_hdd_get_cpu(void)
6693{
6694 int cpu_index = get_cpu();
6695 put_cpu();
6696 return cpu_index;
6697}
6698#endif
6699
6700/**
6701 * hdd_get_fwpath() - get framework path
6702 *
6703 * This function is used to get the string written by
6704 * userspace to start the wlan driver
6705 *
6706 * Return: string
6707 */
6708const char *hdd_get_fwpath(void)
6709{
6710 return fwpath.string;
6711}
6712
6713
6714/* Register the module init/exit functions */
6715module_init(hdd_module_init);
6716module_exit(hdd_module_exit);
6717
6718MODULE_LICENSE("Dual BSD/GPL");
6719MODULE_AUTHOR("Qualcomm Atheros, Inc.");
6720MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
6721
6722#if defined(QCA_WIFI_FTM)
6723module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
6724#else
6725module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
6726 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
6727#endif
6728
6729module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
6730 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
6731
6732module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
6733
6734module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
6735
6736module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);