blob: e2c3b0ad332074eb0e26d42749ec705440a50e69 [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);
Rajeev Kumardca5f812016-02-04 17:28:06 -08002268 hdd_debugfs_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 /*
2270 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2271 * the driver is almost closed and cannot handle either control
2272 * messages or data. However, unregister_netdevice() call above will
2273 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2274 * to close the active connections (basically excites control path) which
2275 * is not right. Setting this flag helps hdd_stop() to recognize that
2276 * the interface is closed and restricts any operations on that
2277 */
2278 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2279
2280 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2281 if (rtnl_held) {
2282 unregister_netdevice(pWlanDev);
2283 } else {
2284 unregister_netdev(pWlanDev);
2285 }
2286 /*
2287 * Note that the adapter is no longer valid at this point
2288 * since the memory has been reclaimed
2289 */
2290 }
2291}
2292
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302293QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294 tSirMacAddr macAddr)
2295{
2296 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2297 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302298 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002299 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302300 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 adapter = adapterNode->pAdapter;
2302 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302303 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002304 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302305 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002306 }
2307 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2308 adapterNode = pNext;
2309 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302310 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311}
2312hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
2313 const char *iface_name, tSirMacAddr macAddr,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002314 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315{
2316 hdd_adapter_t *adapter = NULL;
2317 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302318 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319 hdd_cfg80211_state_t *cfgState;
2320 int ret;
2321
2322 hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type);
2323
2324 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
2325 /*
2326 * Max limit reached on the number of vdevs configured by the
2327 * host. Return error
2328 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302329 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330 FL(
2331 "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d"
2332 ),
2333 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
2334 return NULL;
2335 }
2336
2337 if (macAddr == NULL) {
2338 /* Not received valid macAddr */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302339 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002340 FL(
2341 "Unable to add virtual intf: Not able to get valid mac address"
2342 ));
2343 return NULL;
2344 }
2345 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302346 if (QDF_STATUS_E_FAILURE == status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302347 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348 "Duplicate MAC addr: " MAC_ADDRESS_STR
2349 " already exists",
2350 MAC_ADDR_ARRAY(macAddr));
2351 return NULL;
2352 }
2353
2354 switch (session_type) {
2355 case WLAN_HDD_INFRA_STATION:
2356 /* Reset locally administered bit if the device mode is STA */
2357 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
2358 /* fall through */
2359 case WLAN_HDD_P2P_CLIENT:
2360 case WLAN_HDD_P2P_DEVICE:
2361 case WLAN_HDD_OCB:
2362 {
2363 adapter =
2364 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2365
2366 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302367 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 FL("failed to allocate adapter for session %d"),
2369 session_type);
2370 return NULL;
2371 }
2372
2373 if (WLAN_HDD_P2P_CLIENT == session_type)
2374 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 else if (WLAN_HDD_P2P_DEVICE == session_type)
2376 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 else
2378 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2379
2380 adapter->device_mode = session_type;
2381
2382 status = hdd_init_station_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302383 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 goto err_free_netdev;
2385
2386 hdd_lro_enable(hdd_ctx, adapter);
2387
2388 /*
2389 * Workqueue which gets scheduled in IPv4 notification
2390 * callback
2391 */
2392#ifdef CONFIG_CNSS
2393 cnss_init_work(&adapter->ipv4NotifierWorkQueue,
2394 hdd_ipv4_notifier_work_queue);
2395#else
2396 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
2397 hdd_ipv4_notifier_work_queue);
2398#endif
2399
2400#ifdef WLAN_NS_OFFLOAD
2401 /*
2402 * Workqueue which gets scheduled in IPv6
2403 * notification callback.
2404 */
2405#ifdef CONFIG_CNSS
2406 cnss_init_work(&adapter->ipv6NotifierWorkQueue,
2407 hdd_ipv6_notifier_work_queue);
2408#else
2409 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
2410 hdd_ipv6_notifier_work_queue);
2411#endif
2412#endif
2413 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302414 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2416 goto err_lro_cleanup;
2417 }
2418
2419 /* Stop the Interface TX queue. */
2420 hddLog(LOG1, FL("Disabling queues"));
2421 wlan_hdd_netif_queue_control(adapter,
2422 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2423 WLAN_CONTROL_PATH);
2424
2425 hdd_register_tx_flow_control(adapter,
2426 hdd_tx_resume_timer_expired_handler,
2427 hdd_tx_resume_cb);
2428
2429 break;
2430 }
2431
2432 case WLAN_HDD_P2P_GO:
2433 case WLAN_HDD_SOFTAP:
2434 {
2435 adapter =
2436 hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
2437 (uint8_t *) iface_name);
2438 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302439 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 FL("failed to allocate adapter for session %d"),
2441 session_type);
2442 return NULL;
2443 }
2444
2445 adapter->wdev.iftype =
2446 (session_type ==
2447 WLAN_HDD_SOFTAP) ? NL80211_IFTYPE_AP :
2448 NL80211_IFTYPE_P2P_GO;
2449 adapter->device_mode = session_type;
2450
2451 status = hdd_init_ap_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302452 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 goto err_free_netdev;
2454
2455 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302456 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2458 goto err_free_netdev;
2459 }
2460
2461 hddLog(LOG1, FL("Disabling queues"));
2462 wlan_hdd_netif_queue_control(adapter,
2463 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2464 WLAN_CONTROL_PATH);
2465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 break;
2467 }
2468 case WLAN_HDD_FTM:
2469 {
2470 adapter =
2471 hdd_alloc_station_adapter(hdd_ctx, macAddr, iface_name);
2472
2473 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302474 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 FL("failed to allocate adapter for session %d"),
2476 session_type);
2477 return NULL;
2478 }
2479
2480 /*
2481 * Assign NL80211_IFTYPE_STATION as interface type to resolve
2482 * Kernel Warning message while loading driver in FTM mode.
2483 */
2484 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2485 adapter->device_mode = session_type;
2486 status = hdd_register_interface(adapter, rtnl_held);
2487
2488 hdd_init_tx_rx(adapter);
2489
2490 /* Stop the Interface TX queue. */
2491 hddLog(LOG1, FL("Disabling queues"));
2492 wlan_hdd_netif_queue_control(adapter,
2493 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2494 WLAN_CONTROL_PATH);
2495 }
2496 break;
2497 default:
2498 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302499 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002500 FL("Invalid session type %d"),
2501 session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302502 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 return NULL;
2504 }
2505 }
2506
2507 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2508 mutex_init(&cfgState->remain_on_chan_ctx_lock);
2509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302510 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511 /* Add it to the hdd's session list. */
2512 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302513 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302515 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 } else {
2517 pHddAdapterNode->pAdapter = adapter;
2518 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
2519 }
2520 }
2521
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302522 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 if (NULL != adapter) {
2524 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
2525 adapter = NULL;
2526 }
2527 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302528 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529 }
2530 return NULL;
2531 }
2532
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302533 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002534 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535
2536 /* Initialize the WoWL service */
2537 if (!hdd_init_wowl(adapter)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302538 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 FL("hdd_init_wowl failed"));
2540 goto err_lro_cleanup;
2541 }
2542
2543 /* Adapter successfully added. Increment the vdev count */
2544 hdd_ctx->current_intf_count++;
2545
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302546 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 hdd_ctx->current_intf_count);
2548
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002549 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 }
2551
Anurag Chouhan6d760662016-02-20 16:05:43 +05302552 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 && (!hdd_ctx->config->enable2x2)) {
2554#define HDD_DTIM_1CHAIN_RX_ID 0x5
2555#define HDD_SMPS_PARAM_VALUE_S 29
2556
2557 /*
2558 * Disable DTIM 1 chain Rx when in 1x1, we are passing two value
2559 * as param_id << 29 | param_value.
2560 * Below param_value = 0(disable)
2561 */
2562 ret = wma_cli_set_command(adapter->sessionId,
2563 WMI_STA_SMPS_PARAM_CMDID,
2564 HDD_DTIM_1CHAIN_RX_ID <<
2565 HDD_SMPS_PARAM_VALUE_S,
2566 VDEV_CMD);
2567
2568 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302569 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 FL("DTIM 1 chain set failed %d"), ret);
2571 goto err_lro_cleanup;
2572 }
2573
2574 ret = wma_cli_set_command(adapter->sessionId,
2575 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2576 hdd_ctx->config->txchainmask1x1,
2577 PDEV_CMD);
2578 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302579 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"),
2581 ret);
2582 goto err_lro_cleanup;
2583 }
2584 ret = wma_cli_set_command(adapter->sessionId,
2585 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2586 hdd_ctx->config->rxchainmask1x1,
2587 PDEV_CMD);
2588 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302589 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590 FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"),
2591 ret);
2592 goto err_lro_cleanup;
2593 }
2594#undef HDD_DTIM_1CHAIN_RX_ID
2595#undef HDD_SMPS_PARAM_VALUE_S
2596 }
2597
Anurag Chouhan6d760662016-02-20 16:05:43 +05302598 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 ret = wma_cli_set_command(adapter->sessionId,
2600 WMI_PDEV_PARAM_HYST_EN,
2601 hdd_ctx->config->enableMemDeepSleep,
2602 PDEV_CMD);
2603
2604 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302605 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 FL("WMI_PDEV_PARAM_HYST_EN set failed %d"),
2607 ret);
2608 goto err_lro_cleanup;
2609 }
2610 }
2611
2612#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2613
2614 /* Enable FW logs based on INI configuration */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302615 if ((QDF_GLOBAL_FTM_MODE != cds_get_conparam()) &&
Komal Seelamc11bb222016-01-27 18:57:10 +05302616 (hdd_ctx->config->enable_fw_log)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617 uint8_t count = 0;
2618 uint32_t value = 0;
2619 uint8_t numEntries = 0;
2620 uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2621
2622 hdd_ctx->fw_log_settings.dl_type =
2623 hdd_ctx->config->enableFwLogType;
2624 ret = wma_cli_set_command(adapter->sessionId,
2625 WMI_DBGLOG_TYPE,
2626 hdd_ctx->config->enableFwLogType,
2627 DBG_CMD);
2628 if (ret != 0) {
2629 hddLog(LOGE, FL("Failed to enable FW log type ret %d"),
2630 ret);
2631 }
2632
2633 hdd_ctx->fw_log_settings.dl_loglevel =
2634 hdd_ctx->config->enableFwLogLevel;
2635 ret = wma_cli_set_command(adapter->sessionId,
2636 WMI_DBGLOG_LOG_LEVEL,
2637 hdd_ctx->config->enableFwLogLevel,
2638 DBG_CMD);
2639 if (ret != 0) {
2640 hddLog(LOGE, FL("Failed to enable FW log level ret %d"),
2641 ret);
2642 }
2643
2644 hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel,
2645 moduleLoglevel,
2646 &numEntries,
2647 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2648 while (count < numEntries) {
2649 /*
2650 * FW module log level input string looks like below:
2651 * gFwDebugModuleLoglevel=<FW Module ID>,<Log Level>,...
2652 * For example:
2653 * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6
2654 * Above input string means :
2655 * For FW module ID 1 enable log level 0
2656 * For FW module ID 2 enable log level 1
2657 * For FW module ID 3 enable log level 2
2658 * For FW module ID 4 enable log level 3
2659 * For FW module ID 5 enable log level 4
2660 * For FW module ID 6 enable log level 5
2661 * For FW module ID 7 enable log level 6
2662 */
2663
2664 /* FW expects WMI command value =
2665 * Module ID * 10 + Module Log level
2666 */
2667 value = ((moduleLoglevel[count] * 10) +
2668 moduleLoglevel[count + 1]);
2669 ret = wma_cli_set_command(adapter->sessionId,
2670 WMI_DBGLOG_MOD_LOG_LEVEL,
2671 value, DBG_CMD);
2672 if (ret != 0) {
2673 hddLog(LOGE,
2674 FL
2675 ("Failed to enable FW module log level %d ret %d"),
2676 value, ret);
2677 }
2678
2679 count += 2;
2680 }
2681 }
2682#endif
Rajeev Kumardca5f812016-02-04 17:28:06 -08002683 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
2684 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685
2686 return adapter;
2687
2688err_lro_cleanup:
2689 hdd_lro_disable(hdd_ctx, adapter);
2690err_free_netdev:
2691 free_netdev(adapter->dev);
2692 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2693
2694 return NULL;
2695}
2696
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302697QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002698 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699{
2700 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302701 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702
2703 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302704 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302705 hddLog(QDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 status);
2707 return status;
2708 }
2709
2710 while (pCurrent->pAdapter != adapter) {
2711 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302712 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 break;
2714
2715 pCurrent = pNext;
2716 }
2717 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302718 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002719 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
2721
2722 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302723 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 adapterNode = NULL;
2725
2726 /* Adapter removed. Decrement vdev count */
2727 if (hdd_ctx->current_intf_count != 0)
2728 hdd_ctx->current_intf_count--;
2729
2730 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302731 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002732 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302733 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002734}
2735
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002736/**
2737 * hdd_close_all_adapters - Close all open adapters
2738 * @hdd_ctx: Hdd context
2739 * rtnl_held: True if RTNL lock held
2740 *
2741 * Close all open adapters.
2742 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302743 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002744 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302745QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002746{
2747 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302748 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749
2750 ENTER();
2751
2752 do {
2753 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302754 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002755 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002756 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302757 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302759 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760
2761 EXIT();
2762
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302763 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764}
2765
2766void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
2767{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302768 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 tSirUpdateIE updateIE;
2770 switch (pHostapdAdapter->device_mode) {
2771 case WLAN_HDD_INFRA_STATION:
2772 case WLAN_HDD_P2P_CLIENT:
2773 {
2774 hdd_station_ctx_t *pHddStaCtx =
2775 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002776 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 break;
2778 }
2779 case WLAN_HDD_SOFTAP:
2780 case WLAN_HDD_P2P_GO:
2781 case WLAN_HDD_IBSS:
2782 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002783 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 break;
2785 }
2786 case WLAN_HDD_FTM:
2787 case WLAN_HDD_P2P_DEVICE:
2788 default:
2789 /*
2790 * wlan_hdd_reset_prob_rspies should not have been called
2791 * for these kind of devices
2792 */
2793 hddLog(LOGE,
2794 FL("Unexpected request for the current device type %d"),
2795 pHostapdAdapter->device_mode);
2796 return;
2797 }
2798
Anurag Chouhanc5548422016-02-24 18:33:27 +05302799 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 updateIE.smeSessionId = pHostapdAdapter->sessionId;
2801 updateIE.ieBufferlength = 0;
2802 updateIE.pAdditionIEBuffer = NULL;
2803 updateIE.append = true;
2804 updateIE.notify = false;
2805 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
2806 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302807 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
2809 }
2810}
2811
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302812QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 const bool bCloseSession)
2814{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302815 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
2817 union iwreq_data wrqu;
2818 tSirUpdateIE updateIE;
2819 unsigned long rc;
2820
2821 ENTER();
2822
2823 hddLog(LOG1, FL("Disabling queues"));
2824 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
2825 WLAN_CONTROL_PATH);
2826 switch (adapter->device_mode) {
2827 case WLAN_HDD_INFRA_STATION:
2828 case WLAN_HDD_P2P_CLIENT:
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302829 case WLAN_HDD_IBSS:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 case WLAN_HDD_P2P_DEVICE:
2831 if (hdd_conn_is_connected(
2832 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
2833 hdd_is_connecting(
2834 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
2835 if (pWextState->roamProfile.BSSType ==
2836 eCSR_BSS_TYPE_START_IBSS)
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302837 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002838 sme_roam_disconnect(hdd_ctx->hHal,
2839 adapter->sessionId,
2840 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2841 else
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302842 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 sme_roam_disconnect(hdd_ctx->hHal,
2844 adapter->sessionId,
2845 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2846 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302847 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 rc = wait_for_completion_timeout(
2849 &adapter->disconnect_comp_var,
2850 msecs_to_jiffies
2851 (WLAN_WAIT_TIME_DISCONNECT));
2852 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302853 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002854 FL(
2855 "wait on disconnect_comp_var failed"
2856 ));
2857 }
2858 } else {
2859 hddLog(LOGE,
2860 FL(
2861 "failed to post disconnect event to SME"
2862 ));
2863 }
2864 memset(&wrqu, '\0', sizeof(wrqu));
2865 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2866 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
2867 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
2868 NULL);
2869 } else {
2870 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
2871 eCSR_SCAN_ABORT_DEFAULT);
2872 }
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05302873 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002874
2875#ifdef WLAN_OPEN_SOURCE
2876 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
2877#endif
2878
2879 hdd_deregister_tx_flow_control(adapter);
2880
2881#ifdef WLAN_NS_OFFLOAD
2882#ifdef WLAN_OPEN_SOURCE
2883 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
2884#endif
2885#endif
2886
2887 /*
2888 * It is possible that the caller of this function does not
2889 * wish to close the session
2890 */
2891 if (true == bCloseSession &&
2892 test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2893 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302894 if (QDF_STATUS_SUCCESS ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
2896 hdd_sme_close_session_callback,
2897 adapter)) {
2898 /*
2899 * Block on a completion variable. Can't wait
2900 * forever though.
2901 */
2902 rc = wait_for_completion_timeout(
2903 &adapter->session_close_comp_var,
2904 msecs_to_jiffies
2905 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2906 if (!rc) {
2907 hddLog(LOGE,
2908 FL(
2909 "failure waiting for session_close_comp_var"
2910 ));
2911 }
2912 }
2913 }
2914 break;
2915
2916 case WLAN_HDD_SOFTAP:
2917 case WLAN_HDD_P2P_GO:
2918 if (hdd_ctx->config->conc_custom_rule1 &&
2919 (WLAN_HDD_SOFTAP == adapter->device_mode)) {
2920 /*
2921 * Before stopping the sap adapter, lets make sure there
2922 * is no sap restart work pending.
2923 */
2924 cds_flush_work(&hdd_ctx->sap_start_work);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302925 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 FL("Canceled the pending SAP restart work"));
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002927 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 }
2929 /* Any softap specific cleanup here... */
2930 if (adapter->device_mode == WLAN_HDD_P2P_GO)
2931 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
2932
2933 hdd_deregister_tx_flow_control(adapter);
2934
2935 mutex_lock(&hdd_ctx->sap_lock);
2936 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302937 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05302938 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002939
2940 /* Stop Bss. */
2941#ifdef WLAN_FEATURE_MBSSID
2942 status = wlansap_stop_bss(
2943 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
2944#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002945 status = wlansap_stop_bss(
2946 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947#endif
2948
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302949 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 hdd_hostapd_state_t *hostapd_state =
2951 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302952 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302953 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05302954 qdf_status =
2955 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302956 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 BSS_WAIT_TIMEOUT);
2958
Anurag Chouhance0dc992016-02-16 18:18:03 +05302959 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 hddLog(LOGE,
2961 FL(
2962 "failure waiting for wlansap_stop_bss %d"
2963 ),
Anurag Chouhance0dc992016-02-16 18:18:03 +05302964 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 }
2966 } else {
2967 hddLog(LOGE, FL("failure in wlansap_stop_bss"));
2968 }
2969 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002970 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971 adapter->device_mode,
2972 adapter->sessionId);
2973
Anurag Chouhanc5548422016-02-24 18:33:27 +05302974 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002975 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 updateIE.smeSessionId = adapter->sessionId;
2977 updateIE.ieBufferlength = 0;
2978 updateIE.pAdditionIEBuffer = NULL;
2979 updateIE.append = false;
2980 updateIE.notify = false;
2981 /* Probe bcn reset */
2982 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2983 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302984 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 hddLog(LOGE,
2986 FL(
2987 "Could not pass on PROBE_RSP_BCN data to PE"
2988 ));
2989 }
2990 /* Assoc resp reset */
2991 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
2992 &updateIE,
2993 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302994 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 hddLog(LOGE,
2996 FL(
2997 "Could not pass on ASSOC_RSP data to PE"
2998 ));
2999 }
3000 /* Reset WNI_CFG_PROBE_RSP Flags */
3001 wlan_hdd_reset_prob_rspies(adapter);
3002 kfree(adapter->sessionCtx.ap.beacon);
3003 adapter->sessionCtx.ap.beacon = NULL;
3004 }
3005 mutex_unlock(&hdd_ctx->sap_lock);
3006 break;
3007 case WLAN_HDD_OCB:
3008 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3009 conn_info.staId[0]);
3010 break;
3011 default:
3012 break;
3013 }
3014
3015 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303016 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017}
3018
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303019QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020{
3021 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303022 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 hdd_adapter_t *adapter;
3024
3025 ENTER();
3026
3027 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3028
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303029 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 adapter = adapterNode->pAdapter;
3031 hdd_stop_adapter(hdd_ctx, adapter, true);
3032 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3033 adapterNode = pNext;
3034 }
3035
3036 EXIT();
3037
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303038 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039}
3040
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303041QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042{
3043 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303044 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045 hdd_adapter_t *adapter;
3046
3047 ENTER();
3048
3049 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3050
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303051 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 adapter = adapterNode->pAdapter;
3053 hddLog(LOG1, FL("Disabling queues"));
3054 wlan_hdd_netif_queue_control(adapter,
3055 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3056 WLAN_CONTROL_PATH);
3057
3058 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3059
3060 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003061 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003062 adapter->sessionId);
3063 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3064 hdd_wmm_adapter_close(adapter);
3065 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3066 }
3067
3068 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3069 adapterNode = pNext;
3070 }
3071
3072 EXIT();
3073
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303074 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003075}
3076
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303077QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078{
3079 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303080 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003081 hdd_adapter_t *adapter;
3082#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303083 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084#endif
3085 eConnectionState connState;
3086
3087 ENTER();
3088
3089 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3090
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303091 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 adapter = adapterNode->pAdapter;
3093
3094 hdd_wmm_init(adapter);
3095
3096 switch (adapter->device_mode) {
3097 case WLAN_HDD_INFRA_STATION:
3098 case WLAN_HDD_P2P_CLIENT:
3099 case WLAN_HDD_P2P_DEVICE:
3100
3101 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3102 ->conn_info.connState;
3103
3104 hdd_init_station_mode(adapter);
3105 /* Open the gates for HDD to receive Wext commands */
3106 adapter->isLinkUpSvcNeeded = false;
3107 adapter->scan_info.mScanPending = false;
3108
3109 /* Indicate disconnect event to supplicant if associated previously */
3110 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003111 eConnectionState_IbssConnected == connState ||
3112 eConnectionState_NotConnected == connState ||
3113 eConnectionState_IbssDisconnected == connState ||
3114 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 union iwreq_data wrqu;
3116 memset(&wrqu, '\0', sizeof(wrqu));
3117 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3118 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3119 wireless_send_event(adapter->dev, SIOCGIWAP,
3120 &wrqu, NULL);
3121 adapter->sessionCtx.station.
3122 hdd_ReassocScenario = false;
3123
3124 /* indicate disconnected event to nl80211 */
3125 cfg80211_disconnected(adapter->dev,
3126 WLAN_REASON_UNSPECIFIED,
3127 NULL, 0, GFP_KERNEL);
3128 } else if (eConnectionState_Connecting == connState) {
3129 /*
3130 * Indicate connect failure to supplicant if we were in the
3131 * process of connecting
3132 */
3133 cfg80211_connect_result(adapter->dev, NULL,
3134 NULL, 0, NULL, 0,
3135 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3136 GFP_KERNEL);
3137 }
3138
3139 hdd_register_tx_flow_control(adapter,
3140 hdd_tx_resume_timer_expired_handler,
3141 hdd_tx_resume_cb);
3142
3143 break;
3144
3145 case WLAN_HDD_SOFTAP:
3146 /* softAP can handle SSR */
3147 break;
3148
3149 case WLAN_HDD_P2P_GO:
3150#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303151 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152 FL("[SSR] send stop ap to supplicant"));
3153 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3154#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303155 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 FL("[SSR] send restart supplicant"));
3157 /* event supplicant to restart */
3158 cfg80211_del_sta(adapter->dev,
3159 (const u8 *)&bcastMac.bytes[0],
3160 GFP_KERNEL);
3161#endif
3162 break;
3163
3164 default:
3165 break;
3166 }
3167
3168 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3169 adapterNode = pNext;
3170 }
3171
3172 EXIT();
3173
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303174 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175}
3176
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303177QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 hdd_adapter_list_node_t **padapterNode)
3179{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303180 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303181 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303182 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3183 (qdf_list_node_t **) padapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303184 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 return status;
3186}
3187
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303188QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189 hdd_adapter_list_node_t *adapterNode,
3190 hdd_adapter_list_node_t **pNextAdapterNode)
3191{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303192 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303193 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303194 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3195 (qdf_list_node_t *) adapterNode,
3196 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303198 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199 return status;
3200}
3201
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303202QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 hdd_adapter_list_node_t *adapterNode)
3204{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303205 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303206 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303207 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 &adapterNode->node);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303209 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 return status;
3211}
3212
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303213QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 hdd_adapter_list_node_t **padapterNode)
3215{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303216 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303217 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303218 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3219 (qdf_list_node_t **) padapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303220 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003221 return status;
3222}
3223
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303224QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 hdd_adapter_list_node_t *adapterNode)
3226{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303227 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303228 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303229 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3230 (qdf_list_node_t *) adapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303231 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 return status;
3233}
3234
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303235QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 hdd_adapter_list_node_t *adapterNode)
3237{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303238 QDF_STATUS status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303239 qdf_spin_lock(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303240 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3241 (qdf_list_node_t *) adapterNode);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303242 qdf_spin_unlock(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 return status;
3244}
3245
3246hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3247 tSirMacAddr macAddr)
3248{
3249 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3250 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303251 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252
3253 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3254
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303255 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256 adapter = adapterNode->pAdapter;
3257
3258 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303259 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 macAddr, sizeof(tSirMacAddr))) {
3261 return adapter;
3262 }
3263 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3264 adapterNode = pNext;
3265 }
3266
3267 return NULL;
3268
3269}
3270
3271hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3272 uint32_t vdev_id)
3273{
3274 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3275 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303276 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303278 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303280 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281 adapter = adapterNode->pAdapter;
3282
3283 if (adapter->sessionId == vdev_id)
3284 return adapter;
3285
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303286 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3288 adapterNode = pNext;
3289 }
3290
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303291 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 FL("vdev_id %d does not exist with host"), vdev_id);
3293
3294 return NULL;
3295}
3296
Abhishek Singh7996eb72015-12-30 17:24:02 +05303297/**
3298 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3299 * the sessionid
3300 * @hdd_ctx: hdd context.
3301 * @sme_session_id: sme session is for the adapter to get.
3302 *
3303 * This function is used to get the adapter with provided session id
3304 *
3305 * Return: adapter pointer if found
3306 *
3307 */
3308hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3309 uint32_t sme_session_id)
3310{
3311 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3312 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303313 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303314
3315
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303316 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303317
3318 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303319 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303320 adapter = adapter_node->pAdapter;
3321
3322 if (adapter &&
3323 adapter->sessionId == sme_session_id)
3324 return adapter;
3325
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303326 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303327 hdd_get_next_adapter(hdd_ctx,
3328 adapter_node, &next);
3329 adapter_node = next;
3330 }
3331 return NULL;
3332}
3333
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003334hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx, device_mode_t mode)
3335{
3336 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3337 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303338 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339
3340 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3341
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303342 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003343 adapter = adapterNode->pAdapter;
3344
3345 if (adapter && (mode == adapter->device_mode))
3346 return adapter;
3347
3348 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3349 adapterNode = pNext;
3350 }
3351
3352 return NULL;
3353
3354}
3355
3356/**
3357 * hdd_get_operating_channel() - return operating channel of the device mode
3358 * @hdd_ctx: Pointer to the HDD context.
3359 * @mode: Device mode for which operating channel is required.
3360 * Suported modes:
3361 * WLAN_HDD_INFRA_STATION,
3362 * WLAN_HDD_P2P_CLIENT,
3363 * WLAN_HDD_SOFTAP,
3364 * WLAN_HDD_P2P_GO.
3365 *
3366 * This API returns the operating channel of the requested device mode
3367 *
3368 * Return: channel number. "0" id the requested device is not found OR it is
3369 * not connected.
3370 */
3371uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx, device_mode_t mode)
3372{
3373 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303374 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375 hdd_adapter_t *adapter;
3376 uint8_t operatingChannel = 0;
3377
3378 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3379
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303380 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003381 adapter = adapterNode->pAdapter;
3382
3383 if (mode == adapter->device_mode) {
3384 switch (adapter->device_mode) {
3385 case WLAN_HDD_INFRA_STATION:
3386 case WLAN_HDD_P2P_CLIENT:
3387 if (hdd_conn_is_connected
3388 (WLAN_HDD_GET_STATION_CTX_PTR
3389 (adapter))) {
3390 operatingChannel =
3391 (WLAN_HDD_GET_STATION_CTX_PTR
3392 (adapter))->conn_info.
3393 operationChannel;
3394 }
3395 break;
3396 case WLAN_HDD_SOFTAP:
3397 case WLAN_HDD_P2P_GO:
3398 /* softap connection info */
3399 if (test_bit
3400 (SOFTAP_BSS_STARTED,
3401 &adapter->event_flags))
3402 operatingChannel =
3403 (WLAN_HDD_GET_AP_CTX_PTR
3404 (adapter))->operatingChannel;
3405 break;
3406 default:
3407 break;
3408 }
3409
3410 break; /* Found the device of interest. break the loop */
3411 }
3412
3413 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3414 adapterNode = pNext;
3415 }
3416 return operatingChannel;
3417}
3418
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303419static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 hdd_ctx)
3421{
3422 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303423 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 hdd_adapter_t *adapter;
3425
3426 ENTER();
3427
3428 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3429
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303430 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003431 adapter = adapterNode->pAdapter;
3432 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3433 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3434 (adapter->device_mode == WLAN_HDD_IBSS) ||
3435 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3436 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3437 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3438 wlan_hdd_cfg80211_deregister_frames(adapter);
3439 hdd_unregister_wext(adapter->dev);
3440 }
3441 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3442 adapterNode = pNext;
3443 }
3444
3445 EXIT();
3446
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303447 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003448}
3449
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303450QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451{
3452 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303453 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454 hdd_adapter_t *adapter;
3455
3456 ENTER();
3457
3458 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3459
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303460 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003461 adapter = adapterNode->pAdapter;
3462 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION) ||
3463 (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
3464 (adapter->device_mode == WLAN_HDD_IBSS) ||
3465 (adapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
3466 (adapter->device_mode == WLAN_HDD_SOFTAP) ||
3467 (adapter->device_mode == WLAN_HDD_P2P_GO)) {
3468 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3469 eCSR_SCAN_ABORT_DEFAULT);
3470 }
3471 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3472 adapterNode = pNext;
3473 }
3474
3475 EXIT();
3476
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303477 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003478}
3479
3480#ifdef WLAN_NS_OFFLOAD
3481/**
3482 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3483 * @hdd_ctx: Pointer to hdd context
3484 *
3485 * Return: None
3486 */
3487static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3488{
3489 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3490
3491 return;
3492}
3493
3494/**
3495 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3496 * @hdd_ctx: Pointer to hdd context
3497 *
3498 * Return: None
3499 */
3500static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3501{
3502 int ret;
3503
3504 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
3505 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3506 if (ret)
3507 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
3508 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003509 hdd_info("Registered IPv6 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003510
3511 return;
3512}
3513#else
3514/**
3515 * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier
3516 * @hdd_ctx: Pointer to hdd context
3517 *
3518 * Return: None
3519 */
3520static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3521{
3522}
3523/**
3524 * hdd_wlan_register_ip6_notifier() - register IP6 change notifier
3525 * @hdd_ctx: Pointer to hdd context
3526 *
3527 * Return: None
3528 */
3529static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
3530{
3531}
3532#endif
3533
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003534#ifdef QCA_WIFI_FTM
3535/**
3536 * hdd_disable_ftm() - Disable FTM mode
3537 * @hdd_ctx: HDD context
3538 *
3539 * Helper function to disable FTM mode.
3540 *
3541 * Return: None.
3542 */
3543static void hdd_disable_ftm(hdd_context_t *hdd_ctx)
3544{
3545 hdd_notice("Disabling FTM mode");
3546
3547 if (hdd_ftm_stop(hdd_ctx)) {
3548 hdd_alert("hdd_ftm_stop Failed!");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303549 QDF_ASSERT(0);
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003550 }
3551
3552 hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED;
3553
3554 wlan_hdd_ftm_close(hdd_ctx);
3555
3556 return;
3557}
3558
3559/**
3560 * hdd_enable_ftm() - Enable FTM mode
3561 * @hdd_ctx: HDD context
3562 *
3563 * Helper function to enable FTM mode.
3564 *
3565 * Return: 0 on success and errno on failure.
3566 */
3567int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3568{
3569 int ret;
3570
3571 ret = wlan_hdd_ftm_open(hdd_ctx);
3572 if (ret) {
3573 hdd_alert("wlan_hdd_ftm_open Failed: %d", ret);
3574 goto err_out;
3575 }
3576
3577 ret = hdd_ftm_start(hdd_ctx);
3578
3579 if (ret) {
3580 hdd_alert("hdd_ftm_start Failed: %d", ret);
3581 goto err_ftm_close;
3582 }
3583
3584 ret = wiphy_register(hdd_ctx->wiphy);
3585 if (ret) {
3586 hdd_alert("wiphy register failed: %d", ret);
3587 goto err_ftm_stop;
3588 }
3589
3590 hdd_err("FTM driver loaded");
3591
3592 return 0;
3593
3594err_ftm_stop:
3595 hdd_ftm_stop(hdd_ctx);
3596err_ftm_close:
3597 wlan_hdd_ftm_close(hdd_ctx);
3598err_out:
3599 return ret;
3600
3601}
3602#else
3603int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3604{
3605 hdd_err("Driver built without FTM feature enabled!");
3606
3607 return -ENOTSUPP;
3608}
3609
3610static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { }
3611#endif
3612
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303613#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3614/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003615 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303616 * @hdd_ctx: HDD context
3617 *
3618 * Activates the logging service
3619 *
3620 * Return: Zero in case of success, negative value otherwise
3621 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003622static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303623{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003624 int ret;
3625 struct hdd_config *config = hdd_ctx->config;
3626
3627 if (!config->wlanLoggingEnable)
3628 return 0;
3629
3630 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
3631 config->wlanLoggingNumBuf);
3632 if (ret)
3633 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
3634 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303635}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003636
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303637/**
3638 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
3639 * @hdd_ctx: HDD context
3640 *
3641 * Deactivates the logging service
3642 *
3643 * Return: 0 on deactivating the logging service
3644 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003645static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303646{
3647 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
3648 return wlan_logging_sock_deactivate_svc();
3649
3650 return 0;
3651}
3652#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003653static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303654{
3655 return 0;
3656}
3657
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003658static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303659{
3660 return 0;
3661}
3662#endif
3663
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003665 * hdd_free_context - Free HDD context
3666 * @hdd_ctx: HDD context to be freed.
3667 *
3668 * Free config and HDD context.
3669 *
3670 * Return: None
3671 */
3672static void hdd_free_context(hdd_context_t *hdd_ctx)
3673{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303674 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003675 hdd_logging_sock_deactivate_svc(hdd_ctx);
3676
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303677 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003678 hdd_ctx->config = NULL;
3679
3680 wiphy_free(hdd_ctx->wiphy);
3681}
3682
3683/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003684 * hdd_wlan_exit() - HDD WLAN exit function
3685 * @hdd_ctx: Pointer to the HDD Context
3686 *
3687 * This is the driver exit point (invoked during rmmod)
3688 *
3689 * Return: None
3690 */
3691void hdd_wlan_exit(hdd_context_t *hdd_ctx)
3692{
3693 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303694 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003695 struct wiphy *wiphy = hdd_ctx->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696
3697 ENTER();
3698
3699 hddLog(LOGE, FL("Unregister IPv6 notifier"));
3700 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3701 hddLog(LOGE, FL("Unregister IPv4 notifier"));
3702 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3703
3704 hdd_unregister_wext_all_adapters(hdd_ctx);
3705
Anurag Chouhan6d760662016-02-20 16:05:43 +05303706 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003707 hdd_disable_ftm(hdd_ctx);
3708
3709 hdd_alert("FTM driver unloaded");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003710 goto free_hdd_ctx;
3711 }
3712
3713 /*
3714 * Cancel any outstanding scan requests. We are about to close all
3715 * of our adapters, but an adapter structure is what SME passes back
3716 * to our callback function. Hence if there are any outstanding scan
3717 * requests then there is a race condition between when the adapter
3718 * is closed and when the callback is invoked. We try to resolve that
3719 * race condition here by canceling any outstanding scans before we
3720 * close the adapters.
3721 * Note that the scans may be cancelled in an asynchronous manner, so
3722 * ideally there needs to be some kind of synchronization. Rather than
3723 * introduce a new synchronization here, we will utilize the fact that
3724 * we are about to Request Full Power, and since that is synchronized,
3725 * the expectation is that by the time Request Full Power has completed,
3726 * all scans will be cancelled
3727 */
3728 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3729
3730#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05303731 if (QDF_TIMER_STATE_RUNNING ==
3732 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
3733 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 }
3735
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303736 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303737 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303738 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 FL("Cannot deallocate Bus bandwidth timer"));
3740 }
3741#endif
3742
3743#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05303744 if (QDF_TIMER_STATE_RUNNING ==
3745 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
3746 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003747 }
3748
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303749 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05303750 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303751 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752 FL("Cannot deallocate ACS Skip timer"));
3753 }
3754#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003755
3756 /*
3757 * Powersave Offload Case
3758 * Disable Idle Power Save Mode
3759 */
3760 hdd_set_idle_ps_config(hdd_ctx, false);
3761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762 /* Unregister the Net Device Notifier */
3763 unregister_netdevice_notifier(&hdd_netdev_notifier);
3764
3765 /*
3766 * Stop all adapters, this will ensure the termination of active
3767 * connections on the interface. Make sure the cds_scheduler is
3768 * still available to handle those control messages
3769 */
3770 hdd_stop_all_adapters(hdd_ctx);
3771
3772 /* Stop all the modules */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303773 qdf_status = cds_disable(p_cds_context);
3774 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303775 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 FL("Failed to stop CDS"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303777 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 }
3779
3780 /*
3781 * Close the scheduler before calling cds_close to make sure no thread
3782 * is scheduled after the each module close is called i.e after all the
3783 * data structures are freed.
3784 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303785 qdf_status = cds_sched_close(p_cds_context);
3786 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303787 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303789 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003790 }
3791#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3792 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303793 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003794#endif
3795 /* Destroy the wake lock */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303796 qdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797
3798 hdd_hostapd_channel_wakelock_deinit(hdd_ctx);
3799
3800 /*
3801 * Close CDS
3802 * This frees pMac(HAL) context. There should not be any call
3803 * that requires pMac access after this.
3804 */
3805 cds_close(p_cds_context);
3806
3807 hdd_wlan_green_ap_deinit(hdd_ctx);
3808
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003809#ifdef WLAN_KD_READY_NOTIFIER
3810 cnss_diag_notify_wlan_close();
3811 ptt_sock_deactivate_svc();
3812#endif /* WLAN_KD_READY_NOTIFIER */
3813 nl_srv_exit();
3814
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003815 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816
3817 hdd_ipa_cleanup(hdd_ctx);
3818
3819 /* Free up RoC request queue and flush workqueue */
3820 cds_flush_work(&hdd_ctx->roc_req_work);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303821 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
3822 qdf_list_destroy(&hdd_ctx->hdd_scan_req_q);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003823
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303824 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08003825 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 /* Proceed and complete the clean up */
3827 }
3828
3829free_hdd_ctx:
3830
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 wiphy_unregister(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003832
3833 hdd_free_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834}
3835
3836void __hdd_wlan_exit(void)
3837{
3838 hdd_context_t *hdd_ctx;
3839
3840 ENTER();
3841
Anurag Chouhan6d760662016-02-20 16:05:43 +05303842 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303844 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 EXIT();
3846 return;
3847 }
3848
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003849 /* Check IPA HW Pipe shutdown */
3850 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
3851
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852#ifdef WLAN_FEATURE_LPSS
3853 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
3854#endif
3855
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08003856 memdump_deinit();
3857
3858#ifdef QCA_PKT_PROTO_TRACE
3859 cds_pkt_proto_trace_close();
3860#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003861 /* Do all the cleanup before deregistering the driver */
3862 hdd_wlan_exit(hdd_ctx);
3863 EXIT();
3864}
3865
3866#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
3867void hdd_skip_acs_scan_timer_handler(void *data)
3868{
3869 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
3870
3871 hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
3872 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
3873
3874 if (!hdd_ctx->hHal)
3875 return;
3876 sme_scan_flush_result(hdd_ctx->hHal);
3877}
3878#endif
3879
3880#ifdef QCA_HT_2040_COEX
3881/**
3882 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
3883 * @adapter: pointer to adapter
3884 * @staId: station id
3885 * @macAddrSTA: station MAC address
3886 * @channel_type: channel type
3887 *
3888 * This function notifies FW with HT20/HT40 mode
3889 *
3890 * Return: 0 if successful, error number otherwise
3891 */
3892int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303893 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894{
3895 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303896 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897 hdd_context_t *hdd_ctx = NULL;
3898
3899 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3900
3901 status = wlan_hdd_validate_context(hdd_ctx);
3902 if (0 != status) {
3903 hddLog(LOGE, FL("HDD context is not valid"));
3904 return status;
3905 }
3906 if (!hdd_ctx->hHal)
3907 return -EINVAL;
3908
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303909 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003910 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303911 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912 hddLog(LOGE, "Fail to send notification with ht2040 mode");
3913 return -EINVAL;
3914 }
3915
3916 return 0;
3917}
3918#endif
3919
3920/**
3921 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
3922 * @state: state
3923 *
3924 * This function notifies FW with modem power status
3925 *
3926 * Return: 0 if successful, error number otherwise
3927 */
3928int hdd_wlan_notify_modem_power_state(int state)
3929{
3930 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303931 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003932 hdd_context_t *hdd_ctx;
3933
Anurag Chouhan6d760662016-02-20 16:05:43 +05303934 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003935 status = wlan_hdd_validate_context(hdd_ctx);
3936 if (0 != status) {
3937 hddLog(LOGE, FL("HDD context is not valid"));
3938 return status;
3939 }
3940 if (!hdd_ctx->hHal)
3941 return -EINVAL;
3942
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303943 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
3944 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945 hddLog(LOGE,
3946 "Fail to send notification with modem power state %d",
3947 state);
3948 return -EINVAL;
3949 }
3950 return 0;
3951}
3952
3953/**
3954 *
3955 * hdd_post_cds_enable_config() - HDD post cds start config helper
3956 * @adapter - Pointer to the HDD
3957 *
3958 * Return: None
3959 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303960QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003961{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303962 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963
3964 /*
3965 * Send ready indication to the HDD. This will kick off the MAC
3966 * into a 'running' state and should kick off an initial scan.
3967 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303968 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
3969 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303970 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971 FL(
3972 "sme_hdd_ready_ind() failed with status code %08d [x%08x]"
3973 ),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303974 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303975 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003976 }
3977
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303978 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979}
3980
3981/* wake lock APIs for HDD */
3982void hdd_prevent_suspend(uint32_t reason)
3983{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303984 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003985}
3986
3987void hdd_allow_suspend(uint32_t reason)
3988{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303989 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990}
3991
3992void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
3993{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303994 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995}
3996
3997/**
3998 * hdd_exchange_version_and_caps() - exchange version and capability with target
3999 * @hdd_ctx: Pointer to HDD context
4000 *
4001 * This is the HDD function to exchange version and capability information
4002 * between Host and Target
4003 *
4004 * This function gets reported version of FW.
4005 * It also finds the version of target headers used to compile the host;
4006 * It compares the above two and prints a warning if they are different;
4007 * It gets the SW and HW version string;
4008 * Finally, it exchanges capabilities between host and target i.e. host
4009 * and target exchange a msg indicating the features they support through a
4010 * bitmap
4011 *
4012 * Return: None
4013 */
4014void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4015{
4016
4017 tSirVersionType versionCompiled;
4018 tSirVersionType versionReported;
4019 tSirVersionString versionString;
4020 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304021 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022
4023 memset(&versionCompiled, 0, sizeof(versionCompiled));
4024 memset(&versionReported, 0, sizeof(versionReported));
4025
4026 /* retrieve and display WCNSS version information */
4027 do {
4028
4029 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4030 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304031 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304032 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 FL(
4034 "unable to retrieve WCNSS WLAN compiled version"
4035 ));
4036 break;
4037 }
4038
4039 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4040 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304041 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304042 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 FL(
4044 "unable to retrieve WCNSS WLAN reported version"
4045 ));
4046 break;
4047 }
4048
4049 if ((versionCompiled.major != versionReported.major) ||
4050 (versionCompiled.minor != versionReported.minor) ||
4051 (versionCompiled.version != versionReported.version) ||
4052 (versionCompiled.revision != versionReported.revision)) {
4053 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4054 "Host expected %u.%u.%u.%u\n",
4055 WLAN_MODULE_NAME,
4056 (int)versionReported.major,
4057 (int)versionReported.minor,
4058 (int)versionReported.version,
4059 (int)versionReported.revision,
4060 (int)versionCompiled.major,
4061 (int)versionCompiled.minor,
4062 (int)versionCompiled.version,
4063 (int)versionCompiled.revision);
4064 } else {
4065 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4066 WLAN_MODULE_NAME,
4067 (int)versionReported.major,
4068 (int)versionReported.minor,
4069 (int)versionReported.version,
4070 (int)versionReported.revision);
4071 }
4072
4073 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4074 versionString,
4075 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304076 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304077 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078 FL(
4079 "unable to retrieve WCNSS software version string"
4080 ));
4081 break;
4082 }
4083
4084 pr_info("%s: WCNSS software version %s\n",
4085 WLAN_MODULE_NAME, versionString);
4086
4087 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4088 versionString,
4089 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304090 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304091 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 FL(
4093 "unable to retrieve WCNSS hardware version string"
4094 ));
4095 break;
4096 }
4097
4098 pr_info("%s: WCNSS hardware version %s\n",
4099 WLAN_MODULE_NAME, versionString);
4100
4101 /*
4102 * 1.Check if FW version is greater than 0.1.1.0. Only then
4103 * send host-FW capability exchange message
4104 * 2.Host-FW capability exchange message is only present on
4105 * target 1.1 so send the message only if it the target is 1.1
4106 * minor numbers for different target branches:
4107 * 0 -> (1.0)Mainline Build
4108 * 1 -> (1.1)Mainline Build
4109 * 2->(1.04) Stability Build
4110 */
4111 if (((versionReported.major > 0) || (versionReported.minor > 1)
4112 || ((versionReported.minor >= 1)
4113 && (versionReported.version >= 1)))
4114 && ((versionReported.major == 1)
4115 && (versionReported.minor >= 1)))
4116 fwFeatCapsMsgSupported = 1;
4117
4118 if (fwFeatCapsMsgSupported) {
4119 /*
4120 * Indicate if IBSS heartbeat monitoring needs to be
4121 * offloaded
4122 */
4123 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4124 sme_disable_feature_capablity
4125 (IBSS_HEARTBEAT_OFFLOAD);
4126 }
4127
4128 sme_feature_caps_exchange(hdd_ctx->hHal);
4129 }
4130
4131 } while (0);
4132
4133}
4134
4135/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304136QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137{
4138 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4139 hdd_ctx->reg.cc_src);
4140}
4141
4142/**
4143 * hdd_is_5g_supported() - check if hardware supports 5GHz
4144 * @hdd_ctx: Pointer to the hdd context
4145 *
4146 * HDD function to know if hardware supports 5GHz
4147 *
4148 * Return: true if hardware supports 5GHz
4149 */
4150bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4151{
4152 /*
4153 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4154 * then hardware support 5Ghz.
4155 */
4156 return true;
4157}
4158
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304159static QDF_STATUS wlan_hdd_regulatory_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004160{
4161 struct wiphy *wiphy;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304162 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163
4164 wiphy = hdd_ctx->wiphy;
4165
4166 /*
4167 * The channel information in
4168 * wiphy needs to be initialized before wiphy registration
4169 */
4170 status = cds_regulatory_init();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304171 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304172 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004173 FL("cds_init_wiphy failed"));
4174 return status;
4175 }
4176
4177#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4178 wiphy->wowlan = &wowlan_support_reg_init;
4179#else
4180 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4181 WIPHY_WOWLAN_MAGIC_PKT |
4182 WIPHY_WOWLAN_DISCONNECT |
4183 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4184 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4185 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4186 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4187 WIPHY_WOWLAN_RFKILL_RELEASE;
4188
4189 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4190 WOW_MAX_FILTERS_PER_LIST);
4191 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4192 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4193#endif
4194
4195 /* registration of wiphy dev with cfg80211 */
4196 if (0 > wlan_hdd_cfg80211_register(wiphy)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304197 hddLog(QDF_TRACE_LEVEL_ERROR, FL("wiphy register failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304198 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004199 }
4200
4201 return status;
4202}
4203
4204#ifdef MSM_PLATFORM
4205void hdd_cnss_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004206 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207{
4208#ifdef CONFIG_CNSS
4209 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004210 uint64_t temp_rx = 0;
4211 uint64_t temp_tx = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212 enum cnss_bus_width_type next_vote_level = CNSS_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004213 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4214 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215
Mohit Khannae71e2262015-11-10 09:37:24 -08004216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004217 if (total > hdd_ctx->config->busBandwidthHighThreshold)
4218 next_vote_level = CNSS_BUS_WIDTH_HIGH;
4219 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
4220 next_vote_level = CNSS_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004221 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 next_vote_level = CNSS_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004223 else
4224 next_vote_level = CNSS_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225
Mohit Khannae71e2262015-11-10 09:37:24 -08004226 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4227 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004228
4229 if (hdd_ctx->cur_vote_level != next_vote_level) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304230 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231 FL(
4232 "trigger level %d, tx_packets: %lld, rx_packets: %lld"
4233 ),
4234 next_vote_level, tx_packets, rx_packets);
4235 hdd_ctx->cur_vote_level = next_vote_level;
4236 cnss_request_bus_bandwidth(next_vote_level);
4237 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004238
4239 /* fine-tuning parameters for RX Flows */
4240 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4241
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004242 hdd_ctx->prev_rx = rx_packets;
4243 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004244 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004246 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247
Mohit Khannae71e2262015-11-10 09:37:24 -08004248 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4249 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004250
4251 if (hdd_ctx->cur_rx_level != next_rx_level) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304252 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 FL("TCP DELACK trigger level %d, average_rx: %llu"),
4254 next_rx_level, temp_rx);
4255 hdd_ctx->cur_rx_level = next_rx_level;
4256 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
4257 &next_rx_level,
4258 sizeof(next_rx_level));
4259 }
4260
Mohit Khannae71e2262015-11-10 09:37:24 -08004261 /* fine-tuning parameters for TX Flows */
4262 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4263 hdd_ctx->prev_tx = tx_packets;
4264 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4265 next_tx_level = WLAN_SVC_TP_HIGH;
4266 else
4267 next_tx_level = WLAN_SVC_TP_LOW;
4268
4269 if (hdd_ctx->cur_tx_level != next_tx_level) {
4270 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4271 next_tx_level, temp_tx);
4272 hdd_ctx->cur_tx_level = next_tx_level;
4273 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4274 &next_tx_level,
4275 sizeof(next_tx_level));
4276 }
4277
4278 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4279 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 hdd_ctx->hdd_txrx_hist_idx++;
4281 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
4282#endif
4283}
4284
4285#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4286static void hdd_bus_bw_compute_cbk(void *priv)
4287{
4288 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4289 hdd_adapter_t *adapter = NULL;
4290 uint64_t tx_packets = 0, rx_packets = 0;
4291 uint64_t total_tx = 0, total_rx = 0;
4292 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304293 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004294 bool connected = false;
4295 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4296
4297 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304298 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299 status =
4300 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4301
4302 if (adapterNode->pAdapter == NULL)
4303 continue;
4304 adapter = adapterNode->pAdapter;
4305
4306 if ((adapter->device_mode == WLAN_HDD_INFRA_STATION ||
4307 adapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
4308 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4309 != eConnectionState_Associated) {
4310
4311 continue;
4312 }
4313
4314 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
4315 adapter->device_mode == WLAN_HDD_P2P_GO) &&
4316 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4317
4318 continue;
4319 }
4320
4321 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4322 adapter->prev_tx_packets);
4323 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4324 adapter->prev_rx_packets);
4325
4326 total_rx += adapter->stats.rx_packets;
4327 total_tx += adapter->stats.tx_packets;
4328
4329 spin_lock_bh(&hdd_ctx->bus_bw_lock);
4330 adapter->prev_tx_packets = adapter->stats.tx_packets;
4331 adapter->prev_rx_packets = adapter->stats.rx_packets;
4332 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
4333 connected = true;
4334 }
4335
4336 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
4337 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
4338 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
4339 rx_packets;
4340 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
4341 tx_packets;
4342
4343 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
4344 tx_packets += (uint64_t)ipa_tx_packets;
4345 rx_packets += (uint64_t)ipa_rx_packets;
4346
4347 if (!connected) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304348 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 FL("bus bandwidth timer running in disconnected state"));
4350 return;
4351 }
4352
4353 hdd_cnss_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
4354
4355 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
4356 hdd_ipa_uc_stat_request(adapter, 2);
4357
Anurag Chouhan210db072016-02-22 18:42:15 +05304358 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 hdd_ctx->config->busBandwidthComputeInterval);
4360}
4361#endif
4362
4363/**
4364 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
4365 * @hdd_ctx: hdd context
4366 *
4367 * Return: none
4368 */
4369void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
4370{
4371 int i;
4372
4373#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304374 hddLog(QDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 hdd_ctx->config->busBandwidthComputeInterval,
4376 hdd_ctx->hdd_txrx_hist_idx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304377 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 "BW High TH: %d BW Med TH: %d BW Low TH: %d",
4379 hdd_ctx->config->busBandwidthHighThreshold,
4380 hdd_ctx->config->busBandwidthMediumThreshold,
4381 hdd_ctx->config->busBandwidthLowThreshold);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304382 hddLog(QDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 hdd_ctx->config->tcpDelackThresholdHigh,
4384 hdd_ctx->config->tcpDelackThresholdLow);
4385#endif
4386
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304387 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004388 "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 -08004389
4390 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304391 hddLog(QDF_TRACE_LEVEL_ERROR,
Mohit Khannae71e2262015-11-10 09:37:24 -08004392 "%d: %llu, %llu, %llu, %llu, %d, %d, %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
4394 hdd_ctx->hdd_txrx_hist[i].interval_rx,
4395 hdd_ctx->hdd_txrx_hist[i].total_tx,
4396 hdd_ctx->hdd_txrx_hist[i].interval_tx,
4397 hdd_ctx->hdd_txrx_hist[i].next_vote_level,
Mohit Khannae71e2262015-11-10 09:37:24 -08004398 hdd_ctx->hdd_txrx_hist[i].next_rx_level,
4399 hdd_ctx->hdd_txrx_hist[i].next_tx_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 }
4401 return;
4402}
4403
4404/**
4405 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
4406 * @hdd_ctx: hdd context
4407 *
4408 * Return: none
4409 */
4410void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
4411{
4412 hdd_ctx->hdd_txrx_hist_idx = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304413 qdf_mem_zero(hdd_ctx->hdd_txrx_hist, sizeof(hdd_ctx->hdd_txrx_hist));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414}
4415
4416/**
4417 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
4418 * @pHddCtx: hdd context
4419 *
4420 * Return: none
4421 */
4422void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
4423{
4424
4425 hdd_adapter_t *adapter = NULL;
4426 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304427 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 int i;
4429
4430 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304431 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004432 adapter = adapter_node->pAdapter;
4433
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304434 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435 "Session_id %d device mode %d current index %d",
4436 adapter->sessionId, adapter->device_mode,
4437 adapter->history_index);
4438
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304439 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004440 "Netif queue operation statistics:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304441 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004442 "Current pause_map value %x", adapter->pause_map);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304443 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444 " reason_type: pause_cnt: unpause_cnt");
4445
4446 for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304447 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004448 "%s: %d: %d",
4449 hdd_reason_type_to_string(i),
4450 adapter->queue_oper_stats[i].pause_count,
4451 adapter->queue_oper_stats[i].unpause_count);
4452 }
4453
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304454 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004455 "Netif queue operation history:");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304456 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457 "index: time: action_type: reason_type: pause_map");
4458
4459 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304460 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004461 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05304462 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 adapter->queue_oper_history[i].time),
4464 hdd_action_type_to_string(
4465 adapter->queue_oper_history[i].netif_action),
4466 hdd_reason_type_to_string(
4467 adapter->queue_oper_history[i].netif_reason),
4468 adapter->queue_oper_history[i].pause_map);
4469 }
4470
4471 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4472 adapter_node = next;
4473 }
4474
4475
4476}
4477
4478/**
4479 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
4480 * @hdd_ctx: hdd context
4481 *
4482 * Return: none
4483 */
4484void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
4485{
4486 hdd_adapter_t *adapter = NULL;
4487 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304488 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489
4490 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304491 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492 adapter = adapter_node->pAdapter;
4493
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304494 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304496 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 sizeof(adapter->queue_oper_history));
4498
4499 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
4500 adapter_node = next;
4501 }
4502}
4503
4504/**
4505 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
4506 * @halHandle: Hal handle
4507 * @pContext: Pointer to the context
4508 * @sessionId: Session ID
4509 * @scanId: Scan ID
4510 * @status: Status
4511 *
4512 * This is the callback to be executed when 11d scan is completed to flush out
4513 * the scan results
4514 *
4515 * 11d scan is done during driver load and is a passive scan on all
4516 * channels supported by the device, 11d scans may find some APs on
4517 * frequencies which are forbidden to be used in the regulatory domain
4518 * the device is operating in. If these APs are notified to the supplicant
4519 * it may try to connect to these APs, thus flush out all the scan results
4520 * which are present in SME after 11d scan is done.
4521 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304522 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304524static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525 uint8_t sessionId, uint32_t scanId,
4526 eCsrScanStatus status)
4527{
4528 ENTER();
4529
4530 sme_scan_flush_result(halHandle);
4531
4532 EXIT();
4533
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304534 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535}
4536
4537#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4538/**
4539 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
4540 * @hdd_ctx: hdd global context
4541 *
4542 * Return: none
4543 */
4544static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4545{
4546 uint8_t i;
4547
4548 mutex_init(&hdd_ctx->op_ctx.op_lock);
4549 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4550 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4551 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
4552 }
4553}
4554#else
4555static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
4556{
4557}
4558#endif
4559
4560#ifdef WLAN_FEATURE_FASTPATH
4561/**
4562 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
4563 * @hdd_cfg: hdd config
4564 * @context: lower layer context
4565 *
4566 * Return: none
4567 */
4568static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4569 void *context)
4570{
4571 if (hdd_cfg->fastpath_enable)
4572 hif_enable_fastpath(context);
4573}
4574#else
4575static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
4576 void *context)
4577{
4578}
4579#endif
4580
4581#if defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS)
4582/**
4583 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004584 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 * @level: thermal level
4586 *
4587 * Change IPA data path to SW path when the thermal throttle level greater
4588 * than 0, and restore the original data path when throttle level is 0
4589 *
4590 * Return: none
4591 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004592static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004594 hdd_context_t *hdd_ctx = context;
4595
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004596 /* Change IPA to SW path when throttle level greater than 0 */
4597 if (level > THROTTLE_LEVEL_0)
4598 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
4599 else
4600 /* restore original concurrency mode */
4601 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
4602}
4603
4604/**
4605 * hdd_find_prefd_safe_chnl() - find safe channel within preferred channel
4606 * @hdd_ctxt: hdd context pointer
4607 * @ap_adapter: hdd hostapd adapter pointer
4608 *
4609 * Try to find safe channel within preferred channel
4610 * In case auto channel selection enabled
4611 * - Preferred and safe channel should be used
4612 * - If no overlapping, preferred channel should be used
4613 *
4614 * Return: 1: found preferred safe channel
4615 * 0: could not found preferred safe channel
4616 */
4617static uint8_t hdd_find_prefd_safe_chnl(hdd_context_t *hdd_ctxt,
4618 hdd_adapter_t *ap_adapter)
4619{
4620 uint16_t safe_channels[NUM_20MHZ_RF_CHANNELS];
4621 uint16_t safe_channel_count;
4622 uint16_t unsafe_channel_count;
4623 uint8_t is_unsafe = 1;
4624 uint16_t i;
4625 uint16_t channel_loop;
4626
4627 if (!hdd_ctxt || !ap_adapter) {
4628 hdd_err("invalid context/adapter");
4629 return 0;
4630 }
4631
4632 safe_channel_count = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304633 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctxt->unsafe_channel_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004634 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4635
4636 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
4637 is_unsafe = 0;
4638 for (channel_loop = 0;
4639 channel_loop < unsafe_channel_count; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004640 if (CDS_CHANNEL_NUM(i) ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004641 hdd_ctxt->unsafe_channel_list[channel_loop]) {
4642 is_unsafe = 1;
4643 break;
4644 }
4645 }
4646 if (!is_unsafe) {
4647 safe_channels[safe_channel_count] =
Amar Singhal7a1726a2015-10-14 16:28:11 -07004648 CDS_CHANNEL_NUM(i);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304649 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004650 FL("safe channel %d"),
4651 safe_channels[safe_channel_count]);
4652 safe_channel_count++;
4653 }
4654 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304655 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004656 FL("perferred range %d - %d"),
4657 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
4658 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
4659 for (i = 0; i < safe_channel_count; i++) {
4660 if (safe_channels[i] >=
4661 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch
4662 && safe_channels[i] <=
4663 ap_adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304664 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 FL("safe channel %d is in perferred range"),
4666 safe_channels[i]);
4667 return 1;
4668 }
4669 }
4670 return 0;
4671}
Abhishek Singh7996eb72015-12-30 17:24:02 +05304672/**
4673 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
4674 * user space
4675 * @frame_ind: Management frame data to be informed.
4676 *
4677 * This function is used to indicate management frame to
4678 * user space
4679 *
4680 * Return: None
4681 *
4682 */
4683void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
4684{
4685 hdd_context_t *hdd_ctx = NULL;
4686 hdd_adapter_t *adapter = NULL;
4687 void *cds_context = NULL;
4688 int i;
4689
4690 /* Get the global VOSS context.*/
4691 cds_context = cds_get_global_context();
4692 if (!cds_context) {
4693 hddLog(LOGE, FL("Global VOS context is Null"));
4694 return;
4695 }
4696 /* Get the HDD context.*/
4697 hdd_ctx =
Anurag Chouhan6d760662016-02-20 16:05:43 +05304698 (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304699
4700 if (0 != wlan_hdd_validate_context(hdd_ctx))
4701 return;
4702
4703 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
4704 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
4705 adapter =
4706 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
4707 if (adapter)
4708 break;
4709 }
4710 } else {
4711 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
4712 frame_ind->sessionId);
4713 }
4714
4715 if ((NULL != adapter) &&
4716 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
4717 __hdd_indicate_mgmt_frame(adapter,
4718 frame_ind->frame_len,
4719 frame_ind->frameBuf,
4720 frame_ind->frameType,
4721 frame_ind->rxChan,
4722 frame_ind->rxRssi);
4723 return;
4724}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725
4726/**
4727 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
4728 * @adapter: HDD adapter pointer
4729 * @indParam: Channel avoid notification parameter
4730 *
4731 * Avoid channel notification from FW handler.
4732 * FW will send un-safe channel list to avoid over wrapping.
4733 * hostapd should not use notified channel
4734 *
4735 * Return: None
4736 */
4737static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
4738{
4739 hdd_adapter_t *hostapd_adapter = NULL;
4740 hdd_context_t *hdd_ctxt;
4741 tSirChAvoidIndType *ch_avoid_indi;
4742 uint8_t range_loop;
Amar Singhala297bfa2015-10-15 15:07:29 -07004743 enum channel_enum channel_loop, start_channel_idx = INVALID_RF_CHANNEL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004744 end_channel_idx = INVALID_RF_CHANNEL;
4745 uint16_t start_channel;
4746 uint16_t end_channel;
4747 v_CONTEXT_t cds_context;
4748 static int restart_sap_in_progress;
4749 tHddAvoidFreqList hdd_avoid_freq_list;
4750 uint32_t i;
4751
4752 /* Basic sanity */
4753 if (!hdd_context || !indi_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304754 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid arguments"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 return;
4756 }
4757
4758 hdd_ctxt = (hdd_context_t *) hdd_context;
4759 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
4760 cds_context = hdd_ctxt->pcds_context;
4761
4762 /* Make unsafe channel list */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304763 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 FL("band count %d"),
4765 ch_avoid_indi->avoid_range_count);
4766
4767 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304768 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004769 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
4770 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
4771 ch_avoid_indi->avoid_freq_range[i].start_freq;
4772 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
4773 ch_avoid_indi->avoid_freq_range[i].end_freq;
4774 }
4775 hdd_avoid_freq_list.avoidFreqRangeCount =
4776 ch_avoid_indi->avoid_range_count;
4777
4778 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
4779
4780 /* clear existing unsafe channel cache */
4781 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304782 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004783 sizeof(hdd_ctxt->unsafe_channel_list));
4784
4785 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
4786 range_loop++) {
4787 if (hdd_ctxt->unsafe_channel_count >= NUM_20MHZ_RF_CHANNELS) {
4788 hddLog(LOGW, FL("LTE Coex unsafe channel list full"));
4789 break;
4790 }
4791
4792 start_channel = ieee80211_frequency_to_channel(
4793 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
4794 end_channel = ieee80211_frequency_to_channel(
4795 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
4796 hddLog(LOG1, "%s : start %d : %d, end %d : %d", __func__,
4797 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
4798 start_channel,
4799 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
4800 end_channel);
4801
4802 /* do not process frequency bands that are not mapped to
4803 * predefined channels
4804 */
4805 if (start_channel == 0 || end_channel == 0)
4806 continue;
4807
4808 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4809 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004810 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 ch_avoid_indi->avoid_freq_range[
4812 range_loop].start_freq) {
4813 start_channel_idx = channel_loop;
4814 break;
4815 }
4816 }
4817 for (channel_loop = MIN_20MHZ_RF_CHANNEL; channel_loop <=
4818 MAX_20MHZ_RF_CHANNEL; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07004819 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 ch_avoid_indi->avoid_freq_range[
4821 range_loop].end_freq) {
4822 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07004823 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824 ch_avoid_indi->avoid_freq_range[
4825 range_loop].end_freq)
4826 end_channel_idx--;
4827 break;
4828 }
4829 }
4830
4831 if (start_channel_idx == INVALID_RF_CHANNEL ||
4832 end_channel_idx == INVALID_RF_CHANNEL)
4833 continue;
4834
4835 for (channel_loop = start_channel_idx; channel_loop <=
4836 end_channel_idx; channel_loop++) {
4837 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07004838 hdd_ctxt->unsafe_channel_count++] =
4839 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004840 if (hdd_ctxt->unsafe_channel_count >=
4841 NUM_20MHZ_RF_CHANNELS) {
4842 hddLog(LOGW, FL("LTECoex unsafe ch list full"));
4843 break;
4844 }
4845 }
4846 }
4847
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304848 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 FL("number of unsafe channels is %d "),
4850 hdd_ctxt->unsafe_channel_count);
4851
4852 if (cnss_set_wlan_unsafe_channel(hdd_ctxt->unsafe_channel_list,
4853 hdd_ctxt->unsafe_channel_count)) {
4854 hdd_err("Failed to set unsafe channel");
4855
4856 /* clear existing unsafe channel cache */
4857 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304858 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859 sizeof(hdd_ctxt->unsafe_channel_list));
4860
4861 return;
4862 }
4863
4864 for (channel_loop = 0;
4865 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304866 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 FL("channel %d is not safe "),
4868 hdd_ctxt->unsafe_channel_list[channel_loop]);
4869 }
4870
4871 /*
4872 * If auto channel select is enabled
4873 * preferred channel is in safe channel,
4874 * re-start softap interface with safe channel.
4875 * no overlap with preferred channel and safe channel
4876 * do not re-start softap interface
4877 * stay current operating channel.
4878 */
4879 if (hdd_ctxt->unsafe_channel_count) {
4880 hostapd_adapter = hdd_get_adapter(hdd_ctxt, WLAN_HDD_SOFTAP);
4881 if (hostapd_adapter) {
4882 if ((hostapd_adapter->sessionCtx.ap.sapConfig.
4883 acs_cfg.acs_mode) &&
4884 (!hdd_find_prefd_safe_chnl(hdd_ctxt,
4885 hostapd_adapter)))
4886 return;
4887
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304888 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004889 FL(
4890 "Current operation channel %d, sessionCtx.ap.sapConfig.channel %d"
4891 ),
4892 hostapd_adapter->sessionCtx.ap.
4893 operatingChannel,
4894 hostapd_adapter->sessionCtx.ap.sapConfig.
4895 channel);
4896 for (channel_loop = 0;
4897 channel_loop < hdd_ctxt->unsafe_channel_count;
4898 channel_loop++) {
4899 if (((hdd_ctxt->
4900 unsafe_channel_list[channel_loop] ==
4901 hostapd_adapter->sessionCtx.ap.
4902 operatingChannel)) &&
4903 (hostapd_adapter->sessionCtx.ap.
4904 sapConfig.acs_cfg.acs_mode
4905 == true) &&
4906 !restart_sap_in_progress) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304907 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908 FL("Restarting SAP"));
4909 wlan_hdd_send_svc_nlink_msg
4910 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
4911 restart_sap_in_progress = 1;
4912 /*
4913 * current operating channel is un-safe
4914 * channel, restart driver
4915 */
4916 hdd_hostapd_stop(hostapd_adapter->dev);
4917 break;
4918 }
4919 }
4920 }
4921 }
4922 return;
4923}
4924
4925/**
4926 * hdd_init_channel_avoidance() - Initialize channel avoidance
4927 * @hdd_ctx: HDD global context
4928 *
4929 * Initialize the channel avoidance logic by retrieving the unsafe
4930 * channel list from the CNSS platform driver and plumbing the data
4931 * down to the lower layers. Then subscribe to subsequent channel
4932 * avoidance events.
4933 *
4934 * Return: None
4935 */
4936static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4937{
4938 uint16_t unsafe_channel_count;
4939 int index;
4940
4941 cnss_get_wlan_unsafe_channel(hdd_ctx->unsafe_channel_list,
4942 &(hdd_ctx->unsafe_channel_count),
4943 sizeof(uint16_t) * NUM_20MHZ_RF_CHANNELS);
4944
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304945 hddLog(QDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004946 hdd_ctx->unsafe_channel_count);
4947
Anurag Chouhan6d760662016-02-20 16:05:43 +05304948 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 (uint16_t)NUM_20MHZ_RF_CHANNELS);
4950
4951 for (index = 0; index < unsafe_channel_count; index++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304952 hddLog(QDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953 hdd_ctx->unsafe_channel_list[index]);
4954
4955 }
4956
4957 /* Plug in avoid channel notification callback */
4958 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
4959}
4960#else
4961static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
4962{
4963}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08004964static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004965{
4966}
4967#endif /* defined(FEATURE_WLAN_CH_AVOID) && defined(CONFIG_CNSS) */
4968
4969/**
4970 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
4971 * @hdd_ctx: HDD context
4972 *
4973 * Disables all the dual mac features like DBS, Agile DFS etc.
4974 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304975 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304977static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004978{
4979 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304980 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981
4982 if (!hdd_ctx) {
4983 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304984 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004985 }
4986
4987 cfg.scan_config = 0;
4988 cfg.fw_mode_config = 0;
4989 cfg.set_dual_mac_cb =
4990 (void *)cds_soc_set_dual_mac_cfg_cb;
4991
4992 hdd_debug("Disabling all dual mac features...");
4993
4994 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304995 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004996 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
4997 return status;
4998 }
4999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305000 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005001}
5002
5003/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005004 * hdd_override_ini_config - Override INI config
5005 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005007 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005009 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005011static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005013
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005014 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
5015 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5016 hdd_notice("Module enable_dfs_chan_scan set to %d",
5017 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005019 if (0 == enable_11d || 1 == enable_11d) {
5020 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5021 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005022 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005023}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005025/**
5026 * hdd_set_trace_level_for_each - Set trace level for each INI config
5027 * @hdd_ctx - HDD context
5028 *
5029 * Set trace level for each module based on INI config.
5030 *
5031 * Return: None
5032 */
5033static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5034{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305035 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
5036 hdd_ctx->config->qdf_trace_enable_wdi);
5037 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
5038 hdd_ctx->config->qdf_trace_enable_hdd);
5039 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
5040 hdd_ctx->config->qdf_trace_enable_sme);
5041 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
5042 hdd_ctx->config->qdf_trace_enable_pe);
5043 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
5044 hdd_ctx->config->qdf_trace_enable_wma);
5045 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
5046 hdd_ctx->config->qdf_trace_enable_sys);
5047 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
5048 hdd_ctx->config->qdf_trace_enable_qdf);
5049 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
5050 hdd_ctx->config->qdf_trace_enable_sap);
5051 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
5052 hdd_ctx->config->qdf_trace_enable_hdd_sap);
5053 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
5054 hdd_ctx->config->qdf_trace_enable_bmi);
5055 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
5056 hdd_ctx->config->qdf_trace_enable_cfg);
5057 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
5058 hdd_ctx->config->qdf_trace_enable_epping);
5059 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
5060 hdd_ctx->config->qdf_trace_enable_qdf_devices);
5061 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05305062 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305063 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
5064 hdd_ctx->config->qdf_trace_enable_htc);
5065 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
5066 hdd_ctx->config->qdf_trace_enable_hif);
5067 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
5068 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
5069 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
5070 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305071
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005073}
5074
5075/**
5076 * hdd_init_context - Alloc and initialize HDD context
5077 * @dev: Pointer to the underlying device
5078 * @hif_sc: HIF context
5079 *
5080 * Allocate and initialize HDD context. HDD context is allocated as part of
5081 * wiphy allocation and then context is initialized.
5082 *
5083 * Return: HDD context on success and ERR_PTR on failure
5084 */
5085hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc)
5086{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305087 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005088 int ret = 0;
5089 hdd_context_t *hdd_ctx;
5090 v_CONTEXT_t p_cds_context;
Komal Seelamc11bb222016-01-27 18:57:10 +05305091 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_sc);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005092
5093 ENTER();
5094
5095 p_cds_context = cds_get_global_context();
5096 if (p_cds_context == NULL) {
5097 hdd_alert("Failed to get CDS global context");
5098 ret = -EINVAL;
5099 goto err_out;
5100 }
5101
5102 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
5103
5104 if (hdd_ctx == NULL) {
5105 ret = -ENOMEM;
5106 goto err_out;
5107 }
5108
5109 hdd_ctx->pcds_context = p_cds_context;
5110
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305111 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005112 if (hdd_ctx->config == NULL) {
5113 hdd_alert("Failed to alloc memory for HDD config!");
5114 ret = -ENOMEM;
5115 goto err_free_hdd_context;
5116 }
5117
5118 /* Read and parse the qcom_cfg.ini file */
5119 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305120 if (QDF_STATUS_SUCCESS != status) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005121 hdd_alert("Error (status: %d) parsing INI file: %s", status,
5122 WLAN_INI_FILE);
5123 ret = -EINVAL;
5124 goto err_free_config;
5125 }
5126
5127 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
5128
5129 hdd_ctx->parent_dev = dev;
5130
5131 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5132
5133 hdd_init_ll_stats_ctx();
5134
5135 init_completion(&hdd_ctx->mc_sus_event_var);
5136 init_completion(&hdd_ctx->ready_to_suspend);
5137
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305138 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
5139 qdf_spinlock_create(&hdd_ctx->sched_scan_lock);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005140
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305141 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305142 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005143
5144 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
5145
5146 hdd_tdls_pre_init(hdd_ctx);
5147 mutex_init(&hdd_ctx->dfs_lock);
5148
Komal Seelamc11bb222016-01-27 18:57:10 +05305149 hdd_ctx->target_type = tgt_info->target_type;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005150
5151 hdd_init_offloaded_packets_ctx(hdd_ctx);
5152
Komal Seelamc11bb222016-01-27 18:57:10 +05305153 icnss_set_fw_debug_mode(hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005154
5155 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5156
5157 hdd_ctx->configuredMcastBcastFilter =
5158 hdd_ctx->config->mcastBcastFilterSetting;
5159
5160 hdd_notice("Setting configuredMcastBcastFilter: %d",
5161 hdd_ctx->config->mcastBcastFilterSetting);
5162
5163 hdd_override_ini_config(hdd_ctx);
5164
5165 ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config);
5166
5167 if (ret) {
5168 hdd_err("CFG80211 wiphy init failed: %d", ret);
5169 goto err_free_config;
5170 }
5171
5172 hdd_enable_fastpath(hdd_ctx->config, hif_sc);
5173
5174 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05305175 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005176
Anurag Chouhan6d760662016-02-20 16:05:43 +05305177 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005178 goto skip_multicast_logging;
5179
5180 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
5181
5182 ret = hdd_logging_sock_activate_svc(hdd_ctx);
5183 if (ret)
5184 goto err_free_config;
5185
5186 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305187 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005188 * levels of the code need not be set when the logger thread
5189 * is not enabled.
5190 */
5191 if (cds_is_multicast_logging())
5192 wlan_logging_set_log_level();
5193
5194skip_multicast_logging:
5195 hdd_set_trace_level_for_each(hdd_ctx);
5196
5197 return hdd_ctx;
5198
5199err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305200 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005201
5202err_free_hdd_context:
5203 wiphy_free(hdd_ctx->wiphy);
5204
5205err_out:
5206 return ERR_PTR(ret);
5207}
5208
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005209#ifdef WLAN_OPEN_P2P_INTERFACE
5210/**
5211 * hdd_open_p2p_interface - Open P2P interface
5212 * @hdd_ctx: HDD context
5213 * @rtnl_held: True if RTNL lock held
5214 *
5215 * Open P2P interface during probe. This function called to open the P2P
5216 * interface at probe along with STA interface.
5217 *
5218 * Return: 0 on success and errno on failure
5219 */
5220static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
5221{
5222 hdd_adapter_t *adapter;
5223 uint8_t *p2p_dev_addr;
5224
5225 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
5226 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305227 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005228 hdd_ctx->config->intfMacAddr[0].bytes,
5229 sizeof(tSirMacAddr));
5230
5231 /*
5232 * Generate the P2P Device Address. This consists of
5233 * the device's primary MAC address with the locally
5234 * administered bit set.
5235 */
5236 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
5237 } else {
5238 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
5239 if (p2p_dev_addr == NULL) {
5240 hdd_alert("Failed to allocate mac_address for p2p_device");
5241 return -ENOSPC;
5242 }
5243
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305244 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305245 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005246 }
5247
5248 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
5249 &hdd_ctx->p2pDeviceAddress.bytes[0],
5250 rtnl_held);
5251
5252 if (NULL == adapter) {
5253 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
5254 return -ENOSPC;
5255 }
5256
5257 return 0;
5258}
5259#else
5260static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx,
5261 bool rtnl_held)
5262{
5263 return 0;
5264}
5265#endif
5266
5267/**
5268 * hdd_open_interfaces - Open all required interfaces
5269 * hdd_ctx: HDD context
5270 * rtnl_held: True if RTNL lock is held
5271 *
5272 * Open all the interfaces like STA, P2P and OCB based on the configuration.
5273 *
5274 * Return: Primary adapter on success and PTR_ERR on failure
5275 */
5276static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
5277 bool rtnl_held)
5278{
5279 hdd_adapter_t *adapter = NULL;
5280 hdd_adapter_t *adapter_11p = NULL;
5281 int ret;
5282
5283 /* Create only 802.11p interface */
5284 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
5285 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB, "wlanocb%d",
5286 wlan_hdd_get_intf_addr(hdd_ctx),
5287 rtnl_held);
5288
5289 if (adapter == NULL)
5290 return ERR_PTR(-ENOSPC);
5291
5292 return adapter;
5293 }
5294
5295 adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION, "wlan%d",
5296 wlan_hdd_get_intf_addr(hdd_ctx),
5297 rtnl_held);
5298
5299 if (adapter == NULL)
5300 return ERR_PTR(-ENOSPC);
5301
5302 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
5303 if (ret)
5304 goto err_close_adapter;
5305
5306 /* Open 802.11p Interface */
5307 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
5308 adapter_11p = hdd_open_adapter(hdd_ctx, WLAN_HDD_OCB,
5309 "wlanocb%d",
5310 wlan_hdd_get_intf_addr(hdd_ctx),
5311 rtnl_held);
5312 if (adapter_11p == NULL) {
5313 hdd_err("Failed to open 802.11p interface");
5314 goto err_close_adapter;
5315 }
5316 }
5317
5318 return adapter;
5319
5320err_close_adapter:
5321 hdd_close_all_adapters(hdd_ctx, rtnl_held);
5322 return ERR_PTR(ret);
5323}
5324
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005325/**
5326 * hdd_update_country_code - Update country code
5327 * @hdd_ctx: HDD context
5328 * @adapter: Primary adapter context
5329 *
5330 * Update country code based on module parameter country_code at SME and wait
5331 * for the settings to take effect.
5332 *
5333 * Return: 0 on success and errno on failure
5334 */
5335static int hdd_update_country_code(hdd_context_t *hdd_ctx,
5336 hdd_adapter_t *adapter)
5337{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305338 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005339 int ret = 0;
5340 unsigned long rc;
5341
5342 if (country_code == NULL)
5343 return 0;
5344
5345 INIT_COMPLETION(adapter->change_country_code);
5346
5347 status = sme_change_country_code(hdd_ctx->hHal,
5348 wlan_hdd_change_country_code_callback,
5349 country_code, adapter,
5350 hdd_ctx->pcds_context, eSIR_TRUE,
5351 eSIR_TRUE);
5352
5353
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305354 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005355 hdd_err("SME Change Country code from module param fail ret=%d",
5356 ret);
5357 return -EINVAL;
5358 }
5359
5360 rc = wait_for_completion_timeout(&adapter->change_country_code,
5361 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
5362 if (!rc) {
5363 hdd_err("SME while setting country code timed out");
5364 ret = -ETIMEDOUT;
5365 }
5366
5367 return ret;
5368}
5369
5370/**
5371 * hdd_init_thermal_info - Initialize thermal level
5372 * @hdd_ctx: HDD context
5373 *
5374 * Initialize thermal level at SME layer and set the thermal level callback
5375 * which would be called when a configured thermal threshold is hit.
5376 *
5377 * Return: 0 on success and errno on failure
5378 */
5379static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
5380{
5381 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305382 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005383
5384 thermal_param.smeThermalMgmtEnabled =
5385 hdd_ctx->config->thermalMitigationEnable;
5386 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
5387
5388 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
5389 hdd_ctx->config->thermalTempMinLevel0;
5390 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
5391 hdd_ctx->config->thermalTempMaxLevel0;
5392 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
5393 hdd_ctx->config->thermalTempMinLevel1;
5394 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
5395 hdd_ctx->config->thermalTempMaxLevel1;
5396 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
5397 hdd_ctx->config->thermalTempMinLevel2;
5398 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
5399 hdd_ctx->config->thermalTempMaxLevel2;
5400 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
5401 hdd_ctx->config->thermalTempMinLevel3;
5402 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
5403 hdd_ctx->config->thermalTempMaxLevel3;
5404
5405 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
5406
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305407 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05305408 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005409
5410 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
5411 hdd_set_thermal_level_cb);
5412
5413 return 0;
5414
5415}
5416
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005417#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
5418/**
5419 * hdd_hold_rtnl_lock - Hold RTNL lock
5420 *
5421 * Hold RTNL lock
5422 *
5423 * Return: True if held and false otherwise
5424 */
5425static inline bool hdd_hold_rtnl_lock(void)
5426{
5427 rtnl_lock();
5428 return true;
5429}
5430
5431/**
5432 * hdd_release_rtnl_lock - Release RTNL lock
5433 *
5434 * Release RTNL lock
5435 *
5436 * Return: None
5437 */
5438static inline void hdd_release_rtnl_lock(void)
5439{
5440 rtnl_unlock();
5441}
5442#else
5443static inline bool hdd_hold_rtnl_lock(void) { return false; }
5444static inline void hdd_release_rtnl_lock(void) { }
5445#endif
5446
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005447/**
5448 * hdd_wlan_startup() - HDD init function
5449 * @dev: Pointer to the underlying device
5450 *
5451 * This is the driver startup code executed once a WLAN device has been detected
5452 *
5453 * Return: 0 for success, < 0 for failure
5454 */
5455int hdd_wlan_startup(struct device *dev, void *hif_sc)
5456{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305457 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005458 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005459 hdd_context_t *hdd_ctx = NULL;
5460 int ret;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005461 tSirTxPowerLimit hddtxlimit;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005462 bool rtnl_held;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005463 tSirRetStatus hal_status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005464
5465 ENTER();
5466
5467 if (WLAN_IS_EPPING_ENABLED(con_mode)) {
5468 ret = epping_enable(dev);
5469 EXIT();
5470 return ret;
5471 }
5472
5473 hdd_ctx = hdd_init_context(dev, hif_sc);
5474
5475 if (IS_ERR(hdd_ctx))
5476 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477
Anurag Chouhan6d760662016-02-20 16:05:43 +05305478 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005479 ret = hdd_enable_ftm(hdd_ctx);
5480
5481 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005482 goto err_hdd_free_context;
Prashanth Bhattad1d44692015-12-22 17:32:59 -08005483
5484 goto success;
5485 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08005487 hdd_wlan_green_ap_init(hdd_ctx);
5488
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005489 status = cds_open();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305490 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305491 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_open failed"));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005492 goto err_hdd_free_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 }
5494
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005495 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496
Anurag Chouhan6d760662016-02-20 16:05:43 +05305497 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005498
5499 if (NULL == hdd_ctx->hHal) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305500 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HAL context is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501 goto err_cds_close;
5502 }
5503
5504 status = cds_pre_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305505 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305506 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005507 goto err_cds_close;
5508 }
5509
5510 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
5511
5512 status = wlan_hdd_regulatory_init(hdd_ctx);
5513
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305514 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305515 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516 FL("Failed to init channel list"));
5517 goto err_cds_close;
5518 }
5519
5520 /*
5521 * Set 802.11p config
5522 * TODO-OCB: This has been temporarily added here to ensure this
5523 * parameter is set in CSR when we init the channel list. This should
5524 * be removed once the 5.9 GHz channels are added to the regulatory
5525 * domain.
5526 */
5527 hdd_set_dot11p_config(hdd_ctx);
5528
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005529 /*
5530 * Note that the cds_pre_enable() sequence triggers the cfg download.
5531 * The cfg download must occur before we update the SME config
5532 * since the SME config operation must access the cfg database
5533 */
5534 status = hdd_set_sme_config(hdd_ctx);
5535
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305536 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305537 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 goto err_wiphy_unregister;
5539 }
5540
5541 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
5542 hdd_ctx->config->tx_chain_mask_1ss,
5543 PDEV_CMD);
5544 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305545 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d",
5547 __func__, ret);
5548 }
5549
5550 status = hdd_set_sme_chan_list(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305551 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305552 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553 FL("Failed to init channel list"));
5554 goto err_wiphy_unregister;
5555 }
5556
5557 /* Apply the cfg.ini to cfg.dat */
5558 if (false == hdd_update_config_dat(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305559 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005560 FL("config update failed"));
5561 goto err_wiphy_unregister;
5562 }
5563
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305564 if (QDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305565 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005566 FL("can't update mac config, using MAC from ini file"));
5567 }
5568
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005569 /*
5570 * Set the MAC Address Currently this is used by HAL to add self sta.
5571 * Remove this once self sta is added as part of session open.
5572 */
5573 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
5574 hdd_ctx->config->intfMacAddr[0].bytes,
5575 sizeof(hdd_ctx->config->intfMacAddr[0]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005576
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005577 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
5578 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
5579 hal_status, hal_status);
5580 ret = -EINVAL;
5581 goto err_wiphy_unregister;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 }
5583
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305584 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005585 goto err_wiphy_unregister;
5586
5587 /*
5588 * Start CDS which starts up the SME/MAC/HAL modules and everything
5589 * else
5590 */
5591 status = cds_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305592 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305593 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_enable failed"));
Yun Park6a46ad82016-01-04 16:48:19 -08005594 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005595 }
5596
5597 hdd_init_channel_avoidance(hdd_ctx);
5598
5599 status = hdd_post_cds_enable_config(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305600 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305601 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 FL("hdd_post_cds_enable_config failed"));
5603 goto err_cds_disable;
5604 }
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005605
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005606 cds_pkt_proto_trace_init();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005607
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005608 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005609
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005610 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005612 if (IS_ERR(adapter)) {
5613 ret = PTR_ERR(adapter);
5614 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615 }
5616
5617 /*
5618 * target hw version/revision would only be retrieved after firmware
5619 * donwload
5620 */
5621 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
5622 &hdd_ctx->target_hw_revision,
5623 &hdd_ctx->target_hw_name);
5624
5625 /* Get the wlan hw/fw version */
5626 hdd_wlan_get_version(adapter, NULL, NULL);
5627
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005628 ret = hdd_update_country_code(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005629
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005630 if (ret)
5631 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632
5633 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
5634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
5636 hdd_send_oem_data_rsp_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638 /* FW capabilities received, Set the Dot11 mode */
5639 sme_setdef_dot11mode(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005640
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 /* Initialize the nlink service */
5642 if (nl_srv_init() != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305643 hddLog(QDF_TRACE_LEVEL_FATAL, FL("nl_srv_init failed"));
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005644 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005645 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005647 ret = oem_activate_service(hdd_ctx);
5648 if (ret) {
5649 hdd_alert("oem_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 goto err_nl_srv;
5651 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005653 ret = ptt_sock_activate_svc();
5654 if (ret) {
5655 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005656 goto err_nl_srv;
5657 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005658
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005659 ret = cnss_diag_activate_service();
5660 if (ret) {
5661 hdd_alert("cnss_diag_activate_service failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005662 goto err_nl_srv;
5663 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005664
Peng Xuf5d60c82015-10-02 17:17:03 -07005665 /*
5666 * Action frame registered in one adapter which will
5667 * applicable to all interfaces
5668 */
5669 wlan_hdd_cfg80211_register_frames(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005670
5671 mutex_init(&hdd_ctx->sap_lock);
5672
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005673 hdd_release_rtnl_lock();
5674 rtnl_held = false;
5675
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005676 ret = register_netdevice_notifier(&hdd_netdev_notifier);
5677 if (ret < 0) {
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005678 hdd_err("register_netdevice_notifier failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005679 goto err_nl_srv;
5680 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005681
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
5683 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305684 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005685#endif
5686 /* Initialize the wake lcok */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305687 qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005688
5689 hdd_hostapd_channel_wakelock_init(hdd_ctx);
5690
Kiran Kumar Lokerefc2803d2016-01-11 19:31:38 -08005691 if (hdd_ctx->config->fIsImpsEnabled)
5692 hdd_set_idle_ps_config(hdd_ctx, true);
5693 else
5694 hdd_set_idle_ps_config(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005695#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
5696 if (hdd_ctx->config->WlanAutoShutdown != 0)
5697 if (sme_set_auto_shutdown_cb
5698 (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305699 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005700 hddLog(LOGE,
5701 FL(
5702 "Auto shutdown feature could not be enabled"
5703 ));
5704#endif
5705
5706#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05305707 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305708 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005709 hdd_skip_acs_scan_timer_handler,
5710 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305711 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712 hddLog(LOGE, FL("Failed to init ACS Skip timer"));
5713#endif
5714
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005715 wlan_hdd_nan_init(hdd_ctx);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005716 status = cds_init_policy_mgr();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305717 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005718 hdd_err("Policy manager initialization failed");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005719 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005720 }
5721
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005722 ret = hdd_init_thermal_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005724 if (ret) {
5725 hdd_err("Error while initializing thermal information");
5726 goto err_unreg_netdev_notifier;
5727 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005728
5729 if (0 != hdd_lro_init(hdd_ctx))
5730 hdd_err("Unable to initialize LRO in fw");
5731
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005732 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
5733 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
5734 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305735 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005736 hdd_err("Error setting txlimit in sme: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005737
5738#ifdef MSM_PLATFORM
5739 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05305740 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305741 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
5743#endif
5744
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005745 wlan_hdd_cfg80211_stats_ext_init(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005746
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005747 sme_ext_scan_register_callback(hdd_ctx->hHal,
5748 wlan_hdd_cfg80211_extscan_callback);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
5751 hdd_rssi_threshold_breached);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005752
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08005753 hdd_cfg80211_link_layer_stats_init(hdd_ctx);
5754
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005755 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
5756 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
5757 hdd_ctx->target_hw_version,
5758 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305760 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305761 qdf_list_create((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305762 qdf_spinlock_create(&hdd_ctx->hdd_scan_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05305763 qdf_list_create((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005764#ifdef CONFIG_CNSS
5765 cnss_init_delayed_work(&hdd_ctx->roc_req_work,
5766 wlan_hdd_roc_request_dequeue);
5767#else
5768 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
5769#endif
5770
5771 /*
5772 * Register IPv6 notifier to notify if any change in IP
5773 * So that we can reconfigure the offload parameters
5774 */
5775 hdd_wlan_register_ip6_notifier(hdd_ctx);
5776
5777 /*
5778 * Register IPv4 notifier to notify if any change in IP
5779 * So that we can reconfigure the offload parameters
5780 */
5781 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
5782 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
5783 if (ret)
5784 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
5785 else
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005786 hdd_info("Registered IPv4 notifier");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005787
5788 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
5789
5790 if (hdd_ctx->config->dual_mac_feature_disable) {
5791 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305792 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005793 hdd_err("Failed to disable dual mac features");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005794 goto err_unreg_netdev_notifier;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005795 }
5796 }
5797
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08005798 memdump_init();
5799
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800 goto success;
5801
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005802err_unreg_netdev_notifier:
5803 unregister_netdevice_notifier(&hdd_netdev_notifier);
5804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005805err_nl_srv:
5806#ifdef WLAN_KD_READY_NOTIFIER
5807 cnss_diag_notify_wlan_close();
5808 ptt_sock_deactivate_svc();
5809#endif /* WLAN_KD_READY_NOTIFIER */
5810 nl_srv_exit();
5811
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305812 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08005813 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814 /* Proceed and complete the clean up */
5815 }
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005816
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005818 hdd_release_rtnl_lock();
5819
5820 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005821
5822err_cds_disable:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005823 cds_disable(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005824
Yun Park6a46ad82016-01-04 16:48:19 -08005825err_ipa_cleanup:
5826 hdd_ipa_cleanup(hdd_ctx);
5827
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005828err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005829 wiphy_unregister(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830
5831err_cds_close:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005832 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305833 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305834 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005835 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305836 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005837 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005838 cds_close(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005839
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005840err_hdd_free_context:
5841 hdd_free_context(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305842 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 return -EIO;
5845
5846success:
5847 EXIT();
5848 return 0;
5849}
5850
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005851/**
5852 * hdd_softap_sta_deauth() - handle deauth req from HDD
5853 * @adapter: Pointer to the HDD
5854 * @enable: bool value
5855 *
5856 * This to take counter measure to handle deauth req from HDD
5857 *
5858 * Return: None
5859 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305860QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 struct tagCsrDelStaParams *pDelStaParams)
5862{
5863#ifndef WLAN_FEATURE_MBSSID
5864 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5865#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305866 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867
5868 ENTER();
5869
5870 hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"),
5871 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5872
5873 /* Ignore request to deauth bcmc station */
5874 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305875 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876
5877#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305878 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5880 pDelStaParams);
5881#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305882 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005883#endif
5884
5885 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305886 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005887}
5888
5889/**
5890 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
5891 * @adapter: Pointer to the HDD
5892 *
5893 * This to take counter measure to handle deauth req from HDD
5894 *
5895 * Return: None
5896 */
5897void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
5898 uint8_t *pDestMacAddress)
5899{
5900#ifndef WLAN_FEATURE_MBSSID
5901 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5902#endif
5903
5904 ENTER();
5905
5906 hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"),
5907 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5908
5909 /* Ignore request to disassoc bcmc station */
5910 if (pDestMacAddress[0] & 0x1)
5911 return;
5912
5913#ifdef WLAN_FEATURE_MBSSID
5914 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5915 pDestMacAddress);
5916#else
5917 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
5918#endif
5919}
5920
5921void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
5922 bool enable)
5923{
5924#ifndef WLAN_FEATURE_MBSSID
5925 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
5926#endif
5927
5928 ENTER();
5929
5930 hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"),
5931 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
5932
5933#ifdef WLAN_FEATURE_MBSSID
5934 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
5935 (bool) enable);
5936#else
5937 wlansap_set_counter_measure(p_cds_context, (bool) enable);
5938#endif
5939}
5940
5941/**
5942 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
5943 * @hdd_ctx: HDD Context
5944 *
5945 * API to find if there is any STA or P2P-Client is connected
5946 *
5947 * Return: true if connected; false otherwise
5948 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305949QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005950{
5951 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
5952}
5953
5954#ifdef WLAN_FEATURE_LPSS
5955int wlan_hdd_gen_wlan_status_pack(struct wlan_status_data *data,
5956 hdd_adapter_t *adapter,
5957 hdd_station_ctx_t *pHddStaCtx,
5958 uint8_t is_on, uint8_t is_connected)
5959{
5960 hdd_context_t *hdd_ctx = NULL;
5961 uint8_t buflen = WLAN_SVC_COUNTRY_CODE_LEN;
5962
5963 if (!data) {
5964 hddLog(LOGE, FL("invalid data pointer"));
5965 return -EINVAL;
5966 }
5967 if (!adapter) {
5968 if (is_on) {
5969 /* no active interface */
5970 data->lpss_support = 0;
5971 data->is_on = is_on;
5972 return 0;
5973 }
5974 hddLog(LOGE, FL("invalid adapter pointer"));
5975 return -EINVAL;
5976 }
5977
5978 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelamc11bb222016-01-27 18:57:10 +05305979 if (hdd_ctx->lpss_support && hdd_ctx->config->enable_lpass_support)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980 data->lpss_support = 1;
5981 else
5982 data->lpss_support = 0;
5983 data->numChannels = WLAN_SVC_MAX_NUM_CHAN;
5984 sme_get_cfg_valid_channels(hdd_ctx->hHal, data->channel_list,
5985 &data->numChannels);
5986 sme_get_country_code(hdd_ctx->hHal, data->country_code, &buflen);
5987 data->is_on = is_on;
5988 data->vdev_id = adapter->sessionId;
5989 data->vdev_mode = adapter->device_mode;
5990 if (pHddStaCtx) {
5991 data->is_connected = is_connected;
5992 data->rssi = adapter->rssi;
5993 data->freq =
5994 cds_chan_to_freq(pHddStaCtx->conn_info.operationChannel);
5995 if (WLAN_SVC_MAX_SSID_LEN >=
5996 pHddStaCtx->conn_info.SSID.SSID.length) {
5997 data->ssid_len = pHddStaCtx->conn_info.SSID.SSID.length;
5998 memcpy(data->ssid,
5999 pHddStaCtx->conn_info.SSID.SSID.ssId,
6000 pHddStaCtx->conn_info.SSID.SSID.length);
6001 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05306002 if (QDF_MAC_ADDR_SIZE >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006003 sizeof(pHddStaCtx->conn_info.bssId))
6004 memcpy(data->bssid, pHddStaCtx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306005 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006006 }
6007 return 0;
6008}
6009
6010int wlan_hdd_gen_wlan_version_pack(struct wlan_version_data *data,
6011 uint32_t fw_version,
6012 uint32_t chip_id, const char *chip_name)
6013{
6014 if (!data) {
6015 hddLog(LOGE, FL("invalid data pointer"));
6016 return -EINVAL;
6017 }
6018
6019 data->chip_id = chip_id;
6020 strlcpy(data->chip_name, chip_name, WLAN_SVC_MAX_STR_LEN);
6021 if (strncmp(chip_name, "Unknown", 7))
6022 strlcpy(data->chip_from, "Qualcomm", WLAN_SVC_MAX_STR_LEN);
6023 else
6024 strlcpy(data->chip_from, "Unknown", WLAN_SVC_MAX_STR_LEN);
6025 strlcpy(data->host_version, QWLAN_VERSIONSTR, WLAN_SVC_MAX_STR_LEN);
6026 scnprintf(data->fw_version, WLAN_SVC_MAX_STR_LEN, "%d.%d.%d.%d",
6027 (fw_version & 0xf0000000) >> 28,
6028 (fw_version & 0xf000000) >> 24,
6029 (fw_version & 0xf00000) >> 20, (fw_version & 0x7fff));
6030 return 0;
6031}
6032#endif
6033
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006034/**
6035 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
6036 * @adapter: HDD adapter pointer
6037 *
6038 * This function loop through each adapter and disable roaming on each STA
6039 * device mode except the input adapter.
6040 *
6041 * Note: On the input adapter roaming is not enabled yet hence no need to
6042 * disable.
6043 *
6044 * Return: None
6045 */
6046void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
6047{
6048 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6049 hdd_adapter_t *adapterIdx = NULL;
6050 hdd_adapter_list_node_t *adapterNode = NULL;
6051 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306052 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006053
6054 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6055 hdd_ctx->config->isRoamOffloadScanEnabled &&
6056 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6057 cds_is_sta_active_connection_exists()) {
6058 hddLog(LOG1, FL("Connect received on STA sessionId(%d)"),
6059 adapter->sessionId);
6060 /*
6061 * Loop through adapter and disable roaming for each STA device
6062 * mode except the input adapter.
6063 */
6064 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6065
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306066 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006067 adapterIdx = adapterNode->pAdapter;
6068
6069 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6070 && adapter->sessionId != adapterIdx->sessionId) {
6071 hddLog(LOG1,
6072 FL("Disable Roaming on sessionId(%d)"),
6073 adapterIdx->sessionId);
6074 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
6075 (adapterIdx),
6076 adapterIdx->sessionId, 0);
6077 }
6078
6079 status = hdd_get_next_adapter(hdd_ctx,
6080 adapterNode,
6081 &pNext);
6082 adapterNode = pNext;
6083 }
6084 }
6085}
6086
6087/**
6088 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
6089 * @adapter: HDD adapter pointer
6090 *
6091 * This function loop through each adapter and enable roaming on each STA
6092 * device mode except the input adapter.
6093 * Note: On the input adapter no need to enable roaming because link got
6094 * disconnected on this.
6095 *
6096 * Return: None
6097 */
6098void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
6099{
6100 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6101 hdd_adapter_t *adapterIdx = NULL;
6102 hdd_adapter_list_node_t *adapterNode = NULL;
6103 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306104 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006105
6106 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6107 hdd_ctx->config->isRoamOffloadScanEnabled &&
6108 WLAN_HDD_INFRA_STATION == adapter->device_mode &&
6109 cds_is_sta_active_connection_exists()) {
6110 hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"),
6111 adapter->sessionId);
6112 /*
6113 * Loop through adapter and enable roaming for each STA device
6114 * mode except the input adapter.
6115 */
6116 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6117
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306118 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006119 adapterIdx = adapterNode->pAdapter;
6120
6121 if (WLAN_HDD_INFRA_STATION == adapterIdx->device_mode
6122 && adapter->sessionId != adapterIdx->sessionId) {
6123 hddLog(LOG1,
6124 FL("Enabling Roaming on sessionId(%d)"),
6125 adapterIdx->sessionId);
6126 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
6127 (adapterIdx),
6128 adapterIdx->sessionId,
6129 REASON_CONNECT);
6130 }
6131
6132 status = hdd_get_next_adapter(hdd_ctx,
6133 adapterNode,
6134 &pNext);
6135 adapterNode = pNext;
6136 }
6137 }
6138}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006139
6140void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
6141{
6142 struct sk_buff *skb;
6143 struct nlmsghdr *nlh;
6144 tAniMsgHdr *ani_hdr;
6145 void *nl_data = NULL;
6146 int flags = GFP_KERNEL;
6147
6148 if (in_interrupt() || irqs_disabled() || in_atomic())
6149 flags = GFP_ATOMIC;
6150
6151 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
6152
6153 if (skb == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306154 hddLog(QDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006155 return;
6156 }
6157
6158 nlh = (struct nlmsghdr *)skb->data;
6159 nlh->nlmsg_pid = 0; /* from kernel */
6160 nlh->nlmsg_flags = 0;
6161 nlh->nlmsg_seq = 0;
6162 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
6163
6164 ani_hdr = NLMSG_DATA(nlh);
6165 ani_hdr->type = type;
6166
6167 switch (type) {
6168 case WLAN_SVC_FW_CRASHED_IND:
6169 case WLAN_SVC_LTE_COEX_IND:
6170#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6171 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
6172#endif
6173 ani_hdr->length = 0;
6174 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
6175 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
6176 break;
6177 case WLAN_SVC_WLAN_STATUS_IND:
6178 case WLAN_SVC_WLAN_VERSION_IND:
6179 case WLAN_SVC_DFS_CAC_START_IND:
6180 case WLAN_SVC_DFS_CAC_END_IND:
6181 case WLAN_SVC_DFS_RADAR_DETECT_IND:
6182 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
6183 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08006184 case WLAN_SVC_WLAN_TP_TX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006185 ani_hdr->length = len;
6186 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
6187 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
6188 memcpy(nl_data, data, len);
6189 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
6190 break;
6191
6192 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306193 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006194 FL("WLAN SVC: Attempt to send unknown nlink message %d"),
6195 type);
6196 kfree_skb(skb);
6197 return;
6198 }
6199
6200 nl_srv_bcast(skb);
6201
6202 return;
6203}
6204
6205#ifdef WLAN_FEATURE_LPSS
6206void wlan_hdd_send_status_pkg(hdd_adapter_t *adapter,
6207 hdd_station_ctx_t *pHddStaCtx,
6208 uint8_t is_on, uint8_t is_connected)
6209{
6210 int ret = 0;
6211 struct wlan_status_data data;
6212
Anurag Chouhan6d760662016-02-20 16:05:43 +05306213 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006214 return;
6215
6216 memset(&data, 0, sizeof(struct wlan_status_data));
6217 if (is_on)
6218 ret = wlan_hdd_gen_wlan_status_pack(&data, adapter, pHddStaCtx,
6219 is_on, is_connected);
6220 if (!ret)
6221 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_STATUS_IND,
6222 &data,
6223 sizeof(struct wlan_status_data));
6224}
6225
6226void wlan_hdd_send_version_pkg(uint32_t fw_version,
6227 uint32_t chip_id, const char *chip_name)
6228{
6229 int ret = 0;
6230 struct wlan_version_data data;
6231#ifdef CONFIG_CNSS
6232 struct cnss_platform_cap cap;
6233
6234 ret = cnss_get_platform_cap(&cap);
6235 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306236 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006237 FL("platform capability info from CNSS not available"));
6238 return;
6239 }
6240
6241 if (!(cap.cap_flag & CNSS_HAS_UART_ACCESS))
6242 return;
6243#endif
6244
Anurag Chouhan6d760662016-02-20 16:05:43 +05306245 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006246 return;
6247
6248 memset(&data, 0, sizeof(struct wlan_version_data));
6249 ret =
6250 wlan_hdd_gen_wlan_version_pack(&data, fw_version, chip_id,
6251 chip_name);
6252 if (!ret)
6253 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_VERSION_IND,
6254 &data,
6255 sizeof(struct wlan_version_data));
6256}
6257
6258void wlan_hdd_send_all_scan_intf_info(hdd_context_t *hdd_ctx)
6259{
6260 hdd_adapter_t *pDataAdapter = NULL;
6261 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6262 bool scan_intf_found = false;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306263 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006264
6265 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306266 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006267 FL("NULL pointer for hdd_ctx"));
6268 return;
6269 }
6270
6271 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306272 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006273 pDataAdapter = adapterNode->pAdapter;
6274 if (pDataAdapter) {
6275 if (pDataAdapter->device_mode == WLAN_HDD_INFRA_STATION
6276 || pDataAdapter->device_mode == WLAN_HDD_P2P_CLIENT
6277 || pDataAdapter->device_mode ==
6278 WLAN_HDD_P2P_DEVICE) {
6279 scan_intf_found = true;
6280 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1,
6281 0);
6282 }
6283 }
6284 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6285 adapterNode = pNext;
6286 }
6287
6288 if (!scan_intf_found)
6289 wlan_hdd_send_status_pkg(pDataAdapter, NULL, 1, 0);
6290}
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006291#else
6292static inline void wlan_hdd_send_status_pkg(hdd_adapter_t *pAdapter,
6293 hdd_station_ctx_t *pHddStaCtx,
6294 uint8_t is_on, uint8_t is_connected)
6295{
6296 return;
6297}
6298
6299static inline void wlan_hdd_send_version_pkg(uint32_t fw_version, uint32_t
6300 chip_id, const char *chip_name)
6301{
6302 return;
6303}
6304
6305static inline void wlan_hdd_send_all_scan_intf_info(hdd_context_t *pHddCtx)
6306{
6307 return;
6308}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006309#endif
6310
6311#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6312void wlan_hdd_auto_shutdown_cb(void)
6313{
6314 hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event.."));
6315 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
6316}
6317
6318void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
6319{
6320 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306321 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006322 hdd_adapter_t *adapter;
6323 bool ap_connected = false, sta_connected = false;
6324 tHalHandle hal_handle;
6325
6326 hal_handle = hdd_ctx->hHal;
6327 if (hal_handle == NULL)
6328 return;
6329
6330 if (hdd_ctx->config->WlanAutoShutdown == 0)
6331 return;
6332
6333 if (enable == false) {
6334 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306335 QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006336 hddLog(LOGE,
6337 FL("Failed to stop wlan auto shutdown timer"));
6338 }
6339 return;
6340 }
6341
6342 /* To enable shutdown timer check conncurrency */
6343 if (cds_concurrent_open_sessions_running()) {
6344 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6345
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306346 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006347 adapter = adapterNode->pAdapter;
6348 if (adapter
6349 && adapter->device_mode ==
6350 WLAN_HDD_INFRA_STATION) {
6351 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6352 conn_info.connState ==
6353 eConnectionState_Associated) {
6354 sta_connected = true;
6355 break;
6356 }
6357 }
6358 if (adapter
6359 && adapter->device_mode == WLAN_HDD_SOFTAP) {
6360 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
6361 bApActive == true) {
6362 ap_connected = true;
6363 break;
6364 }
6365 }
6366 status = hdd_get_next_adapter(hdd_ctx,
6367 adapterNode,
6368 &pNext);
6369 adapterNode = pNext;
6370 }
6371 }
6372
6373 if (ap_connected == true || sta_connected == true) {
6374 hddLog(LOG1,
6375 FL("CC Session active. Shutdown timer not enabled"));
6376 return;
6377 } else {
6378 if (sme_set_auto_shutdown_timer(hal_handle,
6379 hdd_ctx->config->
6380 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306381 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006382 hddLog(LOGE,
6383 FL("Failed to start wlan auto shutdown timer"));
6384 else
6385 hddLog(LOG1,
6386 FL("Auto Shutdown timer for %d seconds enabled"),
6387 hdd_ctx->config->WlanAutoShutdown);
6388
6389 }
6390}
6391#endif
6392
6393hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
6394 bool check_start_bss)
6395{
6396 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
6397 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306398 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006399 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
6400
6401 con_sap_adapter = NULL;
6402
6403 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306404 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006405 adapter = adapterNode->pAdapter;
6406 if (adapter && ((adapter->device_mode == WLAN_HDD_SOFTAP) ||
6407 (adapter->device_mode == WLAN_HDD_P2P_GO)) &&
6408 adapter != this_sap_adapter) {
6409 if (check_start_bss) {
6410 if (test_bit(SOFTAP_BSS_STARTED,
6411 &adapter->event_flags)) {
6412 con_sap_adapter = adapter;
6413 break;
6414 }
6415 } else {
6416 con_sap_adapter = adapter;
6417 break;
6418 }
6419 }
6420 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
6421 adapterNode = pNext;
6422 }
6423
6424 return con_sap_adapter;
6425}
6426
6427#ifdef MSM_PLATFORM
6428void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
6429{
6430 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6431
Anurag Chouhan210db072016-02-22 18:42:15 +05306432 if (QDF_TIMER_STATE_RUNNING ==
6433 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006434 return;
6435
Anurag Chouhan210db072016-02-22 18:42:15 +05306436 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006437 hdd_ctx->config->busBandwidthComputeInterval);
6438}
6439
6440void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
6441{
6442 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306443 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006444 bool can_stop = true;
6445 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6446
Anurag Chouhan210db072016-02-22 18:42:15 +05306447 if (QDF_TIMER_STATE_RUNNING !=
6448 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006449 /* trying to stop timer, when not running is not good */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306450 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006451 FL("bus band width compute timer is not running"));
6452 return;
6453 }
6454
6455 if (cds_concurrent_open_sessions_running()) {
6456 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6457
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306458 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006459 adapter = adapterNode->pAdapter;
6460 if (adapter
6461 && (adapter->device_mode == WLAN_HDD_INFRA_STATION
6462 || adapter->device_mode == WLAN_HDD_P2P_CLIENT)
6463 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
6464 conn_info.connState ==
6465 eConnectionState_Associated) {
6466 can_stop = false;
6467 break;
6468 }
6469 if (adapter
6470 && (adapter->device_mode == WLAN_HDD_SOFTAP
6471 || adapter->device_mode == WLAN_HDD_P2P_GO)
6472 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
6473 true) {
6474 can_stop = false;
6475 break;
6476 }
6477 status = hdd_get_next_adapter(hdd_ctx,
6478 adapterNode,
6479 &pNext);
6480 adapterNode = pNext;
6481 }
6482 }
6483
6484 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05306485 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006486}
6487#endif
6488
6489/**
6490 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
6491 * and sta's operating channel.
6492 * @sta_adapter: Describe the first argument to foobar.
6493 * @ap_adapter: Describe the second argument to foobar.
6494 * @roam_profile: Roam profile of AP to which STA wants to connect.
6495 * @concurrent_chnl_same: If both SAP and STA channels are same then
6496 * set this flag to true else false.
6497 *
6498 * This function checks the sap's operating channel and sta's operating channel.
6499 * if both are same then it will return false else it will restart the sap in
6500 * sta's channel and return true.
6501 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306502 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006503 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306504QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006505 hdd_adapter_t *ap_adapter,
6506 tCsrRoamProfile *roam_profile,
6507 tScanResultHandle *scan_cache,
6508 bool *concurrent_chnl_same)
6509{
6510 hdd_ap_ctx_t *hdd_ap_ctx;
6511 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306512 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006513 device_mode_t device_mode = ap_adapter->device_mode;
6514 *concurrent_chnl_same = true;
6515
6516 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6517 status =
6518 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
6519 roam_profile,
6520 scan_cache,
6521 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306522 if ((QDF_STATUS_SUCCESS == status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006523 if ((WLAN_HDD_SOFTAP == device_mode) &&
6524 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
6525 if (hdd_ap_ctx->operatingChannel != channel_id) {
6526 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306527 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006528 FL("channels are different"));
6529 }
6530 } else if ((WLAN_HDD_P2P_GO == device_mode) &&
6531 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
6532 if (hdd_ap_ctx->operatingChannel != channel_id) {
6533 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306534 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006535 FL("channels are different"));
6536 }
6537 }
6538 } else {
6539 /*
6540 * Lets handle worst case scenario here, Scan cache lookup is
6541 * failed so we have to stop the SAP to avoid any channel
6542 * discrepancy between SAP's channel and STA's channel.
6543 * Return the status as failure so caller function could know
6544 * that scan look up is failed.
6545 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306546 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006547 FL("Finding AP from scan cache failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306548 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006549 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306550 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006551}
6552
6553#ifdef WLAN_FEATURE_MBSSID
6554/**
6555 * wlan_hdd_stop_sap() - This function stops bss of SAP.
6556 * @ap_adapter: SAP adapter
6557 *
6558 * This function will process the stopping of sap adapter.
6559 *
6560 * Return: None
6561 */
6562void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
6563{
6564 hdd_ap_ctx_t *hdd_ap_ctx;
6565 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306566 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006567 hdd_context_t *hdd_ctx;
6568#ifdef CFG80211_DEL_STA_V2
6569 struct station_del_parameters delStaParams;
6570#endif
6571
6572 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306573 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006574 FL("ap_adapter is NULL here"));
6575 return;
6576 }
6577
6578 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6579 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6580 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306581 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006582 FL("HDD context is not valid"));
6583 return;
6584 }
6585 mutex_lock(&hdd_ctx->sap_lock);
6586 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
6587#ifdef CFG80211_DEL_STA_V2
6588 delStaParams.mac = NULL;
6589 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
6590 delStaParams.reason_code = eCsrForcedDeauthSta;
6591 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6592 ap_adapter->dev,
6593 &delStaParams);
6594#else
6595 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy,
6596 ap_adapter->dev,
6597 NULL);
6598#endif
6599 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
6600 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306601 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602 FL("Now doing SAP STOPBSS"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306603 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306604 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006605 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05306606 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306607 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306609 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006610 mutex_unlock(&hdd_ctx->sap_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306611 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006612 FL("SAP Stop Failed"));
6613 return;
6614 }
6615 }
6616 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08006617 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618 ap_adapter->sessionId);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306619 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006620 FL("SAP Stop Success"));
6621 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306622 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006623 FL("Can't stop ap because its not started"));
6624 }
6625 mutex_unlock(&hdd_ctx->sap_lock);
6626 return;
6627}
6628
6629/**
6630 * wlan_hdd_start_sap() - this function starts bss of SAP.
6631 * @ap_adapter: SAP adapter
6632 *
6633 * This function will process the starting of sap adapter.
6634 *
6635 * Return: None
6636 */
6637void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
6638{
6639 hdd_ap_ctx_t *hdd_ap_ctx;
6640 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05306641 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006642 hdd_context_t *hdd_ctx;
6643 tsap_Config_t *sap_config;
6644
6645 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306646 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006647 FL("ap_adapter is NULL here"));
6648 return;
6649 }
6650
Peng Xuf5d60c82015-10-02 17:17:03 -07006651 if (WLAN_HDD_SOFTAP != ap_adapter->device_mode) {
6652 hdd_err("SoftAp role has not been enabled");
6653 return;
6654 }
6655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006656 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
6657 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6658 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
6659 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
6660
6661 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306662 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006663 FL("HDD context is not valid"));
6664 return;
6665 }
6666 mutex_lock(&hdd_ctx->sap_lock);
6667 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
6668 goto end;
6669
6670 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
6671 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
6672 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
6673 goto end;
6674 }
6675
6676 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
6677 &hdd_ap_ctx->sapConfig,
6678 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306679 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006680 goto end;
6681
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306682 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006683 FL("Waiting for SAP to start"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306684 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006685 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05306686 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306687 hddLog(QDF_TRACE_LEVEL_ERROR, FL("SAP Start failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006688 goto end;
6689 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306690 hddLog(QDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006691 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006692 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006693 ap_adapter->sessionId);
6694 hostapd_state->bCommit = true;
6695
6696end:
6697 mutex_unlock(&hdd_ctx->sap_lock);
6698 return;
6699}
6700#endif
6701
6702/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703 * hdd_get_fw_version() - Get FW version
6704 * @hdd_ctx: pointer to HDD context.
6705 * @major_spid: FW version - major spid.
6706 * @minor_spid: FW version - minor spid
6707 * @ssid: FW version - ssid
6708 * @crmid: FW version - crmid
6709 *
6710 * This function is called to get the firmware build version stored
6711 * as part of the HDD context
6712 *
6713 * Return: None
6714 */
6715void hdd_get_fw_version(hdd_context_t *hdd_ctx,
6716 uint32_t *major_spid, uint32_t *minor_spid,
6717 uint32_t *siid, uint32_t *crmid)
6718{
6719 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
6720 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
6721 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
6722 *crmid = hdd_ctx->target_fw_version & 0x7fff;
6723}
6724
6725#ifdef QCA_CONFIG_SMP
6726/**
6727 * wlan_hdd_get_cpu() - get cpu_index
6728 *
6729 * Return: cpu_index
6730 */
6731int wlan_hdd_get_cpu(void)
6732{
6733 int cpu_index = get_cpu();
6734 put_cpu();
6735 return cpu_index;
6736}
6737#endif
6738
6739/**
6740 * hdd_get_fwpath() - get framework path
6741 *
6742 * This function is used to get the string written by
6743 * userspace to start the wlan driver
6744 *
6745 * Return: string
6746 */
6747const char *hdd_get_fwpath(void)
6748{
6749 return fwpath.string;
6750}
6751
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006752/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006753 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006754 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006755 * This function initilizes CDS global context with the help of cds_init. This
6756 * has to be the first function called after probe to get a valid global
6757 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006758 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006759 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006760 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006761int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006762{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006763 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006764 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006765
6766#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6767 wlan_logging_sock_init_svc();
6768#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006769 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006770
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006771 if (p_cds_context == NULL) {
6772 hdd_alert("Failed to allocate CDS context");
6773 ret = -ENOMEM;
6774 goto err_out;
6775 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006776
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006777 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006778
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006779err_out:
6780 return ret;
6781}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006782
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006783/**
6784 * hdd_deinit() - Deinitialize Driver
6785 *
6786 * This function frees CDS global context with the help of cds_deinit. This
6787 * has to be the last function call in remove callback to free the global
6788 * context.
6789 */
6790void hdd_deinit(void)
6791{
6792 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006793
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006794#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
6795 wlan_logging_sock_deinit_svc();
6796#endif
6797}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006798
6799#ifdef QCA_WIFI_3_0_ADRASTEA
6800#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
6801#else
6802#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
6803#endif
6804
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006805/**
6806 * __hdd_module_init - Module init helper
6807 *
6808 * Module init helper function used by both module and static driver.
6809 *
6810 * Return: 0 for success, errno on failure
6811 */
6812static int __hdd_module_init(void)
6813{
6814 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006815
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006816 pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
6817 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006818
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306819 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006820
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006821 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006822
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006823 ret = wlan_hdd_register_driver();
6824 if (ret) {
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006825 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006826 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006827 }
6828
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306829 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006830
6831 return 0;
6832out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306833 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006834 return ret;
6835}
6836
6837/**
6838 * __hdd_module_exit - Module exit helper
6839 *
6840 * Module exit helper function used by both module and static driver.
6841 */
6842static void __hdd_module_exit(void)
6843{
6844 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
6845 QWLAN_VERSIONSTR);
6846
6847 wlan_hdd_unregister_driver();
6848
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306849 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006850
6851 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006852}
6853
6854/**
6855 * hdd_module_init() - Init Function
6856 *
6857 * This is the driver entry point (invoked when module is loaded using insmod)
6858 *
6859 * Return: 0 for success, non zero for failure
6860 */
6861#ifdef MODULE
6862static int __init hdd_module_init(void)
6863{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006864 return __hdd_module_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006865}
6866#else /* #ifdef MODULE */
6867static int __init hdd_module_init(void)
6868{
6869 /* Driver initialization is delayed to fwpath_changed_handler */
6870 return 0;
6871}
6872#endif /* #ifdef MODULE */
6873
6874/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006875 * hdd_module_exit() - Exit function
6876 *
6877 * This is the driver exit point (invoked when module is unloaded using rmmod)
6878 *
6879 * Return: None
6880 */
6881static void __exit hdd_module_exit(void)
6882{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006883 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006884}
6885
6886#ifdef MODULE
6887static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6888{
6889 return param_set_copystring(kmessage, kp);
6890}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006891#else /* #ifdef MODULE */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006892
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006893/**
6894 * kickstart_driver() - driver entry point
6895 *
6896 * This is the driver entry point
6897 * - delayed driver initialization when driver is statically linked
6898 * - invoked when module parameter fwpath is modified from userspace to signal
6899 * initializing the WLAN driver or when con_mode is modified from userspace
6900 * to signal a switch in operating mode
6901 *
6902 * Return: 0 for success, non zero for failure
6903 */
6904static int kickstart_driver(void)
6905{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006906 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006907
6908 if (!wlan_hdd_inited) {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006909 ret = __hdd_module_init();
6910 wlan_hdd_inited = ret ? 0 : 1;
6911
6912 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006913 }
6914
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006915 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006916
6917 msleep(200);
6918
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006919 ret = __hdd_module_init();
6920
6921 wlan_hdd_inited = ret ? 0 : 1;
6922
6923 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006924}
6925
6926/**
6927 * fwpath_changed_handler() - Handler Function
6928 *
6929 * Handle changes to the fwpath parameter
6930 *
6931 * Return: 0 for success, non zero for failure
6932 */
6933static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
6934{
6935 int ret;
6936
6937 ret = param_set_copystring(kmessage, kp);
6938 if (0 == ret)
6939 ret = kickstart_driver();
6940 return ret;
6941}
6942
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006943#ifdef QCA_WIFI_FTM
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006944/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006945 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006946 *
6947 * Handler function for module param con_mode when it is changed by userspace
6948 * Dynamically linked - do nothing
6949 * Statically linked - exit and init driver, as in rmmod and insmod
6950 *
6951 * Return -
6952 */
6953static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
6954{
6955 int ret;
6956
6957 ret = param_set_int(kmessage, kp);
6958 if (0 == ret)
6959 ret = kickstart_driver();
6960 return ret;
6961}
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006962#endif /* QCA_WIFI_FTM */
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006963#endif /* #ifdef MODULE */
6964
6965/**
6966 * hdd_get_conparam() - driver exit point
6967 *
6968 * This is the driver exit point (invoked when module is unloaded using rmmod)
6969 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05306970 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006971 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306972enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006973{
Anurag Chouhan6d760662016-02-20 16:05:43 +05306974 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006975}
6976
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006977void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006978{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08006979 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08006980}
6981
Komal Seelamc11bb222016-01-27 18:57:10 +05306982#ifdef WLAN_FEATURE_LPSS
6983static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6984{
6985 return hdd_ctx->config->enable_lpass_support;
6986}
6987#else
6988static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
6989{
6990 return false;
6991}
6992#endif
6993
6994/**
Komal Seelamec702b02016-02-24 18:42:16 +05306995 * hdd_update_ol_config - API to update ol configuration parameters
6996 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05306997 *
Komal Seelamc11bb222016-01-27 18:57:10 +05306998 * Return: void
6999 */
Komal Seelamec702b02016-02-24 18:42:16 +05307000static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05307001{
Komal Seelamec702b02016-02-24 18:42:16 +05307002 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307003 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05307004
Komal Seelamec702b02016-02-24 18:42:16 +05307005 if (!ol_ctx)
7006 return;
7007
7008 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
7009 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
7010 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
7011 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
7012 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
7013
7014 ol_init_ini_config(ol_ctx, &cfg);
7015}
7016
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007017#ifdef FEATURE_RUNTIME_PM
7018/**
7019 * hdd_populate_runtime_cfg() - populate runtime configuration
7020 * @hdd_ctx: hdd context
7021 * @cfg: pointer to the configuration memory being populated
7022 *
7023 * Return: void
7024 */
7025static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7026 struct hif_config_info *cfg)
7027{
7028 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
7029 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
7030}
7031#else
7032static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7033 struct hif_config_info *cfg)
7034{
7035}
7036#endif
7037
Komal Seelamec702b02016-02-24 18:42:16 +05307038/**
7039 * hdd_update_hif_config - API to update HIF configuration parameters
7040 * @hdd_ctx: HDD Context
7041 *
7042 * Return: void
7043 */
7044static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
7045{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307046 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05307047 struct hif_config_info cfg;
7048
7049 if (!scn)
7050 return;
7051
7052 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007053 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05307054 hif_init_ini_config(scn, &cfg);
7055}
7056
7057/**
7058 * hdd_update_config() - Initialize driver per module ini parameters
7059 * @hdd_ctx: HDD Context
7060 *
7061 * API is used to initialize all driver per module configuration parameters
7062 * Return: void
7063 */
7064void hdd_update_config(hdd_context_t *hdd_ctx)
7065{
7066 hdd_update_ol_config(hdd_ctx);
7067 hdd_update_hif_config(hdd_ctx);
Komal Seelamc11bb222016-01-27 18:57:10 +05307068}
7069
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007070/* Register the module init/exit functions */
7071module_init(hdd_module_init);
7072module_exit(hdd_module_exit);
7073
7074MODULE_LICENSE("Dual BSD/GPL");
7075MODULE_AUTHOR("Qualcomm Atheros, Inc.");
7076MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
7077
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007078#if !defined(MODULE) && defined(QCA_WIFI_FTM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007079module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
7080 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007081#else
7082module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007083#endif
7084
7085module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
7086 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
7087
7088module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
7089
7090module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
7091
7092module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);