blob: af0d983eb9bfe30e406ca2c56378328aaa31db74 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
39#ifdef WLAN_FEATURE_LPSS
40#include <cds_utils.h>
41#endif
42#include <linux/etherdevice.h>
43#include <linux/firmware.h>
44#include <wlan_hdd_tx_rx.h>
45#include <wni_api.h>
46#include <wlan_hdd_cfg.h>
47#include <wlan_ptt_sock_svc.h>
48#include <dbglog_host.h>
49#include <wlan_logging_sock_svc.h>
50#include <wlan_hdd_wowl.h>
51#include <wlan_hdd_misc.h>
52#include <wlan_hdd_wext.h>
53#include "wlan_hdd_trace.h"
54#include "wlan_hdd_ioctl.h"
55#include "wlan_hdd_ftm.h"
56#include "wlan_hdd_power.h"
57#include "wlan_hdd_stats.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053058#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053059#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070060#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080061
62#include <net/addrconf.h>
63#include <linux/wireless.h>
64#include <net/cfg80211.h>
65#include <linux/inetdevice.h>
66#include <net/addrconf.h>
67#include "wlan_hdd_cfg80211.h"
68#include "wlan_hdd_ext_scan.h"
69#include "wlan_hdd_p2p.h"
70#include <linux/rtnetlink.h>
71#include "sap_api.h"
72#include <linux/semaphore.h>
73#include <linux/ctype.h>
74#include <linux/compat.h>
75#ifdef MSM_PLATFORM
76#ifdef CONFIG_CNSS
77#include <soc/qcom/subsystem_restart.h>
78#endif
79#endif
80#include <wlan_hdd_hostapd.h>
81#include <wlan_hdd_softap_tx_rx.h>
82#include "cfg_api.h"
83#include "qwlan_version.h"
84#include "wma_types.h"
85#include "wlan_hdd_tdls.h"
86#ifdef FEATURE_WLAN_CH_AVOID
87#ifdef CONFIG_CNSS
88#include <net/cnss.h>
89#endif
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053090#include "cds_regdomain.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091
92#include "wlan_hdd_ocb.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080093#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094
95extern int hdd_hostapd_stop(struct net_device *dev);
96#endif /* FEATURE_WLAN_CH_AVOID */
97
98#include "wlan_hdd_nan.h"
99#include "wlan_hdd_debugfs.h"
100#include "wlan_hdd_driver_ops.h"
101#include "epping_main.h"
102#include "wlan_hdd_memdump.h"
103
104#include <wlan_hdd_ipa.h>
105#include "hif.h"
106#include "wma.h"
107#include "cds_concurrency.h"
108#include "wlan_hdd_green_ap.h"
Yuanyuan Liuedcbc302015-12-02 10:39:51 -0800109#include "platform_icnss.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530110#include "bmi.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111
112#ifdef MODULE
113#define WLAN_MODULE_NAME module_name(THIS_MODULE)
114#else
115#define WLAN_MODULE_NAME "wlan"
116#endif
117
118#ifdef TIMER_MANAGER
119#define TIMER_MANAGER_STR " +TIMER_MANAGER"
120#else
121#define TIMER_MANAGER_STR ""
122#endif
123
124#ifdef MEMORY_DEBUG
125#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
126#else
127#define MEMORY_DEBUG_STR ""
128#endif
129
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800130/* the Android framework expects this param even though we don't use it */
131#define BUF_LEN 20
132static char fwpath_buffer[BUF_LEN];
133static struct kparam_string fwpath = {
134 .string = fwpath_buffer,
135 .maxlen = BUF_LEN,
136};
137
138static char *country_code;
139static int enable_11d = -1;
140static int enable_dfs_chan_scan = -1;
141
142#ifndef MODULE
143static int wlan_hdd_inited;
144#endif
145
146/*
147 * spinlock for synchronizing asynchronous request/response
148 * (full description of use in wlan_hdd_main.h)
149 */
150DEFINE_SPINLOCK(hdd_context_lock);
151
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530152static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153
154#define WOW_MAX_FILTER_LISTS 1
155#define WOW_MAX_FILTERS_PER_LIST 4
156#define WOW_MIN_PATTERN_SIZE 6
157#define WOW_MAX_PATTERN_SIZE 64
158
159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
160static const struct wiphy_wowlan_support wowlan_support_reg_init = {
161 .flags = WIPHY_WOWLAN_ANY |
162 WIPHY_WOWLAN_MAGIC_PKT |
163 WIPHY_WOWLAN_DISCONNECT |
164 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
165 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
166 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
167 WIPHY_WOWLAN_4WAY_HANDSHAKE |
168 WIPHY_WOWLAN_RFKILL_RELEASE,
169 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
170 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
171 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
172};
173#endif
174
175/* internal function declaration */
176
177struct sock *cesium_nl_srv_sock;
178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
180void wlan_hdd_auto_shutdown_cb(void);
181#endif
182
183/**
184 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
185 * @vdev_id: vdev_id
186 * @action: action type
187 * @reason: reason type
188 *
189 * Return: none
190 */
191void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
192 enum netif_action_type action, enum netif_reason_type reason)
193{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530194 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 hdd_adapter_t *adapter;
196
197 if (!hdd_ctx) {
198 hdd_err("hdd ctx is NULL");
199 return;
200 }
201 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
202
203 wlan_hdd_netif_queue_control(adapter, action, reason);
204 return;
205}
206
207/*
208 * Store WLAN driver version info in a global variable such that crash debugger
209 * can extract it from driver debug symbol and crashdump for post processing
210 */
211uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
212
213/**
214 * hdd_device_mode_to_string() - return string conversion of device mode
215 * @device_mode: device mode
216 *
217 * This utility function helps log string conversion of device mode.
218 *
219 * Return: string conversion of device mode, if match found;
220 * "Unknown" otherwise.
221 */
222const char *hdd_device_mode_to_string(uint8_t device_mode)
223{
224 switch (device_mode) {
225 CASE_RETURN_STRING(WLAN_HDD_INFRA_STATION);
226 CASE_RETURN_STRING(WLAN_HDD_SOFTAP);
227 CASE_RETURN_STRING(WLAN_HDD_P2P_CLIENT);
228 CASE_RETURN_STRING(WLAN_HDD_P2P_GO);
229 CASE_RETURN_STRING(WLAN_HDD_FTM);
230 CASE_RETURN_STRING(WLAN_HDD_IBSS);
231 CASE_RETURN_STRING(WLAN_HDD_P2P_DEVICE);
232 CASE_RETURN_STRING(WLAN_HDD_OCB);
233 default:
234 return "Unknown";
235 }
236}
237
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530238/**
239 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
240 * @adapter: HDD adapter
241 * @chan_number: Channel number
242 * @chan_bw: Bandwidth
243 *
244 * Checks if the given bandwidth is valid for the given channel number.
245 *
246 * Return: 0 for success, non-zero for failure
247 */
248int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
249 uint32_t chan_number,
250 phy_ch_width chan_bw)
251{
252 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
253 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
254 bool found = false;
255 tHalHandle hal;
256
257 hal = WLAN_HDD_GET_HAL_CTX(adapter);
258 if (!hal) {
259 hdd_err("Invalid HAL context");
260 return -EINVAL;
261 }
262
263 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
264 hdd_err("No valid channel list");
265 return -EOPNOTSUPP;
266 }
267
268 for (i = 0; i < len; i++) {
269 if (chan[i] == chan_number) {
270 found = true;
271 break;
272 }
273 }
274
275 if (found == false) {
276 hdd_err("Channel not in driver's valid channel list");
277 return -EOPNOTSUPP;
278 }
279
280 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
281 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
282 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
283 return -EINVAL;
284 }
285
286 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
287 if (chan_bw == CH_WIDTH_80MHZ) {
288 hdd_err("BW80 not possible in 2.4GHz band");
289 return -EINVAL;
290 }
291 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
292 (chan_bw != CH_WIDTH_MAX)) {
293 hdd_err("Only BW20 possible on channel 14");
294 return -EINVAL;
295 }
296 }
297
298 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
299 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
300 (chan_bw != CH_WIDTH_MAX)) {
301 hdd_err("Only BW20 possible on channel 165");
302 return -EINVAL;
303 }
304 }
305
306 return 0;
307}
308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309static int __hdd_netdev_notifier_call(struct notifier_block *nb,
310 unsigned long state, void *data)
311{
312#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
313 struct netdev_notifier_info *dev_notif_info = data;
314 struct net_device *dev = dev_notif_info->dev;
315#else
316 struct net_device *dev = data;
317#endif
318 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
319 hdd_context_t *hdd_ctx;
320
321 /* Make sure that this callback corresponds to our device. */
322 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
323 return NOTIFY_DONE;
324
325 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
326 (adapter->dev != dev)) {
327 hddLog(LOGE, FL("device adapter is not matching!!!"));
328 return NOTIFY_DONE;
329 }
330
331 if (!dev->ieee80211_ptr) {
332 hddLog(LOGE, FL("ieee80211_ptr is NULL!!!"));
333 return NOTIFY_DONE;
334 }
335
336 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
337 if (NULL == hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530338 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HDD Context Null Pointer"));
339 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340 return NOTIFY_DONE;
341 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800342 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343 return NOTIFY_DONE;
344
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530345 hddLog(QDF_TRACE_LEVEL_INFO, FL("%s New Net Device State = %lu"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800346 dev->name, state);
347
348 switch (state) {
349 case NETDEV_REGISTER:
350 break;
351
352 case NETDEV_UNREGISTER:
353 break;
354
355 case NETDEV_UP:
356 sme_ch_avoid_update_req(hdd_ctx->hHal);
357 break;
358
359 case NETDEV_DOWN:
360 break;
361
362 case NETDEV_CHANGE:
363 if (true == adapter->isLinkUpSvcNeeded)
364 complete(&adapter->linkup_event_var);
365 break;
366
367 case NETDEV_GOING_DOWN:
368 if (adapter->scan_info.mScanPending != false) {
369 unsigned long rc;
370 INIT_COMPLETION(adapter->scan_info.
371 abortscan_event_var);
372 hdd_abort_mac_scan(adapter->pHddCtx,
373 adapter->sessionId,
374 eCSR_SCAN_ABORT_DEFAULT);
375 rc = wait_for_completion_timeout(
376 &adapter->scan_info.abortscan_event_var,
377 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
378 if (!rc) {
379 hddLog(LOGE,
380 FL("Timeout occurred while waiting for abortscan"));
381 }
382 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530383 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 FL("Scan is not Pending from user"));
385 }
386 break;
387
388 default:
389 break;
390 }
391
392 return NOTIFY_DONE;
393}
394
395/**
396 * hdd_netdev_notifier_call() - netdev notifier callback function
397 * @nb: pointer to notifier block
398 * @state: state
399 * @ndev: ndev pointer
400 *
401 * Return: 0 on success, error number otherwise.
402 */
403static int hdd_netdev_notifier_call(struct notifier_block *nb,
404 unsigned long state,
405 void *ndev)
406{
407 int ret;
408
409 cds_ssr_protect(__func__);
410 ret = __hdd_netdev_notifier_call(nb, state, ndev);
411 cds_ssr_unprotect(__func__);
412
413 return ret;
414}
415
416struct notifier_block hdd_netdev_notifier = {
417 .notifier_call = hdd_netdev_notifier_call,
418};
419
420/* variable to hold the insmod parameters */
421static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800422
423/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530426/**
427 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
428 * @ch_width: NL channel width
429 *
430 * Converts the NL channel width to the driver's internal representation
431 *
432 * Return: Converted channel width. In case of non matching NL channel width,
433 * CH_WIDTH_MAX will be returned.
434 */
435phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
436{
437 switch (ch_width) {
438 case NL80211_CHAN_WIDTH_20_NOHT:
439 case NL80211_CHAN_WIDTH_20:
440 return CH_WIDTH_20MHZ;
441 case NL80211_CHAN_WIDTH_40:
442 return CH_WIDTH_40MHZ;
443 break;
444 case NL80211_CHAN_WIDTH_80:
445 return CH_WIDTH_80MHZ;
446 case NL80211_CHAN_WIDTH_80P80:
447 return CH_WIDTH_80P80MHZ;
448 case NL80211_CHAN_WIDTH_160:
449 return CH_WIDTH_160MHZ;
450 case NL80211_CHAN_WIDTH_5:
451 case NL80211_CHAN_WIDTH_10:
452 default:
453 hdd_err("Invalid channel width %d, setting to default",
454 ch_width);
455 return CH_WIDTH_MAX;
456 }
457}
458
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530459/* wlan_hdd_find_opclass() - Find operating class for a channel
460 * @hal: handler to HAL
461 * @channel: channel id
462 * @bw_offset: bandwidth offset
463 *
464 * Function invokes sme api to find the operating class
465 *
466 * Return: operating class
467 */
468uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
469 uint8_t bw_offset)
470{
471 uint8_t opclass = 0;
472
473 sme_get_opclass(hal, channel, bw_offset, &opclass);
474 return opclass;
475}
476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530478 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800479 * @moduleId: Module whose trace level is being configured
480 * @bitmask: Bitmask of log levels to be enabled
481 *
482 * Called immediately after the cfg.ini is read in order to configure
483 * the desired trace levels.
484 *
485 * Return: None
486 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530487static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530489 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490
491 /*
492 * if the bitmask is the default value, then a bitmask was not
493 * specified in cfg.ini, so leave the logging level alone (it
494 * will remain at the "compiled in" default value)
495 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530496 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 return;
498 }
499
500 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530501 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502
503 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530504 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 while (0 != bitmask) {
506 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530507 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 }
509 level++;
510 bitmask >>= 1;
511 }
512}
513
514/**
515 * wlan_hdd_validate_context() - check the HDD context
516 * @hdd_ctx: HDD context pointer
517 *
518 * Return: 0 if the context is valid. Error code otherwise
519 */
520int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
521{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
523 hddLog(LOGE, FL("HDD context is Null"));
524 return -ENODEV;
525 }
526
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800527 if (cds_is_driver_recovering()) {
528 hdd_err("Recovery in Progress. State: 0x%x Ignore!!!",
529 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530 return -EAGAIN;
531 }
532
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800533 if (cds_is_load_or_unload_in_progress()) {
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800534 hdd_err("Unloading/Loading in Progress. Ignore!!!: 0x%x",
535 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536 return -EAGAIN;
537 }
538 return 0;
539}
540
541void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
542{
543 hdd_adapter_t *adapter = NULL;
544 hdd_station_ctx_t *pHddStaCtx = NULL;
545 eCsrPhyMode phyMode;
546 struct hdd_config *cfg_param = NULL;
547
548 if (NULL == hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530549 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HDD Context is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 return;
551 }
552
553 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
554 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530555 hddLog(QDF_TRACE_LEVEL_FATAL, FL("adapter is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 return;
557 }
558
559 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
560
561 cfg_param = hdd_ctx->config;
562 if (NULL == cfg_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530563 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564 FL("cfg_params not available !!"));
565 return;
566 }
567
568 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
569
570 if (!hdd_ctx->isVHT80Allowed) {
571 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
572 (eCSR_DOT11_MODE_11ac == phyMode) ||
573 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530574 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575 FL("Setting phymode to 11n!!"));
576 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
577 eCSR_DOT11_MODE_11n);
578 }
579 } else {
580 /*
581 * New country Supports 11ac as well resetting value back from
582 * .ini
583 */
584 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
585 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
586 dot11Mode));
587 return;
588 }
589
590 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
591 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
592 || (eCSR_CFG_DOT11_MODE_11AC ==
593 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530594 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595
596 /* need to issue a disconnect to CSR. */
597 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530598 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599 adapter->sessionId,
600 eCSR_DISCONNECT_REASON_UNSPECIFIED);
601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530602 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 unsigned long rc;
604
605 rc = wait_for_completion_timeout(
606 &adapter->disconnect_comp_var,
607 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
608 if (!rc)
609 hddLog(LOGE,
610 FL("failure waiting for disconnect_comp_var"));
611 }
612 }
613}
614
615/**
616 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
617 * @hdd_adapter_t Hdd adapter.
618 *
619 * This function sets the IBSS power save config parameters to WMA
620 * which will send it to firmware if FW supports IBSS power save
621 * before vdev start.
622 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530623 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 * on failure.
625 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530626QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627{
628 int ret;
629 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
630
631 if (hdd_ctx == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530632 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800633 FL("HDD context is null"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530634 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 }
636
637 ret = wma_cli_set_command(adapter->sessionId,
638 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
639 hdd_ctx->config->ibssATIMWinSize,
640 VDEV_CMD);
641 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530642 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643 FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530644 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645 }
646
647 ret = wma_cli_set_command(adapter->sessionId,
648 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
649 hdd_ctx->config->isIbssPowerSaveAllowed,
650 VDEV_CMD);
651 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530652 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"),
654 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530655 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 }
657
658 ret = wma_cli_set_command(adapter->sessionId,
659 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
660 hdd_ctx->config->
661 isIbssPowerCollapseAllowed, VDEV_CMD);
662 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530663 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"),
665 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530666 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 }
668
669 ret = wma_cli_set_command(adapter->sessionId,
670 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
671 hdd_ctx->config->isIbssAwakeOnTxRx,
672 VDEV_CMD);
673 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530674 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 }
678
679 ret = wma_cli_set_command(adapter->sessionId,
680 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
681 hdd_ctx->config->ibssInactivityCount,
682 VDEV_CMD);
683 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530684 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530686 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 }
688
689 ret = wma_cli_set_command(adapter->sessionId,
690 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
691 hdd_ctx->config->ibssTxSpEndInactivityTime,
692 VDEV_CMD);
693 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530694 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 FL(
696 "WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d"
697 ),
698 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530699 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 }
701
702 ret = wma_cli_set_command(adapter->sessionId,
703 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
704 hdd_ctx->config->ibssPsWarmupTime,
705 VDEV_CMD);
706 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530707 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"),
709 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530710 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 }
712
713 ret = wma_cli_set_command(adapter->sessionId,
714 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
715 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
716 VDEV_CMD);
717 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530718 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 FL(
720 "WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d"
721 ),
722 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530723 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 }
725
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530726 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727}
728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729#define INTF_MACADDR_MASK 0x7
730
731/**
732 * hdd_update_macaddr() - update mac address
733 * @config: hdd configuration
734 * @hw_macaddr: mac address
735 *
736 * Mac address for multiple virtual interface is found as following
737 * i) The mac address of the first interface is just the actual hw mac address.
738 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
739 * define the mac address for the remaining interfaces and locally
740 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
741 * supported virtual interfaces, right now this is 0x07 (meaning 8
742 * interface).
743 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
744 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
745 *
746 * Return: None
747 */
748void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530749 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800750{
751 int8_t i;
752 uint8_t macaddr_b3, tmp_br3;
753
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530754 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530755 QDF_MAC_ADDR_SIZE);
756 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530757 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530758 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800759 macaddr_b3 = config->intfMacAddr[i].bytes[3];
760 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
761 INTF_MACADDR_MASK;
762 macaddr_b3 += tmp_br3;
763
764 /* XOR-ing bit-24 of the mac address. This will give enough
765 * mac address range before collision
766 */
767 macaddr_b3 ^= (1 << 7);
768
769 /* Set locally administered bit */
770 config->intfMacAddr[i].bytes[0] |= 0x02;
771 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530772 hddLog(QDF_TRACE_LEVEL_INFO, "config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 MAC_ADDRESS_STR, i,
774 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
775 }
776}
777
778static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
779 struct wma_tgt_services *cfg)
780{
781 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782
783 /* Set up UAPSD */
784 config->apUapsdEnabled &= cfg->uapsd;
785
786#ifdef WLAN_FEATURE_11AC
787 /* 11AC mode support */
788 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
789 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
790 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
791#endif /* #ifdef WLAN_FEATURE_11AC */
792
793 /* ARP offload: override user setting if invalid */
794 config->fhostArpOffload &= cfg->arp_offload;
795
796#ifdef FEATURE_WLAN_SCAN_PNO
797 /* PNO offload */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530798 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 FL("PNO Capability in f/w = %d"), cfg->pno_offload);
800 if (cfg->pno_offload)
801 config->PnoOffload = true;
802#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800803#ifdef FEATURE_WLAN_TDLS
804 config->fEnableTDLSSupport &= cfg->en_tdls;
805 config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan;
806 config->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta;
807 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
808 config->fEnableTDLSSleepSta = true;
809 } else {
810 config->fEnableTDLSSleepSta = false;
811 }
812#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813#ifdef WLAN_FEATURE_ROAM_OFFLOAD
814 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
815#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700816 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817
818}
819
820static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
821 struct wma_tgt_ht_cap *cfg)
822{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530823 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824 uint32_t value, val32;
825 uint16_t val16;
826 struct hdd_config *pconfig = hdd_ctx->config;
827 tSirMacHTCapabilityInfo *phtCapInfo;
828 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
829 uint8_t enable_tx_stbc;
830
831 /* check and update RX STBC */
832 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
833 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
834
835 /* get the MPDU density */
836 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
837
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530838 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530839 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840 FL("could not get MPDU DENSITY"));
841 value = 0;
842 }
843
844 /*
845 * MPDU density:
846 * override user's setting if value is larger
847 * than the one supported by target
848 */
849 if (value > cfg->mpdu_density) {
850 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
851 cfg->mpdu_density);
852
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530853 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530854 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855 FL("could not set MPDU DENSITY to CCM"));
856 }
857
858 /* get the HT capability info */
859 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530860 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530861 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862 FL("could not get HT capability info"));
863 return;
864 }
865 val16 = (uint16_t) val32;
866 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
867
868 /* Set the LDPC capability */
869 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
870
871 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
872 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
873
874 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
875 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
876
877 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
878 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
879
880 enable_tx_stbc = pconfig->enableTxSTBC;
881
882 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
883 pconfig->enable2x2 = 1;
884 } else {
885 pconfig->enable2x2 = 0;
886 enable_tx_stbc = 0;
887
888 /* 1x1 */
889 /* Update Rx Highest Long GI data Rate */
890 if (sme_cfg_set_int(hdd_ctx->hHal,
891 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
892 HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530893 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 hddLog(LOGE,
895 FL(
896 "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"
897 ));
898 }
899
900 /* Update Tx Highest Long GI data Rate */
901 if (sme_cfg_set_int
902 (hdd_ctx->hHal,
903 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
904 HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530905 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 hddLog(LOGE,
907 FL(
908 "Could not pass on HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"
909 ));
910 }
911 }
912 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
913 enable_tx_stbc = 0;
914 phtCapInfo->txSTBC = enable_tx_stbc;
915
916 val32 = val16;
917 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530918 if (status != QDF_STATUS_SUCCESS)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530919 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920 FL("could not set HT capability to CCM"));
921#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
922 value = SIZE_OF_SUPPORTED_MCS_SET;
923 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530924 &value) == QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530925 hddLog(QDF_TRACE_LEVEL_INFO, FL("Read MCS rate set"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926
927 if (pconfig->enable2x2) {
928 for (value = 0; value < cfg->num_rf_chains; value++)
929 mcs_set[value] =
930 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
931
932 status =
933 sme_cfg_set_str(hdd_ctx->hHal,
934 WNI_CFG_SUPPORTED_MCS_SET,
935 mcs_set,
936 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530937 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530938 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 FL("could not set MCS SET to CCM"));
940 }
941 }
942#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
943}
944
945#ifdef WLAN_FEATURE_11AC
946static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
947 struct wma_tgt_vht_cap *cfg)
948{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530949 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 uint32_t value = 0;
951 struct hdd_config *pconfig = hdd_ctx->config;
952 struct wiphy *wiphy = hdd_ctx->wiphy;
953 struct ieee80211_supported_band *band_5g =
954 wiphy->bands[IEEE80211_BAND_5GHZ];
955
956 /* Get the current MPDU length */
957 status =
958 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
959 &value);
960
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530962 hddLog(QDF_TRACE_LEVEL_ERROR, FL("could not get MPDU LENGTH"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 value = 0;
964 }
965
966 /*
967 * VHT max MPDU length:
968 * override if user configured value is too high
969 * that the target cannot support
970 */
971 if (value > cfg->vht_max_mpdu) {
972 status = sme_cfg_set_int(hdd_ctx->hHal,
973 WNI_CFG_VHT_MAX_MPDU_LENGTH,
974 cfg->vht_max_mpdu);
975
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530976 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530977 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 FL("could not set VHT MAX MPDU LENGTH"));
979 }
980 }
981
982 /* Get the current supported chan width */
983 status = sme_cfg_get_int(hdd_ctx->hHal,
984 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
985 &value);
986
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530987 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530988 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989 FL("could not get MPDU LENGTH"));
990 value = 0;
991 }
992
993 /* Get the current RX LDPC setting */
994 status =
995 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
996 &value);
997
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530998 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530999 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 FL("could not get VHT LDPC CODING CAP"));
1001 value = 0;
1002 }
1003
1004 /* Set the LDPC capability */
1005 if (value && !cfg->vht_rx_ldpc) {
1006 status = sme_cfg_set_int(hdd_ctx->hHal,
1007 WNI_CFG_VHT_LDPC_CODING_CAP,
1008 cfg->vht_rx_ldpc);
1009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301010 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301011 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 FL("could not set VHT LDPC CODING CAP to CCM"));
1013 }
1014 }
1015
1016 /* Get current GI 80 value */
1017 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1018 &value);
1019
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301020 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301021 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001022 FL("could not get SHORT GI 80MHZ"));
1023 value = 0;
1024 }
1025
1026 /* set the Guard interval 80MHz */
1027 if (value && !cfg->vht_short_gi_80) {
1028 status = sme_cfg_set_int(hdd_ctx->hHal,
1029 WNI_CFG_VHT_SHORT_GI_80MHZ,
1030 cfg->vht_short_gi_80);
1031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301032 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301033 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001034 FL("could not set SHORT GI 80MHZ to CCM"));
1035 }
1036 }
1037
1038 /* Get current GI 160 value */
1039 status = sme_cfg_get_int(hdd_ctx->hHal,
1040 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1041 &value);
1042
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301043 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301044 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001045 FL("could not get SHORT GI 80 & 160"));
1046 value = 0;
1047 }
1048
1049 /* Get VHT TX STBC cap */
1050 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1051
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301052 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301053 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001054 FL("could not get VHT TX STBC"));
1055 value = 0;
1056 }
1057
1058 /* VHT TX STBC cap */
1059 if (value && !cfg->vht_tx_stbc) {
1060 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1061 cfg->vht_tx_stbc);
1062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301063 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301064 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001065 FL("could not set the VHT TX STBC to CCM"));
1066 }
1067 }
1068
1069 /* Get VHT RX STBC cap */
1070 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1071
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301072 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301073 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 FL("could not get VHT RX STBC"));
1075 value = 0;
1076 }
1077
1078 /* VHT RX STBC cap */
1079 if (value && !cfg->vht_rx_stbc) {
1080 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1081 cfg->vht_rx_stbc);
1082
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301083 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301084 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001085 FL("could not set the VHT RX STBC to CCM"));
1086 }
1087 }
1088
1089 /* Get VHT SU Beamformer cap */
1090 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1091 &value);
1092
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301093 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301094 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001095 FL("could not get VHT SU BEAMFORMER CAP"));
1096 value = 0;
1097 }
1098
1099 /* set VHT SU Beamformer cap */
1100 if (value && !cfg->vht_su_bformer) {
1101 status = sme_cfg_set_int(hdd_ctx->hHal,
1102 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1103 cfg->vht_su_bformer);
1104
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301105 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301106 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107 FL("could not set VHT SU BEAMFORMER CAP"));
1108 }
1109 }
1110
1111 /* check and update SU BEAMFORMEE capabality */
1112 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1113 pconfig->enableTxBF = cfg->vht_su_bformee;
1114
1115 status = sme_cfg_set_int(hdd_ctx->hHal,
1116 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1117 pconfig->enableTxBF);
1118
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301119 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301120 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 FL("could not set VHT SU BEAMFORMEE CAP"));
1122 }
1123
1124 /* Get VHT MU Beamformer cap */
1125 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1126 &value);
1127
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301128 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301129 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130 FL("could not get VHT MU BEAMFORMER CAP"));
1131 value = 0;
1132 }
1133
1134 /* set VHT MU Beamformer cap */
1135 if (value && !cfg->vht_mu_bformer) {
1136 status = sme_cfg_set_int(hdd_ctx->hHal,
1137 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1138 cfg->vht_mu_bformer);
1139
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301140 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301141 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 FL(
1143 "could not set the VHT MU BEAMFORMER CAP to CCM"
1144 ));
1145 }
1146 }
1147
1148 /* Get VHT MU Beamformee cap */
1149 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1150 &value);
1151
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301152 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301153 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 FL("could not get VHT MU BEAMFORMEE CAP"));
1155 value = 0;
1156 }
1157
1158 /* set VHT MU Beamformee cap */
1159 if (value && !cfg->vht_mu_bformee) {
1160 status = sme_cfg_set_int(hdd_ctx->hHal,
1161 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1162 cfg->vht_mu_bformee);
1163
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301164 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301165 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166 FL("could not set VHT MU BEAMFORMER CAP"));
1167 }
1168 }
1169
1170 /* Get VHT MAX AMPDU Len exp */
1171 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1172 &value);
1173
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301174 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301175 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001176 FL("could not get VHT AMPDU LEN"));
1177 value = 0;
1178 }
1179
1180 /*
1181 * VHT max AMPDU len exp:
1182 * override if user configured value is too high
1183 * that the target cannot support.
1184 * Even though Rome publish ampdu_len=7, it can
1185 * only support 4 because of some h/w bug.
1186 */
1187
1188 if (value > cfg->vht_max_ampdu_len_exp) {
1189 status = sme_cfg_set_int(hdd_ctx->hHal,
1190 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1191 cfg->vht_max_ampdu_len_exp);
1192
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301193 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301194 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 FL("could not set the VHT AMPDU LEN EXP"));
1196 }
1197 }
1198
1199 /* Get VHT TXOP PS CAP */
1200 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1201
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301202 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301203 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204 FL("could not get VHT TXOP PS"));
1205 value = 0;
1206 }
1207
1208 /* set VHT TXOP PS cap */
1209 if (value && !cfg->vht_txop_ps) {
1210 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1211 cfg->vht_txop_ps);
1212
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301213 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301214 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 FL("could not set the VHT TXOP PS"));
1216 }
1217 }
1218
1219 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1220 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1221 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1222 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1223 else
1224 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1225
1226
1227 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ)) {
1228 band_5g->vht_cap.cap |=
1229 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1230 }
1231 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ)) {
1232 band_5g->vht_cap.cap |=
1233 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1234 }
1235
1236 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1237 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1238
1239 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1240 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1241 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1242 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1243
1244 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1245 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1246
1247 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1248 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1249 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1250 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1251 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1252 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1253
1254 band_5g->vht_cap.cap |=
1255 (cfg->vht_max_ampdu_len_exp <<
1256 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1257
1258 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1259 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1260 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1261 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1262 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1263 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1264 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1265 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1266
1267 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1268 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1269
1270}
1271#endif /* #ifdef WLAN_FEATURE_11AC */
1272
1273void hdd_update_tgt_cfg(void *context, void *param)
1274{
1275 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1276 struct wma_tgt_cfg *cfg = param;
1277 uint8_t temp_band_cap;
1278
1279 /* first store the INI band capability */
1280 temp_band_cap = hdd_ctx->config->nBandCapability;
1281
1282 hdd_ctx->config->nBandCapability = cfg->band_cap;
1283
1284 /* now overwrite the target band capability with INI
1285 setting if INI setting is a subset */
1286
1287 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1288 (temp_band_cap != eCSR_BAND_ALL))
1289 hdd_ctx->config->nBandCapability = temp_band_cap;
1290 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1291 (temp_band_cap != eCSR_BAND_ALL) &&
1292 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301293 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294 FL("ini BandCapability not supported by the target"));
1295 }
1296
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001297 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1299 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1300 }
1301
1302 /* This can be extended to other configurations like ht, vht cap... */
1303
Anurag Chouhanc5548422016-02-24 18:33:27 +05301304 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1306 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301307 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308 FL(
1309 "Invalid MAC passed from target, using MAC from ini file"
1310 MAC_ADDRESS_STR),
1311 MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes));
1312 }
1313
1314 hdd_ctx->target_fw_version = cfg->target_fw_version;
1315
1316 hdd_ctx->max_intf_count = cfg->max_intf_count;
1317
1318#ifdef WLAN_FEATURE_LPSS
1319 hdd_ctx->lpss_support = cfg->lpss_support;
1320#endif
1321
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001322 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1325 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1326
1327 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1328
1329#ifdef WLAN_FEATURE_11AC
1330 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
1331#endif /* #ifdef WLAN_FEATURE_11AC */
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001332 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
1333 hdd_info(FL("fine_time_meas_cap: 0x%x"),
1334 hdd_ctx->config->fine_time_meas_cap);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001335}
1336
1337/**
1338 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1339 * @context: HDD context pointer
1340 * @param: HDD radar indication pointer
1341 *
1342 * This function is invoked when a radar in found on the
1343 * SAP current operating channel and Data Tx from netif
1344 * has to be stopped to honor the DFS regulations.
1345 * Actions: Stop the netif Tx queues,Indicate Radar present
1346 * in HDD context for future usage.
1347 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301348 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301350bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351{
1352 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1353 struct wma_dfs_radar_ind *hdd_radar_event =
1354 (struct wma_dfs_radar_ind *)param;
1355 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1356 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301357 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301359 if (!hdd_ctx || !hdd_radar_event ||
1360 hdd_ctx->config->disableDFSChSwitch)
1361 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362
1363 if (true == hdd_radar_event->dfs_radar_status) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301364 mutex_lock(&hdd_ctx->dfs_lock);
1365 if (hdd_ctx->dfs_radar_found) {
1366 /*
1367 * Application already triggered channel switch
1368 * on current channel, so return here.
1369 */
1370 mutex_unlock(&hdd_ctx->dfs_lock);
1371 return false;
1372 }
1373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 hdd_ctx->dfs_radar_found = true;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301375 mutex_unlock(&hdd_ctx->dfs_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376
1377 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301378 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 adapter = adapterNode->pAdapter;
1380 if (WLAN_HDD_SOFTAP == adapter->device_mode ||
1381 WLAN_HDD_P2P_GO == adapter->device_mode) {
1382 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1383 dfs_cac_block_tx = true;
1384 }
1385
1386 status = hdd_get_next_adapter(hdd_ctx,
1387 adapterNode,
1388 &pNext);
1389 adapterNode = pNext;
1390 }
1391 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301392
1393 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395
1396/**
1397 * hdd_is_valid_mac_address() - validate MAC address
1398 * @pMacAddr: Pointer to the input MAC address
1399 *
1400 * This function validates whether the given MAC address is valid or not
1401 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1402 * where X is the hexa decimal digit character and separated by ':'
1403 * This algorithm works even if MAC address is not separated by ':'
1404 *
1405 * This code checks given input string mac contains exactly 12 hexadecimal
1406 * digits and a separator colon : appears in the input string only after
1407 * an even number of hex digits.
1408 *
1409 * Return: 1 for valid and 0 for invalid
1410 */
1411bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1412{
1413 int xdigit = 0;
1414 int separator = 0;
1415 while (*pMacAddr) {
1416 if (isxdigit(*pMacAddr)) {
1417 xdigit++;
1418 } else if (':' == *pMacAddr) {
1419 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1420 break;
1421
1422 ++separator;
1423 } else {
1424 /* Invalid MAC found */
1425 return 0;
1426 }
1427 ++pMacAddr;
1428 }
1429 return xdigit == 12 && (separator == 5 || separator == 0);
1430}
1431
1432/**
1433 * __hdd_open() - HDD Open function
1434 * @dev: Pointer to net_device structure
1435 *
1436 * This is called in response to ifconfig up
1437 *
1438 * Return: 0 for success; non-zero for failure
1439 */
1440static int __hdd_open(struct net_device *dev)
1441{
1442 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1443 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1444 int ret;
1445
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301446 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 adapter->sessionId, adapter->device_mode));
1448
1449 ret = wlan_hdd_validate_context(hdd_ctx);
1450 if (0 != ret) {
1451 hddLog(LOGE, FL("HDD context is not valid"));
1452 return ret;
1453 }
1454
1455 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1456 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
1457 hddLog(LOG1, FL("Enabling Tx Queues"));
1458 /* Enable TX queues only when we are connected */
1459 wlan_hdd_netif_queue_control(adapter,
1460 WLAN_START_ALL_NETIF_QUEUE,
1461 WLAN_CONTROL_PATH);
1462 }
1463
1464 return ret;
1465}
1466
1467/**
1468 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1469 * @dev: Pointer to net_device structure
1470 *
1471 * This is called in response to ifconfig up
1472 *
1473 * Return: 0 for success; non-zero for failure
1474 */
1475int hdd_open(struct net_device *dev)
1476{
1477 int ret;
1478
1479 cds_ssr_protect(__func__);
1480 ret = __hdd_open(dev);
1481 cds_ssr_unprotect(__func__);
1482
1483 return ret;
1484}
1485
1486/**
1487 * __hdd_stop() - HDD stop function
1488 * @dev: Pointer to net_device structure
1489 *
1490 * This is called in response to ifconfig down
1491 *
1492 * Return: 0 for success; non-zero for failure
1493 */
1494static int __hdd_stop(struct net_device *dev)
1495{
1496 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1497 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1498 int ret;
1499
1500 ENTER();
1501
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301502 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001503 adapter->sessionId, adapter->device_mode));
1504
1505 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301506 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001507 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508
1509 /* Nothing to be done if the interface is not opened */
1510 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301511 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001512 FL("NETDEV Interface is not OPENED"));
1513 return -ENODEV;
1514 }
1515
1516 /* Make sure the interface is marked as closed */
1517 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301518 hddLog(QDF_TRACE_LEVEL_INFO, FL("Disabling OS Tx queues"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519
1520 /*
1521 * Disable TX on the interface, after this hard_start_xmit() will not
1522 * be called on that interface
1523 */
1524 hddLog(LOG1, FL("Disabling queues"));
1525 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1526 WLAN_CONTROL_PATH);
1527
1528 /*
1529 * The interface is marked as down for outside world (aka kernel)
1530 * But the driver is pretty much alive inside. The driver needs to
1531 * tear down the existing connection on the netdev (session)
1532 * cleanup the data pipes and wait until the control plane is stabilized
1533 * for this interface. The call also needs to wait until the above
1534 * mentioned actions are completed before returning to the caller.
1535 * Notice that the hdd_stop_adapter is requested not to close the session
1536 * That is intentional to be able to scan if it is a STA/P2P interface
1537 */
1538 hdd_stop_adapter(hdd_ctx, adapter, false);
1539
1540 /* DeInit the adapter. This ensures datapath cleanup as well */
1541 hdd_deinit_adapter(hdd_ctx, adapter, true);
1542
1543 EXIT();
1544 return 0;
1545}
1546
1547/**
1548 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
1549 * @dev: pointer to net_device structure
1550 *
1551 * This is called in response to ifconfig down
1552 *
1553 * Return: 0 for success and error number for failure
1554 */
1555int hdd_stop(struct net_device *dev)
1556{
1557 int ret;
1558
1559 cds_ssr_protect(__func__);
1560 ret = __hdd_stop(dev);
1561 cds_ssr_unprotect(__func__);
1562
1563 return ret;
1564}
1565
1566/**
1567 * __hdd_uninit() - HDD uninit function
1568 * @dev: Pointer to net_device structure
1569 *
1570 * This is called during the netdev unregister to uninitialize all data
1571 * associated with the device
1572 *
1573 * Return: None
1574 */
1575static void __hdd_uninit(struct net_device *dev)
1576{
1577 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1578
1579 ENTER();
1580
1581 do {
1582 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1583 hddLog(LOGP, FL("Invalid magic"));
1584 break;
1585 }
1586
1587 if (NULL == adapter->pHddCtx) {
1588 hddLog(LOGP, FL("NULL hdd_ctx"));
1589 break;
1590 }
1591
1592 if (dev != adapter->dev) {
1593 hddLog(LOGP, FL("Invalid device reference"));
1594 /*
1595 * we haven't validated all cases so let this go for
1596 * now
1597 */
1598 }
1599
1600 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
1601
1602 /* after uninit our adapter structure will no longer be valid */
1603 adapter->dev = NULL;
1604 adapter->magic = 0;
1605 } while (0);
1606
1607 EXIT();
1608}
1609
1610/**
1611 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
1612 * @dev: pointer to net_device structure
1613 *
1614 * This is called during the netdev unregister to uninitialize all data
1615 * associated with the device
1616 *
1617 * Return: none
1618 */
1619static void hdd_uninit(struct net_device *dev)
1620{
1621 cds_ssr_protect(__func__);
1622 __hdd_uninit(dev);
1623 cds_ssr_unprotect(__func__);
1624}
1625
1626/**
1627 * __hdd_set_mac_address() - set the user specified mac address
1628 * @dev: Pointer to the net device.
1629 * @addr: Pointer to the sockaddr.
1630 *
1631 * This function sets the user specified mac address using
1632 * the command ifconfig wlanX hw ether <mac adress>.
1633 *
1634 * Return: 0 for success, non zero for failure
1635 */
1636static int __hdd_set_mac_address(struct net_device *dev, void *addr)
1637{
1638 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1639 hdd_context_t *hdd_ctx;
1640 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301641 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001642 int ret;
1643
1644 ENTER();
1645
1646 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1647 ret = wlan_hdd_validate_context(hdd_ctx);
1648 if (0 != ret)
1649 return ret;
1650
1651 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1652 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1653
1654 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301655 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656}
1657
1658/**
1659 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
1660 * function from SSR
1661 * @dev: pointer to net_device structure
1662 * @addr: Pointer to the sockaddr
1663 *
1664 * This function sets the user specified mac address using
1665 * the command ifconfig wlanX hw ether <mac adress>.
1666 *
1667 * Return: 0 for success.
1668 */
1669static int hdd_set_mac_address(struct net_device *dev, void *addr)
1670{
1671 int ret;
1672
1673 cds_ssr_protect(__func__);
1674 ret = __hdd_set_mac_address(dev, addr);
1675 cds_ssr_unprotect(__func__);
1676
1677 return ret;
1678}
1679
1680uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
1681{
1682 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301683 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
1685 break;
1686 }
1687
Anurag Chouhan6d760662016-02-20 16:05:43 +05301688 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689 return NULL;
1690
1691 hdd_ctx->config->intfAddrMask |= (1 << i);
1692 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
1693}
1694
1695void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
1696{
1697 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301698 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001699 if (!memcmp(releaseAddr,
1700 &hdd_ctx->config->intfMacAddr[i].bytes[0],
1701 6)) {
1702 hdd_ctx->config->intfAddrMask &= ~(1 << i);
1703 break;
1704 }
1705 }
1706 return;
1707}
1708
1709#ifdef WLAN_FEATURE_PACKET_FILTERING
1710/**
1711 * __hdd_set_multicast_list() - set the multicast address list
1712 * @dev: Pointer to the WLAN device.
1713 * @skb: Pointer to OS packet (sk_buff).
1714 *
1715 * This funciton sets the multicast address list.
1716 *
1717 * Return: None
1718 */
1719static void __hdd_set_multicast_list(struct net_device *dev)
1720{
1721 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1722 int mc_count;
1723 int i = 0, status;
1724 struct netdev_hw_addr *ha;
1725 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1726 static const uint8_t ipv6_router_solicitation[]
1727 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
1728
Anurag Chouhan6d760662016-02-20 16:05:43 +05301729 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05301730 return;
1731
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301732 ENTER();
1733
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001734 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301735 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737
1738 if (dev->flags & IFF_ALLMULTI) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301739 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001740 FL("allow all multicast frames"));
1741 adapter->mc_addr_list.mc_cnt = 0;
1742 } else {
1743 mc_count = netdev_mc_count(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301744 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001745 FL("mc_count = %u"), mc_count);
1746 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301747 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748 FL(
1749 "No free filter available; allow all multicast frames"
1750 ));
1751 adapter->mc_addr_list.mc_cnt = 0;
1752 return;
1753 }
1754
1755 adapter->mc_addr_list.mc_cnt = mc_count;
1756
1757 netdev_for_each_mc_addr(ha, dev) {
1758 if (i == mc_count)
1759 break;
1760 /*
1761 * Skip following addresses:
1762 * 1)IPv6 router solicitation address
1763 * 2)Any other address pattern if its set during
1764 * RXFILTER REMOVE driver command based on
1765 * addr_filter_pattern
1766 */
1767 if ((!memcmp(ha->addr, ipv6_router_solicitation,
1768 ETH_ALEN)) ||
1769 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
1770 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08001771 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001772 MAC_ADDR_ARRAY(ha->addr));
1773 adapter->mc_addr_list.mc_cnt--;
1774 continue;
1775 }
1776
1777 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
1778 ETH_ALEN);
1779 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
1780 ETH_ALEN);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301781 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 FL("mlist[%d] = " MAC_ADDRESS_STR), i,
1783 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
1784 i++;
1785 }
1786 }
1787 if (hdd_ctx->config->active_mode_offload) {
1788 hdd_info("enable mc filtering");
1789 wlan_hdd_set_mc_addr_list(adapter, true);
1790 } else {
1791 hdd_info("skip mc filtering enable it during cfg80211 suspend");
1792 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301793 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794 return;
1795}
1796
1797/**
1798 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
1799 * @dev: pointer to net_device
1800 *
1801 * Return: none
1802 */
1803static void hdd_set_multicast_list(struct net_device *dev)
1804{
1805 cds_ssr_protect(__func__);
1806 __hdd_set_multicast_list(dev);
1807 cds_ssr_unprotect(__func__);
1808}
1809#endif
1810
1811/**
1812 * hdd_select_queue() - used by Linux OS to decide which queue to use first
1813 * @dev: Pointer to the WLAN device.
1814 * @skb: Pointer to OS packet (sk_buff).
1815 *
1816 * This function is registered with the Linux OS for network
1817 * core to decide which queue to use first.
1818 *
1819 * Return: ac, Queue Index/access category corresponding to UP in IP header
1820 */
1821static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
1822#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
1823 , void *accel_priv
1824#endif
1825#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1826 , select_queue_fallback_t fallback
1827#endif
1828)
1829{
1830 return hdd_wmm_select_queue(dev, skb);
1831}
1832
1833static struct net_device_ops wlan_drv_ops = {
1834 .ndo_open = hdd_open,
1835 .ndo_stop = hdd_stop,
1836 .ndo_uninit = hdd_uninit,
1837 .ndo_start_xmit = hdd_hard_start_xmit,
1838 .ndo_tx_timeout = hdd_tx_timeout,
1839 .ndo_get_stats = hdd_get_stats,
1840 .ndo_do_ioctl = hdd_ioctl,
1841 .ndo_set_mac_address = hdd_set_mac_address,
1842 .ndo_select_queue = hdd_select_queue,
1843#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001844 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001845#endif
1846};
1847
1848void hdd_set_station_ops(struct net_device *pWlanDev)
1849{
1850 pWlanDev->netdev_ops = &wlan_drv_ops;
1851}
1852
1853static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
1854 tSirMacAddr macAddr,
1855 const char *name)
1856{
1857 struct net_device *pWlanDev = NULL;
1858 hdd_adapter_t *adapter = NULL;
1859 /*
1860 * cfg80211 initialization and registration....
1861 */
1862 pWlanDev =
1863 alloc_netdev_mq(sizeof(hdd_adapter_t), name,
1864#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
1865 NET_NAME_UNKNOWN,
1866#endif
1867 ether_setup,
1868 NUM_TX_QUEUES);
1869
1870 if (pWlanDev != NULL) {
1871
1872 /* Save the pointer to the net_device in the HDD adapter */
1873 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
1874
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301875 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876
1877 adapter->dev = pWlanDev;
1878 adapter->pHddCtx = hdd_ctx;
1879 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1880
1881 init_completion(&adapter->session_open_comp_var);
1882 init_completion(&adapter->session_close_comp_var);
1883 init_completion(&adapter->disconnect_comp_var);
1884 init_completion(&adapter->linkup_event_var);
1885 init_completion(&adapter->cancel_rem_on_chan_var);
1886 init_completion(&adapter->rem_on_chan_ready_event);
1887 init_completion(&adapter->sta_authorized_event);
1888 init_completion(&adapter->offchannel_tx_event);
1889 init_completion(&adapter->tx_action_cnf_event);
1890#ifdef FEATURE_WLAN_TDLS
1891 init_completion(&adapter->tdls_add_station_comp);
1892 init_completion(&adapter->tdls_del_station_comp);
1893 init_completion(&adapter->tdls_mgmt_comp);
1894 init_completion(&adapter->tdls_link_establish_req_comp);
1895#endif
1896 init_completion(&adapter->change_country_code);
1897
1898
1899 init_completion(&adapter->scan_info.abortscan_event_var);
1900
1901 adapter->offloads_configured = false;
1902 adapter->isLinkUpSvcNeeded = false;
1903 adapter->higherDtimTransition = true;
1904 /* Init the net_device structure */
1905 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1906
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301907 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301909 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910 sizeof(tSirMacAddr));
1911 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912
1913 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
1914 pWlanDev->features |=
1915 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
1916 pWlanDev->features |= NETIF_F_RXCSUM;
1917
Dhanashri Atre83d373d2015-07-28 16:45:59 -07001918 hdd_set_tso_flags(hdd_ctx, pWlanDev);
1919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920 hdd_set_station_ops(adapter->dev);
1921
1922 pWlanDev->destructor = free_netdev;
1923 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08001924 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001925 adapter->wdev.wiphy = hdd_ctx->wiphy;
1926 adapter->wdev.netdev = pWlanDev;
1927 /* set pWlanDev's parent to underlying device */
1928 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
1929 hdd_wmm_init(adapter);
1930 spin_lock_init(&adapter->pause_map_lock);
1931 }
1932
1933 return adapter;
1934}
1935
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301936QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001937 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938{
1939 struct net_device *pWlanDev = adapter->dev;
1940 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
1941 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301942 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08001944 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
1946 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301947 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 FL("Failed:dev_alloc_name"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301949 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950 }
1951 }
1952 if (register_netdevice(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301953 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301955 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956 }
1957 } else {
1958 if (register_netdev(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301959 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301961 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 }
1963 }
1964 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
1965
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301966 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001967}
1968
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301969static QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970{
1971 hdd_adapter_t *adapter = pContext;
1972
1973 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301974 hddLog(QDF_TRACE_LEVEL_FATAL, FL("NULL adapter"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301975 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 }
1977
1978 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301979 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid magic"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301980 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 }
1982
1983 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
1984
1985#if !defined (CONFIG_CNSS) && \
1986 !defined (WLAN_OPEN_SOURCE)
1987 /*
1988 * need to make sure all of our scheduled work has completed.
1989 * This callback is called from MC thread context, so it is safe to
1990 * to call below flush workqueue API from here.
1991 *
1992 * Even though this is called from MC thread context, if there is a faulty
1993 * work item in the system, that can hang this call forever. So flushing
1994 * this global work queue is not safe; and now we make sure that
1995 * individual work queues are stopped correctly. But the cancel work queue
1996 * is a GPL only API, so the proprietary version of the driver would still
1997 * rely on the global work queue flush.
1998 */
1999 flush_scheduled_work();
2000#endif
2001
2002 /*
2003 * We can be blocked while waiting for scheduled work to be
2004 * flushed, and the adapter structure can potentially be freed, in
2005 * which case the magic will have been reset. So make sure the
2006 * magic is still good, and hence the adapter structure is still
2007 * valid, before signaling completion
2008 */
2009 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2010 complete(&adapter->session_close_comp_var);
2011
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302012 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013}
2014
Krunal Soni8c37e322016-02-03 16:08:37 -08002015/**
2016 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2017 * @adapter: pointer to device adapter
2018 * @type: type of interface
2019 *
2020 * This routine will check the mode of adapter and if it is required then it
2021 * will initialize the TDLS operations
2022 *
2023 * Return: QDF_STATUS
2024 */
2025#ifdef FEATURE_WLAN_TDLS
2026static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2027{
2028 if (QDF_IBSS_MODE != type) {
2029 if (0 != wlan_hdd_tdls_init(adapter)) {
2030 hddLog(LOGE, FL("wlan_hdd_tdls_init failed"));
2031 return QDF_STATUS_E_FAILURE;
2032 }
2033 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2034 }
2035 return QDF_STATUS_SUCCESS;
2036}
2037#else
2038static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2039{
2040 return QDF_STATUS_SUCCESS;
2041}
2042#endif
2043
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302044QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045{
2046 struct net_device *pWlanDev = adapter->dev;
2047 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2048 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302049 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302050 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 uint32_t type, subType;
2052 unsigned long rc;
2053 int ret_val;
2054
2055 INIT_COMPLETION(adapter->session_open_comp_var);
2056 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
2057 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302058 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059 hddLog(LOGE, FL("failed to get vdev type"));
2060 goto error_sme_open;
2061 }
2062 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302063 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2065 (uint8_t *) &adapter->macAddressCurrent,
2066 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302067 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068 hddLog(LOGP,
2069 FL("sme_open_session() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302070 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302071 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 goto error_sme_open;
2073 }
2074 /* Block on a completion variable. Can't wait forever though. */
2075 rc = wait_for_completion_timeout(
2076 &adapter->session_open_comp_var,
2077 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2078 if (!rc) {
2079 hddLog(LOGP,
2080 FL("Session is not opened within timeout period code %ld"),
2081 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302082 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 goto error_sme_open;
2084 }
2085
2086 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302087 qdf_ret_status = hdd_register_wext(pWlanDev);
2088 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002089 hddLog(LOGP,
2090 FL("hdd_register_wext() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302091 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302092 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093 goto error_register_wext;
2094 }
2095 /* Set the Connection State to Not Connected */
2096 hddLog(LOG1,
2097 FL("Set HDD connState to eConnectionState_NotConnected"));
2098 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2099
2100 /* Set the default operation channel */
2101 pHddStaCtx->conn_info.operationChannel =
2102 hdd_ctx->config->OperatingChannel;
2103
2104 /* Make the default Auth Type as OPEN */
2105 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2106
2107 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302108 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002109 hddLog(LOGP,
2110 FL("hdd_init_tx_rx() failed, status code %08d [x%08x]"),
2111 status, status);
2112 goto error_init_txrx;
2113 }
2114
2115 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2116
2117 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302118 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 hddLog(LOGP,
2120 FL("hdd_wmm_adapter_init() failed, status code %08d [x%08x]"),
2121 status, status);
2122 goto error_wmm_init;
2123 }
2124
2125 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2126
2127 ret_val = wma_cli_set_command(adapter->sessionId,
2128 WMI_PDEV_PARAM_BURST_ENABLE,
2129 hdd_ctx->config->enableSifsBurst,
2130 PDEV_CMD);
2131
2132 if (0 != ret_val) {
2133 hddLog(LOGE,
2134 FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
2135 ret_val);
2136 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002137 status = hdd_check_and_init_tdls(adapter, type);
2138 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302141 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142
2143#ifdef FEATURE_WLAN_TDLS
2144error_tdls_init:
2145 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2146 hdd_wmm_adapter_close(adapter);
2147#endif
2148error_wmm_init:
2149 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2150 hdd_deinit_tx_rx(adapter);
2151error_init_txrx:
2152 hdd_unregister_wext(pWlanDev);
2153error_register_wext:
2154 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2155 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302156 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002157 adapter->sessionId,
2158 hdd_sme_close_session_callback,
2159 adapter)) {
2160 unsigned long rc;
2161
2162 /*
2163 * Block on a completion variable.
2164 * Can't wait forever though.
2165 */
2166 rc = wait_for_completion_timeout(
2167 &adapter->session_close_comp_var,
2168 msecs_to_jiffies
2169 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2170 if (rc <= 0)
2171 hddLog(LOGE,
2172 FL("Session is not opened within timeout period code %ld"),
2173 rc);
2174 }
2175 }
2176error_sme_open:
2177 return status;
2178}
2179
2180void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2181{
2182 hdd_cfg80211_state_t *cfgState;
2183
2184 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2185
2186 if (NULL != cfgState->buf) {
2187 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188 rc = wait_for_completion_timeout(
2189 &adapter->tx_action_cnf_event,
2190 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2191 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302192 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 FL("HDD Wait for Action Confirmation Failed!!"));
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302194 /*
2195 * Inform tx status as FAILURE to upper layer and free
2196 * cfgState->buf
2197 */
2198 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002199 }
2200 }
2201 return;
2202}
2203
2204void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2205 bool rtnl_held)
2206{
2207 ENTER();
2208 switch (adapter->device_mode) {
2209 case WLAN_HDD_INFRA_STATION:
2210 case WLAN_HDD_P2P_CLIENT:
2211 case WLAN_HDD_P2P_DEVICE:
2212 {
2213 if (test_bit
2214 (INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2215 hdd_deinit_tx_rx(adapter);
2216 clear_bit(INIT_TX_RX_SUCCESS,
2217 &adapter->event_flags);
2218 }
2219
2220 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2221 hdd_wmm_adapter_close(adapter);
2222 clear_bit(WMM_INIT_DONE,
2223 &adapter->event_flags);
2224 }
2225
2226 hdd_cleanup_actionframe(hdd_ctx, adapter);
2227 wlan_hdd_tdls_exit(adapter);
2228 break;
2229 }
2230
2231 case WLAN_HDD_SOFTAP:
2232 case WLAN_HDD_P2P_GO:
2233 {
2234
2235 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2236 hdd_wmm_adapter_close(adapter);
2237 clear_bit(WMM_INIT_DONE,
2238 &adapter->event_flags);
2239 }
2240
2241 hdd_cleanup_actionframe(hdd_ctx, adapter);
2242
2243 hdd_unregister_hostapd(adapter, rtnl_held);
2244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002245 break;
2246 }
2247
2248 default:
2249 break;
2250 }
2251
2252 EXIT();
2253}
2254
2255void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002256 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257{
2258 struct net_device *pWlanDev = NULL;
2259
2260 if (adapter)
2261 pWlanDev = adapter->dev;
2262 else {
2263 hddLog(LOGE, FL("adapter is Null"));
2264 return;
2265 }
2266
2267 hdd_lro_disable(hdd_ctx, adapter);
2268 /*
2269 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2270 * the driver is almost closed and cannot handle either control
2271 * messages or data. However, unregister_netdevice() call above will
2272 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2273 * to close the active connections (basically excites control path) which
2274 * is not right. Setting this flag helps hdd_stop() to recognize that
2275 * the interface is closed and restricts any operations on that
2276 */
2277 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2278
2279 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2280 if (rtnl_held) {
2281 unregister_netdevice(pWlanDev);
2282 } else {
2283 unregister_netdev(pWlanDev);
2284 }
2285 /*
2286 * Note that the adapter is no longer valid at this point
2287 * since the memory has been reclaimed
2288 */
2289 }
2290}
2291
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302292QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002293 tSirMacAddr macAddr)
2294{
2295 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2296 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302297 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002298 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302299 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 adapter = adapterNode->pAdapter;
2301 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302302 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302304 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002305 }
2306 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2307 adapterNode = pNext;
2308 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302309 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310}
2311hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
2312 const char *iface_name, tSirMacAddr macAddr,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002313 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314{
2315 hdd_adapter_t *adapter = NULL;
2316 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302317 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318 hdd_cfg80211_state_t *cfgState;
2319 int ret;
2320
2321 hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type);
2322
2323 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
2324 /*
2325 * Max limit reached on the number of vdevs configured by the
2326 * host. Return error
2327 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302328 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002329 FL(
2330 "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d"
2331 ),
2332 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
2333 return NULL;
2334 }
2335
2336 if (macAddr == NULL) {
2337 /* Not received valid macAddr */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302338 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 FL(
2340 "Unable to add virtual intf: Not able to get valid mac address"
2341 ));
2342 return NULL;
2343 }
2344 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302345 if (QDF_STATUS_E_FAILURE == status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302346 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 "Duplicate MAC addr: " MAC_ADDRESS_STR
2348 " already exists",
2349 MAC_ADDR_ARRAY(macAddr));
2350 return NULL;
2351 }
2352
2353 switch (session_type) {
2354 case WLAN_HDD_INFRA_STATION:
2355 /* Reset locally administered bit if the device mode is STA */
2356 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
2357 /* fall through */
2358 case WLAN_HDD_P2P_CLIENT:
2359 case WLAN_HDD_P2P_DEVICE:
2360 case WLAN_HDD_OCB:
2361 {
2362 adapter =
2363 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2364
2365 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302366 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 FL("failed to allocate adapter for session %d"),
2368 session_type);
2369 return NULL;
2370 }
2371
2372 if (WLAN_HDD_P2P_CLIENT == session_type)
2373 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 else if (WLAN_HDD_P2P_DEVICE == session_type)
2375 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 else
2377 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2378
2379 adapter->device_mode = session_type;
2380
2381 status = hdd_init_station_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302382 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 goto err_free_netdev;
2384
2385 hdd_lro_enable(hdd_ctx, adapter);
2386
2387 /*
2388 * Workqueue which gets scheduled in IPv4 notification
2389 * callback
2390 */
2391#ifdef CONFIG_CNSS
2392 cnss_init_work(&adapter->ipv4NotifierWorkQueue,
2393 hdd_ipv4_notifier_work_queue);
2394#else
2395 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
2396 hdd_ipv4_notifier_work_queue);
2397#endif
2398
2399#ifdef WLAN_NS_OFFLOAD
2400 /*
2401 * Workqueue which gets scheduled in IPv6
2402 * notification callback.
2403 */
2404#ifdef CONFIG_CNSS
2405 cnss_init_work(&adapter->ipv6NotifierWorkQueue,
2406 hdd_ipv6_notifier_work_queue);
2407#else
2408 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
2409 hdd_ipv6_notifier_work_queue);
2410#endif
2411#endif
2412 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302413 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2415 goto err_lro_cleanup;
2416 }
2417
2418 /* Stop the Interface TX queue. */
2419 hddLog(LOG1, FL("Disabling queues"));
2420 wlan_hdd_netif_queue_control(adapter,
2421 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2422 WLAN_CONTROL_PATH);
2423
2424 hdd_register_tx_flow_control(adapter,
2425 hdd_tx_resume_timer_expired_handler,
2426 hdd_tx_resume_cb);
2427
2428 break;
2429 }
2430
2431 case WLAN_HDD_P2P_GO:
2432 case WLAN_HDD_SOFTAP:
2433 {
2434 adapter =
2435 hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
2436 (uint8_t *) iface_name);
2437 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302438 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 FL("failed to allocate adapter for session %d"),
2440 session_type);
2441 return NULL;
2442 }
2443
2444 adapter->wdev.iftype =
2445 (session_type ==
2446 WLAN_HDD_SOFTAP) ? NL80211_IFTYPE_AP :
2447 NL80211_IFTYPE_P2P_GO;
2448 adapter->device_mode = session_type;
2449
2450 status = hdd_init_ap_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302451 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 goto err_free_netdev;
2453
2454 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302455 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2457 goto err_free_netdev;
2458 }
2459
2460 hddLog(LOG1, FL("Disabling queues"));
2461 wlan_hdd_netif_queue_control(adapter,
2462 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2463 WLAN_CONTROL_PATH);
2464
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 break;
2466 }
2467 case WLAN_HDD_FTM:
2468 {
2469 adapter =
2470 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2471
2472 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302473 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 FL("failed to allocate adapter for session %d"),
2475 session_type);
2476 return NULL;
2477 }
2478
2479 /*
2480 * Assign NL80211_IFTYPE_STATION as interface type to resolve
2481 * Kernel Warning message while loading driver in FTM mode.
2482 */
2483 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2484 adapter->device_mode = session_type;
2485 status = hdd_register_interface(adapter, rtnl_held);
2486
2487 hdd_init_tx_rx(adapter);
2488
2489 /* Stop the Interface TX queue. */
2490 hddLog(LOG1, FL("Disabling queues"));
2491 wlan_hdd_netif_queue_control(adapter,
2492 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2493 WLAN_CONTROL_PATH);
2494 }
2495 break;
2496 default:
2497 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302498 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002499 FL("Invalid session type %d"),
2500 session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302501 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 return NULL;
2503 }
2504 }
2505
2506 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2507 mutex_init(&cfgState->remain_on_chan_ctx_lock);
2508
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302509 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510 /* Add it to the hdd's session list. */
2511 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302512 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002513 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302514 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515 } else {
2516 pHddAdapterNode->pAdapter = adapter;
2517 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
2518 }
2519 }
2520
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302521 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 if (NULL != adapter) {
2523 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
2524 adapter = NULL;
2525 }
2526 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302527 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528 }
2529 return NULL;
2530 }
2531
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302532 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002533 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534
2535 /* Initialize the WoWL service */
2536 if (!hdd_init_wowl(adapter)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302537 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 FL("hdd_init_wowl failed"));
2539 goto err_lro_cleanup;
2540 }
2541
2542 /* Adapter successfully added. Increment the vdev count */
2543 hdd_ctx->current_intf_count++;
2544
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302545 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 hdd_ctx->current_intf_count);
2547
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002548 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 }
2550
Anurag Chouhan6d760662016-02-20 16:05:43 +05302551 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552 && (!hdd_ctx->config->enable2x2)) {
2553#define HDD_DTIM_1CHAIN_RX_ID 0x5
2554#define HDD_SMPS_PARAM_VALUE_S 29
2555
2556 /*
2557 * Disable DTIM 1 chain Rx when in 1x1, we are passing two value
2558 * as param_id << 29 | param_value.
2559 * Below param_value = 0(disable)
2560 */
2561 ret = wma_cli_set_command(adapter->sessionId,
2562 WMI_STA_SMPS_PARAM_CMDID,
2563 HDD_DTIM_1CHAIN_RX_ID <<
2564 HDD_SMPS_PARAM_VALUE_S,
2565 VDEV_CMD);
2566
2567 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302568 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 FL("DTIM 1 chain set failed %d"), ret);
2570 goto err_lro_cleanup;
2571 }
2572
2573 ret = wma_cli_set_command(adapter->sessionId,
2574 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2575 hdd_ctx->config->txchainmask1x1,
2576 PDEV_CMD);
2577 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302578 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"),
2580 ret);
2581 goto err_lro_cleanup;
2582 }
2583 ret = wma_cli_set_command(adapter->sessionId,
2584 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2585 hdd_ctx->config->rxchainmask1x1,
2586 PDEV_CMD);
2587 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302588 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"),
2590 ret);
2591 goto err_lro_cleanup;
2592 }
2593#undef HDD_DTIM_1CHAIN_RX_ID
2594#undef HDD_SMPS_PARAM_VALUE_S
2595 }
2596
Anurag Chouhan6d760662016-02-20 16:05:43 +05302597 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002598 ret = wma_cli_set_command(adapter->sessionId,
2599 WMI_PDEV_PARAM_HYST_EN,
2600 hdd_ctx->config->enableMemDeepSleep,
2601 PDEV_CMD);
2602
2603 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302604 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 FL("WMI_PDEV_PARAM_HYST_EN set failed %d"),
2606 ret);
2607 goto err_lro_cleanup;
2608 }
2609 }
2610
2611#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2612
2613 /* Enable FW logs based on INI configuration */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302614 if ((QDF_GLOBAL_FTM_MODE != cds_get_conparam()) &&
Komal Seelamc11bb222016-01-27 18:57:10 +05302615 (hdd_ctx->config->enable_fw_log)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002616 uint8_t count = 0;
2617 uint32_t value = 0;
2618 uint8_t numEntries = 0;
2619 uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2620
2621 hdd_ctx->fw_log_settings.dl_type =
2622 hdd_ctx->config->enableFwLogType;
2623 ret = wma_cli_set_command(adapter->sessionId,
2624 WMI_DBGLOG_TYPE,
2625 hdd_ctx->config->enableFwLogType,
2626 DBG_CMD);
2627 if (ret != 0) {
2628 hddLog(LOGE, FL("Failed to enable FW log type ret %d"),
2629 ret);
2630 }
2631
2632 hdd_ctx->fw_log_settings.dl_loglevel =
2633 hdd_ctx->config->enableFwLogLevel;
2634 ret = wma_cli_set_command(adapter->sessionId,
2635 WMI_DBGLOG_LOG_LEVEL,
2636 hdd_ctx->config->enableFwLogLevel,
2637 DBG_CMD);
2638 if (ret != 0) {
2639 hddLog(LOGE, FL("Failed to enable FW log level ret %d"),
2640 ret);
2641 }
2642
2643 hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel,
2644 moduleLoglevel,
2645 &numEntries,
2646 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2647 while (count < numEntries) {
2648 /*
2649 * FW module log level input string looks like below:
2650 * gFwDebugModuleLoglevel=<FW Module ID>,<Log Level>,...
2651 * For example:
2652 * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6
2653 * Above input string means :
2654 * For FW module ID 1 enable log level 0
2655 * For FW module ID 2 enable log level 1
2656 * For FW module ID 3 enable log level 2
2657 * For FW module ID 4 enable log level 3
2658 * For FW module ID 5 enable log level 4
2659 * For FW module ID 6 enable log level 5
2660 * For FW module ID 7 enable log level 6
2661 */
2662
2663 /* FW expects WMI command value =
2664 * Module ID * 10 + Module Log level
2665 */
2666 value = ((moduleLoglevel[count] * 10) +
2667 moduleLoglevel[count + 1]);
2668 ret = wma_cli_set_command(adapter->sessionId,
2669 WMI_DBGLOG_MOD_LOG_LEVEL,
2670 value, DBG_CMD);
2671 if (ret != 0) {
2672 hddLog(LOGE,
2673 FL
2674 ("Failed to enable FW module log level %d ret %d"),
2675 value, ret);
2676 }
2677
2678 count += 2;
2679 }
2680 }
2681#endif
2682
2683 return adapter;
2684
2685err_lro_cleanup:
2686 hdd_lro_disable(hdd_ctx, adapter);
2687err_free_netdev:
2688 free_netdev(adapter->dev);
2689 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2690
2691 return NULL;
2692}
2693
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302694QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002695 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696{
2697 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302698 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699
2700 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302701 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302702 hddLog(QDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 status);
2704 return status;
2705 }
2706
2707 while (pCurrent->pAdapter != adapter) {
2708 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302709 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 break;
2711
2712 pCurrent = pNext;
2713 }
2714 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302715 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002716 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002717 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
2718
2719 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302720 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 adapterNode = NULL;
2722
2723 /* Adapter removed. Decrement vdev count */
2724 if (hdd_ctx->current_intf_count != 0)
2725 hdd_ctx->current_intf_count--;
2726
2727 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302728 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302730 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731}
2732
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002733/**
2734 * hdd_close_all_adapters - Close all open adapters
2735 * @hdd_ctx: Hdd context
2736 * rtnl_held: True if RTNL lock held
2737 *
2738 * Close all open adapters.
2739 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302740 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002741 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302742QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743{
2744 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302745 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002746
2747 ENTER();
2748
2749 do {
2750 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302751 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002753 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302754 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302756 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002757
2758 EXIT();
2759
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302760 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761}
2762
2763void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
2764{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302765 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 tSirUpdateIE updateIE;
2767 switch (pHostapdAdapter->device_mode) {
2768 case WLAN_HDD_INFRA_STATION:
2769 case WLAN_HDD_P2P_CLIENT:
2770 {
2771 hdd_station_ctx_t *pHddStaCtx =
2772 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002773 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002774 break;
2775 }
2776 case WLAN_HDD_SOFTAP:
2777 case WLAN_HDD_P2P_GO:
2778 case WLAN_HDD_IBSS:
2779 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002780 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002781 break;
2782 }
2783 case WLAN_HDD_FTM:
2784 case WLAN_HDD_P2P_DEVICE:
2785 default:
2786 /*
2787 * wlan_hdd_reset_prob_rspies should not have been called
2788 * for these kind of devices
2789 */
2790 hddLog(LOGE,
2791 FL("Unexpected request for the current device type %d"),
2792 pHostapdAdapter->device_mode);
2793 return;
2794 }
2795
Anurag Chouhanc5548422016-02-24 18:33:27 +05302796 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 updateIE.smeSessionId = pHostapdAdapter->sessionId;
2798 updateIE.ieBufferlength = 0;
2799 updateIE.pAdditionIEBuffer = NULL;
2800 updateIE.append = true;
2801 updateIE.notify = false;
2802 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
2803 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302804 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
2806 }
2807}
2808
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302809QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 const bool bCloseSession)
2811{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302812 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
2814 union iwreq_data wrqu;
2815 tSirUpdateIE updateIE;
2816 unsigned long rc;
2817
2818 ENTER();
2819
2820 hddLog(LOG1, FL("Disabling queues"));
2821 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2822 WLAN_CONTROL_PATH);
2823 switch (adapter->device_mode) {
2824 case WLAN_HDD_INFRA_STATION:
2825 case WLAN_HDD_P2P_CLIENT:
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302826 case WLAN_HDD_IBSS:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002827 case WLAN_HDD_P2P_DEVICE:
2828 if (hdd_conn_is_connected(
2829 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
2830 hdd_is_connecting(
2831 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
2832 if (pWextState->roamProfile.BSSType ==
2833 eCSR_BSS_TYPE_START_IBSS)
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302834 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835 sme_roam_disconnect(hdd_ctx->hHal,
2836 adapter->sessionId,
2837 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2838 else
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302839 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 sme_roam_disconnect(hdd_ctx->hHal,
2841 adapter->sessionId,
2842 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2843 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302844 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002845 rc = wait_for_completion_timeout(
2846 &adapter->disconnect_comp_var,
2847 msecs_to_jiffies
2848 (WLAN_WAIT_TIME_DISCONNECT));
2849 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302850 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 FL(
2852 "wait on disconnect_comp_var failed"
2853 ));
2854 }
2855 } else {
2856 hddLog(LOGE,
2857 FL(
2858 "failed to post disconnect event to SME"
2859 ));
2860 }
2861 memset(&wrqu, '\0', sizeof(wrqu));
2862 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2863 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
2864 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
2865 NULL);
2866 } else {
2867 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
2868 eCSR_SCAN_ABORT_DEFAULT);
2869 }
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302870 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002871
2872#ifdef WLAN_OPEN_SOURCE
2873 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
2874#endif
2875
2876 hdd_deregister_tx_flow_control(adapter);
2877
2878#ifdef WLAN_NS_OFFLOAD
2879#ifdef WLAN_OPEN_SOURCE
2880 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
2881#endif
2882#endif
2883
2884 /*
2885 * It is possible that the caller of this function does not
2886 * wish to close the session
2887 */
2888 if (true == bCloseSession &&
2889 test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2890 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302891 if (QDF_STATUS_SUCCESS ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2893 hdd_sme_close_session_callback,
2894 adapter)) {
2895 /*
2896 * Block on a completion variable. Can't wait
2897 * forever though.
2898 */
2899 rc = wait_for_completion_timeout(
2900 &adapter->session_close_comp_var,
2901 msecs_to_jiffies
2902 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2903 if (!rc) {
2904 hddLog(LOGE,
2905 FL(
2906 "failure waiting for session_close_comp_var"
2907 ));
2908 }
2909 }
2910 }
2911 break;
2912
2913 case WLAN_HDD_SOFTAP:
2914 case WLAN_HDD_P2P_GO:
2915 if (hdd_ctx->config->conc_custom_rule1 &&
2916 (WLAN_HDD_SOFTAP == adapter->device_mode)) {
2917 /*
2918 * Before stopping the sap adapter, lets make sure there
2919 * is no sap restart work pending.
2920 */
2921 cds_flush_work(&hdd_ctx->sap_start_work);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302922 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002923 FL("Canceled the pending SAP restart work"));
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002924 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 }
2926 /* Any softap specific cleanup here... */
2927 if (adapter->device_mode == WLAN_HDD_P2P_GO)
2928 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
2929
2930 hdd_deregister_tx_flow_control(adapter);
2931
2932 mutex_lock(&hdd_ctx->sap_lock);
2933 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302934 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05302935 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936
2937 /* Stop Bss. */
2938#ifdef WLAN_FEATURE_MBSSID
2939 status = wlansap_stop_bss(
2940 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
2941#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002942 status = wlansap_stop_bss(
2943 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944#endif
2945
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302946 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 hdd_hostapd_state_t *hostapd_state =
2948 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302949 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302950 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302951 qdf_status =
2952 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302953 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 BSS_WAIT_TIMEOUT);
2955
Anurag Chouhance0dc992016-02-16 18:18:03 +05302956 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 hddLog(LOGE,
2958 FL(
2959 "failure waiting for wlansap_stop_bss %d"
2960 ),
Anurag Chouhance0dc992016-02-16 18:18:03 +05302961 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 }
2963 } else {
2964 hddLog(LOGE, FL("failure in wlansap_stop_bss"));
2965 }
2966 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002967 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 adapter->device_mode,
2969 adapter->sessionId);
2970
Anurag Chouhanc5548422016-02-24 18:33:27 +05302971 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002972 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 updateIE.smeSessionId = adapter->sessionId;
2974 updateIE.ieBufferlength = 0;
2975 updateIE.pAdditionIEBuffer = NULL;
2976 updateIE.append = false;
2977 updateIE.notify = false;
2978 /* Probe bcn reset */
2979 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2980 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302981 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 hddLog(LOGE,
2983 FL(
2984 "Could not pass on PROBE_RSP_BCN data to PE"
2985 ));
2986 }
2987 /* Assoc resp reset */
2988 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2989 &updateIE,
2990 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302991 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 hddLog(LOGE,
2993 FL(
2994 "Could not pass on ASSOC_RSP data to PE"
2995 ));
2996 }
2997 /* Reset WNI_CFG_PROBE_RSP Flags */
2998 wlan_hdd_reset_prob_rspies(adapter);
2999 kfree(adapter->sessionCtx.ap.beacon);
3000 adapter->sessionCtx.ap.beacon = NULL;
3001 }
3002 mutex_unlock(&hdd_ctx->sap_lock);
3003 break;
3004 case WLAN_HDD_OCB:
3005 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3006 conn_info.staId[0]);
3007 break;
3008 default:
3009 break;
3010 }
3011
3012 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303013 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014}
3015
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303016QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017{
3018 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303019 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020 hdd_adapter_t *adapter;
3021
3022 ENTER();
3023
3024 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3025
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303026 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 adapter = adapterNode->pAdapter;
3028 hdd_stop_adapter(hdd_ctx, adapter, true);
3029 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3030 adapterNode = pNext;
3031 }
3032
3033 EXIT();
3034
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303035 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003036}
3037
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303038QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039{
3040 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303041 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 hdd_adapter_t *adapter;
3043
3044 ENTER();
3045
3046 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3047
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303048 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 adapter = adapterNode->pAdapter;
3050 hddLog(LOG1, FL("Disabling queues"));
3051 wlan_hdd_netif_queue_control(adapter,
3052 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3053 WLAN_CONTROL_PATH);
3054
3055 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3056
3057 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003058 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 adapter->sessionId);
3060 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3061 hdd_wmm_adapter_close(adapter);
3062 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3063 }
3064
3065 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3066 adapterNode = pNext;
3067 }
3068
3069 EXIT();
3070
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303071 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072}
3073
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303074QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003075{
3076 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303077 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 hdd_adapter_t *adapter;
3079#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303080 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003081#endif
3082 eConnectionState connState;
3083
3084 ENTER();
3085
3086 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3087
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303088 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 adapter = adapterNode->pAdapter;
3090
3091 hdd_wmm_init(adapter);
3092
3093 switch (adapter->device_mode) {
3094 case WLAN_HDD_INFRA_STATION:
3095 case WLAN_HDD_P2P_CLIENT:
3096 case WLAN_HDD_P2P_DEVICE:
3097
3098 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3099 ->conn_info.connState;
3100
3101 hdd_init_station_mode(adapter);
3102 /* Open the gates for HDD to receive Wext commands */
3103 adapter->isLinkUpSvcNeeded = false;
3104 adapter->scan_info.mScanPending = false;
3105
3106 /* Indicate disconnect event to supplicant if associated previously */
3107 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003108 eConnectionState_IbssConnected == connState ||
3109 eConnectionState_NotConnected == connState ||
3110 eConnectionState_IbssDisconnected == connState ||
3111 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 union iwreq_data wrqu;
3113 memset(&wrqu, '\0', sizeof(wrqu));
3114 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3115 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3116 wireless_send_event(adapter->dev, SIOCGIWAP,
3117 &wrqu, NULL);
3118 adapter->sessionCtx.station.
3119 hdd_ReassocScenario = false;
3120
3121 /* indicate disconnected event to nl80211 */
3122 cfg80211_disconnected(adapter->dev,
3123 WLAN_REASON_UNSPECIFIED,
3124 NULL, 0, GFP_KERNEL);
3125 } else if (eConnectionState_Connecting == connState) {
3126 /*
3127 * Indicate connect failure to supplicant if we were in the
3128 * process of connecting
3129 */
3130 cfg80211_connect_result(adapter->dev, NULL,
3131 NULL, 0, NULL, 0,
3132 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3133 GFP_KERNEL);
3134 }
3135
3136 hdd_register_tx_flow_control(adapter,
3137 hdd_tx_resume_timer_expired_handler,
3138 hdd_tx_resume_cb);
3139
3140 break;
3141
3142 case WLAN_HDD_SOFTAP:
3143 /* softAP can handle SSR */
3144 break;
3145
3146 case WLAN_HDD_P2P_GO:
3147#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303148 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003149 FL("[SSR] send stop ap to supplicant"));
3150 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3151#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303152 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003153 FL("[SSR] send restart supplicant"));
3154 /* event supplicant to restart */
3155 cfg80211_del_sta(adapter->dev,
3156 (const u8 *)&bcastMac.bytes[0],
3157 GFP_KERNEL);
3158#endif
3159 break;
3160
3161 default:
3162 break;
3163 }
3164
3165 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3166 adapterNode = pNext;
3167 }
3168
3169 EXIT();
3170
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303171 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172}
3173
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303174QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 hdd_adapter_list_node_t **padapterNode)
3176{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303177 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303178 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303179 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3180 (qdf_list_node_t **) padapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303181 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 return status;
3183}
3184
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303185QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 hdd_adapter_list_node_t *adapterNode,
3187 hdd_adapter_list_node_t **pNextAdapterNode)
3188{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303189 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303190 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303191 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3192 (qdf_list_node_t *) adapterNode,
3193 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303195 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 return status;
3197}
3198
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303199QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200 hdd_adapter_list_node_t *adapterNode)
3201{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303202 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303203 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303204 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 &adapterNode->node);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303206 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 return status;
3208}
3209
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303210QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 hdd_adapter_list_node_t **padapterNode)
3212{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303213 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303214 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303215 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3216 (qdf_list_node_t **) padapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303217 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003218 return status;
3219}
3220
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303221QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 hdd_adapter_list_node_t *adapterNode)
3223{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303224 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303225 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303226 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3227 (qdf_list_node_t *) adapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303228 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229 return status;
3230}
3231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303232QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233 hdd_adapter_list_node_t *adapterNode)
3234{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303235 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303236 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303237 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3238 (qdf_list_node_t *) adapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303239 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 return status;
3241}
3242
3243hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3244 tSirMacAddr macAddr)
3245{
3246 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3247 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303248 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249
3250 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3251
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303252 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253 adapter = adapterNode->pAdapter;
3254
3255 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303256 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003257 macAddr, sizeof(tSirMacAddr))) {
3258 return adapter;
3259 }
3260 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3261 adapterNode = pNext;
3262 }
3263
3264 return NULL;
3265
3266}
3267
3268hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3269 uint32_t vdev_id)
3270{
3271 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3272 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303273 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303275 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303277 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 adapter = adapterNode->pAdapter;
3279
3280 if (adapter->sessionId == vdev_id)
3281 return adapter;
3282
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303283 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3285 adapterNode = pNext;
3286 }
3287
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303288 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 FL("vdev_id %d does not exist with host"), vdev_id);
3290
3291 return NULL;
3292}
3293
Abhishek Singh7996eb72015-12-30 17:24:02 +05303294/**
3295 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3296 * the sessionid
3297 * @hdd_ctx: hdd context.
3298 * @sme_session_id: sme session is for the adapter to get.
3299 *
3300 * This function is used to get the adapter with provided session id
3301 *
3302 * Return: adapter pointer if found
3303 *
3304 */
3305hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3306 uint32_t sme_session_id)
3307{
3308 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3309 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303310 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303311
3312
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303313 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303314
3315 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303316 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303317 adapter = adapter_node->pAdapter;
3318
3319 if (adapter &&
3320 adapter->sessionId == sme_session_id)
3321 return adapter;
3322
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303323 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303324 hdd_get_next_adapter(hdd_ctx,
3325 adapter_node, &next);
3326 adapter_node = next;
3327 }
3328 return NULL;
3329}
3330
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, device_mode_t mode)
3332{
3333 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3334 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303335 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003336
3337 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3338
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303339 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003340 adapter = adapterNode->pAdapter;
3341
3342 if (adapter && (mode == adapter->device_mode))
3343 return adapter;
3344
3345 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3346 adapterNode = pNext;
3347 }
3348
3349 return NULL;
3350
3351}
3352
3353/**
3354 * hdd_get_operating_channel() - return operating channel of the device mode
3355 * @hdd_ctx: Pointer to the HDD context.
3356 * @mode: Device mode for which operating channel is required.
3357 * Suported modes:
3358 * WLAN_HDD_INFRA_STATION,
3359 * WLAN_HDD_P2P_CLIENT,
3360 * WLAN_HDD_SOFTAP,
3361 * WLAN_HDD_P2P_GO.
3362 *
3363 * This API returns the operating channel of the requested device mode
3364 *
3365 * Return: channel number. "0" id the requested device is not found OR it is
3366 * not connected.
3367 */
3368uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx, device_mode_t mode)
3369{
3370 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372 hdd_adapter_t *adapter;
3373 uint8_t operatingChannel = 0;
3374
3375 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3376
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303377 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003378 adapter = adapterNode->pAdapter;
3379
3380 if (mode == adapter->device_mode) {
3381 switch (adapter->device_mode) {
3382 case WLAN_HDD_INFRA_STATION:
3383 case WLAN_HDD_P2P_CLIENT:
3384 if (hdd_conn_is_connected
3385 (WLAN_HDD_GET_STATION_CTX_PTR
3386 (adapter))) {
3387 operatingChannel =
3388 (WLAN_HDD_GET_STATION_CTX_PTR
3389 (adapter))->conn_info.
3390 operationChannel;
3391 }
3392 break;
3393 case WLAN_HDD_SOFTAP:
3394 case WLAN_HDD_P2P_GO:
3395 /* softap connection info */
3396 if (test_bit
3397 (SOFTAP_BSS_STARTED,
3398 &adapter->event_flags))
3399 operatingChannel =
3400 (WLAN_HDD_GET_AP_CTX_PTR
3401 (adapter))->operatingChannel;
3402 break;
3403 default:
3404 break;
3405 }
3406
3407 break; /* Found the device of interest. break the loop */
3408 }
3409
3410 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3411 adapterNode = pNext;
3412 }
3413 return operatingChannel;
3414}
3415
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303416static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 hdd_ctx)
3418{
3419 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303420 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 hdd_adapter_t *adapter;
3422
3423 ENTER();
3424
3425 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3426
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303427 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003428 adapter = adapterNode->pAdapter;
3429 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3430 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3431 (adapter->device_mode == WLAN_HDD_IBSS) ||
3432 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3433 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3434 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3435 wlan_hdd_cfg80211_deregister_frames(adapter);
3436 hdd_unregister_wext(adapter->dev);
3437 }
3438 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3439 adapterNode = pNext;
3440 }
3441
3442 EXIT();
3443
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303444 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003445}
3446
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303447QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003448{
3449 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303450 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451 hdd_adapter_t *adapter;
3452
3453 ENTER();
3454
3455 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3456
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303457 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 adapter = adapterNode->pAdapter;
3459 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3460 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3461 (adapter->device_mode == WLAN_HDD_IBSS) ||
3462 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3463 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3464 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3465 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3466 eCSR_SCAN_ABORT_DEFAULT);
3467 }
3468 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3469 adapterNode = pNext;
3470 }
3471
3472 EXIT();
3473
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303474 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475}
3476
3477#ifdef WLAN_NS_OFFLOAD
3478/**
3479 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3480 * @hdd_ctx: Pointer to hdd context
3481 *
3482 * Return: None
3483 */
3484static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3485{
3486 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3487
3488 return;
3489}
3490
3491/**
3492 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3493 * @hdd_ctx: Pointer to hdd context
3494 *
3495 * Return: None
3496 */
3497static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3498{
3499 int ret;
3500
3501 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
3502 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3503 if (ret)
3504 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
3505 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003506 hdd_info("Registered IPv6 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507
3508 return;
3509}
3510#else
3511/**
3512 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3513 * @hdd_ctx: Pointer to hdd context
3514 *
3515 * Return: None
3516 */
3517static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3518{
3519}
3520/**
3521 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3522 * @hdd_ctx: Pointer to hdd context
3523 *
3524 * Return: None
3525 */
3526static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3527{
3528}
3529#endif
3530
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003531#ifdef QCA_WIFI_FTM
3532/**
3533 * hdd_disable_ftm() - Disable FTM mode
3534 * @hdd_ctx: HDD context
3535 *
3536 * Helper function to disable FTM mode.
3537 *
3538 * Return: None.
3539 */
3540static void hdd_disable_ftm(hdd_context_t *hdd_ctx)
3541{
3542 hdd_notice("Disabling FTM mode");
3543
3544 if (hdd_ftm_stop(hdd_ctx)) {
3545 hdd_alert("hdd_ftm_stop Failed!");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303546 QDF_ASSERT(0);
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003547 }
3548
3549 hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED;
3550
3551 wlan_hdd_ftm_close(hdd_ctx);
3552
3553 return;
3554}
3555
3556/**
3557 * hdd_enable_ftm() - Enable FTM mode
3558 * @hdd_ctx: HDD context
3559 *
3560 * Helper function to enable FTM mode.
3561 *
3562 * Return: 0 on success and errno on failure.
3563 */
3564int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3565{
3566 int ret;
3567
3568 ret = wlan_hdd_ftm_open(hdd_ctx);
3569 if (ret) {
3570 hdd_alert("wlan_hdd_ftm_open Failed: %d", ret);
3571 goto err_out;
3572 }
3573
3574 ret = hdd_ftm_start(hdd_ctx);
3575
3576 if (ret) {
3577 hdd_alert("hdd_ftm_start Failed: %d", ret);
3578 goto err_ftm_close;
3579 }
3580
3581 ret = wiphy_register(hdd_ctx->wiphy);
3582 if (ret) {
3583 hdd_alert("wiphy register failed: %d", ret);
3584 goto err_ftm_stop;
3585 }
3586
3587 hdd_err("FTM driver loaded");
3588
3589 return 0;
3590
3591err_ftm_stop:
3592 hdd_ftm_stop(hdd_ctx);
3593err_ftm_close:
3594 wlan_hdd_ftm_close(hdd_ctx);
3595err_out:
3596 return ret;
3597
3598}
3599#else
3600int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3601{
3602 hdd_err("Driver built without FTM feature enabled!");
3603
3604 return -ENOTSUPP;
3605}
3606
3607static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { }
3608#endif
3609
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303610#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3611/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003612 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303613 * @hdd_ctx: HDD context
3614 *
3615 * Activates the logging service
3616 *
3617 * Return: Zero in case of success, negative value otherwise
3618 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003619static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303620{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003621 int ret;
3622 struct hdd_config *config = hdd_ctx->config;
3623
3624 if (!config->wlanLoggingEnable)
3625 return 0;
3626
3627 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
3628 config->wlanLoggingNumBuf);
3629 if (ret)
3630 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
3631 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303632}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003633
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303634/**
3635 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
3636 * @hdd_ctx: HDD context
3637 *
3638 * Deactivates the logging service
3639 *
3640 * Return: 0 on deactivating the logging service
3641 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003642static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303643{
3644 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
3645 return wlan_logging_sock_deactivate_svc();
3646
3647 return 0;
3648}
3649#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003650static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303651{
3652 return 0;
3653}
3654
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003655static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303656{
3657 return 0;
3658}
3659#endif
3660
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003662 * hdd_free_context - Free HDD context
3663 * @hdd_ctx: HDD context to be freed.
3664 *
3665 * Free config and HDD context.
3666 *
3667 * Return: None
3668 */
3669static void hdd_free_context(hdd_context_t *hdd_ctx)
3670{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303671 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003672 hdd_logging_sock_deactivate_svc(hdd_ctx);
3673
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303674 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003675 hdd_ctx->config = NULL;
3676
3677 wiphy_free(hdd_ctx->wiphy);
3678}
3679
3680/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 * hdd_wlan_exit() - HDD WLAN exit function
3682 * @hdd_ctx: Pointer to the HDD Context
3683 *
3684 * This is the driver exit point (invoked during rmmod)
3685 *
3686 * Return: None
3687 */
3688void hdd_wlan_exit(hdd_context_t *hdd_ctx)
3689{
3690 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303691 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 struct wiphy *wiphy = hdd_ctx->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003693
3694 ENTER();
3695
3696 hddLog(LOGE, FL("Unregister IPv6 notifier"));
3697 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3698 hddLog(LOGE, FL("Unregister IPv4 notifier"));
3699 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3700
3701 hdd_unregister_wext_all_adapters(hdd_ctx);
3702
Anurag Chouhan6d760662016-02-20 16:05:43 +05303703 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003704 hdd_disable_ftm(hdd_ctx);
3705
3706 hdd_alert("FTM driver unloaded");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 goto free_hdd_ctx;
3708 }
3709
3710 /*
3711 * Cancel any outstanding scan requests. We are about to close all
3712 * of our adapters, but an adapter structure is what SME passes back
3713 * to our callback function. Hence if there are any outstanding scan
3714 * requests then there is a race condition between when the adapter
3715 * is closed and when the callback is invoked. We try to resolve that
3716 * race condition here by canceling any outstanding scans before we
3717 * close the adapters.
3718 * Note that the scans may be cancelled in an asynchronous manner, so
3719 * ideally there needs to be some kind of synchronization. Rather than
3720 * introduce a new synchronization here, we will utilize the fact that
3721 * we are about to Request Full Power, and since that is synchronized,
3722 * the expectation is that by the time Request Full Power has completed,
3723 * all scans will be cancelled
3724 */
3725 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3726
3727#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05303728 if (QDF_TIMER_STATE_RUNNING ==
3729 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
3730 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003731 }
3732
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303733 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303734 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303735 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736 FL("Cannot deallocate Bus bandwidth timer"));
3737 }
3738#endif
3739
3740#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05303741 if (QDF_TIMER_STATE_RUNNING ==
3742 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
3743 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003744 }
3745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303746 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303747 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303748 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 FL("Cannot deallocate ACS Skip timer"));
3750 }
3751#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752
3753 /*
3754 * Powersave Offload Case
3755 * Disable Idle Power Save Mode
3756 */
3757 hdd_set_idle_ps_config(hdd_ctx, false);
3758
3759 hdd_debugfs_exit(hdd_ctx);
3760
3761 /* Unregister the Net Device Notifier */
3762 unregister_netdevice_notifier(&hdd_netdev_notifier);
3763
3764 /*
3765 * Stop all adapters, this will ensure the termination of active
3766 * connections on the interface. Make sure the cds_scheduler is
3767 * still available to handle those control messages
3768 */
3769 hdd_stop_all_adapters(hdd_ctx);
3770
3771 /* Stop all the modules */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303772 qdf_status = cds_disable(p_cds_context);
3773 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303774 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 FL("Failed to stop CDS"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303776 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777 }
3778
3779 /*
3780 * Close the scheduler before calling cds_close to make sure no thread
3781 * is scheduled after the each module close is called i.e after all the
3782 * data structures are freed.
3783 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303784 qdf_status = cds_sched_close(p_cds_context);
3785 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303786 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303788 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003789 }
3790#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3791 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303792 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793#endif
3794 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303795 qdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796
3797 hdd_hostapd_channel_wakelock_deinit(hdd_ctx);
3798
3799 /*
3800 * Close CDS
3801 * This frees pMac(HAL) context. There should not be any call
3802 * that requires pMac access after this.
3803 */
3804 cds_close(p_cds_context);
3805
3806 hdd_wlan_green_ap_deinit(hdd_ctx);
3807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808#ifdef WLAN_KD_READY_NOTIFIER
3809 cnss_diag_notify_wlan_close();
3810 ptt_sock_deactivate_svc();
3811#endif /* WLAN_KD_READY_NOTIFIER */
3812 nl_srv_exit();
3813
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003814 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815
3816 hdd_ipa_cleanup(hdd_ctx);
3817
3818 /* Free up RoC request queue and flush workqueue */
3819 cds_flush_work(&hdd_ctx->roc_req_work);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303820 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
3821 qdf_list_destroy(&hdd_ctx->hdd_scan_req_q);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303823 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08003824 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 /* Proceed and complete the clean up */
3826 }
3827
3828free_hdd_ctx:
3829
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830 wiphy_unregister(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003831
3832 hdd_free_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003833}
3834
3835void __hdd_wlan_exit(void)
3836{
3837 hdd_context_t *hdd_ctx;
3838
3839 ENTER();
3840
Anurag Chouhan6d760662016-02-20 16:05:43 +05303841 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303843 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003844 EXIT();
3845 return;
3846 }
3847
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003848 /* Check IPA HW Pipe shutdown */
3849 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
3850
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003851#ifdef WLAN_FEATURE_LPSS
3852 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
3853#endif
3854
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003855 memdump_deinit();
3856
3857#ifdef QCA_PKT_PROTO_TRACE
3858 cds_pkt_proto_trace_close();
3859#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860 /* Do all the cleanup before deregistering the driver */
3861 hdd_wlan_exit(hdd_ctx);
3862 EXIT();
3863}
3864
3865#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3866void hdd_skip_acs_scan_timer_handler(void *data)
3867{
3868 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
3869
3870 hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
3871 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
3872
3873 if (!hdd_ctx->hHal)
3874 return;
3875 sme_scan_flush_result(hdd_ctx->hHal);
3876}
3877#endif
3878
3879#ifdef QCA_HT_2040_COEX
3880/**
3881 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
3882 * @adapter: pointer to adapter
3883 * @staId: station id
3884 * @macAddrSTA: station MAC address
3885 * @channel_type: channel type
3886 *
3887 * This function notifies FW with HT20/HT40 mode
3888 *
3889 * Return: 0 if successful, error number otherwise
3890 */
3891int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303892 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893{
3894 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303895 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 hdd_context_t *hdd_ctx = NULL;
3897
3898 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3899
3900 status = wlan_hdd_validate_context(hdd_ctx);
3901 if (0 != status) {
3902 hddLog(LOGE, FL("HDD context is not valid"));
3903 return status;
3904 }
3905 if (!hdd_ctx->hHal)
3906 return -EINVAL;
3907
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303908 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303910 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003911 hddLog(LOGE, "Fail to send notification with ht2040 mode");
3912 return -EINVAL;
3913 }
3914
3915 return 0;
3916}
3917#endif
3918
3919/**
3920 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
3921 * @state: state
3922 *
3923 * This function notifies FW with modem power status
3924 *
3925 * Return: 0 if successful, error number otherwise
3926 */
3927int hdd_wlan_notify_modem_power_state(int state)
3928{
3929 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303930 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003931 hdd_context_t *hdd_ctx;
3932
Anurag Chouhan6d760662016-02-20 16:05:43 +05303933 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 status = wlan_hdd_validate_context(hdd_ctx);
3935 if (0 != status) {
3936 hddLog(LOGE, FL("HDD context is not valid"));
3937 return status;
3938 }
3939 if (!hdd_ctx->hHal)
3940 return -EINVAL;
3941
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303942 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
3943 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944 hddLog(LOGE,
3945 "Fail to send notification with modem power state %d",
3946 state);
3947 return -EINVAL;
3948 }
3949 return 0;
3950}
3951
3952/**
3953 *
3954 * hdd_post_cds_enable_config() - HDD post cds start config helper
3955 * @adapter - Pointer to the HDD
3956 *
3957 * Return: None
3958 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303959QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303961 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962
3963 /*
3964 * Send ready indication to the HDD. This will kick off the MAC
3965 * into a 'running' state and should kick off an initial scan.
3966 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303967 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
3968 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303969 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970 FL(
3971 "sme_hdd_ready_ind() failed with status code %08d [x%08x]"
3972 ),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303973 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303974 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 }
3976
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303977 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978}
3979
3980/* wake lock APIs for HDD */
3981void hdd_prevent_suspend(uint32_t reason)
3982{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303983 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003984}
3985
3986void hdd_allow_suspend(uint32_t reason)
3987{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303988 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989}
3990
3991void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
3992{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303993 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994}
3995
3996/**
3997 * hdd_exchange_version_and_caps() - exchange version and capability with target
3998 * @hdd_ctx: Pointer to HDD context
3999 *
4000 * This is the HDD function to exchange version and capability information
4001 * between Host and Target
4002 *
4003 * This function gets reported version of FW.
4004 * It also finds the version of target headers used to compile the host;
4005 * It compares the above two and prints a warning if they are different;
4006 * It gets the SW and HW version string;
4007 * Finally, it exchanges capabilities between host and target i.e. host
4008 * and target exchange a msg indicating the features they support through a
4009 * bitmap
4010 *
4011 * Return: None
4012 */
4013void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4014{
4015
4016 tSirVersionType versionCompiled;
4017 tSirVersionType versionReported;
4018 tSirVersionString versionString;
4019 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304020 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021
4022 memset(&versionCompiled, 0, sizeof(versionCompiled));
4023 memset(&versionReported, 0, sizeof(versionReported));
4024
4025 /* retrieve and display WCNSS version information */
4026 do {
4027
4028 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4029 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304030 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304031 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032 FL(
4033 "unable to retrieve WCNSS WLAN compiled version"
4034 ));
4035 break;
4036 }
4037
4038 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4039 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304040 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304041 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 FL(
4043 "unable to retrieve WCNSS WLAN reported version"
4044 ));
4045 break;
4046 }
4047
4048 if ((versionCompiled.major != versionReported.major) ||
4049 (versionCompiled.minor != versionReported.minor) ||
4050 (versionCompiled.version != versionReported.version) ||
4051 (versionCompiled.revision != versionReported.revision)) {
4052 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4053 "Host expected %u.%u.%u.%u\n",
4054 WLAN_MODULE_NAME,
4055 (int)versionReported.major,
4056 (int)versionReported.minor,
4057 (int)versionReported.version,
4058 (int)versionReported.revision,
4059 (int)versionCompiled.major,
4060 (int)versionCompiled.minor,
4061 (int)versionCompiled.version,
4062 (int)versionCompiled.revision);
4063 } else {
4064 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4065 WLAN_MODULE_NAME,
4066 (int)versionReported.major,
4067 (int)versionReported.minor,
4068 (int)versionReported.version,
4069 (int)versionReported.revision);
4070 }
4071
4072 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4073 versionString,
4074 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304075 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304076 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077 FL(
4078 "unable to retrieve WCNSS software version string"
4079 ));
4080 break;
4081 }
4082
4083 pr_info("%s: WCNSS software version %s\n",
4084 WLAN_MODULE_NAME, versionString);
4085
4086 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4087 versionString,
4088 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304089 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304090 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 FL(
4092 "unable to retrieve WCNSS hardware version string"
4093 ));
4094 break;
4095 }
4096
4097 pr_info("%s: WCNSS hardware version %s\n",
4098 WLAN_MODULE_NAME, versionString);
4099
4100 /*
4101 * 1.Check if FW version is greater than 0.1.1.0. Only then
4102 * send host-FW capability exchange message
4103 * 2.Host-FW capability exchange message is only present on
4104 * target 1.1 so send the message only if it the target is 1.1
4105 * minor numbers for different target branches:
4106 * 0 -> (1.0)Mainline Build
4107 * 1 -> (1.1)Mainline Build
4108 * 2->(1.04) Stability Build
4109 */
4110 if (((versionReported.major > 0) || (versionReported.minor > 1)
4111 || ((versionReported.minor >= 1)
4112 && (versionReported.version >= 1)))
4113 && ((versionReported.major == 1)
4114 && (versionReported.minor >= 1)))
4115 fwFeatCapsMsgSupported = 1;
4116
4117 if (fwFeatCapsMsgSupported) {
4118 /*
4119 * Indicate if IBSS heartbeat monitoring needs to be
4120 * offloaded
4121 */
4122 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4123 sme_disable_feature_capablity
4124 (IBSS_HEARTBEAT_OFFLOAD);
4125 }
4126
4127 sme_feature_caps_exchange(hdd_ctx->hHal);
4128 }
4129
4130 } while (0);
4131
4132}
4133
4134/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304135QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004136{
4137 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4138 hdd_ctx->reg.cc_src);
4139}
4140
4141/**
4142 * hdd_is_5g_supported() - check if hardware supports 5GHz
4143 * @hdd_ctx: Pointer to the hdd context
4144 *
4145 * HDD function to know if hardware supports 5GHz
4146 *
4147 * Return: true if hardware supports 5GHz
4148 */
4149bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4150{
4151 /*
4152 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4153 * then hardware support 5Ghz.
4154 */
4155 return true;
4156}
4157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304158static QDF_STATUS wlan_hdd_regulatory_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159{
4160 struct wiphy *wiphy;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304161 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162
4163 wiphy = hdd_ctx->wiphy;
4164
4165 /*
4166 * The channel information in
4167 * wiphy needs to be initialized before wiphy registration
4168 */
4169 status = cds_regulatory_init();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304170 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304171 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172 FL("cds_init_wiphy failed"));
4173 return status;
4174 }
4175
4176#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4177 wiphy->wowlan = &wowlan_support_reg_init;
4178#else
4179 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4180 WIPHY_WOWLAN_MAGIC_PKT |
4181 WIPHY_WOWLAN_DISCONNECT |
4182 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4183 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4184 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4185 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4186 WIPHY_WOWLAN_RFKILL_RELEASE;
4187
4188 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4189 WOW_MAX_FILTERS_PER_LIST);
4190 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4191 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4192#endif
4193
4194 /* registration of wiphy dev with cfg80211 */
4195 if (0 > wlan_hdd_cfg80211_register(wiphy)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304196 hddLog(QDF_TRACE_LEVEL_ERROR, FL("wiphy register failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304197 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004198 }
4199
4200 return status;
4201}
4202
4203#ifdef MSM_PLATFORM
4204void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004205 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004206{
4207#ifdef CONFIG_CNSS
4208 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004209 uint64_t temp_rx = 0;
4210 uint64_t temp_tx = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211 enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004212 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4213 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004214
Mohit Khannae71e2262015-11-10 09:37:24 -08004215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216 if (total > hdd_ctx->config->busBandwidthHighThreshold)
4217 next_vote_level = CNSS_BUS_WIDTH_HIGH;
4218 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
4219 next_vote_level = CNSS_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004220 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 next_vote_level = CNSS_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004222 else
4223 next_vote_level = CNSS_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224
Mohit Khannae71e2262015-11-10 09:37:24 -08004225 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4226 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004227
4228 if (hdd_ctx->cur_vote_level != next_vote_level) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304229 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004230 FL(
4231 "trigger level %d, tx_packets: %lld, rx_packets: %lld"
4232 ),
4233 next_vote_level, tx_packets, rx_packets);
4234 hdd_ctx->cur_vote_level = next_vote_level;
4235 cnss_request_bus_bandwidth(next_vote_level);
4236 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004237
4238 /* fine-tuning parameters for RX Flows */
4239 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4240
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004241 hdd_ctx->prev_rx = rx_packets;
4242 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004243 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004245 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246
Mohit Khannae71e2262015-11-10 09:37:24 -08004247 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4248 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004249
4250 if (hdd_ctx->cur_rx_level != next_rx_level) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304251 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252 FL("TCP DELACK trigger level %d, average_rx: %llu"),
4253 next_rx_level, temp_rx);
4254 hdd_ctx->cur_rx_level = next_rx_level;
4255 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
4256 &next_rx_level,
4257 sizeof(next_rx_level));
4258 }
4259
Mohit Khannae71e2262015-11-10 09:37:24 -08004260 /* fine-tuning parameters for TX Flows */
4261 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4262 hdd_ctx->prev_tx = tx_packets;
4263 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4264 next_tx_level = WLAN_SVC_TP_HIGH;
4265 else
4266 next_tx_level = WLAN_SVC_TP_LOW;
4267
4268 if (hdd_ctx->cur_tx_level != next_tx_level) {
4269 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4270 next_tx_level, temp_tx);
4271 hdd_ctx->cur_tx_level = next_tx_level;
4272 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4273 &next_tx_level,
4274 sizeof(next_tx_level));
4275 }
4276
4277 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4278 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 hdd_ctx->hdd_txrx_hist_idx++;
4280 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
4281#endif
4282}
4283
4284#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4285static void hdd_bus_bw_compute_cbk(void *priv)
4286{
4287 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4288 hdd_adapter_t *adapter = NULL;
4289 uint64_t tx_packets = 0, rx_packets = 0;
4290 uint64_t total_tx = 0, total_rx = 0;
4291 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304292 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 bool connected = false;
4294 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4295
4296 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304297 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298 status =
4299 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4300
4301 if (adapterNode->pAdapter == NULL)
4302 continue;
4303 adapter = adapterNode->pAdapter;
4304
4305 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION ||
4306 adapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
4307 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4308 != eConnectionState_Associated) {
4309
4310 continue;
4311 }
4312
4313 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
4314 adapter->device_mode == WLAN_HDD_P2P_GO) &&
4315 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4316
4317 continue;
4318 }
4319
4320 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4321 adapter->prev_tx_packets);
4322 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4323 adapter->prev_rx_packets);
4324
4325 total_rx += adapter->stats.rx_packets;
4326 total_tx += adapter->stats.tx_packets;
4327
4328 spin_lock_bh(&hdd_ctx->bus_bw_lock);
4329 adapter->prev_tx_packets = adapter->stats.tx_packets;
4330 adapter->prev_rx_packets = adapter->stats.rx_packets;
4331 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
4332 connected = true;
4333 }
4334
4335 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
4336 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
4337 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
4338 rx_packets;
4339 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
4340 tx_packets;
4341
4342 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
4343 tx_packets += (uint64_t)ipa_tx_packets;
4344 rx_packets += (uint64_t)ipa_rx_packets;
4345
4346 if (!connected) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304347 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 FL("bus bandwidth timer running in disconnected state"));
4349 return;
4350 }
4351
4352 hdd_cnss_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
4353
4354 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
4355 hdd_ipa_uc_stat_request(adapter, 2);
4356
Anurag Chouhan210db072016-02-22 18:42:15 +05304357 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 hdd_ctx->config->busBandwidthComputeInterval);
4359}
4360#endif
4361
4362/**
4363 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
4364 * @hdd_ctx: hdd context
4365 *
4366 * Return: none
4367 */
4368void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
4369{
4370 int i;
4371
4372#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304373 hddLog(QDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374 hdd_ctx->config->busBandwidthComputeInterval,
4375 hdd_ctx->hdd_txrx_hist_idx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304376 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377 "BW High TH: %d BW Med TH: %d BW Low TH: %d",
4378 hdd_ctx->config->busBandwidthHighThreshold,
4379 hdd_ctx->config->busBandwidthMediumThreshold,
4380 hdd_ctx->config->busBandwidthLowThreshold);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304381 hddLog(QDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 hdd_ctx->config->tcpDelackThresholdHigh,
4383 hdd_ctx->config->tcpDelackThresholdLow);
4384#endif
4385
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304386 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004387 "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 -08004388
4389 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304390 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004391 "%d: %llu, %llu, %llu, %llu, %d, %d, %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
4393 hdd_ctx->hdd_txrx_hist[i].interval_rx,
4394 hdd_ctx->hdd_txrx_hist[i].total_tx,
4395 hdd_ctx->hdd_txrx_hist[i].interval_tx,
4396 hdd_ctx->hdd_txrx_hist[i].next_vote_level,
Mohit Khannae71e2262015-11-10 09:37:24 -08004397 hdd_ctx->hdd_txrx_hist[i].next_rx_level,
4398 hdd_ctx->hdd_txrx_hist[i].next_tx_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004399 }
4400 return;
4401}
4402
4403/**
4404 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
4405 * @hdd_ctx: hdd context
4406 *
4407 * Return: none
4408 */
4409void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
4410{
4411 hdd_ctx->hdd_txrx_hist_idx = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304412 qdf_mem_zero(hdd_ctx->hdd_txrx_hist, sizeof(hdd_ctx->hdd_txrx_hist));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004413}
4414
4415/**
4416 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
4417 * @pHddCtx: hdd context
4418 *
4419 * Return: none
4420 */
4421void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
4422{
4423
4424 hdd_adapter_t *adapter = NULL;
4425 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304426 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004427 int i;
4428
4429 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304430 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431 adapter = adapter_node->pAdapter;
4432
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304433 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434 "Session_id %d device mode %d current index %d",
4435 adapter->sessionId, adapter->device_mode,
4436 adapter->history_index);
4437
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304438 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 "Netif queue operation statistics:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304440 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004441 "Current pause_map value %x", adapter->pause_map);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304442 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443 " reason_type: pause_cnt: unpause_cnt");
4444
4445 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304446 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 "%s: %d: %d",
4448 hdd_reason_type_to_string(i),
4449 adapter->queue_oper_stats[i].pause_count,
4450 adapter->queue_oper_stats[i].unpause_count);
4451 }
4452
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304453 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454 "Netif queue operation history:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304455 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004456 "index: time: action_type: reason_type: pause_map");
4457
4458 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304459 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05304461 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 adapter->queue_oper_history[i].time),
4463 hdd_action_type_to_string(
4464 adapter->queue_oper_history[i].netif_action),
4465 hdd_reason_type_to_string(
4466 adapter->queue_oper_history[i].netif_reason),
4467 adapter->queue_oper_history[i].pause_map);
4468 }
4469
4470 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4471 adapter_node = next;
4472 }
4473
4474
4475}
4476
4477/**
4478 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
4479 * @hdd_ctx: hdd context
4480 *
4481 * Return: none
4482 */
4483void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
4484{
4485 hdd_adapter_t *adapter = NULL;
4486 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304487 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004488
4489 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304490 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 adapter = adapter_node->pAdapter;
4492
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304493 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304495 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496 sizeof(adapter->queue_oper_history));
4497
4498 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4499 adapter_node = next;
4500 }
4501}
4502
4503/**
4504 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
4505 * @halHandle: Hal handle
4506 * @pContext: Pointer to the context
4507 * @sessionId: Session ID
4508 * @scanId: Scan ID
4509 * @status: Status
4510 *
4511 * This is the callback to be executed when 11d scan is completed to flush out
4512 * the scan results
4513 *
4514 * 11d scan is done during driver load and is a passive scan on all
4515 * channels supported by the device, 11d scans may find some APs on
4516 * frequencies which are forbidden to be used in the regulatory domain
4517 * the device is operating in. If these APs are notified to the supplicant
4518 * it may try to connect to these APs, thus flush out all the scan results
4519 * which are present in SME after 11d scan is done.
4520 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304521 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304523static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004524 uint8_t sessionId, uint32_t scanId,
4525 eCsrScanStatus status)
4526{
4527 ENTER();
4528
4529 sme_scan_flush_result(halHandle);
4530
4531 EXIT();
4532
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304533 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004534}
4535
4536#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4537/**
4538 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
4539 * @hdd_ctx: hdd global context
4540 *
4541 * Return: none
4542 */
4543static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4544{
4545 uint8_t i;
4546
4547 mutex_init(&hdd_ctx->op_ctx.op_lock);
4548 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4549 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4550 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
4551 }
4552}
4553#else
4554static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4555{
4556}
4557#endif
4558
4559#ifdef WLAN_FEATURE_FASTPATH
4560/**
4561 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
4562 * @hdd_cfg: hdd config
4563 * @context: lower layer context
4564 *
4565 * Return: none
4566 */
4567static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4568 void *context)
4569{
4570 if (hdd_cfg->fastpath_enable)
4571 hif_enable_fastpath(context);
4572}
4573#else
4574static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4575 void *context)
4576{
4577}
4578#endif
4579
4580#if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS)
4581/**
4582 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004583 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004584 * @level: thermal level
4585 *
4586 * Change IPA data path to SW path when the thermal throttle level greater
4587 * than 0, and restore the original data path when throttle level is 0
4588 *
4589 * Return: none
4590 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004591static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004593 hdd_context_t *hdd_ctx = context;
4594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004595 /* Change IPA to SW path when throttle level greater than 0 */
4596 if (level > THROTTLE_LEVEL_0)
4597 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
4598 else
4599 /* restore original concurrency mode */
4600 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
4601}
4602
4603/**
4604 * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel
4605 * @hdd_ctxt: hdd context pointer
4606 * @ap_adapter: hdd hostapd adapter pointer
4607 *
4608 * Try to find safe channel within preferred channel
4609 * In case auto channel selection enabled
4610 * - Preferred and safe channel should be used
4611 * - If no overlapping, preferred channel should be used
4612 *
4613 * Return: 1: found preferred safe channel
4614 * 0: could not found preferred safe channel
4615 */
4616static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt,
4617 hdd_adapter_t *ap_adapter)
4618{
4619 uint16_t safe_channels[NUM_20MHZ_RF_CHANNELS];
4620 uint16_t safe_channel_count;
4621 uint16_t unsafe_channel_count;
4622 uint8_t is_unsafe = 1;
4623 uint16_t i;
4624 uint16_t channel_loop;
4625
4626 if (!hdd_ctxt || !ap_adapter) {
4627 hdd_err("invalid context/adapter");
4628 return 0;
4629 }
4630
4631 safe_channel_count = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304632 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctxt->unsafe_channel_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4634
4635 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
4636 is_unsafe = 0;
4637 for (channel_loop = 0;
4638 channel_loop < unsafe_channel_count; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004639 if (CDS_CHANNEL_NUM(i) ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004640 hdd_ctxt->unsafe_channel_list[channel_loop]) {
4641 is_unsafe = 1;
4642 break;
4643 }
4644 }
4645 if (!is_unsafe) {
4646 safe_channels[safe_channel_count] =
Amar Singhal7a1726a2015-10-14 16:28:11 -07004647 CDS_CHANNEL_NUM(i);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304648 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 FL("safe channel %d"),
4650 safe_channels[safe_channel_count]);
4651 safe_channel_count++;
4652 }
4653 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304654 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 FL("perferred range %d - %d"),
4656 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
4657 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
4658 for (i = 0; i < safe_channel_count; i++) {
4659 if (safe_channels[i] >=
4660 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch
4661 && safe_channels[i] <=
4662 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304663 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 FL("safe channel %d is in perferred range"),
4665 safe_channels[i]);
4666 return 1;
4667 }
4668 }
4669 return 0;
4670}
Abhishek Singh7996eb72015-12-30 17:24:02 +05304671/**
4672 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
4673 * user space
4674 * @frame_ind: Management frame data to be informed.
4675 *
4676 * This function is used to indicate management frame to
4677 * user space
4678 *
4679 * Return: None
4680 *
4681 */
4682void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
4683{
4684 hdd_context_t *hdd_ctx = NULL;
4685 hdd_adapter_t *adapter = NULL;
4686 void *cds_context = NULL;
4687 int i;
4688
4689 /* Get the global VOSS context.*/
4690 cds_context = cds_get_global_context();
4691 if (!cds_context) {
4692 hddLog(LOGE, FL("Global VOS context is Null"));
4693 return;
4694 }
4695 /* Get the HDD context.*/
4696 hdd_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05304697 (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304698
4699 if (0 != wlan_hdd_validate_context(hdd_ctx))
4700 return;
4701
4702 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
4703 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4704 adapter =
4705 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
4706 if (adapter)
4707 break;
4708 }
4709 } else {
4710 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
4711 frame_ind->sessionId);
4712 }
4713
4714 if ((NULL != adapter) &&
4715 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
4716 __hdd_indicate_mgmt_frame(adapter,
4717 frame_ind->frame_len,
4718 frame_ind->frameBuf,
4719 frame_ind->frameType,
4720 frame_ind->rxChan,
4721 frame_ind->rxRssi);
4722 return;
4723}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724
4725/**
4726 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
4727 * @adapter: HDD adapter pointer
4728 * @indParam: Channel avoid notification parameter
4729 *
4730 * Avoid channel notification from FW handler.
4731 * FW will send un-safe channel list to avoid over wrapping.
4732 * hostapd should not use notified channel
4733 *
4734 * Return: None
4735 */
4736static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
4737{
4738 hdd_adapter_t *hostapd_adapter = NULL;
4739 hdd_context_t *hdd_ctxt;
4740 tSirChAvoidIndType *ch_avoid_indi;
4741 uint8_t range_loop;
Amar Singhala297bfa2015-10-15 15:07:29 -07004742 enum channel_enum channel_loop, start_channel_idx = INVALID_RF_CHANNEL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004743 end_channel_idx = INVALID_RF_CHANNEL;
4744 uint16_t start_channel;
4745 uint16_t end_channel;
4746 v_CONTEXT_t cds_context;
4747 static int restart_sap_in_progress;
4748 tHddAvoidFreqList hdd_avoid_freq_list;
4749 uint32_t i;
4750
4751 /* Basic sanity */
4752 if (!hdd_context || !indi_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304753 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid arguments"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 return;
4755 }
4756
4757 hdd_ctxt = (hdd_context_t *) hdd_context;
4758 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
4759 cds_context = hdd_ctxt->pcds_context;
4760
4761 /* Make unsafe channel list */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304762 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004763 FL("band count %d"),
4764 ch_avoid_indi->avoid_range_count);
4765
4766 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304767 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004768 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
4769 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
4770 ch_avoid_indi->avoid_freq_range[i].start_freq;
4771 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
4772 ch_avoid_indi->avoid_freq_range[i].end_freq;
4773 }
4774 hdd_avoid_freq_list.avoidFreqRangeCount =
4775 ch_avoid_indi->avoid_range_count;
4776
4777 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
4778
4779 /* clear existing unsafe channel cache */
4780 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304781 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004782 sizeof(hdd_ctxt->unsafe_channel_list));
4783
4784 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
4785 range_loop++) {
4786 if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) {
4787 hddLog(LOGW, FL("LTE Coex unsafe channel list full"));
4788 break;
4789 }
4790
4791 start_channel = ieee80211_frequency_to_channel(
4792 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
4793 end_channel = ieee80211_frequency_to_channel(
4794 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
4795 hddLog(LOG1, "%s : start %d : %d, end %d : %d", __func__,
4796 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
4797 start_channel,
4798 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
4799 end_channel);
4800
4801 /* do not process frequency bands that are not mapped to
4802 * predefined channels
4803 */
4804 if (start_channel == 0 || end_channel == 0)
4805 continue;
4806
4807 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4808 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004809 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004810 ch_avoid_indi->avoid_freq_range[
4811 range_loop].start_freq) {
4812 start_channel_idx = channel_loop;
4813 break;
4814 }
4815 }
4816 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4817 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004818 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 ch_avoid_indi->avoid_freq_range[
4820 range_loop].end_freq) {
4821 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07004822 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 ch_avoid_indi->avoid_freq_range[
4824 range_loop].end_freq)
4825 end_channel_idx--;
4826 break;
4827 }
4828 }
4829
4830 if (start_channel_idx == INVALID_RF_CHANNEL ||
4831 end_channel_idx == INVALID_RF_CHANNEL)
4832 continue;
4833
4834 for (channel_loop = start_channel_idx; channel_loop <=
4835 end_channel_idx; channel_loop++) {
4836 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07004837 hdd_ctxt->unsafe_channel_count++] =
4838 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839 if (hdd_ctxt->unsafe_channel_count >=
4840 NUM_20MHZ_RF_CHANNELS) {
4841 hddLog(LOGW, FL("LTECoex unsafe ch list full"));
4842 break;
4843 }
4844 }
4845 }
4846
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304847 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848 FL("number of unsafe channels is %d "),
4849 hdd_ctxt->unsafe_channel_count);
4850
4851 if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list,
4852 hdd_ctxt->unsafe_channel_count)) {
4853 hdd_err("Failed to set unsafe channel");
4854
4855 /* clear existing unsafe channel cache */
4856 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304857 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858 sizeof(hdd_ctxt->unsafe_channel_list));
4859
4860 return;
4861 }
4862
4863 for (channel_loop = 0;
4864 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304865 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 FL("channel %d is not safe "),
4867 hdd_ctxt->unsafe_channel_list[channel_loop]);
4868 }
4869
4870 /*
4871 * If auto channel select is enabled
4872 * preferred channel is in safe channel,
4873 * re-start softap interface with safe channel.
4874 * no overlap with preferred channel and safe channel
4875 * do not re-start softap interface
4876 * stay current operating channel.
4877 */
4878 if (hdd_ctxt->unsafe_channel_count) {
4879 hostapd_adapter = hdd_get_adapter(hdd_ctxt, WLAN_HDD_SOFTAP);
4880 if (hostapd_adapter) {
4881 if ((hostapd_adapter->sessionCtx.ap.sapConfig.
4882 acs_cfg.acs_mode) &&
4883 (!hdd_find_prefd_safe_chnl(hdd_ctxt,
4884 hostapd_adapter)))
4885 return;
4886
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304887 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 FL(
4889 "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d"
4890 ),
4891 hostapd_adapter->sessionCtx.ap.
4892 operatingChannel,
4893 hostapd_adapter->sessionCtx.ap.sapConfig.
4894 channel);
4895 for (channel_loop = 0;
4896 channel_loop < hdd_ctxt->unsafe_channel_count;
4897 channel_loop++) {
4898 if (((hdd_ctxt->
4899 unsafe_channel_list[channel_loop] ==
4900 hostapd_adapter->sessionCtx.ap.
4901 operatingChannel)) &&
4902 (hostapd_adapter->sessionCtx.ap.
4903 sapConfig.acs_cfg.acs_mode
4904 == true) &&
4905 !restart_sap_in_progress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304906 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 FL("Restarting SAP"));
4908 wlan_hdd_send_svc_nlink_msg
4909 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
4910 restart_sap_in_progress = 1;
4911 /*
4912 * current operating channel is un-safe
4913 * channel, restart driver
4914 */
4915 hdd_hostapd_stop(hostapd_adapter->dev);
4916 break;
4917 }
4918 }
4919 }
4920 }
4921 return;
4922}
4923
4924/**
4925 * hdd_init_channel_avoidance() - Initialize channel avoidance
4926 * @hdd_ctx: HDD global context
4927 *
4928 * Initialize the channel avoidance logic by retrieving the unsafe
4929 * channel list from the CNSS platform driver and plumbing the data
4930 * down to the lower layers. Then subscribe to subsequent channel
4931 * avoidance events.
4932 *
4933 * Return: None
4934 */
4935static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4936{
4937 uint16_t unsafe_channel_count;
4938 int index;
4939
4940 cnss_get_wlan_unsafe_channel(hdd_ctx->unsafe_channel_list,
4941 &(hdd_ctx->unsafe_channel_count),
4942 sizeof(uint16_t) * NUM_20MHZ_RF_CHANNELS);
4943
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304944 hddLog(QDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945 hdd_ctx->unsafe_channel_count);
4946
Anurag Chouhan6d760662016-02-20 16:05:43 +05304947 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4949
4950 for (index = 0; index < unsafe_channel_count; index++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304951 hddLog(QDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 hdd_ctx->unsafe_channel_list[index]);
4953
4954 }
4955
4956 /* Plug in avoid channel notification callback */
4957 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
4958}
4959#else
4960static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4961{
4962}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004963static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004964{
4965}
4966#endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */
4967
4968/**
4969 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
4970 * @hdd_ctx: HDD context
4971 *
4972 * Disables all the dual mac features like DBS, Agile DFS etc.
4973 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304974 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004975 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304976static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004977{
4978 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304979 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004980
4981 if (!hdd_ctx) {
4982 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304983 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984 }
4985
4986 cfg.scan_config = 0;
4987 cfg.fw_mode_config = 0;
4988 cfg.set_dual_mac_cb =
4989 (void *)cds_soc_set_dual_mac_cfg_cb;
4990
4991 hdd_debug("Disabling all dual mac features...");
4992
4993 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304994 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004995 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
4996 return status;
4997 }
4998
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304999 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005000}
5001
5002/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005003 * hdd_override_ini_config - Override INI config
5004 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005006 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005008 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005010static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005013 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
5014 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5015 hdd_notice("Module enable_dfs_chan_scan set to %d",
5016 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005018 if (0 == enable_11d || 1 == enable_11d) {
5019 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5020 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005022}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005024/**
5025 * hdd_set_trace_level_for_each - Set trace level for each INI config
5026 * @hdd_ctx - HDD context
5027 *
5028 * Set trace level for each module based on INI config.
5029 *
5030 * Return: None
5031 */
5032static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5033{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305034 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
5035 hdd_ctx->config->qdf_trace_enable_wdi);
5036 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
5037 hdd_ctx->config->qdf_trace_enable_hdd);
5038 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
5039 hdd_ctx->config->qdf_trace_enable_sme);
5040 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
5041 hdd_ctx->config->qdf_trace_enable_pe);
5042 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
5043 hdd_ctx->config->qdf_trace_enable_wma);
5044 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
5045 hdd_ctx->config->qdf_trace_enable_sys);
5046 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
5047 hdd_ctx->config->qdf_trace_enable_qdf);
5048 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
5049 hdd_ctx->config->qdf_trace_enable_sap);
5050 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
5051 hdd_ctx->config->qdf_trace_enable_hdd_sap);
5052 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
5053 hdd_ctx->config->qdf_trace_enable_bmi);
5054 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
5055 hdd_ctx->config->qdf_trace_enable_cfg);
5056 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
5057 hdd_ctx->config->qdf_trace_enable_epping);
5058 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
5059 hdd_ctx->config->qdf_trace_enable_qdf_devices);
5060 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05305061 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305062 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
5063 hdd_ctx->config->qdf_trace_enable_htc);
5064 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
5065 hdd_ctx->config->qdf_trace_enable_hif);
5066 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
5067 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
5068 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
5069 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305070
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005071 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005072}
5073
5074/**
5075 * hdd_init_context - Alloc and initialize HDD context
5076 * @dev: Pointer to the underlying device
5077 * @hif_sc: HIF context
5078 *
5079 * Allocate and initialize HDD context. HDD context is allocated as part of
5080 * wiphy allocation and then context is initialized.
5081 *
5082 * Return: HDD context on success and ERR_PTR on failure
5083 */
5084hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc)
5085{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305086 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005087 int ret = 0;
5088 hdd_context_t *hdd_ctx;
5089 v_CONTEXT_t p_cds_context;
Komal Seelamc11bb222016-01-27 18:57:10 +05305090 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_sc);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005091
5092 ENTER();
5093
5094 p_cds_context = cds_get_global_context();
5095 if (p_cds_context == NULL) {
5096 hdd_alert("Failed to get CDS global context");
5097 ret = -EINVAL;
5098 goto err_out;
5099 }
5100
5101 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
5102
5103 if (hdd_ctx == NULL) {
5104 ret = -ENOMEM;
5105 goto err_out;
5106 }
5107
5108 hdd_ctx->pcds_context = p_cds_context;
5109
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305110 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005111 if (hdd_ctx->config == NULL) {
5112 hdd_alert("Failed to alloc memory for HDD config!");
5113 ret = -ENOMEM;
5114 goto err_free_hdd_context;
5115 }
5116
5117 /* Read and parse the qcom_cfg.ini file */
5118 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305119 if (QDF_STATUS_SUCCESS != status) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005120 hdd_alert("Error (status: %d) parsing INI file: %s", status,
5121 WLAN_INI_FILE);
5122 ret = -EINVAL;
5123 goto err_free_config;
5124 }
5125
5126 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
5127
5128 hdd_ctx->parent_dev = dev;
5129
5130 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5131
5132 hdd_init_ll_stats_ctx();
5133
5134 init_completion(&hdd_ctx->mc_sus_event_var);
5135 init_completion(&hdd_ctx->ready_to_suspend);
5136
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305137 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
5138 qdf_spinlock_create(&hdd_ctx->sched_scan_lock);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005139
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305140 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305141 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005142
5143 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
5144
5145 hdd_tdls_pre_init(hdd_ctx);
5146 mutex_init(&hdd_ctx->dfs_lock);
5147
Komal Seelamc11bb222016-01-27 18:57:10 +05305148 hdd_ctx->target_type = tgt_info->target_type;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005149
5150 hdd_init_offloaded_packets_ctx(hdd_ctx);
5151
Komal Seelamc11bb222016-01-27 18:57:10 +05305152 icnss_set_fw_debug_mode(hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005153
5154 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5155
5156 hdd_ctx->configuredMcastBcastFilter =
5157 hdd_ctx->config->mcastBcastFilterSetting;
5158
5159 hdd_notice("Setting configuredMcastBcastFilter: %d",
5160 hdd_ctx->config->mcastBcastFilterSetting);
5161
5162 hdd_override_ini_config(hdd_ctx);
5163
5164 ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config);
5165
5166 if (ret) {
5167 hdd_err("CFG80211 wiphy init failed: %d", ret);
5168 goto err_free_config;
5169 }
5170
5171 hdd_enable_fastpath(hdd_ctx->config, hif_sc);
5172
5173 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05305174 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005175
Anurag Chouhan6d760662016-02-20 16:05:43 +05305176 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005177 goto skip_multicast_logging;
5178
5179 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
5180
5181 ret = hdd_logging_sock_activate_svc(hdd_ctx);
5182 if (ret)
5183 goto err_free_config;
5184
5185 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305186 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005187 * levels of the code need not be set when the logger thread
5188 * is not enabled.
5189 */
5190 if (cds_is_multicast_logging())
5191 wlan_logging_set_log_level();
5192
5193skip_multicast_logging:
5194 hdd_set_trace_level_for_each(hdd_ctx);
5195
5196 return hdd_ctx;
5197
5198err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305199 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005200
5201err_free_hdd_context:
5202 wiphy_free(hdd_ctx->wiphy);
5203
5204err_out:
5205 return ERR_PTR(ret);
5206}
5207
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005208#ifdef WLAN_OPEN_P2P_INTERFACE
5209/**
5210 * hdd_open_p2p_interface - Open P2P interface
5211 * @hdd_ctx: HDD context
5212 * @rtnl_held: True if RTNL lock held
5213 *
5214 * Open P2P interface during probe. This function called to open the P2P
5215 * interface at probe along with STA interface.
5216 *
5217 * Return: 0 on success and errno on failure
5218 */
5219static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
5220{
5221 hdd_adapter_t *adapter;
5222 uint8_t *p2p_dev_addr;
5223
5224 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
5225 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305226 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005227 hdd_ctx->config->intfMacAddr[0].bytes,
5228 sizeof(tSirMacAddr));
5229
5230 /*
5231 * Generate the P2P Device Address. This consists of
5232 * the device's primary MAC address with the locally
5233 * administered bit set.
5234 */
5235 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
5236 } else {
5237 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
5238 if (p2p_dev_addr == NULL) {
5239 hdd_alert("Failed to allocate mac_address for p2p_device");
5240 return -ENOSPC;
5241 }
5242
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305243 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305244 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005245 }
5246
5247 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5248 &hdd_ctx->p2pDeviceAddress.bytes[0],
5249 rtnl_held);
5250
5251 if (NULL == adapter) {
5252 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
5253 return -ENOSPC;
5254 }
5255
5256 return 0;
5257}
5258#else
5259static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx,
5260 bool rtnl_held)
5261{
5262 return 0;
5263}
5264#endif
5265
5266/**
5267 * hdd_open_interfaces - Open all required interfaces
5268 * hdd_ctx: HDD context
5269 * rtnl_held: True if RTNL lock is held
5270 *
5271 * Open all the interfaces like STA, P2P and OCB based on the configuration.
5272 *
5273 * Return: Primary adapter on success and PTR_ERR on failure
5274 */
5275static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
5276 bool rtnl_held)
5277{
5278 hdd_adapter_t *adapter = NULL;
5279 hdd_adapter_t *adapter_11p = NULL;
5280 int ret;
5281
5282 /* Create only 802.11p interface */
5283 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
5284 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d",
5285 wlan_hdd_get_intf_addr(hdd_ctx),
5286 rtnl_held);
5287
5288 if (adapter == NULL)
5289 return ERR_PTR(-ENOSPC);
5290
5291 return adapter;
5292 }
5293
5294 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, "wlan%d",
5295 wlan_hdd_get_intf_addr(hdd_ctx),
5296 rtnl_held);
5297
5298 if (adapter == NULL)
5299 return ERR_PTR(-ENOSPC);
5300
5301 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
5302 if (ret)
5303 goto err_close_adapter;
5304
5305 /* Open 802.11p Interface */
5306 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
5307 adapter_11p = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB,
5308 "wlanocb%d",
5309 wlan_hdd_get_intf_addr(hdd_ctx),
5310 rtnl_held);
5311 if (adapter_11p == NULL) {
5312 hdd_err("Failed to open 802.11p interface");
5313 goto err_close_adapter;
5314 }
5315 }
5316
5317 return adapter;
5318
5319err_close_adapter:
5320 hdd_close_all_adapters(hdd_ctx, rtnl_held);
5321 return ERR_PTR(ret);
5322}
5323
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005324/**
5325 * hdd_update_country_code - Update country code
5326 * @hdd_ctx: HDD context
5327 * @adapter: Primary adapter context
5328 *
5329 * Update country code based on module parameter country_code at SME and wait
5330 * for the settings to take effect.
5331 *
5332 * Return: 0 on success and errno on failure
5333 */
5334static int hdd_update_country_code(hdd_context_t *hdd_ctx,
5335 hdd_adapter_t *adapter)
5336{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305337 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005338 int ret = 0;
5339 unsigned long rc;
5340
5341 if (country_code == NULL)
5342 return 0;
5343
5344 INIT_COMPLETION(adapter->change_country_code);
5345
5346 status = sme_change_country_code(hdd_ctx->hHal,
5347 wlan_hdd_change_country_code_callback,
5348 country_code, adapter,
5349 hdd_ctx->pcds_context, eSIR_TRUE,
5350 eSIR_TRUE);
5351
5352
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305353 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005354 hdd_err("SME Change Country code from module param fail ret=%d",
5355 ret);
5356 return -EINVAL;
5357 }
5358
5359 rc = wait_for_completion_timeout(&adapter->change_country_code,
5360 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
5361 if (!rc) {
5362 hdd_err("SME while setting country code timed out");
5363 ret = -ETIMEDOUT;
5364 }
5365
5366 return ret;
5367}
5368
5369/**
5370 * hdd_init_thermal_info - Initialize thermal level
5371 * @hdd_ctx: HDD context
5372 *
5373 * Initialize thermal level at SME layer and set the thermal level callback
5374 * which would be called when a configured thermal threshold is hit.
5375 *
5376 * Return: 0 on success and errno on failure
5377 */
5378static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
5379{
5380 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305381 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005382
5383 thermal_param.smeThermalMgmtEnabled =
5384 hdd_ctx->config->thermalMitigationEnable;
5385 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
5386
5387 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
5388 hdd_ctx->config->thermalTempMinLevel0;
5389 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
5390 hdd_ctx->config->thermalTempMaxLevel0;
5391 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
5392 hdd_ctx->config->thermalTempMinLevel1;
5393 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
5394 hdd_ctx->config->thermalTempMaxLevel1;
5395 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
5396 hdd_ctx->config->thermalTempMinLevel2;
5397 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
5398 hdd_ctx->config->thermalTempMaxLevel2;
5399 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
5400 hdd_ctx->config->thermalTempMinLevel3;
5401 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
5402 hdd_ctx->config->thermalTempMaxLevel3;
5403
5404 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
5405
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305406 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05305407 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005408
5409 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
5410 hdd_set_thermal_level_cb);
5411
5412 return 0;
5413
5414}
5415
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005416#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5417/**
5418 * hdd_hold_rtnl_lock - Hold RTNL lock
5419 *
5420 * Hold RTNL lock
5421 *
5422 * Return: True if held and false otherwise
5423 */
5424static inline bool hdd_hold_rtnl_lock(void)
5425{
5426 rtnl_lock();
5427 return true;
5428}
5429
5430/**
5431 * hdd_release_rtnl_lock - Release RTNL lock
5432 *
5433 * Release RTNL lock
5434 *
5435 * Return: None
5436 */
5437static inline void hdd_release_rtnl_lock(void)
5438{
5439 rtnl_unlock();
5440}
5441#else
5442static inline bool hdd_hold_rtnl_lock(void) { return false; }
5443static inline void hdd_release_rtnl_lock(void) { }
5444#endif
5445
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005446/**
5447 * hdd_wlan_startup() - HDD init function
5448 * @dev: Pointer to the underlying device
5449 *
5450 * This is the driver startup code executed once a WLAN device has been detected
5451 *
5452 * Return: 0 for success, < 0 for failure
5453 */
5454int hdd_wlan_startup(struct device *dev, void *hif_sc)
5455{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305456 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005457 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005458 hdd_context_t *hdd_ctx = NULL;
5459 int ret;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005460 tSirTxPowerLimit hddtxlimit;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005461 bool rtnl_held;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005462 tSirRetStatus hal_status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005463
5464 ENTER();
5465
5466 if (WLAN_IS_EPPING_ENABLED(con_mode)) {
5467 ret = epping_enable(dev);
5468 EXIT();
5469 return ret;
5470 }
5471
5472 hdd_ctx = hdd_init_context(dev, hif_sc);
5473
5474 if (IS_ERR(hdd_ctx))
5475 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476
Anurag Chouhan6d760662016-02-20 16:05:43 +05305477 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005478 ret = hdd_enable_ftm(hdd_ctx);
5479
5480 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005481 goto err_hdd_free_context;
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005482
5483 goto success;
5484 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005485
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08005486 hdd_wlan_green_ap_init(hdd_ctx);
5487
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005488 status = cds_open();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305489 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305490 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_open failed"));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005491 goto err_hdd_free_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492 }
5493
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005494 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005495
Anurag Chouhan6d760662016-02-20 16:05:43 +05305496 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497
5498 if (NULL == hdd_ctx->hHal) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305499 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HAL context is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005500 goto err_cds_close;
5501 }
5502
5503 status = cds_pre_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305504 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305505 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506 goto err_cds_close;
5507 }
5508
5509 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
5510
5511 status = wlan_hdd_regulatory_init(hdd_ctx);
5512
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305513 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305514 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515 FL("Failed to init channel list"));
5516 goto err_cds_close;
5517 }
5518
5519 /*
5520 * Set 802.11p config
5521 * TODO-OCB: This has been temporarily added here to ensure this
5522 * parameter is set in CSR when we init the channel list. This should
5523 * be removed once the 5.9 GHz channels are added to the regulatory
5524 * domain.
5525 */
5526 hdd_set_dot11p_config(hdd_ctx);
5527
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 /*
5529 * Note that the cds_pre_enable() sequence triggers the cfg download.
5530 * The cfg download must occur before we update the SME config
5531 * since the SME config operation must access the cfg database
5532 */
5533 status = hdd_set_sme_config(hdd_ctx);
5534
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305535 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305536 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537 goto err_wiphy_unregister;
5538 }
5539
5540 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
5541 hdd_ctx->config->tx_chain_mask_1ss,
5542 PDEV_CMD);
5543 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305544 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005545 "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d",
5546 __func__, ret);
5547 }
5548
5549 status = hdd_set_sme_chan_list(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305550 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305551 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005552 FL("Failed to init channel list"));
5553 goto err_wiphy_unregister;
5554 }
5555
5556 /* Apply the cfg.ini to cfg.dat */
5557 if (false == hdd_update_config_dat(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305558 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005559 FL("config update failed"));
5560 goto err_wiphy_unregister;
5561 }
5562
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305563 if (QDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305564 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005565 FL("can't update mac config, using MAC from ini file"));
5566 }
5567
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005568 /*
5569 * Set the MAC Address Currently this is used by HAL to add self sta.
5570 * Remove this once self sta is added as part of session open.
5571 */
5572 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
5573 hdd_ctx->config->intfMacAddr[0].bytes,
5574 sizeof(hdd_ctx->config->intfMacAddr[0]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005576 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
5577 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
5578 hal_status, hal_status);
5579 ret = -EINVAL;
5580 goto err_wiphy_unregister;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005581 }
5582
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305583 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005584 goto err_wiphy_unregister;
5585
5586 /*
5587 * Start CDS which starts up the SME/MAC/HAL modules and everything
5588 * else
5589 */
5590 status = cds_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305591 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305592 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_enable failed"));
Yun Park6a46ad82016-01-04 16:48:19 -08005593 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005594 }
5595
5596 hdd_init_channel_avoidance(hdd_ctx);
5597
5598 status = hdd_post_cds_enable_config(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305599 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305600 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005601 FL("hdd_post_cds_enable_config failed"));
5602 goto err_cds_disable;
5603 }
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005604
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005605 cds_pkt_proto_trace_init();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005606
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005607 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005608
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005609 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005610
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005611 if (IS_ERR(adapter)) {
5612 ret = PTR_ERR(adapter);
5613 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614 }
5615
5616 /*
5617 * target hw version/revision would only be retrieved after firmware
5618 * donwload
5619 */
5620 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
5621 &hdd_ctx->target_hw_revision,
5622 &hdd_ctx->target_hw_name);
5623
5624 /* Get the wlan hw/fw version */
5625 hdd_wlan_get_version(adapter, NULL, NULL);
5626
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005627 ret = hdd_update_country_code(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005628
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005629 if (ret)
5630 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005631
5632 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
5633
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005634 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
5635 hdd_send_oem_data_rsp_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005636
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005637 status = hdd_debugfs_init(adapter);
5638
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305639 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005640 hdd_err("hdd_debugfs_init failed: %d!", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641
5642 /* FW capabilities received, Set the Dot11 mode */
5643 sme_setdef_dot11mode(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005645 /* Initialize the nlink service */
5646 if (nl_srv_init() != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305647 hddLog(QDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed"));
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005648 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005649 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005651 ret = oem_activate_service(hdd_ctx);
5652 if (ret) {
5653 hdd_alert("oem_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005654 goto err_nl_srv;
5655 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005657 ret = ptt_sock_activate_svc();
5658 if (ret) {
5659 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 goto err_nl_srv;
5661 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005662
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005663 ret = cnss_diag_activate_service();
5664 if (ret) {
5665 hdd_alert("cnss_diag_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005666 goto err_nl_srv;
5667 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005668
Peng Xuf5d60c82015-10-02 17:17:03 -07005669 /*
5670 * Action frame registered in one adapter which will
5671 * applicable to all interfaces
5672 */
5673 wlan_hdd_cfg80211_register_frames(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005674
5675 mutex_init(&hdd_ctx->sap_lock);
5676
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005677 hdd_release_rtnl_lock();
5678 rtnl_held = false;
5679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5681 if (ret < 0) {
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005682 hdd_err("register_netdevice_notifier failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005683 goto err_nl_srv;
5684 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005685
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5687 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305688 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689#endif
5690 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305691 qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692
5693 hdd_hostapd_channel_wakelock_init(hdd_ctx);
5694
Kiran Kumar Lokerefc2803d2016-01-11 19:31:38 -08005695 if (hdd_ctx->config->fIsImpsEnabled)
5696 hdd_set_idle_ps_config(hdd_ctx, true);
5697 else
5698 hdd_set_idle_ps_config(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5700 if (hdd_ctx->config->WlanAutoShutdown != 0)
5701 if (sme_set_auto_shutdown_cb
5702 (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305703 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704 hddLog(LOGE,
5705 FL(
5706 "Auto shutdown feature could not be enabled"
5707 ));
5708#endif
5709
5710#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305711 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305712 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005713 hdd_skip_acs_scan_timer_handler,
5714 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305715 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005716 hddLog(LOGE, FL("Failed to init ACS Skip timer"));
5717#endif
5718
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005719 wlan_hdd_nan_init(hdd_ctx);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005720 status = cds_init_policy_mgr();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305721 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005722 hdd_err("Policy manager initialization failed");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005723 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005724 }
5725
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005726 ret = hdd_init_thermal_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005728 if (ret) {
5729 hdd_err("Error while initializing thermal information");
5730 goto err_unreg_netdev_notifier;
5731 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005732
5733 if (0 != hdd_lro_init(hdd_ctx))
5734 hdd_err("Unable to initialize LRO in fw");
5735
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005736 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
5737 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
5738 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305739 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005740 hdd_err("Error setting txlimit in sme: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005741
5742#ifdef MSM_PLATFORM
5743 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05305744 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305745 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005746 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5747#endif
5748
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005749 wlan_hdd_cfg80211_stats_ext_init(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751 sme_ext_scan_register_callback(hdd_ctx->hHal,
5752 wlan_hdd_cfg80211_extscan_callback);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005753
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
5755 hdd_rssi_threshold_breached);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005757 hdd_cfg80211_link_layer_stats_init(hdd_ctx);
5758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
5760 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
5761 hdd_ctx->target_hw_version,
5762 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005763
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305764 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305765 qdf_list_create((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305766 qdf_spinlock_create(&hdd_ctx->hdd_scan_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305767 qdf_list_create((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005768#ifdef CONFIG_CNSS
5769 cnss_init_delayed_work(&hdd_ctx->roc_req_work,
5770 wlan_hdd_roc_request_dequeue);
5771#else
5772 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5773#endif
5774
5775 /*
5776 * Register IPv6 notifier to notify if any change in IP
5777 * So that we can reconfigure the offload parameters
5778 */
5779 hdd_wlan_register_ip6_notifier(hdd_ctx);
5780
5781 /*
5782 * Register IPv4 notifier to notify if any change in IP
5783 * So that we can reconfigure the offload parameters
5784 */
5785 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5786 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5787 if (ret)
5788 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
5789 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005790 hdd_info("Registered IPv4 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791
5792 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
5793
5794 if (hdd_ctx->config->dual_mac_feature_disable) {
5795 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305796 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005797 hdd_err("Failed to disable dual mac features");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005798 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799 }
5800 }
5801
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005802 memdump_init();
5803
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005804 goto success;
5805
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005806err_unreg_netdev_notifier:
5807 unregister_netdevice_notifier(&hdd_netdev_notifier);
5808
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809err_nl_srv:
5810#ifdef WLAN_KD_READY_NOTIFIER
5811 cnss_diag_notify_wlan_close();
5812 ptt_sock_deactivate_svc();
5813#endif /* WLAN_KD_READY_NOTIFIER */
5814 nl_srv_exit();
5815
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305816 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08005817 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005818 /* Proceed and complete the clean up */
5819 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005820
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005821 hdd_debugfs_exit(hdd_ctx);
5822
5823err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005824 hdd_release_rtnl_lock();
5825
5826 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005827
5828err_cds_disable:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005829 cds_disable(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830
Yun Park6a46ad82016-01-04 16:48:19 -08005831err_ipa_cleanup:
5832 hdd_ipa_cleanup(hdd_ctx);
5833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005834err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005835 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836
5837err_cds_close:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005838 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305839 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305840 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305842 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005843 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005844 cds_close(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005846err_hdd_free_context:
5847 hdd_free_context(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305848 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 return -EIO;
5851
5852success:
5853 EXIT();
5854 return 0;
5855}
5856
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005857/**
5858 * hdd_softap_sta_deauth() - handle deauth req from HDD
5859 * @adapter: Pointer to the HDD
5860 * @enable: bool value
5861 *
5862 * This to take counter measure to handle deauth req from HDD
5863 *
5864 * Return: None
5865 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305866QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867 struct tagCsrDelStaParams *pDelStaParams)
5868{
5869#ifndef WLAN_FEATURE_MBSSID
5870 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5871#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305872 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005873
5874 ENTER();
5875
5876 hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"),
5877 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5878
5879 /* Ignore request to deauth bcmc station */
5880 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305881 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005882
5883#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305884 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5886 pDelStaParams);
5887#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305888 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005889#endif
5890
5891 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305892 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893}
5894
5895/**
5896 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
5897 * @adapter: Pointer to the HDD
5898 *
5899 * This to take counter measure to handle deauth req from HDD
5900 *
5901 * Return: None
5902 */
5903void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
5904 uint8_t *pDestMacAddress)
5905{
5906#ifndef WLAN_FEATURE_MBSSID
5907 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5908#endif
5909
5910 ENTER();
5911
5912 hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"),
5913 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5914
5915 /* Ignore request to disassoc bcmc station */
5916 if (pDestMacAddress[0] & 0x1)
5917 return;
5918
5919#ifdef WLAN_FEATURE_MBSSID
5920 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5921 pDestMacAddress);
5922#else
5923 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
5924#endif
5925}
5926
5927void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
5928 bool enable)
5929{
5930#ifndef WLAN_FEATURE_MBSSID
5931 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5932#endif
5933
5934 ENTER();
5935
5936 hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"),
5937 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5938
5939#ifdef WLAN_FEATURE_MBSSID
5940 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5941 (bool) enable);
5942#else
5943 wlansap_set_counter_measure(p_cds_context, (bool) enable);
5944#endif
5945}
5946
5947/**
5948 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
5949 * @hdd_ctx: HDD Context
5950 *
5951 * API to find if there is any STA or P2P-Client is connected
5952 *
5953 * Return: true if connected; false otherwise
5954 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305955QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005956{
5957 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
5958}
5959
5960#ifdef WLAN_FEATURE_LPSS
5961int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
5962 hdd_adapter_t *adapter,
5963 hdd_station_ctx_t *pHddStaCtx,
5964 uint8_t is_on, uint8_t is_connected)
5965{
5966 hdd_context_t *hdd_ctx = NULL;
5967 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
5968
5969 if (!data) {
5970 hddLog(LOGE, FL("invalid data pointer"));
5971 return -EINVAL;
5972 }
5973 if (!adapter) {
5974 if (is_on) {
5975 /* no active interface */
5976 data->lpss_support = 0;
5977 data->is_on = is_on;
5978 return 0;
5979 }
5980 hddLog(LOGE, FL("invalid adapter pointer"));
5981 return -EINVAL;
5982 }
5983
5984 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelamc11bb222016-01-27 18:57:10 +05305985 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986 data->lpss_support = 1;
5987 else
5988 data->lpss_support = 0;
5989 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
5990 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
5991 &data->numChannels);
5992 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
5993 data->is_on = is_on;
5994 data->vdev_id = adapter->sessionId;
5995 data->vdev_mode = adapter->device_mode;
5996 if (pHddStaCtx) {
5997 data->is_connected = is_connected;
5998 data->rssi = adapter->rssi;
5999 data->freq =
6000 cds_chan_to_freq(pHddStaCtx->conn_info.operationChannel);
6001 if (WLAN_SVC_MAX_SSID_LEN >=
6002 pHddStaCtx->conn_info.SSID.SSID.length) {
6003 data->ssid_len = pHddStaCtx->conn_info.SSID.SSID.length;
6004 memcpy(data->ssid,
6005 pHddStaCtx->conn_info.SSID.SSID.ssId,
6006 pHddStaCtx->conn_info.SSID.SSID.length);
6007 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05306008 if (QDF_MAC_ADDR_SIZE >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006009 sizeof(pHddStaCtx->conn_info.bssId))
6010 memcpy(data->bssid, pHddStaCtx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306011 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012 }
6013 return 0;
6014}
6015
6016int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
6017 uint32_t fw_version,
6018 uint32_t chip_id, const char *chip_name)
6019{
6020 if (!data) {
6021 hddLog(LOGE, FL("invalid data pointer"));
6022 return -EINVAL;
6023 }
6024
6025 data->chip_id = chip_id;
6026 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
6027 if (strncmp(chip_name, "Unknown", 7))
6028 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
6029 else
6030 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
6031 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
6032 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
6033 (fw_version & 0xf0000000) >> 28,
6034 (fw_version & 0xf000000) >> 24,
6035 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
6036 return 0;
6037}
6038#endif
6039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006040/**
6041 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
6042 * @adapter: HDD adapter pointer
6043 *
6044 * This function loop through each adapter and disable roaming on each STA
6045 * device mode except the input adapter.
6046 *
6047 * Note: On the input adapter roaming is not enabled yet hence no need to
6048 * disable.
6049 *
6050 * Return: None
6051 */
6052void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
6053{
6054 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6055 hdd_adapter_t *adapterIdx = NULL;
6056 hdd_adapter_list_node_t *adapterNode = NULL;
6057 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306058 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059
6060 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6061 hdd_ctx->config->isRoamOffloadScanEnabled &&
6062 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6063 cds_is_sta_active_connection_exists()) {
6064 hddLog(LOG1, FL("Connect received on STA sessionId(%d)"),
6065 adapter->sessionId);
6066 /*
6067 * Loop through adapter and disable roaming for each STA device
6068 * mode except the input adapter.
6069 */
6070 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6071
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306072 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073 adapterIdx = adapterNode->pAdapter;
6074
6075 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6076 && adapter->sessionId != adapterIdx->sessionId) {
6077 hddLog(LOG1,
6078 FL("Disable Roaming on sessionId(%d)"),
6079 adapterIdx->sessionId);
6080 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
6081 (adapterIdx),
6082 adapterIdx->sessionId, 0);
6083 }
6084
6085 status = hdd_get_next_adapter(hdd_ctx,
6086 adapterNode,
6087 &pNext);
6088 adapterNode = pNext;
6089 }
6090 }
6091}
6092
6093/**
6094 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
6095 * @adapter: HDD adapter pointer
6096 *
6097 * This function loop through each adapter and enable roaming on each STA
6098 * device mode except the input adapter.
6099 * Note: On the input adapter no need to enable roaming because link got
6100 * disconnected on this.
6101 *
6102 * Return: None
6103 */
6104void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
6105{
6106 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6107 hdd_adapter_t *adapterIdx = NULL;
6108 hdd_adapter_list_node_t *adapterNode = NULL;
6109 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306110 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006111
6112 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6113 hdd_ctx->config->isRoamOffloadScanEnabled &&
6114 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6115 cds_is_sta_active_connection_exists()) {
6116 hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"),
6117 adapter->sessionId);
6118 /*
6119 * Loop through adapter and enable roaming for each STA device
6120 * mode except the input adapter.
6121 */
6122 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6123
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306124 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006125 adapterIdx = adapterNode->pAdapter;
6126
6127 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6128 && adapter->sessionId != adapterIdx->sessionId) {
6129 hddLog(LOG1,
6130 FL("Enabling Roaming on sessionId(%d)"),
6131 adapterIdx->sessionId);
6132 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
6133 (adapterIdx),
6134 adapterIdx->sessionId,
6135 REASON_CONNECT);
6136 }
6137
6138 status = hdd_get_next_adapter(hdd_ctx,
6139 adapterNode,
6140 &pNext);
6141 adapterNode = pNext;
6142 }
6143 }
6144}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006145
6146void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
6147{
6148 struct sk_buff *skb;
6149 struct nlmsghdr *nlh;
6150 tAniMsgHdr *ani_hdr;
6151 void *nl_data = NULL;
6152 int flags = GFP_KERNEL;
6153
6154 if (in_interrupt() || irqs_disabled() || in_atomic())
6155 flags = GFP_ATOMIC;
6156
6157 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
6158
6159 if (skb == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306160 hddLog(QDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006161 return;
6162 }
6163
6164 nlh = (struct nlmsghdr *)skb->data;
6165 nlh->nlmsg_pid = 0; /* from kernel */
6166 nlh->nlmsg_flags = 0;
6167 nlh->nlmsg_seq = 0;
6168 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
6169
6170 ani_hdr = NLMSG_DATA(nlh);
6171 ani_hdr->type = type;
6172
6173 switch (type) {
6174 case WLAN_SVC_FW_CRASHED_IND:
6175 case WLAN_SVC_LTE_COEX_IND:
6176#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6177 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
6178#endif
6179 ani_hdr->length = 0;
6180 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
6181 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
6182 break;
6183 case WLAN_SVC_WLAN_STATUS_IND:
6184 case WLAN_SVC_WLAN_VERSION_IND:
6185 case WLAN_SVC_DFS_CAC_START_IND:
6186 case WLAN_SVC_DFS_CAC_END_IND:
6187 case WLAN_SVC_DFS_RADAR_DETECT_IND:
6188 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
6189 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08006190 case WLAN_SVC_WLAN_TP_TX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006191 ani_hdr->length = len;
6192 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
6193 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
6194 memcpy(nl_data, data, len);
6195 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
6196 break;
6197
6198 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306199 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006200 FL("WLAN SVC: Attempt to send unknown nlink message %d"),
6201 type);
6202 kfree_skb(skb);
6203 return;
6204 }
6205
6206 nl_srv_bcast(skb);
6207
6208 return;
6209}
6210
6211#ifdef WLAN_FEATURE_LPSS
6212void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
6213 hdd_station_ctx_t *pHddStaCtx,
6214 uint8_t is_on, uint8_t is_connected)
6215{
6216 int ret = 0;
6217 struct wlan_status_data data;
6218
Anurag Chouhan6d760662016-02-20 16:05:43 +05306219 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006220 return;
6221
6222 memset(&data, 0, sizeof(struct wlan_status_data));
6223 if (is_on)
6224 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, pHddStaCtx,
6225 is_on, is_connected);
6226 if (!ret)
6227 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND,
6228 &data,
6229 sizeof(struct wlan_status_data));
6230}
6231
6232void wlan_hdd_send_version_pkg(uint32_t fw_version,
6233 uint32_t chip_id, const char *chip_name)
6234{
6235 int ret = 0;
6236 struct wlan_version_data data;
6237#ifdef CONFIG_CNSS
6238 struct cnss_platform_cap cap;
6239
6240 ret = cnss_get_platform_cap(&cap);
6241 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306242 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006243 FL("platform capability info from CNSS not available"));
6244 return;
6245 }
6246
6247 if (!(cap.cap_flag & CNSS_HAS_UART_ACCESS))
6248 return;
6249#endif
6250
Anurag Chouhan6d760662016-02-20 16:05:43 +05306251 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 return;
6253
6254 memset(&data, 0, sizeof(struct wlan_version_data));
6255 ret =
6256 wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
6257 chip_name);
6258 if (!ret)
6259 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND,
6260 &data,
6261 sizeof(struct wlan_version_data));
6262}
6263
6264void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
6265{
6266 hdd_adapter_t *pDataAdapter = NULL;
6267 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6268 bool scan_intf_found = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306269 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006270
6271 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306272 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006273 FL("NULL pointer for hdd_ctx"));
6274 return;
6275 }
6276
6277 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306278 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006279 pDataAdapter = adapterNode->pAdapter;
6280 if (pDataAdapter) {
6281 if (pDataAdapter->device_mode == WLAN_HDD_INFRA_STATION
6282 || pDataAdapter->device_mode == WLAN_HDD_P2P_CLIENT
6283 || pDataAdapter->device_mode ==
6284 WLAN_HDD_P2P_DEVICE) {
6285 scan_intf_found = true;
6286 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1,
6287 0);
6288 }
6289 }
6290 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6291 adapterNode = pNext;
6292 }
6293
6294 if (!scan_intf_found)
6295 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0);
6296}
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006297#else
6298static inline void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter,
6299 hdd_station_ctx_t *pHddStaCtx,
6300 uint8_t is_on, uint8_t is_connected)
6301{
6302 return;
6303}
6304
6305static inline void wlan_hdd_send_version_pkg(uint32_t fw_version, uint32_t
6306 chip_id, const char *chip_name)
6307{
6308 return;
6309}
6310
6311static inline void wlan_hdd_send_all_scan_intf_info(hdd_context_t *pHddCtx)
6312{
6313 return;
6314}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006315#endif
6316
6317#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6318void wlan_hdd_auto_shutdown_cb(void)
6319{
6320 hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event.."));
6321 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
6322}
6323
6324void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
6325{
6326 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306327 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006328 hdd_adapter_t *adapter;
6329 bool ap_connected = false, sta_connected = false;
6330 tHalHandle hal_handle;
6331
6332 hal_handle = hdd_ctx->hHal;
6333 if (hal_handle == NULL)
6334 return;
6335
6336 if (hdd_ctx->config->WlanAutoShutdown == 0)
6337 return;
6338
6339 if (enable == false) {
6340 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306341 QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006342 hddLog(LOGE,
6343 FL("Failed to stop wlan auto shutdown timer"));
6344 }
6345 return;
6346 }
6347
6348 /* To enable shutdown timer check conncurrency */
6349 if (cds_concurrent_open_sessions_running()) {
6350 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6351
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306352 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006353 adapter = adapterNode->pAdapter;
6354 if (adapter
6355 && adapter->device_mode ==
6356 WLAN_HDD_INFRA_STATION) {
6357 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6358 conn_info.connState ==
6359 eConnectionState_Associated) {
6360 sta_connected = true;
6361 break;
6362 }
6363 }
6364 if (adapter
6365 && adapter->device_mode == WLAN_HDD_SOFTAP) {
6366 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
6367 bApActive == true) {
6368 ap_connected = true;
6369 break;
6370 }
6371 }
6372 status = hdd_get_next_adapter(hdd_ctx,
6373 adapterNode,
6374 &pNext);
6375 adapterNode = pNext;
6376 }
6377 }
6378
6379 if (ap_connected == true || sta_connected == true) {
6380 hddLog(LOG1,
6381 FL("CC Session active. Shutdown timer not enabled"));
6382 return;
6383 } else {
6384 if (sme_set_auto_shutdown_timer(hal_handle,
6385 hdd_ctx->config->
6386 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306387 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006388 hddLog(LOGE,
6389 FL("Failed to start wlan auto shutdown timer"));
6390 else
6391 hddLog(LOG1,
6392 FL("Auto Shutdown timer for %d seconds enabled"),
6393 hdd_ctx->config->WlanAutoShutdown);
6394
6395 }
6396}
6397#endif
6398
6399hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
6400 bool check_start_bss)
6401{
6402 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
6403 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306404 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006405 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6406
6407 con_sap_adapter = NULL;
6408
6409 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306410 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006411 adapter = adapterNode->pAdapter;
6412 if (adapter && ((adapter->device_mode == WLAN_HDD_SOFTAP) ||
6413 (adapter->device_mode == WLAN_HDD_P2P_GO)) &&
6414 adapter != this_sap_adapter) {
6415 if (check_start_bss) {
6416 if (test_bit(SOFTAP_BSS_STARTED,
6417 &adapter->event_flags)) {
6418 con_sap_adapter = adapter;
6419 break;
6420 }
6421 } else {
6422 con_sap_adapter = adapter;
6423 break;
6424 }
6425 }
6426 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6427 adapterNode = pNext;
6428 }
6429
6430 return con_sap_adapter;
6431}
6432
6433#ifdef MSM_PLATFORM
6434void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
6435{
6436 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6437
Anurag Chouhan210db072016-02-22 18:42:15 +05306438 if (QDF_TIMER_STATE_RUNNING ==
6439 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006440 return;
6441
Anurag Chouhan210db072016-02-22 18:42:15 +05306442 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006443 hdd_ctx->config->busBandwidthComputeInterval);
6444}
6445
6446void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
6447{
6448 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306449 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006450 bool can_stop = true;
6451 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6452
Anurag Chouhan210db072016-02-22 18:42:15 +05306453 if (QDF_TIMER_STATE_RUNNING !=
6454 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006455 /* trying to stop timer, when not running is not good */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306456 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006457 FL("bus band width compute timer is not running"));
6458 return;
6459 }
6460
6461 if (cds_concurrent_open_sessions_running()) {
6462 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6463
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306464 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006465 adapter = adapterNode->pAdapter;
6466 if (adapter
6467 && (adapter->device_mode == WLAN_HDD_INFRA_STATION
6468 || adapter->device_mode == WLAN_HDD_P2P_CLIENT)
6469 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6470 conn_info.connState ==
6471 eConnectionState_Associated) {
6472 can_stop = false;
6473 break;
6474 }
6475 if (adapter
6476 && (adapter->device_mode == WLAN_HDD_SOFTAP
6477 || adapter->device_mode == WLAN_HDD_P2P_GO)
6478 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
6479 true) {
6480 can_stop = false;
6481 break;
6482 }
6483 status = hdd_get_next_adapter(hdd_ctx,
6484 adapterNode,
6485 &pNext);
6486 adapterNode = pNext;
6487 }
6488 }
6489
6490 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05306491 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006492}
6493#endif
6494
6495/**
6496 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
6497 * and sta's operating channel.
6498 * @sta_adapter: Describe the first argument to foobar.
6499 * @ap_adapter: Describe the second argument to foobar.
6500 * @roam_profile: Roam profile of AP to which STA wants to connect.
6501 * @concurrent_chnl_same: If both SAP and STA channels are same then
6502 * set this flag to true else false.
6503 *
6504 * This function checks the sap's operating channel and sta's operating channel.
6505 * if both are same then it will return false else it will restart the sap in
6506 * sta's channel and return true.
6507 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306508 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006509 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306510QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006511 hdd_adapter_t *ap_adapter,
6512 tCsrRoamProfile *roam_profile,
6513 tScanResultHandle *scan_cache,
6514 bool *concurrent_chnl_same)
6515{
6516 hdd_ap_ctx_t *hdd_ap_ctx;
6517 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306518 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006519 device_mode_t device_mode = ap_adapter->device_mode;
6520 *concurrent_chnl_same = true;
6521
6522 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6523 status =
6524 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
6525 roam_profile,
6526 scan_cache,
6527 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306528 if ((QDF_STATUS_SUCCESS == status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006529 if ((WLAN_HDD_SOFTAP == device_mode) &&
6530 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
6531 if (hdd_ap_ctx->operatingChannel != channel_id) {
6532 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306533 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006534 FL("channels are different"));
6535 }
6536 } else if ((WLAN_HDD_P2P_GO == device_mode) &&
6537 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
6538 if (hdd_ap_ctx->operatingChannel != channel_id) {
6539 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306540 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006541 FL("channels are different"));
6542 }
6543 }
6544 } else {
6545 /*
6546 * Lets handle worst case scenario here, Scan cache lookup is
6547 * failed so we have to stop the SAP to avoid any channel
6548 * discrepancy between SAP's channel and STA's channel.
6549 * Return the status as failure so caller function could know
6550 * that scan look up is failed.
6551 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306552 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006553 FL("Finding AP from scan cache failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306554 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006555 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306556 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006557}
6558
6559#ifdef WLAN_FEATURE_MBSSID
6560/**
6561 * wlan_hdd_stop_sap() - This function stops bss of SAP.
6562 * @ap_adapter: SAP adapter
6563 *
6564 * This function will process the stopping of sap adapter.
6565 *
6566 * Return: None
6567 */
6568void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
6569{
6570 hdd_ap_ctx_t *hdd_ap_ctx;
6571 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306572 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006573 hdd_context_t *hdd_ctx;
6574#ifdef CFG80211_DEL_STA_V2
6575 struct station_del_parameters delStaParams;
6576#endif
6577
6578 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306579 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006580 FL("ap_adapter is NULL here"));
6581 return;
6582 }
6583
6584 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6585 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6586 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306587 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006588 FL("HDD context is not valid"));
6589 return;
6590 }
6591 mutex_lock(&hdd_ctx->sap_lock);
6592 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
6593#ifdef CFG80211_DEL_STA_V2
6594 delStaParams.mac = NULL;
6595 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
6596 delStaParams.reason_code = eCsrForcedDeauthSta;
6597 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6598 ap_adapter->dev,
6599 &delStaParams);
6600#else
6601 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6602 ap_adapter->dev,
6603 NULL);
6604#endif
6605 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
6606 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306607 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608 FL("Now doing SAP STOPBSS"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306609 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306610 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006611 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05306612 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306613 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006614 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306615 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006616 mutex_unlock(&hdd_ctx->sap_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306617 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618 FL("SAP Stop Failed"));
6619 return;
6620 }
6621 }
6622 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08006623 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006624 ap_adapter->sessionId);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306625 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006626 FL("SAP Stop Success"));
6627 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306628 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006629 FL("Can't stop ap because its not started"));
6630 }
6631 mutex_unlock(&hdd_ctx->sap_lock);
6632 return;
6633}
6634
6635/**
6636 * wlan_hdd_start_sap() - this function starts bss of SAP.
6637 * @ap_adapter: SAP adapter
6638 *
6639 * This function will process the starting of sap adapter.
6640 *
6641 * Return: None
6642 */
6643void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
6644{
6645 hdd_ap_ctx_t *hdd_ap_ctx;
6646 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306647 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006648 hdd_context_t *hdd_ctx;
6649 tsap_Config_t *sap_config;
6650
6651 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306652 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006653 FL("ap_adapter is NULL here"));
6654 return;
6655 }
6656
Peng Xuf5d60c82015-10-02 17:17:03 -07006657 if (WLAN_HDD_SOFTAP != ap_adapter->device_mode) {
6658 hdd_err("SoftAp role has not been enabled");
6659 return;
6660 }
6661
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006662 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6663 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6664 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6665 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
6666
6667 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306668 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006669 FL("HDD context is not valid"));
6670 return;
6671 }
6672 mutex_lock(&hdd_ctx->sap_lock);
6673 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
6674 goto end;
6675
6676 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
6677 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
6678 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
6679 goto end;
6680 }
6681
6682 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
6683 &hdd_ap_ctx->sapConfig,
6684 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306685 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006686 goto end;
6687
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306688 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006689 FL("Waiting for SAP to start"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306690 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306692 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306693 hddLog(QDF_TRACE_LEVEL_ERROR, FL("SAP Start failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006694 goto end;
6695 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306696 hddLog(QDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006697 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006698 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006699 ap_adapter->sessionId);
6700 hostapd_state->bCommit = true;
6701
6702end:
6703 mutex_unlock(&hdd_ctx->sap_lock);
6704 return;
6705}
6706#endif
6707
6708/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006709 * hdd_get_fw_version() - Get FW version
6710 * @hdd_ctx: pointer to HDD context.
6711 * @major_spid: FW version - major spid.
6712 * @minor_spid: FW version - minor spid
6713 * @ssid: FW version - ssid
6714 * @crmid: FW version - crmid
6715 *
6716 * This function is called to get the firmware build version stored
6717 * as part of the HDD context
6718 *
6719 * Return: None
6720 */
6721void hdd_get_fw_version(hdd_context_t *hdd_ctx,
6722 uint32_t *major_spid, uint32_t *minor_spid,
6723 uint32_t *siid, uint32_t *crmid)
6724{
6725 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
6726 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
6727 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
6728 *crmid = hdd_ctx->target_fw_version & 0x7fff;
6729}
6730
6731#ifdef QCA_CONFIG_SMP
6732/**
6733 * wlan_hdd_get_cpu() - get cpu_index
6734 *
6735 * Return: cpu_index
6736 */
6737int wlan_hdd_get_cpu(void)
6738{
6739 int cpu_index = get_cpu();
6740 put_cpu();
6741 return cpu_index;
6742}
6743#endif
6744
6745/**
6746 * hdd_get_fwpath() - get framework path
6747 *
6748 * This function is used to get the string written by
6749 * userspace to start the wlan driver
6750 *
6751 * Return: string
6752 */
6753const char *hdd_get_fwpath(void)
6754{
6755 return fwpath.string;
6756}
6757
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006758/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006759 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006760 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006761 * This function initilizes CDS global context with the help of cds_init. This
6762 * has to be the first function called after probe to get a valid global
6763 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006764 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006765 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006766 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006767int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006768{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006769 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006770 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006771
6772#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6773 wlan_logging_sock_init_svc();
6774#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006775 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006776
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006777 if (p_cds_context == NULL) {
6778 hdd_alert("Failed to allocate CDS context");
6779 ret = -ENOMEM;
6780 goto err_out;
6781 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006782
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006783 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006784
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006785err_out:
6786 return ret;
6787}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006788
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006789/**
6790 * hdd_deinit() - Deinitialize Driver
6791 *
6792 * This function frees CDS global context with the help of cds_deinit. This
6793 * has to be the last function call in remove callback to free the global
6794 * context.
6795 */
6796void hdd_deinit(void)
6797{
6798 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006799
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006800#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6801 wlan_logging_sock_deinit_svc();
6802#endif
6803}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006804
6805#ifdef QCA_WIFI_3_0_ADRASTEA
6806#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
6807#else
6808#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
6809#endif
6810
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006811/**
6812 * __hdd_module_init - Module init helper
6813 *
6814 * Module init helper function used by both module and static driver.
6815 *
6816 * Return: 0 for success, errno on failure
6817 */
6818static int __hdd_module_init(void)
6819{
6820 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006821
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006822 pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
6823 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006824
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306825 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006826
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006827 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006828
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006829 ret = wlan_hdd_register_driver();
6830 if (ret) {
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006831 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006832 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006833 }
6834
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306835 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006836
6837 return 0;
6838out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306839 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006840 return ret;
6841}
6842
6843/**
6844 * __hdd_module_exit - Module exit helper
6845 *
6846 * Module exit helper function used by both module and static driver.
6847 */
6848static void __hdd_module_exit(void)
6849{
6850 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
6851 QWLAN_VERSIONSTR);
6852
6853 wlan_hdd_unregister_driver();
6854
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306855 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006856
6857 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006858}
6859
6860/**
6861 * hdd_module_init() - Init Function
6862 *
6863 * This is the driver entry point (invoked when module is loaded using insmod)
6864 *
6865 * Return: 0 for success, non zero for failure
6866 */
6867#ifdef MODULE
6868static int __init hdd_module_init(void)
6869{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006870 return __hdd_module_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006871}
6872#else /* #ifdef MODULE */
6873static int __init hdd_module_init(void)
6874{
6875 /* Driver initialization is delayed to fwpath_changed_handler */
6876 return 0;
6877}
6878#endif /* #ifdef MODULE */
6879
6880/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006881 * hdd_module_exit() - Exit function
6882 *
6883 * This is the driver exit point (invoked when module is unloaded using rmmod)
6884 *
6885 * Return: None
6886 */
6887static void __exit hdd_module_exit(void)
6888{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006889 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006890}
6891
6892#ifdef MODULE
6893static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6894{
6895 return param_set_copystring(kmessage, kp);
6896}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006897#else /* #ifdef MODULE */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006898
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006899/**
6900 * kickstart_driver() - driver entry point
6901 *
6902 * This is the driver entry point
6903 * - delayed driver initialization when driver is statically linked
6904 * - invoked when module parameter fwpath is modified from userspace to signal
6905 * initializing the WLAN driver or when con_mode is modified from userspace
6906 * to signal a switch in operating mode
6907 *
6908 * Return: 0 for success, non zero for failure
6909 */
6910static int kickstart_driver(void)
6911{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006912 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006913
6914 if (!wlan_hdd_inited) {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006915 ret = __hdd_module_init();
6916 wlan_hdd_inited = ret ? 0 : 1;
6917
6918 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006919 }
6920
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006921 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006922
6923 msleep(200);
6924
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006925 ret = __hdd_module_init();
6926
6927 wlan_hdd_inited = ret ? 0 : 1;
6928
6929 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006930}
6931
6932/**
6933 * fwpath_changed_handler() - Handler Function
6934 *
6935 * Handle changes to the fwpath parameter
6936 *
6937 * Return: 0 for success, non zero for failure
6938 */
6939static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6940{
6941 int ret;
6942
6943 ret = param_set_copystring(kmessage, kp);
6944 if (0 == ret)
6945 ret = kickstart_driver();
6946 return ret;
6947}
6948
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006949#ifdef QCA_WIFI_FTM
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006950/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006951 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006952 *
6953 * Handler function for module param con_mode when it is changed by userspace
6954 * Dynamically linked - do nothing
6955 * Statically linked - exit and init driver, as in rmmod and insmod
6956 *
6957 * Return -
6958 */
6959static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
6960{
6961 int ret;
6962
6963 ret = param_set_int(kmessage, kp);
6964 if (0 == ret)
6965 ret = kickstart_driver();
6966 return ret;
6967}
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006968#endif /* QCA_WIFI_FTM */
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006969#endif /* #ifdef MODULE */
6970
6971/**
6972 * hdd_get_conparam() - driver exit point
6973 *
6974 * This is the driver exit point (invoked when module is unloaded using rmmod)
6975 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05306976 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006977 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306978enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006979{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306980 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006981}
6982
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006983void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006984{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006985 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006986}
6987
Komal Seelamc11bb222016-01-27 18:57:10 +05306988#ifdef WLAN_FEATURE_LPSS
6989static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6990{
6991 return hdd_ctx->config->enable_lpass_support;
6992}
6993#else
6994static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6995{
6996 return false;
6997}
6998#endif
6999
7000/**
Komal Seelamec702b02016-02-24 18:42:16 +05307001 * hdd_update_ol_config - API to update ol configuration parameters
7002 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05307003 *
Komal Seelamc11bb222016-01-27 18:57:10 +05307004 * Return: void
7005 */
Komal Seelamec702b02016-02-24 18:42:16 +05307006static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05307007{
Komal Seelamec702b02016-02-24 18:42:16 +05307008 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307009 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05307010
Komal Seelamec702b02016-02-24 18:42:16 +05307011 if (!ol_ctx)
7012 return;
7013
7014 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
7015 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
7016 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
7017 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
7018 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
7019
7020 ol_init_ini_config(ol_ctx, &cfg);
7021}
7022
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007023#ifdef FEATURE_RUNTIME_PM
7024/**
7025 * hdd_populate_runtime_cfg() - populate runtime configuration
7026 * @hdd_ctx: hdd context
7027 * @cfg: pointer to the configuration memory being populated
7028 *
7029 * Return: void
7030 */
7031static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7032 struct hif_config_info *cfg)
7033{
7034 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
7035 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
7036}
7037#else
7038static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7039 struct hif_config_info *cfg)
7040{
7041}
7042#endif
7043
Komal Seelamec702b02016-02-24 18:42:16 +05307044/**
7045 * hdd_update_hif_config - API to update HIF configuration parameters
7046 * @hdd_ctx: HDD Context
7047 *
7048 * Return: void
7049 */
7050static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
7051{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307052 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05307053 struct hif_config_info cfg;
7054
7055 if (!scn)
7056 return;
7057
7058 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007059 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05307060 hif_init_ini_config(scn, &cfg);
7061}
7062
7063/**
7064 * hdd_update_config() - Initialize driver per module ini parameters
7065 * @hdd_ctx: HDD Context
7066 *
7067 * API is used to initialize all driver per module configuration parameters
7068 * Return: void
7069 */
7070void hdd_update_config(hdd_context_t *hdd_ctx)
7071{
7072 hdd_update_ol_config(hdd_ctx);
7073 hdd_update_hif_config(hdd_ctx);
Komal Seelamc11bb222016-01-27 18:57:10 +05307074}
7075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007076/* Register the module init/exit functions */
7077module_init(hdd_module_init);
7078module_exit(hdd_module_exit);
7079
7080MODULE_LICENSE("Dual BSD/GPL");
7081MODULE_AUTHOR("Qualcomm Atheros, Inc.");
7082MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
7083
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007084#if !defined(MODULE) && defined(QCA_WIFI_FTM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007085module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
7086 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007087#else
7088module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007089#endif
7090
7091module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
7092 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
7093
7094module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
7095
7096module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
7097
7098module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);