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