blob: 28739985225810a7c2e4adc040901e1e1e030c53 [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"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070058#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053059#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053060#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070061#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062
63#include <net/addrconf.h>
64#include <linux/wireless.h>
65#include <net/cfg80211.h>
66#include <linux/inetdevice.h>
67#include <net/addrconf.h>
68#include "wlan_hdd_cfg80211.h"
69#include "wlan_hdd_ext_scan.h"
70#include "wlan_hdd_p2p.h"
71#include <linux/rtnetlink.h>
72#include "sap_api.h"
73#include <linux/semaphore.h>
74#include <linux/ctype.h>
75#include <linux/compat.h>
76#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080077#include <soc/qcom/subsystem_restart.h>
78#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080079#include <wlan_hdd_hostapd.h>
80#include <wlan_hdd_softap_tx_rx.h>
81#include "cfg_api.h"
82#include "qwlan_version.h"
83#include "wma_types.h"
84#include "wlan_hdd_tdls.h"
85#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053086#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080087#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070089#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080090#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091#include "wlan_hdd_nan.h"
92#include "wlan_hdd_debugfs.h"
93#include "wlan_hdd_driver_ops.h"
94#include "epping_main.h"
95#include "wlan_hdd_memdump.h"
96
97#include <wlan_hdd_ipa.h>
98#include "hif.h"
99#include "wma.h"
100#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700101#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800102#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530103#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700104#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530105#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700106#include "wlan_hdd_lpass.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107
108#ifdef MODULE
109#define WLAN_MODULE_NAME module_name(THIS_MODULE)
110#else
111#define WLAN_MODULE_NAME "wlan"
112#endif
113
114#ifdef TIMER_MANAGER
115#define TIMER_MANAGER_STR " +TIMER_MANAGER"
116#else
117#define TIMER_MANAGER_STR ""
118#endif
119
120#ifdef MEMORY_DEBUG
121#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
122#else
123#define MEMORY_DEBUG_STR ""
124#endif
125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800126/* the Android framework expects this param even though we don't use it */
127#define BUF_LEN 20
128static char fwpath_buffer[BUF_LEN];
129static struct kparam_string fwpath = {
130 .string = fwpath_buffer,
131 .maxlen = BUF_LEN,
132};
133
134static char *country_code;
135static int enable_11d = -1;
136static int enable_dfs_chan_scan = -1;
137
138#ifndef MODULE
139static int wlan_hdd_inited;
140#endif
141
142/*
143 * spinlock for synchronizing asynchronous request/response
144 * (full description of use in wlan_hdd_main.h)
145 */
146DEFINE_SPINLOCK(hdd_context_lock);
147
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800148#define WLAN_NLINK_CESIUM 30
149
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530150static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
152#define WOW_MAX_FILTER_LISTS 1
153#define WOW_MAX_FILTERS_PER_LIST 4
154#define WOW_MIN_PATTERN_SIZE 6
155#define WOW_MAX_PATTERN_SIZE 64
156
157#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
158static const struct wiphy_wowlan_support wowlan_support_reg_init = {
159 .flags = WIPHY_WOWLAN_ANY |
160 WIPHY_WOWLAN_MAGIC_PKT |
161 WIPHY_WOWLAN_DISCONNECT |
162 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
163 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
164 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
165 WIPHY_WOWLAN_4WAY_HANDSHAKE |
166 WIPHY_WOWLAN_RFKILL_RELEASE,
167 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
168 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
169 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
170};
171#endif
172
173/* internal function declaration */
174
175struct sock *cesium_nl_srv_sock;
176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
178void wlan_hdd_auto_shutdown_cb(void);
179#endif
180
181/**
182 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
183 * @vdev_id: vdev_id
184 * @action: action type
185 * @reason: reason type
186 *
187 * Return: none
188 */
189void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
190 enum netif_action_type action, enum netif_reason_type reason)
191{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530192 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193 hdd_adapter_t *adapter;
194
195 if (!hdd_ctx) {
196 hdd_err("hdd ctx is NULL");
197 return;
198 }
199 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
200
201 wlan_hdd_netif_queue_control(adapter, action, reason);
202 return;
203}
204
205/*
206 * Store WLAN driver version info in a global variable such that crash debugger
207 * can extract it from driver debug symbol and crashdump for post processing
208 */
209uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
210
211/**
212 * hdd_device_mode_to_string() - return string conversion of device mode
213 * @device_mode: device mode
214 *
215 * This utility function helps log string conversion of device mode.
216 *
217 * Return: string conversion of device mode, if match found;
218 * "Unknown" otherwise.
219 */
220const char *hdd_device_mode_to_string(uint8_t device_mode)
221{
222 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800223 CASE_RETURN_STRING(QDF_STA_MODE);
224 CASE_RETURN_STRING(QDF_SAP_MODE);
225 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
226 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
227 CASE_RETURN_STRING(QDF_FTM_MODE);
228 CASE_RETURN_STRING(QDF_IBSS_MODE);
229 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
230 CASE_RETURN_STRING(QDF_OCB_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 default:
232 return "Unknown";
233 }
234}
235
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530236/**
237 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
238 * @adapter: HDD adapter
239 * @chan_number: Channel number
240 * @chan_bw: Bandwidth
241 *
242 * Checks if the given bandwidth is valid for the given channel number.
243 *
244 * Return: 0 for success, non-zero for failure
245 */
246int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
247 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800248 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530249{
250 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
251 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
252 bool found = false;
253 tHalHandle hal;
254
255 hal = WLAN_HDD_GET_HAL_CTX(adapter);
256 if (!hal) {
257 hdd_err("Invalid HAL context");
258 return -EINVAL;
259 }
260
261 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
262 hdd_err("No valid channel list");
263 return -EOPNOTSUPP;
264 }
265
266 for (i = 0; i < len; i++) {
267 if (chan[i] == chan_number) {
268 found = true;
269 break;
270 }
271 }
272
273 if (found == false) {
274 hdd_err("Channel not in driver's valid channel list");
275 return -EOPNOTSUPP;
276 }
277
278 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
279 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
280 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
281 return -EINVAL;
282 }
283
284 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
285 if (chan_bw == CH_WIDTH_80MHZ) {
286 hdd_err("BW80 not possible in 2.4GHz band");
287 return -EINVAL;
288 }
289 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
290 (chan_bw != CH_WIDTH_MAX)) {
291 hdd_err("Only BW20 possible on channel 14");
292 return -EINVAL;
293 }
294 }
295
296 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
297 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
298 (chan_bw != CH_WIDTH_MAX)) {
299 hdd_err("Only BW20 possible on channel 165");
300 return -EINVAL;
301 }
302 }
303
304 return 0;
305}
306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800307static int __hdd_netdev_notifier_call(struct notifier_block *nb,
308 unsigned long state, void *data)
309{
310#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
311 struct netdev_notifier_info *dev_notif_info = data;
312 struct net_device *dev = dev_notif_info->dev;
313#else
314 struct net_device *dev = data;
315#endif
316 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
317 hdd_context_t *hdd_ctx;
318
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800319 ENTER_DEV(dev);
320
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321 /* 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 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800435enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530436{
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:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800451 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530452 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800453 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530454 default:
455 hdd_err("Invalid channel width %d, setting to default",
456 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800457 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530458 }
459}
460
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530461/* wlan_hdd_find_opclass() - Find operating class for a channel
462 * @hal: handler to HAL
463 * @channel: channel id
464 * @bw_offset: bandwidth offset
465 *
466 * Function invokes sme api to find the operating class
467 *
468 * Return: operating class
469 */
470uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
471 uint8_t bw_offset)
472{
473 uint8_t opclass = 0;
474
475 sme_get_opclass(hal, channel, bw_offset, &opclass);
476 return opclass;
477}
478
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800479/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530480 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481 * @moduleId: Module whose trace level is being configured
482 * @bitmask: Bitmask of log levels to be enabled
483 *
484 * Called immediately after the cfg.ini is read in order to configure
485 * the desired trace levels.
486 *
487 * Return: None
488 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530489static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530491 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492
493 /*
494 * if the bitmask is the default value, then a bitmask was not
495 * specified in cfg.ini, so leave the logging level alone (it
496 * will remain at the "compiled in" default value)
497 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530498 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 return;
500 }
501
502 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530503 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504
505 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530506 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 while (0 != bitmask) {
508 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530509 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 }
511 level++;
512 bitmask >>= 1;
513 }
514}
515
516/**
517 * wlan_hdd_validate_context() - check the HDD context
518 * @hdd_ctx: HDD context pointer
519 *
520 * Return: 0 if the context is valid. Error code otherwise
521 */
522int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
523{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530525 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526 return -ENODEV;
527 }
528
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800529 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530530 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
531 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 return -EAGAIN;
533 }
534
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800535 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530536 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
537 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 return -EAGAIN;
539 }
540 return 0;
541}
542
543void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
544{
545 hdd_adapter_t *adapter = NULL;
546 hdd_station_ctx_t *pHddStaCtx = NULL;
547 eCsrPhyMode phyMode;
548 struct hdd_config *cfg_param = NULL;
549
550 if (NULL == hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530551 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HDD Context is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552 return;
553 }
554
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800555 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530557 hddLog(QDF_TRACE_LEVEL_FATAL, FL("adapter is null !!"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 return;
559 }
560
561 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
562
563 cfg_param = hdd_ctx->config;
564 if (NULL == cfg_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530565 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 FL("cfg_params not available !!"));
567 return;
568 }
569
570 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
571
572 if (!hdd_ctx->isVHT80Allowed) {
573 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
574 (eCSR_DOT11_MODE_11ac == phyMode) ||
575 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530576 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577 FL("Setting phymode to 11n!!"));
578 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
579 eCSR_DOT11_MODE_11n);
580 }
581 } else {
582 /*
583 * New country Supports 11ac as well resetting value back from
584 * .ini
585 */
586 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
587 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
588 dot11Mode));
589 return;
590 }
591
592 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
593 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
594 || (eCSR_CFG_DOT11_MODE_11AC ==
595 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530596 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800597
598 /* need to issue a disconnect to CSR. */
599 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530600 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800601 adapter->sessionId,
602 eCSR_DISCONNECT_REASON_UNSPECIFIED);
603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530604 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800605 unsigned long rc;
606
607 rc = wait_for_completion_timeout(
608 &adapter->disconnect_comp_var,
609 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
610 if (!rc)
611 hddLog(LOGE,
612 FL("failure waiting for disconnect_comp_var"));
613 }
614 }
615}
616
617/**
618 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
619 * @hdd_adapter_t Hdd adapter.
620 *
621 * This function sets the IBSS power save config parameters to WMA
622 * which will send it to firmware if FW supports IBSS power save
623 * before vdev start.
624 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530625 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626 * on failure.
627 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530628QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629{
630 int ret;
631 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
632
633 if (hdd_ctx == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530634 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 FL("HDD context is null"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530636 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637 }
638
639 ret = wma_cli_set_command(adapter->sessionId,
640 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
641 hdd_ctx->config->ibssATIMWinSize,
642 VDEV_CMD);
643 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530644 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645 FL("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530646 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647 }
648
649 ret = wma_cli_set_command(adapter->sessionId,
650 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
651 hdd_ctx->config->isIbssPowerSaveAllowed,
652 VDEV_CMD);
653 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530654 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655 FL("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d"),
656 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530657 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 }
659
660 ret = wma_cli_set_command(adapter->sessionId,
661 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
662 hdd_ctx->config->
663 isIbssPowerCollapseAllowed, VDEV_CMD);
664 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530665 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800666 FL("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d"),
667 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530668 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 }
670
671 ret = wma_cli_set_command(adapter->sessionId,
672 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
673 hdd_ctx->config->isIbssAwakeOnTxRx,
674 VDEV_CMD);
675 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530676 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 FL("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530678 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 }
680
681 ret = wma_cli_set_command(adapter->sessionId,
682 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
683 hdd_ctx->config->ibssInactivityCount,
684 VDEV_CMD);
685 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530686 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 FL("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d"), ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530688 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689 }
690
691 ret = wma_cli_set_command(adapter->sessionId,
692 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
693 hdd_ctx->config->ibssTxSpEndInactivityTime,
694 VDEV_CMD);
695 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530696 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 FL(
698 "WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d"
699 ),
700 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530701 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 }
703
704 ret = wma_cli_set_command(adapter->sessionId,
705 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
706 hdd_ctx->config->ibssPsWarmupTime,
707 VDEV_CMD);
708 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530709 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 FL("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d"),
711 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530712 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 }
714
715 ret = wma_cli_set_command(adapter->sessionId,
716 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
717 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
718 VDEV_CMD);
719 if (0 != ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530720 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800721 FL(
722 "WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d"
723 ),
724 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530725 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 }
727
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530728 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729}
730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800731#define INTF_MACADDR_MASK 0x7
732
733/**
734 * hdd_update_macaddr() - update mac address
735 * @config: hdd configuration
736 * @hw_macaddr: mac address
737 *
738 * Mac address for multiple virtual interface is found as following
739 * i) The mac address of the first interface is just the actual hw mac address.
740 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
741 * define the mac address for the remaining interfaces and locally
742 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
743 * supported virtual interfaces, right now this is 0x07 (meaning 8
744 * interface).
745 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
746 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
747 *
748 * Return: None
749 */
750void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530751 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800752{
753 int8_t i;
754 uint8_t macaddr_b3, tmp_br3;
755
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530756 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530757 QDF_MAC_ADDR_SIZE);
758 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530759 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530760 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800761 macaddr_b3 = config->intfMacAddr[i].bytes[3];
762 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
763 INTF_MACADDR_MASK;
764 macaddr_b3 += tmp_br3;
765
766 /* XOR-ing bit-24 of the mac address. This will give enough
767 * mac address range before collision
768 */
769 macaddr_b3 ^= (1 << 7);
770
771 /* Set locally administered bit */
772 config->intfMacAddr[i].bytes[0] |= 0x02;
773 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530774 hddLog(QDF_TRACE_LEVEL_INFO, "config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 MAC_ADDRESS_STR, i,
776 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
777 }
778}
779
780static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
781 struct wma_tgt_services *cfg)
782{
783 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784
785 /* Set up UAPSD */
786 config->apUapsdEnabled &= cfg->uapsd;
787
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788 /* 11AC mode support */
789 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
790 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
791 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792
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
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700820/**
821 * hdd_update_vdev_nss() - sets the vdev nss
822 * @hdd_ctx: HDD context
823 *
824 * Sets the Nss per vdev type based on INI
825 *
826 * Return: None
827 */
828static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
829{
830 struct hdd_config *cfg_ini = hdd_ctx->config;
831 uint8_t max_supp_nss = 1;
832
833 if (cfg_ini->enable2x2)
834 max_supp_nss = 2;
835
836 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
837 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
838
839 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
840 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
841}
842
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
844 struct wma_tgt_ht_cap *cfg)
845{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530846 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847 uint32_t value, val32;
848 uint16_t val16;
849 struct hdd_config *pconfig = hdd_ctx->config;
850 tSirMacHTCapabilityInfo *phtCapInfo;
851 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
852 uint8_t enable_tx_stbc;
853
854 /* check and update RX STBC */
855 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
856 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
857
858 /* get the MPDU density */
859 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
860
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530861 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530862 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800863 FL("could not get MPDU DENSITY"));
864 value = 0;
865 }
866
867 /*
868 * MPDU density:
869 * override user's setting if value is larger
870 * than the one supported by target
871 */
872 if (value > cfg->mpdu_density) {
873 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
874 cfg->mpdu_density);
875
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530876 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530877 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878 FL("could not set MPDU DENSITY to CCM"));
879 }
880
881 /* get the HT capability info */
882 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530883 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530884 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800885 FL("could not get HT capability info"));
886 return;
887 }
888 val16 = (uint16_t) val32;
889 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
890
891 /* Set the LDPC capability */
892 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
893
894 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
895 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
896
897 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
898 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
899
900 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
901 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
902
903 enable_tx_stbc = pconfig->enableTxSTBC;
904
905 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
906 pconfig->enable2x2 = 1;
907 } else {
908 pconfig->enable2x2 = 0;
909 enable_tx_stbc = 0;
910
911 /* 1x1 */
912 /* Update Rx Highest Long GI data Rate */
913 if (sme_cfg_set_int(hdd_ctx->hHal,
914 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700915 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530916 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 hddLog(LOGE,
918 FL(
919 "Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM"
920 ));
921 }
922
923 /* Update Tx Highest Long GI data Rate */
924 if (sme_cfg_set_int
925 (hdd_ctx->hHal,
926 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700927 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530928 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929 hddLog(LOGE,
930 FL(
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700931 "VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800932 }
933 }
934 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
935 enable_tx_stbc = 0;
936 phtCapInfo->txSTBC = enable_tx_stbc;
937
938 val32 = val16;
939 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530940 if (status != QDF_STATUS_SUCCESS)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530941 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 FL("could not set HT capability to CCM"));
943#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
944 value = SIZE_OF_SUPPORTED_MCS_SET;
945 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530946 &value) == QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530947 hddLog(QDF_TRACE_LEVEL_INFO, FL("Read MCS rate set"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948
949 if (pconfig->enable2x2) {
950 for (value = 0; value < cfg->num_rf_chains; value++)
951 mcs_set[value] =
952 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
953
954 status =
955 sme_cfg_set_str(hdd_ctx->hHal,
956 WNI_CFG_SUPPORTED_MCS_SET,
957 mcs_set,
958 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530959 if (status == QDF_STATUS_E_FAILURE)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530960 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961 FL("could not set MCS SET to CCM"));
962 }
963 }
964#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
965}
966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
968 struct wma_tgt_vht_cap *cfg)
969{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530970 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 uint32_t value = 0;
972 struct hdd_config *pconfig = hdd_ctx->config;
973 struct wiphy *wiphy = hdd_ctx->wiphy;
974 struct ieee80211_supported_band *band_5g =
975 wiphy->bands[IEEE80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700976 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977
978 /* Get the current MPDU length */
979 status =
980 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
981 &value);
982
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530983 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530984 hddLog(QDF_TRACE_LEVEL_ERROR, FL("could not get MPDU LENGTH"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985 value = 0;
986 }
987
988 /*
989 * VHT max MPDU length:
990 * override if user configured value is too high
991 * that the target cannot support
992 */
993 if (value > cfg->vht_max_mpdu) {
994 status = sme_cfg_set_int(hdd_ctx->hHal,
995 WNI_CFG_VHT_MAX_MPDU_LENGTH,
996 cfg->vht_max_mpdu);
997
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530998 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530999 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 FL("could not set VHT MAX MPDU LENGTH"));
1001 }
1002 }
1003
1004 /* Get the current supported chan width */
1005 status = sme_cfg_get_int(hdd_ctx->hHal,
1006 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1007 &value);
1008
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301009 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301010 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001011 FL("could not get MPDU LENGTH"));
1012 value = 0;
1013 }
1014
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001015 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1016 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1017
1018 if (pconfig->enable2x2)
1019 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1020
1021 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1022 QDF_STATUS_E_FAILURE) {
1023 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1024 }
1025
1026 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1027 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1028 if (pconfig->enable2x2)
1029 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1030
1031 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1032 QDF_STATUS_E_FAILURE) {
1033 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1034 }
1035
1036 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1037 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1038 if (pconfig->enable2x2)
1039 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1040
1041 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1042 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1043
1044 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1045 QDF_STATUS_E_FAILURE) {
1046 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1047 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001049 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001050 &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 LDPC CODING CAP"));
1055 value = 0;
1056 }
1057
1058 /* Set the LDPC capability */
1059 if (value && !cfg->vht_rx_ldpc) {
1060 status = sme_cfg_set_int(hdd_ctx->hHal,
1061 WNI_CFG_VHT_LDPC_CODING_CAP,
1062 cfg->vht_rx_ldpc);
1063
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301064 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301065 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 FL("could not set VHT LDPC CODING CAP to CCM"));
1067 }
1068 }
1069
1070 /* Get current GI 80 value */
1071 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1072 &value);
1073
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301074 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301075 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001076 FL("could not get SHORT GI 80MHZ"));
1077 value = 0;
1078 }
1079
1080 /* set the Guard interval 80MHz */
1081 if (value && !cfg->vht_short_gi_80) {
1082 status = sme_cfg_set_int(hdd_ctx->hHal,
1083 WNI_CFG_VHT_SHORT_GI_80MHZ,
1084 cfg->vht_short_gi_80);
1085
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301086 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301087 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001088 FL("could not set SHORT GI 80MHZ to CCM"));
1089 }
1090 }
1091
1092 /* Get current GI 160 value */
1093 status = sme_cfg_get_int(hdd_ctx->hHal,
1094 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1095 &value);
1096
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301097 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301098 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001099 FL("could not get SHORT GI 80 & 160"));
1100 value = 0;
1101 }
1102
1103 /* Get VHT TX STBC cap */
1104 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301106 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301107 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 FL("could not get VHT TX STBC"));
1109 value = 0;
1110 }
1111
1112 /* VHT TX STBC cap */
1113 if (value && !cfg->vht_tx_stbc) {
1114 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1115 cfg->vht_tx_stbc);
1116
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301117 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301118 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001119 FL("could not set the VHT TX STBC to CCM"));
1120 }
1121 }
1122
1123 /* Get VHT RX STBC cap */
1124 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1125
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301126 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301127 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001128 FL("could not get VHT RX STBC"));
1129 value = 0;
1130 }
1131
1132 /* VHT RX STBC cap */
1133 if (value && !cfg->vht_rx_stbc) {
1134 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1135 cfg->vht_rx_stbc);
1136
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301137 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301138 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139 FL("could not set the VHT RX STBC to CCM"));
1140 }
1141 }
1142
1143 /* Get VHT SU Beamformer cap */
1144 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1145 &value);
1146
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301147 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301148 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001149 FL("could not get VHT SU BEAMFORMER CAP"));
1150 value = 0;
1151 }
1152
1153 /* set VHT SU Beamformer cap */
1154 if (value && !cfg->vht_su_bformer) {
1155 status = sme_cfg_set_int(hdd_ctx->hHal,
1156 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1157 cfg->vht_su_bformer);
1158
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301159 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301160 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 FL("could not set VHT SU BEAMFORMER CAP"));
1162 }
1163 }
1164
1165 /* check and update SU BEAMFORMEE capabality */
1166 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1167 pconfig->enableTxBF = cfg->vht_su_bformee;
1168
1169 status = sme_cfg_set_int(hdd_ctx->hHal,
1170 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1171 pconfig->enableTxBF);
1172
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301173 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301174 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001175 FL("could not set VHT SU BEAMFORMEE CAP"));
1176 }
1177
1178 /* Get VHT MU Beamformer cap */
1179 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1180 &value);
1181
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301182 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301183 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001184 FL("could not get VHT MU BEAMFORMER CAP"));
1185 value = 0;
1186 }
1187
1188 /* set VHT MU Beamformer cap */
1189 if (value && !cfg->vht_mu_bformer) {
1190 status = sme_cfg_set_int(hdd_ctx->hHal,
1191 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1192 cfg->vht_mu_bformer);
1193
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301194 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301195 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196 FL(
1197 "could not set the VHT MU BEAMFORMER CAP to CCM"
1198 ));
1199 }
1200 }
1201
1202 /* Get VHT MU Beamformee cap */
1203 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1204 &value);
1205
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301206 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301207 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001208 FL("could not get VHT MU BEAMFORMEE CAP"));
1209 value = 0;
1210 }
1211
1212 /* set VHT MU Beamformee cap */
1213 if (value && !cfg->vht_mu_bformee) {
1214 status = sme_cfg_set_int(hdd_ctx->hHal,
1215 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1216 cfg->vht_mu_bformee);
1217
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301218 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301219 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001220 FL("could not set VHT MU BEAMFORMER CAP"));
1221 }
1222 }
1223
1224 /* Get VHT MAX AMPDU Len exp */
1225 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1226 &value);
1227
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301228 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301229 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 FL("could not get VHT AMPDU LEN"));
1231 value = 0;
1232 }
1233
1234 /*
1235 * VHT max AMPDU len exp:
1236 * override if user configured value is too high
1237 * that the target cannot support.
1238 * Even though Rome publish ampdu_len=7, it can
1239 * only support 4 because of some h/w bug.
1240 */
1241
1242 if (value > cfg->vht_max_ampdu_len_exp) {
1243 status = sme_cfg_set_int(hdd_ctx->hHal,
1244 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1245 cfg->vht_max_ampdu_len_exp);
1246
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301247 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301248 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 FL("could not set the VHT AMPDU LEN EXP"));
1250 }
1251 }
1252
1253 /* Get VHT TXOP PS CAP */
1254 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1255
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301256 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301257 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 FL("could not get VHT TXOP PS"));
1259 value = 0;
1260 }
1261
1262 /* set VHT TXOP PS cap */
1263 if (value && !cfg->vht_txop_ps) {
1264 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1265 cfg->vht_txop_ps);
1266
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301267 if (status == QDF_STATUS_E_FAILURE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301268 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269 FL("could not set the VHT TXOP PS"));
1270 }
1271 }
1272
1273 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1274 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1275 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1276 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1277 else
1278 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1279
1280
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001281 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 band_5g->vht_cap.cap |=
1283 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001284 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001285 band_5g->vht_cap.cap |=
1286 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287
1288 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1289 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1290
1291 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1292 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1293 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1294 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1295
1296 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1297 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1298
1299 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1300 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1301 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1302 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1303 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1304 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1305
1306 band_5g->vht_cap.cap |=
1307 (cfg->vht_max_ampdu_len_exp <<
1308 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1309
1310 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1311 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1312 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1313 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1314 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1315 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1316 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1317 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1318
1319 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1320 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1321
1322}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323
1324void hdd_update_tgt_cfg(void *context, void *param)
1325{
1326 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1327 struct wma_tgt_cfg *cfg = param;
1328 uint8_t temp_band_cap;
1329
1330 /* first store the INI band capability */
1331 temp_band_cap = hdd_ctx->config->nBandCapability;
1332
1333 hdd_ctx->config->nBandCapability = cfg->band_cap;
1334
1335 /* now overwrite the target band capability with INI
1336 setting if INI setting is a subset */
1337
1338 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1339 (temp_band_cap != eCSR_BAND_ALL))
1340 hdd_ctx->config->nBandCapability = temp_band_cap;
1341 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1342 (temp_band_cap != eCSR_BAND_ALL) &&
1343 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301344 hddLog(QDF_TRACE_LEVEL_WARN,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001345 FL("ini BandCapability not supported by the target"));
1346 }
1347
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001348 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1350 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1351 }
1352
1353 /* This can be extended to other configurations like ht, vht cap... */
1354
Anurag Chouhanc5548422016-02-24 18:33:27 +05301355 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1357 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301358 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359 FL(
1360 "Invalid MAC passed from target, using MAC from ini file"
1361 MAC_ADDRESS_STR),
1362 MAC_ADDR_ARRAY(hdd_ctx->config->intfMacAddr[0].bytes));
1363 }
1364
1365 hdd_ctx->target_fw_version = cfg->target_fw_version;
1366
1367 hdd_ctx->max_intf_count = cfg->max_intf_count;
1368
1369#ifdef WLAN_FEATURE_LPSS
1370 hdd_ctx->lpss_support = cfg->lpss_support;
1371#endif
1372
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001373 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1374
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1376 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1377
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001378 hdd_update_vdev_nss(hdd_ctx);
1379
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001383 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001384 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001385 hdd_info(FL("fine_time_meas_cap: 0x%x"),
1386 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001387
1388 hdd_ctx->current_antenna_mode =
1389 (hdd_ctx->config->enable2x2 == 0x01) ?
1390 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1391 hdd_info("Init current antenna mode: %d",
1392 hdd_ctx->current_antenna_mode);
1393
Arun Khandavalli2476ef52016-04-26 20:19:43 +05301394 hdd_ctx->bpf_enabled = cfg->bpf_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395}
1396
1397/**
1398 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1399 * @context: HDD context pointer
1400 * @param: HDD radar indication pointer
1401 *
1402 * This function is invoked when a radar in found on the
1403 * SAP current operating channel and Data Tx from netif
1404 * has to be stopped to honor the DFS regulations.
1405 * Actions: Stop the netif Tx queues,Indicate Radar present
1406 * in HDD context for future usage.
1407 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301408 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001409 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301410bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411{
1412 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1413 struct wma_dfs_radar_ind *hdd_radar_event =
1414 (struct wma_dfs_radar_ind *)param;
1415 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1416 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301417 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301419 if (!hdd_ctx || !hdd_radar_event ||
1420 hdd_ctx->config->disableDFSChSwitch)
1421 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422
1423 if (true == hdd_radar_event->dfs_radar_status) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301424 mutex_lock(&hdd_ctx->dfs_lock);
1425 if (hdd_ctx->dfs_radar_found) {
1426 /*
1427 * Application already triggered channel switch
1428 * on current channel, so return here.
1429 */
1430 mutex_unlock(&hdd_ctx->dfs_lock);
1431 return false;
1432 }
1433
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 hdd_ctx->dfs_radar_found = true;
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301435 mutex_unlock(&hdd_ctx->dfs_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436
1437 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301438 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001439 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08001440 if (QDF_SAP_MODE == adapter->device_mode ||
1441 QDF_P2P_GO_MODE == adapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1443 dfs_cac_block_tx = true;
1444 }
1445
1446 status = hdd_get_next_adapter(hdd_ctx,
1447 adapterNode,
1448 &pNext);
1449 adapterNode = pNext;
1450 }
1451 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301452
1453 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455
1456/**
1457 * hdd_is_valid_mac_address() - validate MAC address
1458 * @pMacAddr: Pointer to the input MAC address
1459 *
1460 * This function validates whether the given MAC address is valid or not
1461 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1462 * where X is the hexa decimal digit character and separated by ':'
1463 * This algorithm works even if MAC address is not separated by ':'
1464 *
1465 * This code checks given input string mac contains exactly 12 hexadecimal
1466 * digits and a separator colon : appears in the input string only after
1467 * an even number of hex digits.
1468 *
1469 * Return: 1 for valid and 0 for invalid
1470 */
1471bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1472{
1473 int xdigit = 0;
1474 int separator = 0;
1475 while (*pMacAddr) {
1476 if (isxdigit(*pMacAddr)) {
1477 xdigit++;
1478 } else if (':' == *pMacAddr) {
1479 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1480 break;
1481
1482 ++separator;
1483 } else {
1484 /* Invalid MAC found */
1485 return 0;
1486 }
1487 ++pMacAddr;
1488 }
1489 return xdigit == 12 && (separator == 5 || separator == 0);
1490}
1491
1492/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001493 * __hdd__mon_open() - HDD Open function
1494 * @dev: Pointer to net_device structure
1495 *
1496 * This is called in response to ifconfig up
1497 *
1498 * Return: 0 for success; non-zero for failure
1499 */
1500static int __hdd_mon_open(struct net_device *dev)
1501{
1502 int ret;
1503
1504 ENTER_DEV(dev);
1505 ret = hdd_set_mon_rx_cb(dev);
1506 return ret;
1507}
1508
1509/**
1510 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1511 * @dev: Pointer to net_device structure
1512 *
1513 * This is called in response to ifconfig up
1514 *
1515 * Return: 0 for success; non-zero for failure
1516 */
1517int hdd_mon_open(struct net_device *dev)
1518{
1519 int ret;
1520
1521 cds_ssr_protect(__func__);
1522 ret = __hdd_mon_open(dev);
1523 cds_ssr_unprotect(__func__);
1524
1525 return ret;
1526}
1527
1528/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529 * __hdd_open() - HDD Open function
1530 * @dev: Pointer to net_device structure
1531 *
1532 * This is called in response to ifconfig up
1533 *
1534 * Return: 0 for success; non-zero for failure
1535 */
1536static int __hdd_open(struct net_device *dev)
1537{
1538 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1539 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1540 int ret;
1541
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001542 ENTER_DEV(dev);
1543
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301544 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 adapter->sessionId, adapter->device_mode));
1546
1547 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301548 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301550
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551
1552 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1553 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
1554 hddLog(LOG1, FL("Enabling Tx Queues"));
1555 /* Enable TX queues only when we are connected */
1556 wlan_hdd_netif_queue_control(adapter,
1557 WLAN_START_ALL_NETIF_QUEUE,
1558 WLAN_CONTROL_PATH);
1559 }
1560
1561 return ret;
1562}
1563
1564/**
1565 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1566 * @dev: Pointer to net_device structure
1567 *
1568 * This is called in response to ifconfig up
1569 *
1570 * Return: 0 for success; non-zero for failure
1571 */
1572int hdd_open(struct net_device *dev)
1573{
1574 int ret;
1575
1576 cds_ssr_protect(__func__);
1577 ret = __hdd_open(dev);
1578 cds_ssr_unprotect(__func__);
1579
1580 return ret;
1581}
1582
1583/**
1584 * __hdd_stop() - HDD stop function
1585 * @dev: Pointer to net_device structure
1586 *
1587 * This is called in response to ifconfig down
1588 *
1589 * Return: 0 for success; non-zero for failure
1590 */
1591static int __hdd_stop(struct net_device *dev)
1592{
1593 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1594 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1595 int ret;
1596
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001597 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301599 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001600 adapter->sessionId, adapter->device_mode));
1601
1602 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301603 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001605
1606 /* Nothing to be done if the interface is not opened */
1607 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301608 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609 FL("NETDEV Interface is not OPENED"));
1610 return -ENODEV;
1611 }
1612
1613 /* Make sure the interface is marked as closed */
1614 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301615 hddLog(QDF_TRACE_LEVEL_INFO, FL("Disabling OS Tx queues"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001616
1617 /*
1618 * Disable TX on the interface, after this hard_start_xmit() will not
1619 * be called on that interface
1620 */
1621 hddLog(LOG1, FL("Disabling queues"));
1622 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1623 WLAN_CONTROL_PATH);
1624
1625 /*
1626 * The interface is marked as down for outside world (aka kernel)
1627 * But the driver is pretty much alive inside. The driver needs to
1628 * tear down the existing connection on the netdev (session)
1629 * cleanup the data pipes and wait until the control plane is stabilized
1630 * for this interface. The call also needs to wait until the above
1631 * mentioned actions are completed before returning to the caller.
1632 * Notice that the hdd_stop_adapter is requested not to close the session
1633 * That is intentional to be able to scan if it is a STA/P2P interface
1634 */
1635 hdd_stop_adapter(hdd_ctx, adapter, false);
1636
1637 /* DeInit the adapter. This ensures datapath cleanup as well */
1638 hdd_deinit_adapter(hdd_ctx, adapter, true);
1639
1640 EXIT();
1641 return 0;
1642}
1643
1644/**
1645 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
1646 * @dev: pointer to net_device structure
1647 *
1648 * This is called in response to ifconfig down
1649 *
1650 * Return: 0 for success and error number for failure
1651 */
1652int hdd_stop(struct net_device *dev)
1653{
1654 int ret;
1655
1656 cds_ssr_protect(__func__);
1657 ret = __hdd_stop(dev);
1658 cds_ssr_unprotect(__func__);
1659
1660 return ret;
1661}
1662
1663/**
1664 * __hdd_uninit() - HDD uninit function
1665 * @dev: Pointer to net_device structure
1666 *
1667 * This is called during the netdev unregister to uninitialize all data
1668 * associated with the device
1669 *
1670 * Return: None
1671 */
1672static void __hdd_uninit(struct net_device *dev)
1673{
1674 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1675
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001676 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677
1678 do {
1679 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1680 hddLog(LOGP, FL("Invalid magic"));
1681 break;
1682 }
1683
1684 if (NULL == adapter->pHddCtx) {
1685 hddLog(LOGP, FL("NULL hdd_ctx"));
1686 break;
1687 }
1688
1689 if (dev != adapter->dev) {
1690 hddLog(LOGP, FL("Invalid device reference"));
1691 /*
1692 * we haven't validated all cases so let this go for
1693 * now
1694 */
1695 }
1696
1697 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
1698
1699 /* after uninit our adapter structure will no longer be valid */
1700 adapter->dev = NULL;
1701 adapter->magic = 0;
1702 } while (0);
1703
1704 EXIT();
1705}
1706
1707/**
1708 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
1709 * @dev: pointer to net_device structure
1710 *
1711 * This is called during the netdev unregister to uninitialize all data
1712 * associated with the device
1713 *
1714 * Return: none
1715 */
1716static void hdd_uninit(struct net_device *dev)
1717{
1718 cds_ssr_protect(__func__);
1719 __hdd_uninit(dev);
1720 cds_ssr_unprotect(__func__);
1721}
1722
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08001723static int hdd_open_cesium_nl_sock(void)
1724{
1725#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1726 struct netlink_kernel_cfg cfg = {
1727 .groups = WLAN_NLINK_MCAST_GRP_ID,
1728 .input = NULL
1729 };
1730#endif
1731 int ret = 0;
1732
1733#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1734 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
1735#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
1736 THIS_MODULE,
1737#endif
1738 &cfg);
1739#else
1740 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
1741 WLAN_NLINK_MCAST_GRP_ID,
1742 NULL, NULL, THIS_MODULE);
1743#endif
1744
1745 if (cesium_nl_srv_sock == NULL) {
1746 hddLog(QDF_TRACE_LEVEL_ERROR,
1747 FL("NLINK: cesium netlink_kernel_create failed"));
1748 ret = -ECONNREFUSED;
1749 }
1750
1751 return ret;
1752}
1753
1754static void hdd_close_cesium_nl_sock(void)
1755{
1756 if (NULL != cesium_nl_srv_sock) {
1757 netlink_kernel_release(cesium_nl_srv_sock);
1758 cesium_nl_srv_sock = NULL;
1759 }
1760}
1761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762/**
1763 * __hdd_set_mac_address() - set the user specified mac address
1764 * @dev: Pointer to the net device.
1765 * @addr: Pointer to the sockaddr.
1766 *
1767 * This function sets the user specified mac address using
1768 * the command ifconfig wlanX hw ether <mac adress>.
1769 *
1770 * Return: 0 for success, non zero for failure
1771 */
1772static int __hdd_set_mac_address(struct net_device *dev, void *addr)
1773{
1774 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1775 hdd_context_t *hdd_ctx;
1776 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301777 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 int ret;
1779
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001780 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781
1782 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1783 ret = wlan_hdd_validate_context(hdd_ctx);
1784 if (0 != ret)
1785 return ret;
1786
1787 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1788 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1789
1790 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05301791 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001792}
1793
1794/**
1795 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
1796 * function from SSR
1797 * @dev: pointer to net_device structure
1798 * @addr: Pointer to the sockaddr
1799 *
1800 * This function sets the user specified mac address using
1801 * the command ifconfig wlanX hw ether <mac adress>.
1802 *
1803 * Return: 0 for success.
1804 */
1805static int hdd_set_mac_address(struct net_device *dev, void *addr)
1806{
1807 int ret;
1808
1809 cds_ssr_protect(__func__);
1810 ret = __hdd_set_mac_address(dev, addr);
1811 cds_ssr_unprotect(__func__);
1812
1813 return ret;
1814}
1815
1816uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
1817{
1818 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301819 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
1821 break;
1822 }
1823
Anurag Chouhan6d760662016-02-20 16:05:43 +05301824 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 return NULL;
1826
1827 hdd_ctx->config->intfAddrMask |= (1 << i);
1828 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
1829}
1830
1831void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
1832{
1833 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05301834 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 if (!memcmp(releaseAddr,
1836 &hdd_ctx->config->intfMacAddr[i].bytes[0],
1837 6)) {
1838 hdd_ctx->config->intfAddrMask &= ~(1 << i);
1839 break;
1840 }
1841 }
1842 return;
1843}
1844
1845#ifdef WLAN_FEATURE_PACKET_FILTERING
1846/**
1847 * __hdd_set_multicast_list() - set the multicast address list
1848 * @dev: Pointer to the WLAN device.
1849 * @skb: Pointer to OS packet (sk_buff).
1850 *
1851 * This funciton sets the multicast address list.
1852 *
1853 * Return: None
1854 */
1855static void __hdd_set_multicast_list(struct net_device *dev)
1856{
1857 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1858 int mc_count;
1859 int i = 0, status;
1860 struct netdev_hw_addr *ha;
1861 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1862 static const uint8_t ipv6_router_solicitation[]
1863 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
1864
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001865 ENTER_DEV(dev);
1866
Anurag Chouhan6d760662016-02-20 16:05:43 +05301867 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05301868 return;
1869
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301871 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001872 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873
1874 if (dev->flags & IFF_ALLMULTI) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301875 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876 FL("allow all multicast frames"));
1877 adapter->mc_addr_list.mc_cnt = 0;
1878 } else {
1879 mc_count = netdev_mc_count(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301880 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 FL("mc_count = %u"), mc_count);
1882 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301883 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 FL(
1885 "No free filter available; allow all multicast frames"
1886 ));
1887 adapter->mc_addr_list.mc_cnt = 0;
1888 return;
1889 }
1890
1891 adapter->mc_addr_list.mc_cnt = mc_count;
1892
1893 netdev_for_each_mc_addr(ha, dev) {
1894 if (i == mc_count)
1895 break;
1896 /*
1897 * Skip following addresses:
1898 * 1)IPv6 router solicitation address
1899 * 2)Any other address pattern if its set during
1900 * RXFILTER REMOVE driver command based on
1901 * addr_filter_pattern
1902 */
1903 if ((!memcmp(ha->addr, ipv6_router_solicitation,
1904 ETH_ALEN)) ||
1905 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
1906 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08001907 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908 MAC_ADDR_ARRAY(ha->addr));
1909 adapter->mc_addr_list.mc_cnt--;
1910 continue;
1911 }
1912
1913 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
1914 ETH_ALEN);
1915 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
1916 ETH_ALEN);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301917 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918 FL("mlist[%d] = " MAC_ADDRESS_STR), i,
1919 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
1920 i++;
1921 }
1922 }
1923 if (hdd_ctx->config->active_mode_offload) {
1924 hdd_info("enable mc filtering");
1925 wlan_hdd_set_mc_addr_list(adapter, true);
1926 } else {
1927 hdd_info("skip mc filtering enable it during cfg80211 suspend");
1928 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301929 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 return;
1931}
1932
1933/**
1934 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
1935 * @dev: pointer to net_device
1936 *
1937 * Return: none
1938 */
1939static void hdd_set_multicast_list(struct net_device *dev)
1940{
1941 cds_ssr_protect(__func__);
1942 __hdd_set_multicast_list(dev);
1943 cds_ssr_unprotect(__func__);
1944}
1945#endif
1946
1947/**
1948 * hdd_select_queue() - used by Linux OS to decide which queue to use first
1949 * @dev: Pointer to the WLAN device.
1950 * @skb: Pointer to OS packet (sk_buff).
1951 *
1952 * This function is registered with the Linux OS for network
1953 * core to decide which queue to use first.
1954 *
1955 * Return: ac, Queue Index/access category corresponding to UP in IP header
1956 */
1957static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
1958#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
1959 , void *accel_priv
1960#endif
1961#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1962 , select_queue_fallback_t fallback
1963#endif
1964)
1965{
1966 return hdd_wmm_select_queue(dev, skb);
1967}
1968
1969static struct net_device_ops wlan_drv_ops = {
1970 .ndo_open = hdd_open,
1971 .ndo_stop = hdd_stop,
1972 .ndo_uninit = hdd_uninit,
1973 .ndo_start_xmit = hdd_hard_start_xmit,
1974 .ndo_tx_timeout = hdd_tx_timeout,
1975 .ndo_get_stats = hdd_get_stats,
1976 .ndo_do_ioctl = hdd_ioctl,
1977 .ndo_set_mac_address = hdd_set_mac_address,
1978 .ndo_select_queue = hdd_select_queue,
1979#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981#endif
1982};
1983
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001984/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
1985static struct net_device_ops wlan_mon_drv_ops = {
1986 .ndo_open = hdd_mon_open,
1987 .ndo_stop = hdd_stop,
1988 .ndo_get_stats = hdd_get_stats,
1989};
1990
1991/**
1992 * hdd_set_station_ops() - update net_device ops for monitor mode
1993 * @pWlanDev: Handle to struct net_device to be updated.
1994 * Return: None
1995 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996void hdd_set_station_ops(struct net_device *pWlanDev)
1997{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001998 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
1999 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2000 else
2001 pWlanDev->netdev_ops = &wlan_drv_ops;
2002}
2003
2004/**
2005 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
2006 * @dev: Handle to struct net_device to be updated.
2007 *
2008 * Return: None
2009 */
2010static void hdd_mon_mode_ether_setup(struct net_device *dev)
2011{
2012 dev->header_ops = NULL;
2013 dev->type = ARPHRD_IEEE80211_RADIOTAP;
2014 dev->hard_header_len = ETH_HLEN;
2015 dev->mtu = ETH_DATA_LEN;
2016 dev->addr_len = ETH_ALEN;
2017 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
2018 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
2019 dev->priv_flags |= IFF_TX_SKB_SHARING;
2020
2021 memset(dev->broadcast, 0xFF, ETH_ALEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022}
2023
Ryan Hsu07495ea2016-01-21 15:25:39 -08002024/**
2025 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2026 * @hdd_ctx: global hdd context
2027 * @macAddr: mac address to assign to the interface
2028 * @name: User-visible name of the interface
2029 *
2030 * hdd adapter pointer would point to the netdev->priv space, this function
2031 * would retrive the pointer, and setup the hdd adapter configuration.
2032 *
2033 * Return: the pointer to hdd adapter, otherwise NULL
2034 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2036 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002037 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 const char *name)
2039{
2040 struct net_device *pWlanDev = NULL;
2041 hdd_adapter_t *adapter = NULL;
2042 /*
2043 * cfg80211 initialization and registration....
2044 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002045 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2046#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2047 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002049 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2050 hdd_mon_mode_ether_setup : ether_setup),
2051 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052
2053 if (pWlanDev != NULL) {
2054
2055 /* Save the pointer to the net_device in the HDD adapter */
2056 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2057
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302058 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059
2060 adapter->dev = pWlanDev;
2061 adapter->pHddCtx = hdd_ctx;
2062 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2063
2064 init_completion(&adapter->session_open_comp_var);
2065 init_completion(&adapter->session_close_comp_var);
2066 init_completion(&adapter->disconnect_comp_var);
2067 init_completion(&adapter->linkup_event_var);
2068 init_completion(&adapter->cancel_rem_on_chan_var);
2069 init_completion(&adapter->rem_on_chan_ready_event);
2070 init_completion(&adapter->sta_authorized_event);
2071 init_completion(&adapter->offchannel_tx_event);
2072 init_completion(&adapter->tx_action_cnf_event);
2073#ifdef FEATURE_WLAN_TDLS
2074 init_completion(&adapter->tdls_add_station_comp);
2075 init_completion(&adapter->tdls_del_station_comp);
2076 init_completion(&adapter->tdls_mgmt_comp);
2077 init_completion(&adapter->tdls_link_establish_req_comp);
2078#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002079 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002080 init_completion(&adapter->change_country_code);
2081
2082
2083 init_completion(&adapter->scan_info.abortscan_event_var);
2084
2085 adapter->offloads_configured = false;
2086 adapter->isLinkUpSvcNeeded = false;
2087 adapter->higherDtimTransition = true;
2088 /* Init the net_device structure */
2089 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2090
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302091 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302093 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094 sizeof(tSirMacAddr));
2095 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002096
2097 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2098 pWlanDev->features |=
2099 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2100 pWlanDev->features |= NETIF_F_RXCSUM;
2101
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002102 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2103
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002104 hdd_set_station_ops(adapter->dev);
2105
2106 pWlanDev->destructor = free_netdev;
2107 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002108 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002109 adapter->wdev.wiphy = hdd_ctx->wiphy;
2110 adapter->wdev.netdev = pWlanDev;
2111 /* set pWlanDev's parent to underlying device */
2112 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2113 hdd_wmm_init(adapter);
2114 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302115 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 }
2117
2118 return adapter;
2119}
2120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302121QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002122 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002123{
2124 struct net_device *pWlanDev = adapter->dev;
2125 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
2126 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302127 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002128
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002129 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2131 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302132 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002133 FL("Failed:dev_alloc_name"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302134 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002135 }
2136 }
2137 if (register_netdevice(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302138 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302140 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141 }
2142 } else {
2143 if (register_netdev(pWlanDev)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302144 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145 FL("Failed:register_netdev"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302146 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002147 }
2148 }
2149 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2150
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302151 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002152}
2153
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302154static QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002155{
2156 hdd_adapter_t *adapter = pContext;
2157
2158 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302159 hddLog(QDF_TRACE_LEVEL_FATAL, FL("NULL adapter"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302160 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002161 }
2162
2163 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302164 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid magic"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302165 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166 }
2167
2168 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 /*
2171 * We can be blocked while waiting for scheduled work to be
2172 * flushed, and the adapter structure can potentially be freed, in
2173 * which case the magic will have been reset. So make sure the
2174 * magic is still good, and hence the adapter structure is still
2175 * valid, before signaling completion
2176 */
2177 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2178 complete(&adapter->session_close_comp_var);
2179
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302180 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181}
2182
Krunal Soni8c37e322016-02-03 16:08:37 -08002183/**
2184 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2185 * @adapter: pointer to device adapter
2186 * @type: type of interface
2187 *
2188 * This routine will check the mode of adapter and if it is required then it
2189 * will initialize the TDLS operations
2190 *
2191 * Return: QDF_STATUS
2192 */
2193#ifdef FEATURE_WLAN_TDLS
2194static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2195{
2196 if (QDF_IBSS_MODE != type) {
2197 if (0 != wlan_hdd_tdls_init(adapter)) {
2198 hddLog(LOGE, FL("wlan_hdd_tdls_init failed"));
2199 return QDF_STATUS_E_FAILURE;
2200 }
2201 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2202 }
2203 return QDF_STATUS_SUCCESS;
2204}
2205#else
2206static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2207{
2208 return QDF_STATUS_SUCCESS;
2209}
2210#endif
2211
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302212QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002213{
2214 struct net_device *pWlanDev = adapter->dev;
2215 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2216 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302217 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302218 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 uint32_t type, subType;
2220 unsigned long rc;
2221 int ret_val;
2222
2223 INIT_COMPLETION(adapter->session_open_comp_var);
2224 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002225 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002226 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302227 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002228 hddLog(LOGE, FL("failed to get vdev type"));
2229 goto error_sme_open;
2230 }
2231 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302232 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2234 (uint8_t *) &adapter->macAddressCurrent,
2235 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302236 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002237 hddLog(LOGP,
2238 FL("sme_open_session() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302239 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302240 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 goto error_sme_open;
2242 }
2243 /* Block on a completion variable. Can't wait forever though. */
2244 rc = wait_for_completion_timeout(
2245 &adapter->session_open_comp_var,
2246 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2247 if (!rc) {
2248 hddLog(LOGP,
2249 FL("Session is not opened within timeout period code %ld"),
2250 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302251 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002252 goto error_sme_open;
2253 }
2254
2255 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302256 qdf_ret_status = hdd_register_wext(pWlanDev);
2257 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258 hddLog(LOGP,
2259 FL("hdd_register_wext() failed, status code %08d [x%08x]"),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302260 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302261 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 goto error_register_wext;
2263 }
2264 /* Set the Connection State to Not Connected */
2265 hddLog(LOG1,
2266 FL("Set HDD connState to eConnectionState_NotConnected"));
2267 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2268
2269 /* Set the default operation channel */
2270 pHddStaCtx->conn_info.operationChannel =
2271 hdd_ctx->config->OperatingChannel;
2272
2273 /* Make the default Auth Type as OPEN */
2274 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2275
2276 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302277 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 hddLog(LOGP,
2279 FL("hdd_init_tx_rx() failed, status code %08d [x%08x]"),
2280 status, status);
2281 goto error_init_txrx;
2282 }
2283
2284 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2285
2286 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302287 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002288 hddLog(LOGP,
2289 FL("hdd_wmm_adapter_init() failed, status code %08d [x%08x]"),
2290 status, status);
2291 goto error_wmm_init;
2292 }
2293
2294 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2295
2296 ret_val = wma_cli_set_command(adapter->sessionId,
2297 WMI_PDEV_PARAM_BURST_ENABLE,
2298 hdd_ctx->config->enableSifsBurst,
2299 PDEV_CMD);
2300
2301 if (0 != ret_val) {
2302 hddLog(LOGE,
2303 FL("WMI_PDEV_PARAM_BURST_ENABLE set failed %d"),
2304 ret_val);
2305 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002306 status = hdd_check_and_init_tdls(adapter, type);
2307 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302310 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311
2312#ifdef FEATURE_WLAN_TDLS
2313error_tdls_init:
2314 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2315 hdd_wmm_adapter_close(adapter);
2316#endif
2317error_wmm_init:
2318 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2319 hdd_deinit_tx_rx(adapter);
2320error_init_txrx:
2321 hdd_unregister_wext(pWlanDev);
2322error_register_wext:
2323 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2324 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302325 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 adapter->sessionId,
2327 hdd_sme_close_session_callback,
2328 adapter)) {
2329 unsigned long rc;
2330
2331 /*
2332 * Block on a completion variable.
2333 * Can't wait forever though.
2334 */
2335 rc = wait_for_completion_timeout(
2336 &adapter->session_close_comp_var,
2337 msecs_to_jiffies
2338 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2339 if (rc <= 0)
2340 hddLog(LOGE,
2341 FL("Session is not opened within timeout period code %ld"),
2342 rc);
2343 }
2344 }
2345error_sme_open:
2346 return status;
2347}
2348
2349void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2350{
2351 hdd_cfg80211_state_t *cfgState;
2352
2353 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2354
2355 if (NULL != cfgState->buf) {
2356 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 rc = wait_for_completion_timeout(
2358 &adapter->tx_action_cnf_event,
2359 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2360 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302361 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362 FL("HDD Wait for Action Confirmation Failed!!"));
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302363 /*
2364 * Inform tx status as FAILURE to upper layer and free
2365 * cfgState->buf
2366 */
2367 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 }
2369 }
2370 return;
2371}
2372
2373void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2374 bool rtnl_held)
2375{
2376 ENTER();
2377 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002378 case QDF_STA_MODE:
2379 case QDF_P2P_CLIENT_MODE:
2380 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 {
2382 if (test_bit
2383 (INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2384 hdd_deinit_tx_rx(adapter);
2385 clear_bit(INIT_TX_RX_SUCCESS,
2386 &adapter->event_flags);
2387 }
2388
2389 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2390 hdd_wmm_adapter_close(adapter);
2391 clear_bit(WMM_INIT_DONE,
2392 &adapter->event_flags);
2393 }
2394
2395 hdd_cleanup_actionframe(hdd_ctx, adapter);
2396 wlan_hdd_tdls_exit(adapter);
2397 break;
2398 }
2399
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002400 case QDF_SAP_MODE:
2401 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002402 {
2403
2404 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2405 hdd_wmm_adapter_close(adapter);
2406 clear_bit(WMM_INIT_DONE,
2407 &adapter->event_flags);
2408 }
2409
2410 hdd_cleanup_actionframe(hdd_ctx, adapter);
2411
2412 hdd_unregister_hostapd(adapter, rtnl_held);
2413
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414 break;
2415 }
2416
2417 default:
2418 break;
2419 }
2420
2421 EXIT();
2422}
2423
2424void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002425 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426{
2427 struct net_device *pWlanDev = NULL;
2428
2429 if (adapter)
2430 pWlanDev = adapter->dev;
2431 else {
2432 hddLog(LOGE, FL("adapter is Null"));
2433 return;
2434 }
2435
2436 hdd_lro_disable(hdd_ctx, adapter);
Rajeev Kumardca5f812016-02-04 17:28:06 -08002437 hdd_debugfs_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 /*
2439 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2440 * the driver is almost closed and cannot handle either control
2441 * messages or data. However, unregister_netdevice() call above will
2442 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2443 * to close the active connections (basically excites control path) which
2444 * is not right. Setting this flag helps hdd_stop() to recognize that
2445 * the interface is closed and restricts any operations on that
2446 */
2447 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2448
2449 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2450 if (rtnl_held) {
2451 unregister_netdevice(pWlanDev);
2452 } else {
2453 unregister_netdev(pWlanDev);
2454 }
2455 /*
2456 * Note that the adapter is no longer valid at this point
2457 * since the memory has been reclaimed
2458 */
2459 }
2460}
2461
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302462QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 tSirMacAddr macAddr)
2464{
2465 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2466 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302467 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302469 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 adapter = adapterNode->pAdapter;
2471 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302472 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302474 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 }
2476 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2477 adapterNode = pNext;
2478 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302479 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002481
2482/**
2483 * hdd_open_adapter() - open and setup the hdd adatper
2484 * @hdd_ctx: global hdd context
2485 * @session_type: type of the interface to be created
2486 * @iface_name: User-visible name of the interface
2487 * @macAddr: MAC address to assign to the interface
2488 * @name_assign_type: the name of assign type of the netdev
2489 * @rtnl_held: the rtnl lock hold flag
2490 *
2491 * This function open and setup the hdd adpater according to the device
2492 * type request, assign the name, the mac address assigned, and then prepared
2493 * the hdd related parameters, queue, lock and ready to start.
2494 *
2495 * Return: the pointer of hdd adapter, otherwise NULL.
2496 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
2498 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002499 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002500 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501{
2502 hdd_adapter_t *adapter = NULL;
2503 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302504 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002505 hdd_cfg80211_state_t *cfgState;
2506 int ret;
2507
2508 hddLog(LOG2, FL("iface(%s) type(%d)"), iface_name, session_type);
2509
2510 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
2511 /*
2512 * Max limit reached on the number of vdevs configured by the
2513 * host. Return error
2514 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302515 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 FL(
2517 "Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d"
2518 ),
2519 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
2520 return NULL;
2521 }
2522
2523 if (macAddr == NULL) {
2524 /* Not received valid macAddr */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302525 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 FL(
2527 "Unable to add virtual intf: Not able to get valid mac address"
2528 ));
2529 return NULL;
2530 }
2531 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302532 if (QDF_STATUS_E_FAILURE == status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302533 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 "Duplicate MAC addr: " MAC_ADDRESS_STR
2535 " already exists",
2536 MAC_ADDR_ARRAY(macAddr));
2537 return NULL;
2538 }
2539
2540 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002541 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 /* Reset locally administered bit if the device mode is STA */
2543 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
2544 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002545 case QDF_P2P_CLIENT_MODE:
2546 case QDF_P2P_DEVICE_MODE:
2547 case QDF_OCB_MODE:
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002548 case QDF_MONITOR_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 {
Ryan Hsu07495ea2016-01-21 15:25:39 -08002550 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
2551 name_assign_type,
2552 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553
2554 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302555 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 FL("failed to allocate adapter for session %d"),
2557 session_type);
2558 return NULL;
2559 }
2560
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002561 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002563 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002565 else if (QDF_MONITOR_MODE == session_type)
2566 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 else
2568 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2569
2570 adapter->device_mode = session_type;
2571
2572 status = hdd_init_station_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302573 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002574 goto err_free_netdev;
2575
2576 hdd_lro_enable(hdd_ctx, adapter);
2577
2578 /*
2579 * Workqueue which gets scheduled in IPv4 notification
2580 * callback
2581 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
2583 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584
2585#ifdef WLAN_NS_OFFLOAD
2586 /*
2587 * Workqueue which gets scheduled in IPv6
2588 * notification callback.
2589 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002590 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
2591 hdd_ipv6_notifier_work_queue);
2592#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302594 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2596 goto err_lro_cleanup;
2597 }
2598
2599 /* Stop the Interface TX queue. */
2600 hddLog(LOG1, FL("Disabling queues"));
2601 wlan_hdd_netif_queue_control(adapter,
2602 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2603 WLAN_CONTROL_PATH);
2604
2605 hdd_register_tx_flow_control(adapter,
2606 hdd_tx_resume_timer_expired_handler,
2607 hdd_tx_resume_cb);
2608
2609 break;
2610 }
2611
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002612 case QDF_P2P_GO_MODE:
2613 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614 {
Ryan Hsu07495ea2016-01-21 15:25:39 -08002615 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
2616 name_assign_type,
2617 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302619 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 FL("failed to allocate adapter for session %d"),
2621 session_type);
2622 return NULL;
2623 }
2624
2625 adapter->wdev.iftype =
2626 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002627 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 NL80211_IFTYPE_P2P_GO;
2629 adapter->device_mode = session_type;
2630
2631 status = hdd_init_ap_mode(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302632 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633 goto err_free_netdev;
2634
2635 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302636 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002637 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
2638 goto err_free_netdev;
2639 }
2640
2641 hddLog(LOG1, FL("Disabling queues"));
2642 wlan_hdd_netif_queue_control(adapter,
2643 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2644 WLAN_CONTROL_PATH);
2645
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002646 break;
2647 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002648 case QDF_FTM_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 {
Ryan Hsu07495ea2016-01-21 15:25:39 -08002650 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
2651 name_assign_type,
2652 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002653
2654 if (NULL == adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302655 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002656 FL("failed to allocate adapter for session %d"),
2657 session_type);
2658 return NULL;
2659 }
2660
2661 /*
2662 * Assign NL80211_IFTYPE_STATION as interface type to resolve
2663 * Kernel Warning message while loading driver in FTM mode.
2664 */
2665 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
2666 adapter->device_mode = session_type;
2667 status = hdd_register_interface(adapter, rtnl_held);
2668
2669 hdd_init_tx_rx(adapter);
2670
2671 /* Stop the Interface TX queue. */
2672 hddLog(LOG1, FL("Disabling queues"));
2673 wlan_hdd_netif_queue_control(adapter,
2674 WLAN_NETIF_TX_DISABLE_N_CARRIER,
2675 WLAN_CONTROL_PATH);
2676 }
2677 break;
2678 default:
2679 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302680 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 FL("Invalid session type %d"),
2682 session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302683 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 return NULL;
2685 }
2686 }
2687
2688 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2689 mutex_init(&cfgState->remain_on_chan_ctx_lock);
2690
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302691 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 /* Add it to the hdd's session list. */
2693 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302694 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302696 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697 } else {
2698 pHddAdapterNode->pAdapter = adapter;
2699 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
2700 }
2701 }
2702
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302703 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 if (NULL != adapter) {
2705 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
2706 adapter = NULL;
2707 }
2708 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302709 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 }
2711 return NULL;
2712 }
2713
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302714 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002715 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716
2717 /* Initialize the WoWL service */
2718 if (!hdd_init_wowl(adapter)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302719 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 FL("hdd_init_wowl failed"));
2721 goto err_lro_cleanup;
2722 }
2723
2724 /* Adapter successfully added. Increment the vdev count */
2725 hdd_ctx->current_intf_count++;
2726
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302727 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("current_intf_count=%d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728 hdd_ctx->current_intf_count);
2729
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002730 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 }
2732
Anurag Chouhan6d760662016-02-20 16:05:43 +05302733 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002734 && (!hdd_ctx->config->enable2x2)) {
2735#define HDD_DTIM_1CHAIN_RX_ID 0x5
2736#define HDD_SMPS_PARAM_VALUE_S 29
2737
2738 /*
2739 * Disable DTIM 1 chain Rx when in 1x1, we are passing two value
2740 * as param_id << 29 | param_value.
2741 * Below param_value = 0(disable)
2742 */
2743 ret = wma_cli_set_command(adapter->sessionId,
2744 WMI_STA_SMPS_PARAM_CMDID,
2745 HDD_DTIM_1CHAIN_RX_ID <<
2746 HDD_SMPS_PARAM_VALUE_S,
2747 VDEV_CMD);
2748
2749 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302750 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002751 FL("DTIM 1 chain set failed %d"), ret);
2752 goto err_lro_cleanup;
2753 }
2754
2755 ret = wma_cli_set_command(adapter->sessionId,
2756 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2757 hdd_ctx->config->txchainmask1x1,
2758 PDEV_CMD);
2759 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302760 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 FL("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d"),
2762 ret);
2763 goto err_lro_cleanup;
2764 }
2765 ret = wma_cli_set_command(adapter->sessionId,
2766 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2767 hdd_ctx->config->rxchainmask1x1,
2768 PDEV_CMD);
2769 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302770 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002771 FL("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d"),
2772 ret);
2773 goto err_lro_cleanup;
2774 }
2775#undef HDD_DTIM_1CHAIN_RX_ID
2776#undef HDD_SMPS_PARAM_VALUE_S
2777 }
2778
Anurag Chouhan6d760662016-02-20 16:05:43 +05302779 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 ret = wma_cli_set_command(adapter->sessionId,
2781 WMI_PDEV_PARAM_HYST_EN,
2782 hdd_ctx->config->enableMemDeepSleep,
2783 PDEV_CMD);
2784
2785 if (ret != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302786 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 FL("WMI_PDEV_PARAM_HYST_EN set failed %d"),
2788 ret);
2789 goto err_lro_cleanup;
2790 }
2791 }
2792
2793#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2794
2795 /* Enable FW logs based on INI configuration */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302796 if ((QDF_GLOBAL_FTM_MODE != cds_get_conparam()) &&
Komal Seelamc11bb222016-01-27 18:57:10 +05302797 (hdd_ctx->config->enable_fw_log)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798 uint8_t count = 0;
2799 uint32_t value = 0;
2800 uint8_t numEntries = 0;
2801 uint8_t moduleLoglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2802
2803 hdd_ctx->fw_log_settings.dl_type =
2804 hdd_ctx->config->enableFwLogType;
2805 ret = wma_cli_set_command(adapter->sessionId,
2806 WMI_DBGLOG_TYPE,
2807 hdd_ctx->config->enableFwLogType,
2808 DBG_CMD);
2809 if (ret != 0) {
2810 hddLog(LOGE, FL("Failed to enable FW log type ret %d"),
2811 ret);
2812 }
2813
2814 hdd_ctx->fw_log_settings.dl_loglevel =
2815 hdd_ctx->config->enableFwLogLevel;
2816 ret = wma_cli_set_command(adapter->sessionId,
2817 WMI_DBGLOG_LOG_LEVEL,
2818 hdd_ctx->config->enableFwLogLevel,
2819 DBG_CMD);
2820 if (ret != 0) {
2821 hddLog(LOGE, FL("Failed to enable FW log level ret %d"),
2822 ret);
2823 }
2824
2825 hdd_string_to_u8_array(hdd_ctx->config->enableFwModuleLogLevel,
2826 moduleLoglevel,
2827 &numEntries,
2828 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2829 while (count < numEntries) {
2830 /*
2831 * FW module log level input string looks like below:
2832 * gFwDebugModuleLoglevel=<FW Module ID>,<Log Level>,...
2833 * For example:
2834 * gFwDebugModuleLoglevel=1,0,2,1,3,2,4,3,5,4,6,5,7,6
2835 * Above input string means :
2836 * For FW module ID 1 enable log level 0
2837 * For FW module ID 2 enable log level 1
2838 * For FW module ID 3 enable log level 2
2839 * For FW module ID 4 enable log level 3
2840 * For FW module ID 5 enable log level 4
2841 * For FW module ID 6 enable log level 5
2842 * For FW module ID 7 enable log level 6
2843 */
2844
2845 /* FW expects WMI command value =
2846 * Module ID * 10 + Module Log level
2847 */
2848 value = ((moduleLoglevel[count] * 10) +
2849 moduleLoglevel[count + 1]);
2850 ret = wma_cli_set_command(adapter->sessionId,
2851 WMI_DBGLOG_MOD_LOG_LEVEL,
2852 value, DBG_CMD);
2853 if (ret != 0) {
2854 hddLog(LOGE,
2855 FL
2856 ("Failed to enable FW module log level %d ret %d"),
2857 value, ret);
2858 }
2859
2860 count += 2;
2861 }
2862 }
2863#endif
Rajeev Kumardca5f812016-02-04 17:28:06 -08002864 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
2865 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866
2867 return adapter;
2868
2869err_lro_cleanup:
2870 hdd_lro_disable(hdd_ctx, adapter);
2871err_free_netdev:
2872 free_netdev(adapter->dev);
2873 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2874
2875 return NULL;
2876}
2877
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302878QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002879 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880{
2881 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302882 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883
2884 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302885 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302886 hddLog(QDF_TRACE_LEVEL_WARN, FL("adapter list empty %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887 status);
2888 return status;
2889 }
2890
2891 while (pCurrent->pAdapter != adapter) {
2892 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302893 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002894 break;
2895
2896 pCurrent = pNext;
2897 }
2898 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302899 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002900 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002901 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
2902
2903 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302904 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002905 adapterNode = NULL;
2906
2907 /* Adapter removed. Decrement vdev count */
2908 if (hdd_ctx->current_intf_count != 0)
2909 hdd_ctx->current_intf_count--;
2910
2911 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302912 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302914 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915}
2916
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002917/**
2918 * hdd_close_all_adapters - Close all open adapters
2919 * @hdd_ctx: Hdd context
2920 * rtnl_held: True if RTNL lock held
2921 *
2922 * Close all open adapters.
2923 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302924 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002925 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302926QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927{
2928 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302929 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002930
2931 ENTER();
2932
2933 do {
2934 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302935 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002937 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302938 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002939 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302940 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941
2942 EXIT();
2943
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302944 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945}
2946
2947void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
2948{
Anurag Chouhan6d760662016-02-20 16:05:43 +05302949 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 tSirUpdateIE updateIE;
2951 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002952 case QDF_STA_MODE:
2953 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 {
2955 hdd_station_ctx_t *pHddStaCtx =
2956 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002957 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 break;
2959 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002960 case QDF_SAP_MODE:
2961 case QDF_P2P_GO_MODE:
2962 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08002964 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 break;
2966 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002967 case QDF_FTM_MODE:
2968 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002969 default:
2970 /*
2971 * wlan_hdd_reset_prob_rspies should not have been called
2972 * for these kind of devices
2973 */
2974 hddLog(LOGE,
2975 FL("Unexpected request for the current device type %d"),
2976 pHostapdAdapter->device_mode);
2977 return;
2978 }
2979
Anurag Chouhanc5548422016-02-24 18:33:27 +05302980 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 updateIE.smeSessionId = pHostapdAdapter->sessionId;
2982 updateIE.ieBufferlength = 0;
2983 updateIE.pAdditionIEBuffer = NULL;
2984 updateIE.append = true;
2985 updateIE.notify = false;
2986 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
2987 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302988 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
2990 }
2991}
2992
Peng Xu66162de2016-02-11 17:01:20 -08002993/**
2994 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
2995 * @hdd_ctx: HDD context which is already NULL validated
2996 * @adapter: HDD adapter which is already NULL validated
2997 *
2998 * Close the SME session and wait for its completion, if needed.
2999 *
3000 * Return: None
3001 */
3002static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3003 hdd_adapter_t *adapter)
3004{
3005 unsigned long rc;
3006
3007 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3008 hdd_err("session is not opened:%d", adapter->sessionId);
3009 return;
3010 }
3011
3012 INIT_COMPLETION(adapter->session_close_comp_var);
3013 if (QDF_STATUS_SUCCESS ==
3014 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3015 hdd_sme_close_session_callback,
3016 adapter)) {
3017 /*
3018 * Block on a completion variable. Can't wait
3019 * forever though.
3020 */
3021 rc = wait_for_completion_timeout(
3022 &adapter->session_close_comp_var,
3023 msecs_to_jiffies
3024 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3025 if (!rc)
3026 hdd_err("failure waiting for session_close_comp_var");
3027 }
3028}
3029
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303030QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 const bool bCloseSession)
3032{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303033 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3035 union iwreq_data wrqu;
3036 tSirUpdateIE updateIE;
3037 unsigned long rc;
3038
3039 ENTER();
3040
3041 hddLog(LOG1, FL("Disabling queues"));
3042 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3043 WLAN_CONTROL_PATH);
3044 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003045 case QDF_STA_MODE:
3046 case QDF_P2P_CLIENT_MODE:
3047 case QDF_IBSS_MODE:
3048 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 if (hdd_conn_is_connected(
3050 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3051 hdd_is_connecting(
3052 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3053 if (pWextState->roamProfile.BSSType ==
3054 eCSR_BSS_TYPE_START_IBSS)
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303055 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 sme_roam_disconnect(hdd_ctx->hHal,
3057 adapter->sessionId,
3058 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
3059 else
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303060 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 sme_roam_disconnect(hdd_ctx->hHal,
3062 adapter->sessionId,
3063 eCSR_DISCONNECT_REASON_UNSPECIFIED);
3064 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303065 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003066 rc = wait_for_completion_timeout(
3067 &adapter->disconnect_comp_var,
3068 msecs_to_jiffies
3069 (WLAN_WAIT_TIME_DISCONNECT));
3070 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303071 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 FL(
3073 "wait on disconnect_comp_var failed"
3074 ));
3075 }
3076 } else {
3077 hddLog(LOGE,
3078 FL(
3079 "failed to post disconnect event to SME"
3080 ));
3081 }
3082 memset(&wrqu, '\0', sizeof(wrqu));
3083 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3084 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3085 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3086 NULL);
3087 } else {
3088 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3089 eCSR_SCAN_ABORT_DEFAULT);
3090 }
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303091 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092
3093#ifdef WLAN_OPEN_SOURCE
3094 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3095#endif
3096
3097 hdd_deregister_tx_flow_control(adapter);
3098
3099#ifdef WLAN_NS_OFFLOAD
3100#ifdef WLAN_OPEN_SOURCE
3101 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3102#endif
3103#endif
3104
3105 /*
3106 * It is possible that the caller of this function does not
3107 * wish to close the session
3108 */
Peng Xu66162de2016-02-11 17:01:20 -08003109 if (true == bCloseSession)
3110 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111 break;
3112
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003113 case QDF_SAP_MODE:
3114 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003116 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003117 /*
3118 * Before stopping the sap adapter, lets make sure there
3119 * is no sap restart work pending.
3120 */
3121 cds_flush_work(&hdd_ctx->sap_start_work);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303122 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003123 FL("Canceled the pending SAP restart work"));
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003124 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003125 }
3126 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003127 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3129
3130 hdd_deregister_tx_flow_control(adapter);
3131
3132 mutex_lock(&hdd_ctx->sap_lock);
3133 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303134 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303135 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003136
3137 /* Stop Bss. */
3138#ifdef WLAN_FEATURE_MBSSID
3139 status = wlansap_stop_bss(
3140 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3141#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003142 status = wlansap_stop_bss(
3143 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144#endif
3145
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303146 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003147 hdd_hostapd_state_t *hostapd_state =
3148 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303149 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303150 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303151 qdf_status =
3152 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303153 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 BSS_WAIT_TIMEOUT);
3155
Anurag Chouhance0dc992016-02-16 18:18:03 +05303156 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157 hddLog(LOGE,
3158 FL(
3159 "failure waiting for wlansap_stop_bss %d"
3160 ),
Anurag Chouhance0dc992016-02-16 18:18:03 +05303161 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 }
3163 } else {
3164 hddLog(LOGE, FL("failure in wlansap_stop_bss"));
3165 }
3166 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003167 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 adapter->device_mode,
3169 adapter->sessionId);
3170
Anurag Chouhanc5548422016-02-24 18:33:27 +05303171 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003172 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 updateIE.smeSessionId = adapter->sessionId;
3174 updateIE.ieBufferlength = 0;
3175 updateIE.pAdditionIEBuffer = NULL;
3176 updateIE.append = false;
3177 updateIE.notify = false;
3178 /* Probe bcn reset */
3179 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3180 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303181 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 hddLog(LOGE,
3183 FL(
3184 "Could not pass on PROBE_RSP_BCN data to PE"
3185 ));
3186 }
3187 /* Assoc resp reset */
3188 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3189 &updateIE,
3190 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303191 QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 hddLog(LOGE,
3193 FL(
3194 "Could not pass on ASSOC_RSP data to PE"
3195 ));
3196 }
3197 /* Reset WNI_CFG_PROBE_RSP Flags */
3198 wlan_hdd_reset_prob_rspies(adapter);
3199 kfree(adapter->sessionCtx.ap.beacon);
3200 adapter->sessionCtx.ap.beacon = NULL;
3201 }
3202 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003203 if (true == bCloseSession)
3204 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003206 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3208 conn_info.staId[0]);
3209 break;
3210 default:
3211 break;
3212 }
3213
3214 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303215 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216}
3217
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303218QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219{
3220 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303221 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003222 hdd_adapter_t *adapter;
3223
3224 ENTER();
3225
3226 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3227
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303228 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229 adapter = adapterNode->pAdapter;
3230 hdd_stop_adapter(hdd_ctx, adapter, true);
3231 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3232 adapterNode = pNext;
3233 }
3234
3235 EXIT();
3236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303237 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238}
3239
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303240QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241{
3242 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303243 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244 hdd_adapter_t *adapter;
3245
3246 ENTER();
3247
3248 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3249
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303250 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003251 adapter = adapterNode->pAdapter;
3252 hddLog(LOG1, FL("Disabling queues"));
3253 wlan_hdd_netif_queue_control(adapter,
3254 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3255 WLAN_CONTROL_PATH);
3256
3257 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3258
3259 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003260 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 adapter->sessionId);
3262 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3263 hdd_wmm_adapter_close(adapter);
3264 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3265 }
3266
3267 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3268 adapterNode = pNext;
3269 }
3270
3271 EXIT();
3272
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303273 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274}
3275
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303276QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277{
3278 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303279 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 hdd_adapter_t *adapter;
3281#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303282 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003283#endif
3284 eConnectionState connState;
3285
3286 ENTER();
3287
3288 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3289
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303290 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291 adapter = adapterNode->pAdapter;
3292
3293 hdd_wmm_init(adapter);
3294
3295 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003296 case QDF_STA_MODE:
3297 case QDF_P2P_CLIENT_MODE:
3298 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299
3300 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3301 ->conn_info.connState;
3302
3303 hdd_init_station_mode(adapter);
3304 /* Open the gates for HDD to receive Wext commands */
3305 adapter->isLinkUpSvcNeeded = false;
3306 adapter->scan_info.mScanPending = false;
3307
3308 /* Indicate disconnect event to supplicant if associated previously */
3309 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003310 eConnectionState_IbssConnected == connState ||
3311 eConnectionState_NotConnected == connState ||
3312 eConnectionState_IbssDisconnected == connState ||
3313 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314 union iwreq_data wrqu;
3315 memset(&wrqu, '\0', sizeof(wrqu));
3316 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3317 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3318 wireless_send_event(adapter->dev, SIOCGIWAP,
3319 &wrqu, NULL);
3320 adapter->sessionCtx.station.
3321 hdd_ReassocScenario = false;
3322
3323 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05303324 wlan_hdd_cfg80211_indicate_disconnect(
3325 adapter->dev, false,
3326 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327 } else if (eConnectionState_Connecting == connState) {
3328 /*
3329 * Indicate connect failure to supplicant if we were in the
3330 * process of connecting
3331 */
3332 cfg80211_connect_result(adapter->dev, NULL,
3333 NULL, 0, NULL, 0,
3334 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3335 GFP_KERNEL);
3336 }
3337
3338 hdd_register_tx_flow_control(adapter,
3339 hdd_tx_resume_timer_expired_handler,
3340 hdd_tx_resume_cb);
3341
3342 break;
3343
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003344 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003345 /* softAP can handle SSR */
3346 break;
3347
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003348 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349#ifdef MSM_PLATFORM
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303350 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 FL("[SSR] send stop ap to supplicant"));
3352 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3353#else
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303354 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355 FL("[SSR] send restart supplicant"));
3356 /* event supplicant to restart */
3357 cfg80211_del_sta(adapter->dev,
3358 (const u8 *)&bcastMac.bytes[0],
3359 GFP_KERNEL);
3360#endif
3361 break;
3362
3363 default:
3364 break;
3365 }
3366
3367 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3368 adapterNode = pNext;
3369 }
3370
3371 EXIT();
3372
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303373 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374}
3375
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303376QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 hdd_adapter_list_node_t **padapterNode)
3378{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303379 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003380 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303381 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3382 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003383 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003384 return status;
3385}
3386
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303387QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003388 hdd_adapter_list_node_t *adapterNode,
3389 hdd_adapter_list_node_t **pNextAdapterNode)
3390{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303391 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003392 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303393 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3394 (qdf_list_node_t *) adapterNode,
3395 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003397 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398 return status;
3399}
3400
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303401QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 hdd_adapter_list_node_t *adapterNode)
3403{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303404 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003405 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303406 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003408 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409 return status;
3410}
3411
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303412QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003413 hdd_adapter_list_node_t **padapterNode)
3414{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303415 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003416 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303417 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3418 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003419 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 return status;
3421}
3422
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303423QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 hdd_adapter_list_node_t *adapterNode)
3425{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303426 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003427 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303428 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3429 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003430 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003431 return status;
3432}
3433
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303434QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 hdd_adapter_list_node_t *adapterNode)
3436{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303437 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003438 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303439 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3440 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003441 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 return status;
3443}
3444
3445hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3446 tSirMacAddr macAddr)
3447{
3448 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3449 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303450 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451
3452 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3453
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303454 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455 adapter = adapterNode->pAdapter;
3456
3457 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303458 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 macAddr, sizeof(tSirMacAddr))) {
3460 return adapter;
3461 }
3462 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3463 adapterNode = pNext;
3464 }
3465
3466 return NULL;
3467
3468}
3469
3470hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3471 uint32_t vdev_id)
3472{
3473 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3474 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303475 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303477 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003478
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303479 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 adapter = adapterNode->pAdapter;
3481
3482 if (adapter->sessionId == vdev_id)
3483 return adapter;
3484
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303485 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3487 adapterNode = pNext;
3488 }
3489
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303490 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 FL("vdev_id %d does not exist with host"), vdev_id);
3492
3493 return NULL;
3494}
3495
Abhishek Singh7996eb72015-12-30 17:24:02 +05303496/**
3497 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3498 * the sessionid
3499 * @hdd_ctx: hdd context.
3500 * @sme_session_id: sme session is for the adapter to get.
3501 *
3502 * This function is used to get the adapter with provided session id
3503 *
3504 * Return: adapter pointer if found
3505 *
3506 */
3507hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3508 uint32_t sme_session_id)
3509{
3510 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3511 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303512 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303513
3514
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303515 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303516
3517 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303518 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303519 adapter = adapter_node->pAdapter;
3520
3521 if (adapter &&
3522 adapter->sessionId == sme_session_id)
3523 return adapter;
3524
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303525 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303526 hdd_get_next_adapter(hdd_ctx,
3527 adapter_node, &next);
3528 adapter_node = next;
3529 }
3530 return NULL;
3531}
3532
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003533/**
3534 * hdd_get_adapter() - to get adapter matching the mode
3535 * @hdd_ctx: hdd context
3536 * @mode: adapter mode
3537 *
3538 * This routine will return the pointer to adapter matching
3539 * with the passed mode.
3540 *
3541 * Return: pointer to adapter or null
3542 */
3543hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
3544 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545{
3546 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3547 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303548 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549
3550 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3551
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303552 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003553 adapter = adapterNode->pAdapter;
3554
3555 if (adapter && (mode == adapter->device_mode))
3556 return adapter;
3557
3558 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3559 adapterNode = pNext;
3560 }
3561
3562 return NULL;
3563
3564}
3565
3566/**
3567 * hdd_get_operating_channel() - return operating channel of the device mode
3568 * @hdd_ctx: Pointer to the HDD context.
3569 * @mode: Device mode for which operating channel is required.
3570 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003571 * QDF_STA_MODE,
3572 * QDF_P2P_CLIENT_MODE,
3573 * QDF_SAP_MODE,
3574 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003575 *
3576 * This API returns the operating channel of the requested device mode
3577 *
3578 * Return: channel number. "0" id the requested device is not found OR it is
3579 * not connected.
3580 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003581uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
3582 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003583{
3584 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303585 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586 hdd_adapter_t *adapter;
3587 uint8_t operatingChannel = 0;
3588
3589 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3590
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303591 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 adapter = adapterNode->pAdapter;
3593
3594 if (mode == adapter->device_mode) {
3595 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003596 case QDF_STA_MODE:
3597 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598 if (hdd_conn_is_connected
3599 (WLAN_HDD_GET_STATION_CTX_PTR
3600 (adapter))) {
3601 operatingChannel =
3602 (WLAN_HDD_GET_STATION_CTX_PTR
3603 (adapter))->conn_info.
3604 operationChannel;
3605 }
3606 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003607 case QDF_SAP_MODE:
3608 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 /* softap connection info */
3610 if (test_bit
3611 (SOFTAP_BSS_STARTED,
3612 &adapter->event_flags))
3613 operatingChannel =
3614 (WLAN_HDD_GET_AP_CTX_PTR
3615 (adapter))->operatingChannel;
3616 break;
3617 default:
3618 break;
3619 }
3620
3621 break; /* Found the device of interest. break the loop */
3622 }
3623
3624 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3625 adapterNode = pNext;
3626 }
3627 return operatingChannel;
3628}
3629
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303630static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003631 hdd_ctx)
3632{
3633 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303634 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635 hdd_adapter_t *adapter;
3636
3637 ENTER();
3638
3639 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303641 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003643 if ((adapter->device_mode == QDF_STA_MODE) ||
3644 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
3645 (adapter->device_mode == QDF_IBSS_MODE) ||
3646 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
3647 (adapter->device_mode == QDF_SAP_MODE) ||
3648 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649 wlan_hdd_cfg80211_deregister_frames(adapter);
3650 hdd_unregister_wext(adapter->dev);
3651 }
3652 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3653 adapterNode = pNext;
3654 }
3655
3656 EXIT();
3657
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303658 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659}
3660
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303661QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662{
3663 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303664 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 hdd_adapter_t *adapter;
3666
3667 ENTER();
3668
3669 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3670
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303671 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003673 if ((adapter->device_mode == QDF_STA_MODE) ||
3674 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
3675 (adapter->device_mode == QDF_IBSS_MODE) ||
3676 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
3677 (adapter->device_mode == QDF_SAP_MODE) ||
3678 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3680 eCSR_SCAN_ABORT_DEFAULT);
3681 }
3682 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3683 adapterNode = pNext;
3684 }
3685
3686 EXIT();
3687
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303688 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689}
3690
3691#ifdef WLAN_NS_OFFLOAD
3692/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003693 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694 * @hdd_ctx: Pointer to hdd context
3695 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003696 * Unregister for IPv6 address change notifications.
3697 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 * Return: None
3699 */
3700static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3701{
3702 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
3703
3704 return;
3705}
3706
3707/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003708 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 * @hdd_ctx: Pointer to hdd context
3710 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003711 * Register for IPv6 address change notifications.
3712 *
3713 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003714 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003715static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003716{
3717 int ret;
3718
3719 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
3720 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003721 if (ret) {
3722 hdd_err("Failed to register IPv6 notifier: %d", ret);
3723 goto out;
3724 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003725
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003726 hdd_info("Registered IPv6 notifier");
3727out:
3728 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729}
3730#else
3731/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003732 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 * @hdd_ctx: Pointer to hdd context
3734 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003735 * Unregister for IPv6 address change notifications.
3736 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 * Return: None
3738 */
3739static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
3740{
3741}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003742
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003744 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003745 * @hdd_ctx: Pointer to hdd context
3746 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003747 * Register for IPv6 address change notifications.
3748 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 * Return: None
3750 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003751static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003753 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003754}
3755#endif
3756
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003757#ifdef QCA_WIFI_FTM
3758/**
3759 * hdd_disable_ftm() - Disable FTM mode
3760 * @hdd_ctx: HDD context
3761 *
3762 * Helper function to disable FTM mode.
3763 *
3764 * Return: None.
3765 */
3766static void hdd_disable_ftm(hdd_context_t *hdd_ctx)
3767{
3768 hdd_notice("Disabling FTM mode");
3769
3770 if (hdd_ftm_stop(hdd_ctx)) {
3771 hdd_alert("hdd_ftm_stop Failed!");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303772 QDF_ASSERT(0);
Prashanth Bhattad1d44692015-12-22 17:32:59 -08003773 }
3774
3775 hdd_ctx->ftm.ftm_state = WLAN_FTM_STOPPED;
3776
3777 wlan_hdd_ftm_close(hdd_ctx);
3778
3779 return;
3780}
3781
3782/**
3783 * hdd_enable_ftm() - Enable FTM mode
3784 * @hdd_ctx: HDD context
3785 *
3786 * Helper function to enable FTM mode.
3787 *
3788 * Return: 0 on success and errno on failure.
3789 */
3790int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3791{
3792 int ret;
3793
3794 ret = wlan_hdd_ftm_open(hdd_ctx);
3795 if (ret) {
3796 hdd_alert("wlan_hdd_ftm_open Failed: %d", ret);
3797 goto err_out;
3798 }
3799
3800 ret = hdd_ftm_start(hdd_ctx);
3801
3802 if (ret) {
3803 hdd_alert("hdd_ftm_start Failed: %d", ret);
3804 goto err_ftm_close;
3805 }
3806
3807 ret = wiphy_register(hdd_ctx->wiphy);
3808 if (ret) {
3809 hdd_alert("wiphy register failed: %d", ret);
3810 goto err_ftm_stop;
3811 }
3812
3813 hdd_err("FTM driver loaded");
3814
3815 return 0;
3816
3817err_ftm_stop:
3818 hdd_ftm_stop(hdd_ctx);
3819err_ftm_close:
3820 wlan_hdd_ftm_close(hdd_ctx);
3821err_out:
3822 return ret;
3823
3824}
3825#else
3826int hdd_enable_ftm(hdd_context_t *hdd_ctx)
3827{
3828 hdd_err("Driver built without FTM feature enabled!");
3829
3830 return -ENOTSUPP;
3831}
3832
3833static inline void hdd_disable_ftm(hdd_context_t *hdd_ctx) { }
3834#endif
3835
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303836#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3837/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003838 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303839 * @hdd_ctx: HDD context
3840 *
3841 * Activates the logging service
3842 *
3843 * Return: Zero in case of success, negative value otherwise
3844 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003845static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303846{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003847 int ret;
3848 struct hdd_config *config = hdd_ctx->config;
3849
3850 if (!config->wlanLoggingEnable)
3851 return 0;
3852
3853 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
3854 config->wlanLoggingNumBuf);
3855 if (ret)
3856 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
3857 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303858}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003859
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303860/**
3861 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
3862 * @hdd_ctx: HDD context
3863 *
3864 * Deactivates the logging service
3865 *
3866 * Return: 0 on deactivating the logging service
3867 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003868static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303869{
3870 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
3871 return wlan_logging_sock_deactivate_svc();
3872
3873 return 0;
3874}
3875#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003876static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303877{
3878 return 0;
3879}
3880
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08003881static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05303882{
3883 return 0;
3884}
3885#endif
3886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003887/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07003888 * hdd_register_notifiers - Register netdev notifiers.
3889 * @hdd_ctx: HDD context
3890 *
3891 * Register netdev notifiers like IPv4 and IPv6.
3892 *
3893 * Return: 0 on success and errno on failure
3894 */
3895static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
3896{
3897 int ret;
3898
3899 ret = register_netdevice_notifier(&hdd_netdev_notifier);
3900 if (ret) {
3901 hdd_err("register_netdevice_notifier failed: %d", ret);
3902 goto out;
3903 }
3904
3905 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
3906 if (ret)
3907 goto unregister_notifier;
3908
3909 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
3910 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3911 if (ret) {
3912 hdd_err("Failed to register IPv4 notifier: %d", ret);
3913 goto unregister_ip6_notifier;
3914 }
3915
3916 return 0;
3917
3918unregister_ip6_notifier:
3919 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3920unregister_notifier:
3921 unregister_netdevice_notifier(&hdd_netdev_notifier);
3922out:
3923 return ret;
3924
3925}
3926
3927/**
3928 * hdd_unregister_notifiers - Unregister netdev notifiers.
3929 * @hdd_ctx: HDD context
3930 *
3931 * Unregister netdev notifiers like IPv4 and IPv6.
3932 *
3933 * Return: None.
3934 */
3935static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
3936{
3937 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
3938
3939 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
3940
3941 unregister_netdevice_notifier(&hdd_netdev_notifier);
3942}
3943
3944/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08003945 * hdd_exit_netlink_services - Exit netlink services
3946 * @hdd_ctx: HDD context
3947 *
3948 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
3949 * nl service.
3950 *
3951 * Return: None.
3952 */
3953static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
3954{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08003955 hdd_close_cesium_nl_sock();
3956
3957 ptt_sock_deactivate_svc();
3958
3959 nl_srv_exit();
3960}
3961
3962/**
3963 * hdd_init_netlink_services- Init netlink services
3964 * @hdd_ctx: HDD context
3965 *
3966 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
3967 * nl service.
3968 *
3969 * Return: 0 on success and errno on failure.
3970 */
3971static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
3972{
3973 int ret;
3974
Ryan Hsuceddceb2016-04-28 10:20:14 -07003975 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08003976 if (ret) {
3977 hdd_alert("nl_srv_init failed: %d", ret);
3978 goto out;
3979 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07003980 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08003981
3982 ret = oem_activate_service(hdd_ctx);
3983 if (ret) {
3984 hdd_alert("oem_activate_service failed: %d", ret);
3985 goto err_nl_srv;
3986 }
3987
3988 ret = ptt_sock_activate_svc();
3989 if (ret) {
3990 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
3991 goto err_nl_srv;
3992 }
3993
3994 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07003995 if (ret)
3996 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08003997
3998 ret = cnss_diag_activate_service();
3999 if (ret) {
4000 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4001 goto err_close_cesium;
4002 }
4003
4004 return 0;
4005
4006err_close_cesium:
4007 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004008 ptt_sock_deactivate_svc();
4009err_nl_srv:
4010 nl_srv_exit();
4011out:
4012 return ret;
4013}
4014
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004015#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4016/**
4017 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4018 * @hdd_ctx: HDD context.
4019 *
4020 * Destroy RX wakelock.
4021 *
4022 * Return: None.
4023 */
4024static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4025{
4026 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4027}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004028
4029/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004030 * hdd_rx_wake_lock_create() - Create RX wakelock
4031 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004032 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004033 * Create RX wakelock.
4034 *
4035 * Return: None.
4036 */
4037static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4038{
4039 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4040}
4041#else
4042static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { }
4043static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { }
4044#endif
4045
4046/**
4047 * hdd_roc_context_init() - Init ROC context
4048 * @hdd_ctx: HDD context.
4049 *
4050 * Initialize ROC context.
4051 *
4052 * Return: 0 on success and errno on failure.
4053 */
4054static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4055{
4056 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4057 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4058
4059 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4060
4061 return 0;
4062}
4063
4064/**
4065 * hdd_roc_context_destroy() - Destroy ROC context
4066 * @hdd_ctx: HDD context.
4067 *
4068 * Destroy roc list and flush the pending roc work.
4069 *
4070 * Return: None.
4071 */
4072static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4073{
4074 flush_delayed_work(&hdd_ctx->roc_req_work);
4075 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4076}
4077
4078/**
4079 * hdd_context_destroy() - Destroy HDD context
4080 * @hdd_ctx: HDD context to be destroyed.
4081 *
4082 * Free config and HDD context as well as destroy all the resources.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004083 *
4084 * Return: None
4085 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004086static void hdd_context_destroy(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004087{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304088 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004089 hdd_logging_sock_deactivate_svc(hdd_ctx);
4090
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004091 hdd_roc_context_destroy(hdd_ctx);
4092
4093 hdd_sap_context_destroy(hdd_ctx);
4094
4095 hdd_rx_wake_lock_destroy(hdd_ctx);
4096
4097 hdd_tdls_context_destroy(hdd_ctx);
4098
4099 hdd_scan_context_destroy(hdd_ctx);
4100
4101 qdf_list_destroy(&hdd_ctx->hddAdapters);
4102
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304103 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004104 hdd_ctx->config = NULL;
4105
4106 wiphy_free(hdd_ctx->wiphy);
4107}
4108
4109/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004110 * hdd_wlan_exit() - HDD WLAN exit function
4111 * @hdd_ctx: Pointer to the HDD Context
4112 *
4113 * This is the driver exit point (invoked during rmmod)
4114 *
4115 * Return: None
4116 */
4117void hdd_wlan_exit(hdd_context_t *hdd_ctx)
4118{
4119 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304120 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 struct wiphy *wiphy = hdd_ctx->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122
4123 ENTER();
4124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004125 hdd_unregister_wext_all_adapters(hdd_ctx);
4126
Ryan Hsucfef0ae2016-04-28 10:20:46 -07004127 hdd_exit_netlink_services(hdd_ctx);
4128
Anurag Chouhan6d760662016-02-20 16:05:43 +05304129 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08004130 hdd_disable_ftm(hdd_ctx);
4131
4132 hdd_alert("FTM driver unloaded");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004133 goto free_hdd_ctx;
4134 }
4135
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004136 hdd_unregister_notifiers(hdd_ctx);
4137
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 /*
4139 * Cancel any outstanding scan requests. We are about to close all
4140 * of our adapters, but an adapter structure is what SME passes back
4141 * to our callback function. Hence if there are any outstanding scan
4142 * requests then there is a race condition between when the adapter
4143 * is closed and when the callback is invoked. We try to resolve that
4144 * race condition here by canceling any outstanding scans before we
4145 * close the adapters.
4146 * Note that the scans may be cancelled in an asynchronous manner, so
4147 * ideally there needs to be some kind of synchronization. Rather than
4148 * introduce a new synchronization here, we will utilize the fact that
4149 * we are about to Request Full Power, and since that is synchronized,
4150 * the expectation is that by the time Request Full Power has completed,
4151 * all scans will be cancelled
4152 */
4153 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4154
4155#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05304156 if (QDF_TIMER_STATE_RUNNING ==
4157 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
4158 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004159 }
4160
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304161 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304162 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304163 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 FL("Cannot deallocate Bus bandwidth timer"));
4165 }
4166#endif
4167
4168#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304169 if (QDF_TIMER_STATE_RUNNING ==
4170 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4171 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172 }
4173
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304174 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304175 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304176 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004177 FL("Cannot deallocate ACS Skip timer"));
4178 }
4179#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180
4181 /*
4182 * Powersave Offload Case
4183 * Disable Idle Power Save Mode
4184 */
4185 hdd_set_idle_ps_config(hdd_ctx, false);
4186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 /* Unregister the Net Device Notifier */
4188 unregister_netdevice_notifier(&hdd_netdev_notifier);
4189
4190 /*
4191 * Stop all adapters, this will ensure the termination of active
4192 * connections on the interface. Make sure the cds_scheduler is
4193 * still available to handle those control messages
4194 */
4195 hdd_stop_all_adapters(hdd_ctx);
4196
4197 /* Stop all the modules */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304198 qdf_status = cds_disable(p_cds_context);
4199 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304200 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004201 FL("Failed to stop CDS"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304202 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203 }
4204
4205 /*
4206 * Close the scheduler before calling cds_close to make sure no thread
4207 * is scheduled after the each module close is called i.e after all the
4208 * data structures are freed.
4209 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304210 qdf_status = cds_sched_close(p_cds_context);
4211 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304212 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004213 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304214 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304217 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4218 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4219 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 /*
4222 * Close CDS
4223 * This frees pMac(HAL) context. There should not be any call
4224 * that requires pMac access after this.
4225 */
4226 cds_close(p_cds_context);
4227
4228 hdd_wlan_green_ap_deinit(hdd_ctx);
4229
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004230 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231
4232 hdd_ipa_cleanup(hdd_ctx);
4233
4234 /* Free up RoC request queue and flush workqueue */
4235 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304237 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
Krunal Soni03a882b2016-01-13 15:59:52 -08004238 hdd_err("Failed to deinit policy manager");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004239 /* Proceed and complete the clean up */
4240 }
4241
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304242 wlansap_global_deinit();
4243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244free_hdd_ctx:
4245
Nirav Shahed34b212016-04-25 10:59:16 +05304246 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304248 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004249
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004250 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251}
4252
4253void __hdd_wlan_exit(void)
4254{
4255 hdd_context_t *hdd_ctx;
4256
4257 ENTER();
4258
Anurag Chouhan6d760662016-02-20 16:05:43 +05304259 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304261 hddLog(QDF_TRACE_LEVEL_FATAL, FL("Invalid HDD Context"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262 EXIT();
4263 return;
4264 }
4265
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004266 /* Check IPA HW Pipe shutdown */
4267 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4268
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269#ifdef WLAN_FEATURE_LPSS
4270 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
4271#endif
4272
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004273 memdump_deinit();
4274
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275 /* Do all the cleanup before deregistering the driver */
4276 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278 EXIT();
4279}
4280
4281#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4282void hdd_skip_acs_scan_timer_handler(void *data)
4283{
4284 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4285
4286 hddLog(LOG1, FL("ACS Scan result expired. Reset ACS scan skip"));
4287 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4288
4289 if (!hdd_ctx->hHal)
4290 return;
4291 sme_scan_flush_result(hdd_ctx->hHal);
4292}
4293#endif
4294
4295#ifdef QCA_HT_2040_COEX
4296/**
4297 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4298 * @adapter: pointer to adapter
4299 * @staId: station id
4300 * @macAddrSTA: station MAC address
4301 * @channel_type: channel type
4302 *
4303 * This function notifies FW with HT20/HT40 mode
4304 *
4305 * Return: 0 if successful, error number otherwise
4306 */
4307int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304308 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004309{
4310 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304311 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 hdd_context_t *hdd_ctx = NULL;
4313
4314 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4315
4316 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304317 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004320 if (!hdd_ctx->hHal)
4321 return -EINVAL;
4322
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304323 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304325 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004326 hddLog(LOGE, "Fail to send notification with ht2040 mode");
4327 return -EINVAL;
4328 }
4329
4330 return 0;
4331}
4332#endif
4333
4334/**
4335 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4336 * @state: state
4337 *
4338 * This function notifies FW with modem power status
4339 *
4340 * Return: 0 if successful, error number otherwise
4341 */
4342int hdd_wlan_notify_modem_power_state(int state)
4343{
4344 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304345 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004346 hdd_context_t *hdd_ctx;
4347
Anurag Chouhan6d760662016-02-20 16:05:43 +05304348 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304350 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 if (!hdd_ctx->hHal)
4354 return -EINVAL;
4355
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304356 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4357 if (QDF_STATUS_SUCCESS != qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 hddLog(LOGE,
4359 "Fail to send notification with modem power state %d",
4360 state);
4361 return -EINVAL;
4362 }
4363 return 0;
4364}
4365
4366/**
4367 *
4368 * hdd_post_cds_enable_config() - HDD post cds start config helper
4369 * @adapter - Pointer to the HDD
4370 *
4371 * Return: None
4372 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304373QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304375 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376
4377 /*
4378 * Send ready indication to the HDD. This will kick off the MAC
4379 * into a 'running' state and should kick off an initial scan.
4380 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304381 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4382 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304383 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 FL(
4385 "sme_hdd_ready_ind() failed with status code %08d [x%08x]"
4386 ),
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304387 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304388 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004389 }
4390
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304391 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392}
4393
4394/* wake lock APIs for HDD */
4395void hdd_prevent_suspend(uint32_t reason)
4396{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304397 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398}
4399
4400void hdd_allow_suspend(uint32_t reason)
4401{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304402 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403}
4404
4405void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
4406{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304407 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408}
4409
4410/**
4411 * hdd_exchange_version_and_caps() - exchange version and capability with target
4412 * @hdd_ctx: Pointer to HDD context
4413 *
4414 * This is the HDD function to exchange version and capability information
4415 * between Host and Target
4416 *
4417 * This function gets reported version of FW.
4418 * It also finds the version of target headers used to compile the host;
4419 * It compares the above two and prints a warning if they are different;
4420 * It gets the SW and HW version string;
4421 * Finally, it exchanges capabilities between host and target i.e. host
4422 * and target exchange a msg indicating the features they support through a
4423 * bitmap
4424 *
4425 * Return: None
4426 */
4427void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4428{
4429
4430 tSirVersionType versionCompiled;
4431 tSirVersionType versionReported;
4432 tSirVersionString versionString;
4433 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304434 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435
4436 memset(&versionCompiled, 0, sizeof(versionCompiled));
4437 memset(&versionReported, 0, sizeof(versionReported));
4438
4439 /* retrieve and display WCNSS version information */
4440 do {
4441
4442 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4443 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304444 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304445 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446 FL(
4447 "unable to retrieve WCNSS WLAN compiled version"
4448 ));
4449 break;
4450 }
4451
4452 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4453 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304454 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304455 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004456 FL(
4457 "unable to retrieve WCNSS WLAN reported version"
4458 ));
4459 break;
4460 }
4461
4462 if ((versionCompiled.major != versionReported.major) ||
4463 (versionCompiled.minor != versionReported.minor) ||
4464 (versionCompiled.version != versionReported.version) ||
4465 (versionCompiled.revision != versionReported.revision)) {
4466 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4467 "Host expected %u.%u.%u.%u\n",
4468 WLAN_MODULE_NAME,
4469 (int)versionReported.major,
4470 (int)versionReported.minor,
4471 (int)versionReported.version,
4472 (int)versionReported.revision,
4473 (int)versionCompiled.major,
4474 (int)versionCompiled.minor,
4475 (int)versionCompiled.version,
4476 (int)versionCompiled.revision);
4477 } else {
4478 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4479 WLAN_MODULE_NAME,
4480 (int)versionReported.major,
4481 (int)versionReported.minor,
4482 (int)versionReported.version,
4483 (int)versionReported.revision);
4484 }
4485
4486 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4487 versionString,
4488 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304489 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304490 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 FL(
4492 "unable to retrieve WCNSS software version string"
4493 ));
4494 break;
4495 }
4496
4497 pr_info("%s: WCNSS software version %s\n",
4498 WLAN_MODULE_NAME, versionString);
4499
4500 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4501 versionString,
4502 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304503 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304504 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505 FL(
4506 "unable to retrieve WCNSS hardware version string"
4507 ));
4508 break;
4509 }
4510
4511 pr_info("%s: WCNSS hardware version %s\n",
4512 WLAN_MODULE_NAME, versionString);
4513
4514 /*
4515 * 1.Check if FW version is greater than 0.1.1.0. Only then
4516 * send host-FW capability exchange message
4517 * 2.Host-FW capability exchange message is only present on
4518 * target 1.1 so send the message only if it the target is 1.1
4519 * minor numbers for different target branches:
4520 * 0 -> (1.0)Mainline Build
4521 * 1 -> (1.1)Mainline Build
4522 * 2->(1.04) Stability Build
4523 */
4524 if (((versionReported.major > 0) || (versionReported.minor > 1)
4525 || ((versionReported.minor >= 1)
4526 && (versionReported.version >= 1)))
4527 && ((versionReported.major == 1)
4528 && (versionReported.minor >= 1)))
4529 fwFeatCapsMsgSupported = 1;
4530
4531 if (fwFeatCapsMsgSupported) {
4532 /*
4533 * Indicate if IBSS heartbeat monitoring needs to be
4534 * offloaded
4535 */
4536 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4537 sme_disable_feature_capablity
4538 (IBSS_HEARTBEAT_OFFLOAD);
4539 }
4540
4541 sme_feature_caps_exchange(hdd_ctx->hHal);
4542 }
4543
4544 } while (0);
4545
4546}
4547
4548/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304549QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004550{
4551 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4552 hdd_ctx->reg.cc_src);
4553}
4554
4555/**
4556 * hdd_is_5g_supported() - check if hardware supports 5GHz
4557 * @hdd_ctx: Pointer to the hdd context
4558 *
4559 * HDD function to know if hardware supports 5GHz
4560 *
4561 * Return: true if hardware supports 5GHz
4562 */
4563bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4564{
4565 /*
4566 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4567 * then hardware support 5Ghz.
4568 */
4569 return true;
4570}
4571
Amar Singhale4f28ee2015-10-21 14:36:56 -07004572static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573{
4574 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07004575 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576
4577 wiphy = hdd_ctx->wiphy;
4578
4579 /*
4580 * The channel information in
4581 * wiphy needs to be initialized before wiphy registration
4582 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004583 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
4584 if (ret_val) {
4585 hdd_alert("regulatory init failed");
4586 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004587 }
4588
4589#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4590 wiphy->wowlan = &wowlan_support_reg_init;
4591#else
4592 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4593 WIPHY_WOWLAN_MAGIC_PKT |
4594 WIPHY_WOWLAN_DISCONNECT |
4595 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4596 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4597 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4598 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4599 WIPHY_WOWLAN_RFKILL_RELEASE;
4600
4601 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4602 WOW_MAX_FILTERS_PER_LIST);
4603 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4604 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4605#endif
4606
4607 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004608 ret_val = wlan_hdd_cfg80211_register(wiphy);
4609 if (0 > ret_val)
4610 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004611
Amar Singhale4f28ee2015-10-21 14:36:56 -07004612 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613}
4614
Ravi Joshie2331e82015-07-01 18:18:54 -07004615/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07004616 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07004617 * @hdd_ctx - handle to hdd context
4618 * @tx_packets - transmit packet count
4619 * @rx_packets - receive packet count
4620 *
4621 * The function controls the bus bandwidth and dynamic control of
4622 * tcp delayed ack configuration
4623 *
4624 * Returns: None
4625 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626#ifdef MSM_PLATFORM
Yuanyuan Liu13738502016-04-06 17:41:37 -07004627void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004628 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004629{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004631 uint64_t temp_rx = 0;
4632 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07004633 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004634 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4635 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004636
Mohit Khannae71e2262015-11-10 09:37:24 -08004637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004639 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004640 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004641 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004642 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004643 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004644 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07004645 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004646
Mohit Khannae71e2262015-11-10 09:37:24 -08004647 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4648 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649
4650 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004651 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
4652 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07004654 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004656
4657 /* fine-tuning parameters for RX Flows */
4658 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660 hdd_ctx->prev_rx = rx_packets;
4661 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004662 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004664 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665
Mohit Khannae71e2262015-11-10 09:37:24 -08004666 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4667 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668
4669 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004670 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004671 next_rx_level, temp_rx);
4672 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07004673 /* Send throughput indication only if it is enabled.
4674 * Disabling tcp_del_ack will revert the tcp stack behavior
4675 * to default delayed ack. Note that this will disable the
4676 * dynamic delayed ack mechanism across the system
4677 */
4678 if (hdd_ctx->config->enable_tcp_delack)
4679 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 &next_rx_level,
4681 sizeof(next_rx_level));
4682 }
4683
Mohit Khannae71e2262015-11-10 09:37:24 -08004684 /* fine-tuning parameters for TX Flows */
4685 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4686 hdd_ctx->prev_tx = tx_packets;
4687 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4688 next_tx_level = WLAN_SVC_TP_HIGH;
4689 else
4690 next_tx_level = WLAN_SVC_TP_LOW;
4691
4692 if (hdd_ctx->cur_tx_level != next_tx_level) {
4693 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4694 next_tx_level, temp_tx);
4695 hdd_ctx->cur_tx_level = next_tx_level;
4696 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4697 &next_tx_level,
4698 sizeof(next_tx_level));
4699 }
4700
4701 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4702 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 hdd_ctx->hdd_txrx_hist_idx++;
4704 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004705}
4706
4707#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4708static void hdd_bus_bw_compute_cbk(void *priv)
4709{
4710 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4711 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304712 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05304713 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
4714 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715 uint64_t total_tx = 0, total_rx = 0;
4716 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304717 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304718 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004719 bool connected = false;
4720 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4721
4722 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304723 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724 status =
4725 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4726
4727 if (adapterNode->pAdapter == NULL)
4728 continue;
4729 adapter = adapterNode->pAdapter;
4730
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004731 if ((adapter->device_mode == QDF_STA_MODE ||
4732 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004733 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4734 != eConnectionState_Associated) {
4735
4736 continue;
4737 }
4738
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004739 if ((adapter->device_mode == QDF_SAP_MODE ||
4740 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4742
4743 continue;
4744 }
4745
4746 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4747 adapter->prev_tx_packets);
4748 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4749 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304750
4751 if (adapter->device_mode == QDF_SAP_MODE ||
4752 adapter->device_mode == QDF_P2P_GO_MODE ||
4753 adapter->device_mode == QDF_IBSS_MODE) {
4754
4755 ret = ol_get_intra_bss_fwd_pkts_count(
4756 adapter->sessionId,
4757 &fwd_tx_packets, &fwd_rx_packets);
4758 if (ret == A_OK) {
4759 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
4760 fwd_tx_packets,
4761 adapter->prev_fwd_tx_packets);
4762 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
4763 fwd_tx_packets,
4764 adapter->prev_fwd_rx_packets);
4765 }
4766 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767
4768 total_rx += adapter->stats.rx_packets;
4769 total_tx += adapter->stats.tx_packets;
4770
4771 spin_lock_bh(&hdd_ctx->bus_bw_lock);
4772 adapter->prev_tx_packets = adapter->stats.tx_packets;
4773 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304774 adapter->prev_fwd_tx_packets = fwd_tx_packets;
4775 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
4777 connected = true;
4778 }
4779
4780 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
4781 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
4782 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
4783 rx_packets;
4784 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
4785 tx_packets;
4786
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304787 /* add intra bss forwarded tx and rx packets */
4788 tx_packets += fwd_tx_packets_diff;
4789 rx_packets += fwd_rx_packets_diff;
4790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004791 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
4792 tx_packets += (uint64_t)ipa_tx_packets;
4793 rx_packets += (uint64_t)ipa_rx_packets;
4794
4795 if (!connected) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304796 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797 FL("bus bandwidth timer running in disconnected state"));
4798 return;
4799 }
4800
Yuanyuan Liu13738502016-04-06 17:41:37 -07004801 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004802
4803 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
4804 hdd_ipa_uc_stat_request(adapter, 2);
4805
Anurag Chouhan210db072016-02-22 18:42:15 +05304806 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 hdd_ctx->config->busBandwidthComputeInterval);
4808}
4809#endif
4810
4811/**
Nirav Shahed34b212016-04-25 10:59:16 +05304812 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
4813 * @hdd_ctx: hdd context
4814 *
4815 * Return: 0 for success or error code
4816 */
4817int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
4818{
4819 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
4820 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
4821 if (hdd_ctx->hdd_txrx_hist == NULL) {
4822 hdd_err("%s: Failed malloc for hdd_txrx_hist", __func__);
4823 return -ENOMEM;
4824 }
4825 return 0;
4826}
4827
4828/**
4829 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
4830 * @hdd_ctx: hdd context
4831 *
4832 * Return: none
4833 */
4834void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
4835{
4836 if (hdd_ctx->hdd_txrx_hist) {
4837 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
4838 hdd_ctx->hdd_txrx_hist = NULL;
4839 }
4840}
4841
Nirav Shahda008342016-05-17 18:50:40 +05304842static uint8_t *convert_level_to_string(uint32_t level)
4843{
4844 switch (level) {
4845 /* initialize the wlan sub system */
4846 case WLAN_SVC_TP_NONE:
4847 return "NONE";
4848 case WLAN_SVC_TP_LOW:
4849 return "LOW";
4850 case WLAN_SVC_TP_MEDIUM:
4851 return "MED";
4852 case WLAN_SVC_TP_HIGH:
4853 return "HIGH";
4854 default:
4855 return "INVAL";
4856 }
4857}
4858
Nirav Shahed34b212016-04-25 10:59:16 +05304859
4860/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
4862 * @hdd_ctx: hdd context
4863 *
4864 * Return: none
4865 */
4866void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
4867{
4868 int i;
4869
4870#ifdef MSM_PLATFORM
Nirav Shahda008342016-05-17 18:50:40 +05304871 hddLog(QDF_TRACE_LEVEL_ERROR, "BW compute Interval: %dms",
4872 hdd_ctx->config->busBandwidthComputeInterval);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304873 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874 "BW High TH: %d BW Med TH: %d BW Low TH: %d",
4875 hdd_ctx->config->busBandwidthHighThreshold,
4876 hdd_ctx->config->busBandwidthMediumThreshold,
4877 hdd_ctx->config->busBandwidthLowThreshold);
Nirav Shahda008342016-05-17 18:50:40 +05304878 hddLog(QDF_TRACE_LEVEL_ERROR, "Enable TCP DEL ACK: %d",
4879 hdd_ctx->config->enable_tcp_delack);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304880 hddLog(QDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 hdd_ctx->config->tcpDelackThresholdHigh,
4882 hdd_ctx->config->tcpDelackThresholdLow);
Nirav Shahda008342016-05-17 18:50:40 +05304883 hddLog(QDF_TRACE_LEVEL_ERROR,
4884 "TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
4885 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886#endif
4887
Nirav Shahda008342016-05-17 18:50:40 +05304888 hddLog(QDF_TRACE_LEVEL_ERROR, "Total entries: %d Current index: %d",
4889 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
4890
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304891 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shahda008342016-05-17 18:50:40 +05304892 "index, total_rx, interval_rx, total_tx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893
4894 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304895 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shahda008342016-05-17 18:50:40 +05304896 "%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004897 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
4898 hdd_ctx->hdd_txrx_hist[i].interval_rx,
4899 hdd_ctx->hdd_txrx_hist[i].total_tx,
4900 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05304901 convert_level_to_string(
4902 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
4903 convert_level_to_string(
4904 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
4905 convert_level_to_string(
4906 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 }
4908 return;
4909}
4910
4911/**
4912 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
4913 * @hdd_ctx: hdd context
4914 *
4915 * Return: none
4916 */
4917void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
4918{
4919 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05304920 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
4921 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922}
4923
4924/**
4925 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
4926 * @pHddCtx: hdd context
4927 *
4928 * Return: none
4929 */
4930void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
4931{
4932
4933 hdd_adapter_t *adapter = NULL;
4934 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304935 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004936 int i;
Nirav Shahda008342016-05-17 18:50:40 +05304937 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938
4939 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304940 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941 adapter = adapter_node->pAdapter;
4942
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304943 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shahda008342016-05-17 18:50:40 +05304944 "\nNetif queue operation statistics:");
4945 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shah617cff92016-04-25 10:24:24 +05304946 "Session_id %d device mode %d",
4947 adapter->sessionId, adapter->device_mode);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304948 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 "Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05304950 curr_time = qdf_system_ticks();
4951 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05304952 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05304953 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05304954 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05304955 unpause = adapter->total_unpause_time;
4956 } else {
Nirav Shahda008342016-05-17 18:50:40 +05304957 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05304958 pause = adapter->total_pause_time;
4959 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304960 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shah617cff92016-04-25 10:24:24 +05304961 "Total: %ums Pause: %ums Unpause: %ums",
4962 qdf_system_ticks_to_msecs(total),
4963 qdf_system_ticks_to_msecs(pause),
4964 qdf_system_ticks_to_msecs(unpause));
4965 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shahda008342016-05-17 18:50:40 +05304966 "reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004967
Nirav Shahda008342016-05-17 18:50:40 +05304968 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
4969 qdf_time_t pause_delta = 0;
4970
4971 if (adapter->pause_map & (1 << i))
4972 pause_delta = delta;
4973
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304974 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shahda008342016-05-17 18:50:40 +05304975 "%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 hdd_reason_type_to_string(i),
4977 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05304978 adapter->queue_oper_stats[i].unpause_count,
4979 qdf_system_ticks_to_msecs(
4980 adapter->queue_oper_stats[i].total_pause_time +
4981 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004982 }
4983
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304984 hddLog(QDF_TRACE_LEVEL_ERROR,
Nirav Shahda008342016-05-17 18:50:40 +05304985 "\nNetif queue operation history:");
4986 hddLog(QDF_TRACE_LEVEL_ERROR,
4987 "Total entries: %d current index %d",
4988 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
4989
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304990 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004991 "index: time: action_type: reason_type: pause_map");
4992
4993 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304994 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004995 "%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05304996 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997 adapter->queue_oper_history[i].time),
4998 hdd_action_type_to_string(
4999 adapter->queue_oper_history[i].netif_action),
5000 hdd_reason_type_to_string(
5001 adapter->queue_oper_history[i].netif_reason),
5002 adapter->queue_oper_history[i].pause_map);
5003 }
5004
5005 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5006 adapter_node = next;
5007 }
5008
5009
5010}
5011
5012/**
5013 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5014 * @hdd_ctx: hdd context
5015 *
5016 * Return: none
5017 */
5018void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5019{
5020 hdd_adapter_t *adapter = NULL;
5021 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305022 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023
5024 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305025 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005026 adapter = adapter_node->pAdapter;
5027
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305028 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305030 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305032 adapter->history_index = 0;
5033 adapter->start_time = adapter->last_time = qdf_system_ticks();
5034 adapter->total_pause_time = 0;
5035 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5037 adapter_node = next;
5038 }
5039}
5040
5041/**
5042 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5043 * @halHandle: Hal handle
5044 * @pContext: Pointer to the context
5045 * @sessionId: Session ID
5046 * @scanId: Scan ID
5047 * @status: Status
5048 *
5049 * This is the callback to be executed when 11d scan is completed to flush out
5050 * the scan results
5051 *
5052 * 11d scan is done during driver load and is a passive scan on all
5053 * channels supported by the device, 11d scans may find some APs on
5054 * frequencies which are forbidden to be used in the regulatory domain
5055 * the device is operating in. If these APs are notified to the supplicant
5056 * it may try to connect to these APs, thus flush out all the scan results
5057 * which are present in SME after 11d scan is done.
5058 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305059 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005060 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305061static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062 uint8_t sessionId, uint32_t scanId,
5063 eCsrScanStatus status)
5064{
5065 ENTER();
5066
5067 sme_scan_flush_result(halHandle);
5068
5069 EXIT();
5070
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305071 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072}
5073
5074#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5075/**
5076 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5077 * @hdd_ctx: hdd global context
5078 *
5079 * Return: none
5080 */
5081static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5082{
5083 uint8_t i;
5084
5085 mutex_init(&hdd_ctx->op_ctx.op_lock);
5086 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5087 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5088 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5089 }
5090}
5091#else
5092static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5093{
5094}
5095#endif
5096
5097#ifdef WLAN_FEATURE_FASTPATH
5098/**
5099 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5100 * @hdd_cfg: hdd config
5101 * @context: lower layer context
5102 *
5103 * Return: none
5104 */
5105static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
5106 void *context)
5107{
5108 if (hdd_cfg->fastpath_enable)
5109 hif_enable_fastpath(context);
5110}
5111#else
5112static void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
5113 void *context)
5114{
5115}
5116#endif
5117
Yuanyuan Liu13738502016-04-06 17:41:37 -07005118#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005119/**
5120 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005121 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122 * @level: thermal level
5123 *
5124 * Change IPA data path to SW path when the thermal throttle level greater
5125 * than 0, and restore the original data path when throttle level is 0
5126 *
5127 * Return: none
5128 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005129static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005130{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005131 hdd_context_t *hdd_ctx = context;
5132
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133 /* Change IPA to SW path when throttle level greater than 0 */
5134 if (level > THROTTLE_LEVEL_0)
5135 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5136 else
5137 /* restore original concurrency mode */
5138 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5139}
5140
5141/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305142 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5143 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305144 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005145 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305146 * Get a safe channel to restart SAP. PCL already takes into account the
5147 * unsafe channels. So, the PCL is validated with the ACS range to provide
5148 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305150 * Return: Channel number to restart SAP in case of success. In case of any
5151 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005152 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305153static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5154 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005155{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305156 struct sir_pcl_list pcl;
5157 QDF_STATUS status;
5158 uint32_t i, j;
5159 tHalHandle *hal_handle;
5160 hdd_context_t *hdd_ctx;
5161 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005162
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305163 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5164 if (!hdd_ctx) {
5165 hdd_err("invalid HDD context");
5166 return INVALID_CHANNEL_ID;
5167 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305169 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5170 if (!hal_handle) {
5171 hdd_err("invalid HAL handle");
5172 return INVALID_CHANNEL_ID;
5173 }
5174
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305175 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5176 pcl.pcl_list, &pcl.pcl_len,
5177 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5178 if (QDF_IS_STATUS_ERROR(status)) {
5179 hdd_err("Get PCL failed");
5180 return INVALID_CHANNEL_ID;
5181 }
5182
5183 if (!pcl.pcl_len) {
5184 hdd_alert("pcl length is zero. this is not expected");
5185 return INVALID_CHANNEL_ID;
5186 }
5187
5188 hdd_info("start:%d end:%d",
5189 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5190 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5191
5192 /* PCL already takes unsafe channel into account */
5193 for (i = 0; i < pcl.pcl_len; i++) {
5194 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5195 if ((pcl.pcl_list[i] >=
5196 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5197 (pcl.pcl_list[i] <=
5198 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5199 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5200 return pcl.pcl_list[i];
5201 }
5202 }
5203
5204 hdd_info("no safe channel from PCL found in ACS range");
5205
5206 /* Try for safe channel from all valid channel */
5207 pcl.pcl_len = MAX_NUM_CHAN;
5208 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5209 &pcl.pcl_len);
5210 if (QDF_IS_STATUS_ERROR(status)) {
5211 hdd_err("error in getting valid channel list");
5212 return INVALID_CHANNEL_ID;
5213 }
5214
5215 for (i = 0; i < pcl.pcl_len; i++) {
5216 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5217 found = false;
5218 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
5219 if (cds_chan_to_freq(pcl.pcl_list[i]) ==
5220 hdd_ctx->unsafe_channel_list[j]) {
5221 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5222 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 break;
5224 }
5225 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305226
5227 if (found)
5228 continue;
5229
5230 if ((pcl.pcl_list[i] >=
5231 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5232 (pcl.pcl_list[i] <=
5233 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5234 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5235 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236 }
5237 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305238
5239 return INVALID_CHANNEL_ID;
5240}
5241
5242/**
5243 * hdd_restart_sap() - Restarts SAP on the given channel
5244 * @adapter: AP adapter
5245 * @channel: Channel
5246 *
5247 * Restarts the SAP interface by invoking the function which executes the
5248 * callback to perform channel switch using (E)CSA.
5249 *
5250 * Return: None
5251 */
5252void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
5253{
5254 hdd_ap_ctx_t *hdd_ap_ctx;
5255 tHalHandle *hal_handle;
5256
5257 if (!adapter) {
5258 hdd_err("invalid adapter");
5259 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305261
5262 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5263
5264 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5265 if (!hal_handle) {
5266 hdd_err("invalid HAL handle");
5267 return;
5268 }
5269
5270 hdd_ap_ctx->sapConfig.channel = channel;
5271 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5272 hdd_ap_ctx->sapConfig.ch_width_orig;
5273
5274 hdd_info("chan:%d width:%d",
5275 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5276
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005277 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305278 hdd_ap_ctx->sapConfig.sec_ch,
5279 &hdd_ap_ctx->sapConfig.ch_params);
5280
5281 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005282}
5283
5284/**
5285 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
5286 * @adapter: HDD adapter pointer
5287 * @indParam: Channel avoid notification parameter
5288 *
5289 * Avoid channel notification from FW handler.
5290 * FW will send un-safe channel list to avoid over wrapping.
5291 * hostapd should not use notified channel
5292 *
5293 * Return: None
5294 */
5295static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
5296{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 hdd_context_t *hdd_ctxt;
5298 tSirChAvoidIndType *ch_avoid_indi;
5299 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08005300 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
5301 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005302 uint16_t start_channel;
5303 uint16_t end_channel;
5304 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005305 tHddAvoidFreqList hdd_avoid_freq_list;
5306 uint32_t i;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305307 QDF_STATUS status;
5308 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
5309 hdd_adapter_t *adapter_temp;
5310 uint8_t restart_chan;
5311 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005312
5313 /* Basic sanity */
5314 if (!hdd_context || !indi_param) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305315 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid arguments"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005316 return;
5317 }
5318
5319 hdd_ctxt = (hdd_context_t *) hdd_context;
5320 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
5321 cds_context = hdd_ctxt->pcds_context;
5322
5323 /* Make unsafe channel list */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305324 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325 FL("band count %d"),
5326 ch_avoid_indi->avoid_range_count);
5327
5328 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305329 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
5331 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
5332 ch_avoid_indi->avoid_freq_range[i].start_freq;
5333 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
5334 ch_avoid_indi->avoid_freq_range[i].end_freq;
5335 }
5336 hdd_avoid_freq_list.avoidFreqRangeCount =
5337 ch_avoid_indi->avoid_range_count;
5338
5339 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
5340
5341 /* clear existing unsafe channel cache */
5342 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305343 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005344 sizeof(hdd_ctxt->unsafe_channel_list));
5345
5346 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
5347 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08005348 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 hddLog(LOGW, FL("LTE Coex unsafe channel list full"));
5350 break;
5351 }
5352
5353 start_channel = ieee80211_frequency_to_channel(
5354 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
5355 end_channel = ieee80211_frequency_to_channel(
5356 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
5357 hddLog(LOG1, "%s : start %d : %d, end %d : %d", __func__,
5358 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
5359 start_channel,
5360 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
5361 end_channel);
5362
5363 /* do not process frequency bands that are not mapped to
5364 * predefined channels
5365 */
5366 if (start_channel == 0 || end_channel == 0)
5367 continue;
5368
Amar Singhalb8d4f152016-02-10 10:21:43 -08005369 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5370 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005371 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 ch_avoid_indi->avoid_freq_range[
5373 range_loop].start_freq) {
5374 start_channel_idx = channel_loop;
5375 break;
5376 }
5377 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08005378 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5379 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005380 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381 ch_avoid_indi->avoid_freq_range[
5382 range_loop].end_freq) {
5383 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07005384 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 ch_avoid_indi->avoid_freq_range[
5386 range_loop].end_freq)
5387 end_channel_idx--;
5388 break;
5389 }
5390 }
5391
Amar Singhalb8d4f152016-02-10 10:21:43 -08005392 if (start_channel_idx == INVALID_CHANNEL ||
5393 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005394 continue;
5395
5396 for (channel_loop = start_channel_idx; channel_loop <=
5397 end_channel_idx; channel_loop++) {
5398 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07005399 hdd_ctxt->unsafe_channel_count++] =
5400 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005401 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08005402 NUM_CHANNELS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005403 hddLog(LOGW, FL("LTECoex unsafe ch list full"));
5404 break;
5405 }
5406 }
5407 }
5408
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305409 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410 FL("number of unsafe channels is %d "),
5411 hdd_ctxt->unsafe_channel_count);
5412
Yuanyuan Liu13738502016-04-06 17:41:37 -07005413 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
5414 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 hdd_ctxt->unsafe_channel_count)) {
5416 hdd_err("Failed to set unsafe channel");
5417
5418 /* clear existing unsafe channel cache */
5419 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305420 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 sizeof(hdd_ctxt->unsafe_channel_list));
5422
5423 return;
5424 }
5425
5426 for (channel_loop = 0;
5427 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305428 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429 FL("channel %d is not safe "),
5430 hdd_ctxt->unsafe_channel_list[channel_loop]);
5431 }
5432
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305433 if (!hdd_ctxt->unsafe_channel_count) {
5434 hdd_info("no unsafe channels - not restarting SAP");
5435 return;
5436 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305438 /* No channel change is done for fixed channel SAP.
5439 * Loop through all ACS SAP interfaces and change the channels for
5440 * the ones operating on unsafe channels.
5441 */
5442 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
5443 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5444 adapter_temp = adapter_node->pAdapter;
5445
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305446 if (!adapter_temp) {
5447 hdd_err("adapter is NULL, moving to next one");
5448 goto next_adapater;
5449 }
5450
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305451 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
5452 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
5453 hdd_info("skip device mode:%d acs:%d",
5454 adapter_temp->device_mode,
5455 adapter_temp->sessionCtx.ap.sapConfig.
5456 acs_cfg.acs_mode);
5457 goto next_adapater;
5458 }
5459
5460 found = false;
5461 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
5462 if (cds_chan_to_freq(
5463 adapter_temp->sessionCtx.ap.operatingChannel) ==
5464 hdd_ctxt->unsafe_channel_list[i]) {
5465 found = true;
5466 hdd_info("operating ch:%d is unsafe",
5467 adapter_temp->sessionCtx.ap.operatingChannel);
5468 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469 }
5470 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305471
5472 if (!found) {
5473 hdd_info("ch:%d is safe. no need to change channel",
5474 adapter_temp->sessionCtx.ap.operatingChannel);
5475 goto next_adapater;
5476 }
5477
5478 restart_chan =
5479 hdd_get_safe_channel_from_pcl_and_acs_range(
5480 adapter_temp);
5481 if (!restart_chan) {
5482 hdd_alert("fail to restart SAP");
5483 } else {
5484 hdd_info("sending coex indication");
5485 wlan_hdd_send_svc_nlink_msg
5486 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
5487 hdd_restart_sap(adapter_temp, restart_chan);
5488 }
5489
5490next_adapater:
5491 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
5492 adapter_node = next;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 }
5494 return;
5495}
5496
5497/**
5498 * hdd_init_channel_avoidance() - Initialize channel avoidance
5499 * @hdd_ctx: HDD global context
5500 *
5501 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07005502 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005503 * down to the lower layers. Then subscribe to subsequent channel
5504 * avoidance events.
5505 *
5506 * Return: None
5507 */
5508static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5509{
5510 uint16_t unsafe_channel_count;
5511 int index;
5512
Yuanyuan Liu13738502016-04-06 17:41:37 -07005513 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
5514 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08005516 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305518 hddLog(QDF_TRACE_LEVEL_INFO, FL("num of unsafe channels is %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005519 hdd_ctx->unsafe_channel_count);
5520
Anurag Chouhan6d760662016-02-20 16:05:43 +05305521 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08005522 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523
5524 for (index = 0; index < unsafe_channel_count; index++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305525 hddLog(QDF_TRACE_LEVEL_INFO, FL("channel %d is not safe"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526 hdd_ctx->unsafe_channel_list[index]);
5527
5528 }
5529
5530 /* Plug in avoid channel notification callback */
5531 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
5532}
5533#else
5534static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5535{
5536}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005537static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538{
5539}
Yuanyuan Liu13738502016-04-06 17:41:37 -07005540#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541
5542/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08005543 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
5544 * user space
5545 * @frame_ind: Management frame data to be informed.
5546 *
5547 * This function is used to indicate management frame to
5548 * user space
5549 *
5550 * Return: None
5551 *
5552 */
5553void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
5554{
5555 hdd_context_t *hdd_ctx = NULL;
5556 hdd_adapter_t *adapter = NULL;
5557 void *cds_context = NULL;
5558 int i;
5559
5560 /* Get the global VOSS context.*/
5561 cds_context = cds_get_global_context();
5562 if (!cds_context) {
5563 hdd_err("Global CDS context is Null");
5564 return;
5565 }
5566 /* Get the HDD context.*/
5567 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
5568
5569 if (0 != wlan_hdd_validate_context(hdd_ctx))
5570 return;
5571
5572 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
5573 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
5574 adapter =
5575 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
5576 if (adapter)
5577 break;
5578 }
5579 } else {
5580 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
5581 frame_ind->sessionId);
5582 }
5583
5584 if ((NULL != adapter) &&
5585 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
5586 __hdd_indicate_mgmt_frame(adapter,
5587 frame_ind->frame_len,
5588 frame_ind->frameBuf,
5589 frame_ind->frameType,
5590 frame_ind->rxChan,
5591 frame_ind->rxRssi);
5592 return;
5593}
5594
5595/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005596 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
5597 * @hdd_ctx: HDD context
5598 *
5599 * Disables all the dual mac features like DBS, Agile DFS etc.
5600 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305601 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305603static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604{
5605 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305606 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005607
5608 if (!hdd_ctx) {
5609 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305610 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611 }
5612
5613 cfg.scan_config = 0;
5614 cfg.fw_mode_config = 0;
5615 cfg.set_dual_mac_cb =
5616 (void *)cds_soc_set_dual_mac_cfg_cb;
5617
5618 hdd_debug("Disabling all dual mac features...");
5619
5620 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305621 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005622 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
5623 return status;
5624 }
5625
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305626 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627}
5628
5629/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005630 * hdd_override_ini_config - Override INI config
5631 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005633 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005634 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005635 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005636 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005637static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005638{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005639
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005640 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
5641 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5642 hdd_notice("Module enable_dfs_chan_scan set to %d",
5643 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005645 if (0 == enable_11d || 1 == enable_11d) {
5646 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5647 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005648 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005649}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005651/**
5652 * hdd_set_trace_level_for_each - Set trace level for each INI config
5653 * @hdd_ctx - HDD context
5654 *
5655 * Set trace level for each module based on INI config.
5656 *
5657 * Return: None
5658 */
5659static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5660{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305661 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
5662 hdd_ctx->config->qdf_trace_enable_wdi);
5663 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
5664 hdd_ctx->config->qdf_trace_enable_hdd);
5665 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
5666 hdd_ctx->config->qdf_trace_enable_sme);
5667 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
5668 hdd_ctx->config->qdf_trace_enable_pe);
5669 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
5670 hdd_ctx->config->qdf_trace_enable_wma);
5671 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
5672 hdd_ctx->config->qdf_trace_enable_sys);
5673 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
5674 hdd_ctx->config->qdf_trace_enable_qdf);
5675 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
5676 hdd_ctx->config->qdf_trace_enable_sap);
5677 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
5678 hdd_ctx->config->qdf_trace_enable_hdd_sap);
5679 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
5680 hdd_ctx->config->qdf_trace_enable_bmi);
5681 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
5682 hdd_ctx->config->qdf_trace_enable_cfg);
5683 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
5684 hdd_ctx->config->qdf_trace_enable_epping);
5685 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
5686 hdd_ctx->config->qdf_trace_enable_qdf_devices);
5687 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05305688 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305689 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
5690 hdd_ctx->config->qdf_trace_enable_htc);
5691 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
5692 hdd_ctx->config->qdf_trace_enable_hif);
5693 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
5694 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
5695 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
5696 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005698 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005699}
5700
5701/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005702 * hdd_context_init() - Initialize HDD context
5703 * @hdd_ctx: HDD context.
5704 *
5705 * Initialize HDD context along with all the feature specific contexts.
5706 *
5707 * return: 0 on success and errno on failure.
5708 */
5709static int hdd_context_init(hdd_context_t *hdd_ctx)
5710{
5711 int ret;
5712
5713 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5714 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5715
5716 hdd_init_ll_stats_ctx();
5717
5718 init_completion(&hdd_ctx->mc_sus_event_var);
5719 init_completion(&hdd_ctx->ready_to_suspend);
5720
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305721 hdd_init_bpf_completion();
5722
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005723 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305724 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005725 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305726
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005727 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
5728
5729 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
5730
5731 ret = hdd_scan_context_init(hdd_ctx);
5732 if (ret)
5733 goto list_destroy;
5734
5735 hdd_tdls_context_init(hdd_ctx);
5736
5737 hdd_rx_wake_lock_create(hdd_ctx);
5738
5739 ret = hdd_sap_context_init(hdd_ctx);
5740 if (ret)
5741 goto scan_destroy;
5742
5743 ret = hdd_roc_context_init(hdd_ctx);
5744 if (ret)
5745 goto sap_destroy;
5746
5747 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
5748
5749 hdd_init_offloaded_packets_ctx(hdd_ctx);
5750
5751 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
5752 hdd_ctx->config);
5753 if (ret)
5754 goto roc_destroy;
5755
5756 return 0;
5757
5758roc_destroy:
5759 hdd_roc_context_destroy(hdd_ctx);
5760
5761sap_destroy:
5762 hdd_sap_context_destroy(hdd_ctx);
5763
5764scan_destroy:
5765 hdd_scan_context_destroy(hdd_ctx);
5766 hdd_rx_wake_lock_destroy(hdd_ctx);
5767 hdd_tdls_context_destroy(hdd_ctx);
5768
5769list_destroy:
5770 qdf_list_destroy(&hdd_ctx->hddAdapters);
5771 return ret;
5772}
5773
5774/**
5775 * hdd_context_create() - Allocate and inialize HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005776 * @dev: Pointer to the underlying device
5777 * @hif_sc: HIF context
5778 *
5779 * Allocate and initialize HDD context. HDD context is allocated as part of
5780 * wiphy allocation and then context is initialized.
5781 *
5782 * Return: HDD context on success and ERR_PTR on failure
5783 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005784hdd_context_t *hdd_context_create(struct device *dev, void *hif_sc)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005785{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305786 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005787 int ret = 0;
5788 hdd_context_t *hdd_ctx;
5789 v_CONTEXT_t p_cds_context;
Komal Seelamc11bb222016-01-27 18:57:10 +05305790 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_sc);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005791
5792 ENTER();
5793
5794 p_cds_context = cds_get_global_context();
5795 if (p_cds_context == NULL) {
5796 hdd_alert("Failed to get CDS global context");
5797 ret = -EINVAL;
5798 goto err_out;
5799 }
5800
5801 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
5802
5803 if (hdd_ctx == NULL) {
5804 ret = -ENOMEM;
5805 goto err_out;
5806 }
5807
5808 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005809 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005810
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305811 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005812 if (hdd_ctx->config == NULL) {
5813 hdd_alert("Failed to alloc memory for HDD config!");
5814 ret = -ENOMEM;
5815 goto err_free_hdd_context;
5816 }
5817
5818 /* Read and parse the qcom_cfg.ini file */
5819 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305820 if (QDF_STATUS_SUCCESS != status) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005821 hdd_alert("Error (status: %d) parsing INI file: %s", status,
5822 WLAN_INI_FILE);
5823 ret = -EINVAL;
5824 goto err_free_config;
5825 }
5826
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005827 hdd_ctx->configuredMcastBcastFilter =
5828 hdd_ctx->config->mcastBcastFilterSetting;
5829
5830 hdd_notice("Setting configuredMcastBcastFilter: %d",
5831 hdd_ctx->config->mcastBcastFilterSetting);
5832
Abhishek Singh5ea86532016-04-27 14:10:53 +05305833 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
5834
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005835 hdd_override_ini_config(hdd_ctx);
5836
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005837 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005838
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005839 ret = hdd_context_init(hdd_ctx);
5840
5841 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005842 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005843
5844 hdd_ctx->target_type = tgt_info->target_type;
5845
Yuanyuan Liu13738502016-04-06 17:41:37 -07005846 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
5847 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005848
5849 hdd_enable_fastpath(hdd_ctx->config, hif_sc);
5850
5851 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05305852 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005853
Anurag Chouhan6d760662016-02-20 16:05:43 +05305854 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005855 goto skip_multicast_logging;
5856
5857 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
5858
Nirav Shahed34b212016-04-25 10:59:16 +05305859 status = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
5860 if (status)
5861 goto err_free_config;
5862
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005863 ret = hdd_logging_sock_activate_svc(hdd_ctx);
5864 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05305865 goto err_free_histogram;
5866
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005867
5868 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305869 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005870 * levels of the code need not be set when the logger thread
5871 * is not enabled.
5872 */
5873 if (cds_is_multicast_logging())
5874 wlan_logging_set_log_level();
5875
5876skip_multicast_logging:
5877 hdd_set_trace_level_for_each(hdd_ctx);
5878
5879 return hdd_ctx;
5880
Nirav Shahed34b212016-04-25 10:59:16 +05305881err_free_histogram:
5882 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
5883
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005884err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305885 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005886
5887err_free_hdd_context:
5888 wiphy_free(hdd_ctx->wiphy);
5889
5890err_out:
5891 return ERR_PTR(ret);
5892}
5893
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005894#ifdef WLAN_OPEN_P2P_INTERFACE
5895/**
5896 * hdd_open_p2p_interface - Open P2P interface
5897 * @hdd_ctx: HDD context
5898 * @rtnl_held: True if RTNL lock held
5899 *
5900 * Open P2P interface during probe. This function called to open the P2P
5901 * interface at probe along with STA interface.
5902 *
5903 * Return: 0 on success and errno on failure
5904 */
5905static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
5906{
5907 hdd_adapter_t *adapter;
5908 uint8_t *p2p_dev_addr;
5909
5910 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
5911 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305912 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005913 hdd_ctx->config->intfMacAddr[0].bytes,
5914 sizeof(tSirMacAddr));
5915
5916 /*
5917 * Generate the P2P Device Address. This consists of
5918 * the device's primary MAC address with the locally
5919 * administered bit set.
5920 */
5921 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
5922 } else {
5923 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
5924 if (p2p_dev_addr == NULL) {
5925 hdd_alert("Failed to allocate mac_address for p2p_device");
5926 return -ENOSPC;
5927 }
5928
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305929 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305930 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005931 }
5932
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005933 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005934 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08005935 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005936
5937 if (NULL == adapter) {
5938 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
5939 return -ENOSPC;
5940 }
5941
5942 return 0;
5943}
5944#else
5945static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx,
5946 bool rtnl_held)
5947{
5948 return 0;
5949}
5950#endif
5951
5952/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07005953 * hdd_open_monitor_interface() - Open monitor mode interface
5954 * @hdd_ctx: HDD context
5955 * @rtnl_held: True if RTNL lock is held
5956 *
5957 * Return: Primary adapter on success and PTR_ERR on failure
5958 */
5959static hdd_adapter_t *hdd_open_monitor_interface(hdd_context_t *hdd_ctx,
5960 bool rtnl_held)
5961{
5962 return hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d",
5963 wlan_hdd_get_intf_addr(hdd_ctx),
5964 NET_NAME_UNKNOWN, rtnl_held);
5965}
5966
5967/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005968 * hdd_open_interfaces - Open all required interfaces
5969 * hdd_ctx: HDD context
5970 * rtnl_held: True if RTNL lock is held
5971 *
5972 * Open all the interfaces like STA, P2P and OCB based on the configuration.
5973 *
5974 * Return: Primary adapter on success and PTR_ERR on failure
5975 */
5976static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
5977 bool rtnl_held)
5978{
5979 hdd_adapter_t *adapter = NULL;
5980 hdd_adapter_t *adapter_11p = NULL;
5981 int ret;
5982
5983 /* Create only 802.11p interface */
5984 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005985 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005986 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08005987 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005988
5989 if (adapter == NULL)
5990 return ERR_PTR(-ENOSPC);
5991
5992 return adapter;
5993 }
5994
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005995 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005996 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08005997 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08005998
5999 if (adapter == NULL)
6000 return ERR_PTR(-ENOSPC);
6001
6002 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6003 if (ret)
6004 goto err_close_adapter;
6005
6006 /* Open 802.11p Interface */
6007 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006008 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006009 "wlanocb%d",
6010 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006011 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006012 if (adapter_11p == NULL) {
6013 hdd_err("Failed to open 802.11p interface");
6014 goto err_close_adapter;
6015 }
6016 }
6017
6018 return adapter;
6019
6020err_close_adapter:
6021 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6022 return ERR_PTR(ret);
6023}
6024
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006025/**
6026 * hdd_update_country_code - Update country code
6027 * @hdd_ctx: HDD context
6028 * @adapter: Primary adapter context
6029 *
6030 * Update country code based on module parameter country_code at SME and wait
6031 * for the settings to take effect.
6032 *
6033 * Return: 0 on success and errno on failure
6034 */
6035static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6036 hdd_adapter_t *adapter)
6037{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306038 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006039 int ret = 0;
6040 unsigned long rc;
6041
6042 if (country_code == NULL)
6043 return 0;
6044
6045 INIT_COMPLETION(adapter->change_country_code);
6046
6047 status = sme_change_country_code(hdd_ctx->hHal,
6048 wlan_hdd_change_country_code_callback,
6049 country_code, adapter,
6050 hdd_ctx->pcds_context, eSIR_TRUE,
6051 eSIR_TRUE);
6052
6053
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306054 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006055 hdd_err("SME Change Country code from module param fail ret=%d",
6056 ret);
6057 return -EINVAL;
6058 }
6059
6060 rc = wait_for_completion_timeout(&adapter->change_country_code,
6061 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6062 if (!rc) {
6063 hdd_err("SME while setting country code timed out");
6064 ret = -ETIMEDOUT;
6065 }
6066
6067 return ret;
6068}
6069
6070/**
6071 * hdd_init_thermal_info - Initialize thermal level
6072 * @hdd_ctx: HDD context
6073 *
6074 * Initialize thermal level at SME layer and set the thermal level callback
6075 * which would be called when a configured thermal threshold is hit.
6076 *
6077 * Return: 0 on success and errno on failure
6078 */
6079static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
6080{
6081 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306082 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006083
6084 thermal_param.smeThermalMgmtEnabled =
6085 hdd_ctx->config->thermalMitigationEnable;
6086 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
6087
Poddar, Siddarth83905022016-04-16 17:56:08 -07006088 thermal_param.sme_throttle_duty_cycle_tbl[0] =
6089 hdd_ctx->config->throttle_dutycycle_level0;
6090 thermal_param.sme_throttle_duty_cycle_tbl[1] =
6091 hdd_ctx->config->throttle_dutycycle_level1;
6092 thermal_param.sme_throttle_duty_cycle_tbl[2] =
6093 hdd_ctx->config->throttle_dutycycle_level2;
6094 thermal_param.sme_throttle_duty_cycle_tbl[3] =
6095 hdd_ctx->config->throttle_dutycycle_level3;
6096
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006097 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
6098 hdd_ctx->config->thermalTempMinLevel0;
6099 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
6100 hdd_ctx->config->thermalTempMaxLevel0;
6101 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
6102 hdd_ctx->config->thermalTempMinLevel1;
6103 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
6104 hdd_ctx->config->thermalTempMaxLevel1;
6105 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
6106 hdd_ctx->config->thermalTempMinLevel2;
6107 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
6108 hdd_ctx->config->thermalTempMaxLevel2;
6109 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
6110 hdd_ctx->config->thermalTempMinLevel3;
6111 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
6112 hdd_ctx->config->thermalTempMaxLevel3;
6113
6114 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
6115
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306116 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05306117 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006118
6119 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
6120 hdd_set_thermal_level_cb);
6121
6122 return 0;
6123
6124}
6125
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006126#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
6127/**
6128 * hdd_hold_rtnl_lock - Hold RTNL lock
6129 *
6130 * Hold RTNL lock
6131 *
6132 * Return: True if held and false otherwise
6133 */
6134static inline bool hdd_hold_rtnl_lock(void)
6135{
6136 rtnl_lock();
6137 return true;
6138}
6139
6140/**
6141 * hdd_release_rtnl_lock - Release RTNL lock
6142 *
6143 * Release RTNL lock
6144 *
6145 * Return: None
6146 */
6147static inline void hdd_release_rtnl_lock(void)
6148{
6149 rtnl_unlock();
6150}
6151#else
6152static inline bool hdd_hold_rtnl_lock(void) { return false; }
6153static inline void hdd_release_rtnl_lock(void) { }
6154#endif
6155
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05306156#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
6157/**
6158 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
6159 * switch without restart
6160 *
6161 * Registers callback function to change the operating channel of SAP by using
6162 * channel switch announcements instead of restarting SAP.
6163 *
6164 * Return: QDF_STATUS
6165 */
6166QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
6167{
6168 QDF_STATUS status;
6169
6170 status = cds_register_sap_restart_channel_switch_cb(
6171 (void *)hdd_sap_restart_with_channel_switch);
6172 if (!QDF_IS_STATUS_SUCCESS(status))
6173 hdd_err("restart cb registration failed");
6174
6175 return status;
6176}
6177#endif
6178
Komal Seelam92fff912016-03-24 11:51:41 +05306179#ifdef CONFIG_CNSS
6180/**
6181 * hdd_get_cnss_wlan_mac_buff() - API to query platform driver for MAC address
6182 * @dev: Device Pointer
6183 * @num: Number of Valid Mac address
6184 *
6185 * Return: Pointer to MAC address buffer
6186 */
6187static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6188{
6189 return cnss_common_get_wlan_mac_address(dev, num);
6190}
6191#else
6192static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6193{
6194 *num = 0;
6195 return NULL;
6196}
6197#endif
6198
6199/**
6200 * hdd_populate_random_mac_addr() - API to populate random mac addresses
6201 * @hdd_ctx: HDD Context
6202 * @num: Number of random mac addresses needed
6203 *
6204 * Generate random addresses using bit manipulation on the base mac address
6205 *
6206 * Return: None
6207 */
6208static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
6209{
6210 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
6211 uint32_t iter;
6212 struct hdd_config *ini = hdd_ctx->config;
6213 uint8_t *buf = NULL;
6214 uint8_t macaddr_b3, tmp_br3;
6215 uint8_t *src = ini->intfMacAddr[0].bytes;
6216
6217 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
6218 buf = ini->intfMacAddr[iter].bytes;
6219 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
6220 macaddr_b3 = buf[3];
6221 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
6222 INTF_MACADDR_MASK;
6223 macaddr_b3 += tmp_br3;
6224 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
6225 buf[0] |= 0x02;
6226 buf[3] = macaddr_b3;
6227 hdd_info(FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(buf));
6228 }
6229}
6230
6231/**
6232 * hdd_cnss_wlan_mac() - API to get mac addresses from cnss platform driver
6233 * @hdd_ctx: HDD Context
6234 *
6235 * API to get mac addresses from platform driver and update the driver
6236 * structures and configure FW with the base mac address.
6237 * Return: int
6238 */
6239static int hdd_cnss_wlan_mac(hdd_context_t *hdd_ctx)
6240{
6241 uint32_t no_of_mac_addr, iter;
6242 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
6243 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
6244 uint8_t *addr, *buf;
6245 struct device *dev = hdd_ctx->parent_dev;
6246 struct hdd_config *ini = hdd_ctx->config;
6247 tSirMacAddr mac_addr;
6248 QDF_STATUS status;
6249
6250 addr = hdd_get_cnss_wlan_mac_buff(dev, &no_of_mac_addr);
6251
6252 if (no_of_mac_addr == 0 || !addr) {
6253 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
6254 return -EINVAL;
6255 }
6256
6257 if (no_of_mac_addr > max_mac_addr)
6258 no_of_mac_addr = max_mac_addr;
6259
6260 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
6261
6262 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
6263 buf = ini->intfMacAddr[iter].bytes;
6264 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
6265 hdd_info(FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(buf));
6266 }
6267
6268 status = sme_set_custom_mac_addr(mac_addr);
6269
6270 if (!QDF_IS_STATUS_SUCCESS(status))
6271 return -EAGAIN;
6272 if (no_of_mac_addr < max_mac_addr)
6273 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
6274 no_of_mac_addr);
6275 return 0;
6276}
6277
6278/**
6279 * hdd_initialize_mac_address() - API to get wlan mac addresses
6280 * @hdd_ctx: HDD Context
6281 *
6282 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
6283 * is provisioned with mac addresses, driver uses it, else it will use
6284 * wlan_mac.bin to update HW MAC addresses.
6285 *
6286 * Return: None
6287 */
6288static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
6289{
6290 QDF_STATUS status;
6291 int ret;
6292
6293 ret = hdd_cnss_wlan_mac(hdd_ctx);
6294 if (ret == 0)
6295 return;
6296
6297 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
6298
6299 status = hdd_update_mac_config(hdd_ctx);
6300
6301 if (!QDF_IS_STATUS_SUCCESS(status))
6302 hdd_warn("can't update mac config, using MAC from ini file");
6303}
6304
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006305/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07006306 * hdd_tsf_init() - Initialize the TSF synchronization interface
6307 * @hdd_ctx: HDD global context
6308 *
6309 * When TSF synchronization via GPIO is supported by the driver and
6310 * has been enabled in the configuration file, this function plumbs
6311 * the GPIO value down to firmware via SME.
6312 *
6313 * Return: None
6314 */
6315#ifdef WLAN_FEATURE_TSF
6316static void hdd_tsf_init(hdd_context_t *hdd_ctx)
6317{
6318 QDF_STATUS status;
6319
6320 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
6321 return;
6322
6323 status = sme_set_tsf_gpio(hdd_ctx->hHal,
6324 hdd_ctx->config->tsf_gpio_pin);
6325 if (!QDF_IS_STATUS_SUCCESS(status))
6326 hdd_err("Set tsf GPIO failed, status: %d", status);
6327}
6328#else
6329static void hdd_tsf_init(hdd_context_t *hdd_ctx)
6330{
6331}
6332#endif
6333
6334/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07006335 * hdd_pre_enable_configure() - Configurations prior to cds_enable
6336 * @hdd_ctx: HDD context
6337 *
6338 * Pre configurations to be done at lower layer before calling cds enable.
6339 *
6340 * Return: 0 on success and errno on failure.
6341 */
6342static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
6343{
6344 int ret;
6345 QDF_STATUS status;
6346 tSirRetStatus hal_status;
6347
6348 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
6349
6350 /*
6351 * Set 802.11p config
6352 * TODO-OCB: This has been temporarily added here to ensure this
6353 * parameter is set in CSR when we init the channel list. This should
6354 * be removed once the 5.9 GHz channels are added to the regulatory
6355 * domain.
6356 */
6357 hdd_set_dot11p_config(hdd_ctx);
6358
6359 /*
6360 * Note that the cds_pre_enable() sequence triggers the cfg download.
6361 * The cfg download must occur before we update the SME config
6362 * since the SME config operation must access the cfg database
6363 */
6364 status = hdd_set_sme_config(hdd_ctx);
6365
6366 if (QDF_STATUS_SUCCESS != status) {
6367 hdd_alert("Failed hdd_set_sme_config: %d", status);
6368 ret = qdf_status_to_os_return(status);
6369 goto out;
6370 }
6371
6372 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
6373 hdd_ctx->config->tx_chain_mask_1ss,
6374 PDEV_CMD);
6375 if (0 != ret) {
6376 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
6377 goto out;
6378 }
6379
6380 hdd_program_country_code(hdd_ctx);
6381
6382 status = hdd_set_sme_chan_list(hdd_ctx);
6383 if (status != QDF_STATUS_SUCCESS) {
6384 hdd_alert("Failed to init channel list: %d", status);
6385 ret = qdf_status_to_os_return(status);
6386 goto out;
6387 }
6388
6389 /* Apply the cfg.ini to cfg.dat */
6390 if (!hdd_update_config_dat(hdd_ctx)) {
6391 hdd_alert("config update failed");
6392 ret = -EINVAL;
6393 goto out;
6394 }
6395
Komal Seelam92fff912016-03-24 11:51:41 +05306396 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta07998752016-04-28 12:35:33 -07006397
6398 /*
6399 * Set the MAC Address Currently this is used by HAL to add self sta.
6400 * Remove this once self sta is added as part of session open.
6401 */
6402 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
6403 hdd_ctx->config->intfMacAddr[0].bytes,
6404 sizeof(hdd_ctx->config->intfMacAddr[0]));
6405
6406 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
6407 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
6408 hal_status, hal_status);
6409 ret = -EINVAL;
6410 goto out;
6411 }
6412
6413 hdd_init_channel_avoidance(hdd_ctx);
6414
6415out:
6416 return ret;
6417}
6418
6419/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05306420 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
6421 * @hdd_ctx: HDD context
6422 *
6423 * This function sends the adaptive dwell time config configuration to the
6424 * firmware via WMA
6425 *
6426 * Return: 0 - success, < 0 - failure
6427 */
6428static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
6429{
6430 QDF_STATUS status;
6431 struct adaptive_dwelltime_params dwelltime_params;
6432
6433 dwelltime_params.is_enabled =
6434 hdd_ctx->config->adaptive_dwell_mode_enabled;
6435 dwelltime_params.dwelltime_mode =
6436 hdd_ctx->config->global_adapt_dwelltime_mode;
6437 dwelltime_params.lpf_weight =
6438 hdd_ctx->config->adapt_dwell_lpf_weight;
6439 dwelltime_params.passive_mon_intval =
6440 hdd_ctx->config->adapt_dwell_passive_mon_intval;
6441 dwelltime_params.wifi_act_threshold =
6442 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
6443
6444 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
6445 &dwelltime_params);
6446
6447 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
6448 if (!QDF_IS_STATUS_SUCCESS(status)) {
6449 hdd_err("Failed to send Adaptive Dwelltime configuration!");
6450 return -EAGAIN;
6451 }
6452 return 0;
6453}
6454
6455/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006456 * hdd_wlan_startup() - HDD init function
6457 * @dev: Pointer to the underlying device
6458 *
6459 * This is the driver startup code executed once a WLAN device has been detected
6460 *
6461 * Return: 0 for success, < 0 for failure
6462 */
6463int hdd_wlan_startup(struct device *dev, void *hif_sc)
6464{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306465 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006466 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006467 hdd_context_t *hdd_ctx = NULL;
6468 int ret;
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006469 tSirTxPowerLimit hddtxlimit;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006470 bool rtnl_held;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006471
6472 ENTER();
6473
Houston Hoffman371d4a92016-04-14 17:02:37 -07006474 if (QDF_IS_EPPING_ENABLED(con_mode)) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006475 ret = epping_enable(dev);
6476 EXIT();
6477 return ret;
6478 }
6479
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006480 hdd_ctx = hdd_context_create(dev, hif_sc);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006481
6482 if (IS_ERR(hdd_ctx))
6483 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006484
Ryan Hsucfef0ae2016-04-28 10:20:46 -07006485 ret = hdd_init_netlink_services(hdd_ctx);
6486 if (ret)
6487 goto err_hdd_free_context;
6488
Anurag Chouhan6d760662016-02-20 16:05:43 +05306489 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prashanth Bhattad1d44692015-12-22 17:32:59 -08006490 ret = hdd_enable_ftm(hdd_ctx);
Prashanth Bhattad1d44692015-12-22 17:32:59 -08006491 if (ret)
Ryan Hsucfef0ae2016-04-28 10:20:46 -07006492 goto err_exit_nl_srv;
Prashanth Bhattad1d44692015-12-22 17:32:59 -08006493
6494 goto success;
6495 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006496
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08006497 hdd_wlan_green_ap_init(hdd_ctx);
6498
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006499 status = cds_open();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306500 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306501 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_open failed"));
Ryan Hsucfef0ae2016-04-28 10:20:46 -07006502 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006503 }
6504
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006505 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006506
Anurag Chouhan6d760662016-02-20 16:05:43 +05306507 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006508
6509 if (NULL == hdd_ctx->hHal) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306510 hddLog(QDF_TRACE_LEVEL_FATAL, FL("HAL context is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006511 goto err_cds_close;
6512 }
6513
6514 status = cds_pre_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306515 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306516 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_pre_enable failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006517 goto err_cds_close;
6518 }
6519
Prashanth Bhatta07998752016-04-28 12:35:33 -07006520 ret = hdd_wiphy_init(hdd_ctx);
6521 if (ret) {
6522 hdd_alert("Failed to initialize wiphy: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006523 goto err_cds_close;
6524 }
6525
Prashanth Bhatta07998752016-04-28 12:35:33 -07006526 ret = hdd_pre_enable_configure(hdd_ctx);
6527 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006528 goto err_wiphy_unregister;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006529
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05306530 if (hdd_ctx->config->enable_dp_trace)
6531 qdf_dp_trace_init();
6532
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306533 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006534 goto err_wiphy_unregister;
6535
6536 /*
6537 * Start CDS which starts up the SME/MAC/HAL modules and everything
6538 * else
6539 */
6540 status = cds_enable(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306541 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306542 hddLog(QDF_TRACE_LEVEL_FATAL, FL("cds_enable failed"));
Yun Park6a46ad82016-01-04 16:48:19 -08006543 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006544 }
6545
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006546 status = hdd_post_cds_enable_config(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306547 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306548 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006549 FL("hdd_post_cds_enable_config failed"));
6550 goto err_cds_disable;
6551 }
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006552
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006553 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006554
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07006555 if (QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam())
6556 adapter = hdd_open_monitor_interface(hdd_ctx, rtnl_held);
6557 else
6558 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006559
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006560 if (IS_ERR(adapter)) {
6561 ret = PTR_ERR(adapter);
6562 goto err_cds_disable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006563 }
6564
6565 /*
6566 * target hw version/revision would only be retrieved after firmware
6567 * donwload
6568 */
6569 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
6570 &hdd_ctx->target_hw_revision,
6571 &hdd_ctx->target_hw_name);
6572
6573 /* Get the wlan hw/fw version */
6574 hdd_wlan_get_version(adapter, NULL, NULL);
6575
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006576 ret = hdd_update_country_code(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006577
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006578 if (ret)
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08006579 goto err_close_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006580
6581 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
6582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006583 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
6584 hdd_send_oem_data_rsp_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006586 /* FW capabilities received, Set the Dot11 mode */
6587 sme_setdef_dot11mode(hdd_ctx->hHal);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006588
Peng Xuf5d60c82015-10-02 17:17:03 -07006589 /*
6590 * Action frame registered in one adapter which will
6591 * applicable to all interfaces
6592 */
6593 wlan_hdd_cfg80211_register_frames(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006594
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006595 hdd_release_rtnl_lock();
6596 rtnl_held = false;
6597
Kiran Kumar Lokerefc2803d2016-01-11 19:31:38 -08006598 if (hdd_ctx->config->fIsImpsEnabled)
6599 hdd_set_idle_ps_config(hdd_ctx, true);
6600 else
6601 hdd_set_idle_ps_config(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6603 if (hdd_ctx->config->WlanAutoShutdown != 0)
6604 if (sme_set_auto_shutdown_cb
6605 (hdd_ctx->hHal, wlan_hdd_auto_shutdown_cb)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306606 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006607 hddLog(LOGE,
6608 FL(
6609 "Auto shutdown feature could not be enabled"
6610 ));
6611#endif
6612
6613#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05306614 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306615 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006616 hdd_skip_acs_scan_timer_handler,
6617 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306618 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006619 hddLog(LOGE, FL("Failed to init ACS Skip timer"));
6620#endif
6621
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006622 wlan_hdd_nan_init(hdd_ctx);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306623 status = cds_init_policy_mgr(sme_get_cfg_valid_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306624 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006625 hdd_err("Policy manager initialization failed");
Ryan Hsucfef0ae2016-04-28 10:20:46 -07006626 goto err_debugfs_exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006627 }
6628
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006629 ret = hdd_init_thermal_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006630
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006631 if (ret) {
6632 hdd_err("Error while initializing thermal information");
Ryan Hsucfef0ae2016-04-28 10:20:46 -07006633 goto err_debugfs_exit;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006634 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006635
6636 if (0 != hdd_lro_init(hdd_ctx))
6637 hdd_err("Unable to initialize LRO in fw");
6638
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05306639 if (0 != hdd_adaptive_dwelltime_init(hdd_ctx))
6640 hdd_err("Unable to send adaptive dwelltime setting to FW");
6641
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006642 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
6643 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
6644 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306645 if (QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006646 hdd_err("Error setting txlimit in sme: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006647
Jeff Johnson89c66ff2016-04-22 15:21:37 -07006648 hdd_tsf_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006649#ifdef MSM_PLATFORM
6650 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05306651 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306652 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006653 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
6654#endif
6655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006656 wlan_hdd_cfg80211_stats_ext_init(hdd_ctx);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006657
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006658 sme_ext_scan_register_callback(hdd_ctx->hHal,
6659 wlan_hdd_cfg80211_extscan_callback);
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006660
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05306661 status = hdd_register_for_sap_restart_with_channel_switch();
6662 if (!QDF_IS_STATUS_SUCCESS(status))
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07006663 goto err_exit_nl_srv;
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05306664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006665 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
6666 hdd_rssi_threshold_breached);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006667
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306668 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
6669 hdd_get_bpf_offload_cb);
6670 if (QDF_IS_STATUS_SUCCESS(status))
6671 hdd_err("set bpf offload callback failed");
6672
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08006673 hdd_cfg80211_link_layer_stats_init(hdd_ctx);
Manikandan Mohandcc21ba2016-03-15 14:31:56 -07006674 wlan_hdd_tsf_init(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006675 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
6676 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
6677 hdd_ctx->target_hw_version,
6678 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006680 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
6681
6682 if (hdd_ctx->config->dual_mac_feature_disable) {
6683 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306684 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006685 hdd_err("Failed to disable dual mac features");
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05306686 goto err_debugfs_exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006687 }
6688 }
6689
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07006690 ret = hdd_register_notifiers(hdd_ctx);
6691 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05306692 goto err_debugfs_exit;
6693
6694 status = wlansap_global_init();
6695 if (QDF_IS_STATUS_ERROR(status))
6696 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07006697
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08006698 memdump_init();
6699
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006700 goto success;
6701
Ryan Hsucfef0ae2016-04-28 10:20:46 -07006702err_debugfs_exit:
6703 hdd_debugfs_exit(adapter);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006705err_close_adapter:
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006706 hdd_release_rtnl_lock();
6707
6708 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006709
6710err_cds_disable:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006711 cds_disable(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006712
Yun Park6a46ad82016-01-04 16:48:19 -08006713err_ipa_cleanup:
6714 hdd_ipa_cleanup(hdd_ctx);
6715
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006716err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006717 wiphy_unregister(hdd_ctx->wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05306718 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006719
6720err_cds_close:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006721 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306722 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306723 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006724 FL("Failed to close CDS Scheduler"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306725 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006726 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006727 cds_close(hdd_ctx->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006728
Ryan Hsucfef0ae2016-04-28 10:20:46 -07006729err_exit_nl_srv:
6730 hdd_exit_netlink_services(hdd_ctx);
6731
6732 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
6733 hdd_err("Failed to deinit policy manager");
6734 /* Proceed and complete the clean up */
6735 }
6736
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006737err_hdd_free_context:
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006738 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306739 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006741 return -EIO;
6742
6743success:
6744 EXIT();
6745 return 0;
6746}
6747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006748/**
6749 * hdd_softap_sta_deauth() - handle deauth req from HDD
6750 * @adapter: Pointer to the HDD
6751 * @enable: bool value
6752 *
6753 * This to take counter measure to handle deauth req from HDD
6754 *
6755 * Return: None
6756 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306757QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006758 struct tagCsrDelStaParams *pDelStaParams)
6759{
6760#ifndef WLAN_FEATURE_MBSSID
6761 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
6762#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306763 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006764
6765 ENTER();
6766
6767 hddLog(LOG1, FL("hdd_softap_sta_deauth:(%p, false)"),
6768 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
6769
6770 /* Ignore request to deauth bcmc station */
6771 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306772 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006773
6774#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306775 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006776 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6777 pDelStaParams);
6778#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306779 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006780#endif
6781
6782 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306783 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006784}
6785
6786/**
6787 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
6788 * @adapter: Pointer to the HDD
6789 *
6790 * This to take counter measure to handle deauth req from HDD
6791 *
6792 * Return: None
6793 */
6794void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
6795 uint8_t *pDestMacAddress)
6796{
6797#ifndef WLAN_FEATURE_MBSSID
6798 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
6799#endif
6800
6801 ENTER();
6802
6803 hddLog(LOGE, FL("hdd_softap_sta_disassoc:(%p, false)"),
6804 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
6805
6806 /* Ignore request to disassoc bcmc station */
6807 if (pDestMacAddress[0] & 0x1)
6808 return;
6809
6810#ifdef WLAN_FEATURE_MBSSID
6811 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6812 pDestMacAddress);
6813#else
6814 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
6815#endif
6816}
6817
6818void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
6819 bool enable)
6820{
6821#ifndef WLAN_FEATURE_MBSSID
6822 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
6823#endif
6824
6825 ENTER();
6826
6827 hddLog(LOGE, FL("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)"),
6828 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
6829
6830#ifdef WLAN_FEATURE_MBSSID
6831 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
6832 (bool) enable);
6833#else
6834 wlansap_set_counter_measure(p_cds_context, (bool) enable);
6835#endif
6836}
6837
6838/**
6839 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
6840 * @hdd_ctx: HDD Context
6841 *
6842 * API to find if there is any STA or P2P-Client is connected
6843 *
6844 * Return: true if connected; false otherwise
6845 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306846QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006847{
6848 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
6849}
6850
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006851/**
6852 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
6853 * @adapter: HDD adapter pointer
6854 *
6855 * This function loop through each adapter and disable roaming on each STA
6856 * device mode except the input adapter.
6857 *
6858 * Note: On the input adapter roaming is not enabled yet hence no need to
6859 * disable.
6860 *
6861 * Return: None
6862 */
6863void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
6864{
6865 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6866 hdd_adapter_t *adapterIdx = NULL;
6867 hdd_adapter_list_node_t *adapterNode = NULL;
6868 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306869 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006870
6871 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6872 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006873 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006874 cds_is_sta_active_connection_exists()) {
6875 hddLog(LOG1, FL("Connect received on STA sessionId(%d)"),
6876 adapter->sessionId);
6877 /*
6878 * Loop through adapter and disable roaming for each STA device
6879 * mode except the input adapter.
6880 */
6881 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6882
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306883 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006884 adapterIdx = adapterNode->pAdapter;
6885
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006886 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006887 && adapter->sessionId != adapterIdx->sessionId) {
6888 hddLog(LOG1,
6889 FL("Disable Roaming on sessionId(%d)"),
6890 adapterIdx->sessionId);
6891 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
6892 (adapterIdx),
6893 adapterIdx->sessionId, 0);
6894 }
6895
6896 status = hdd_get_next_adapter(hdd_ctx,
6897 adapterNode,
6898 &pNext);
6899 adapterNode = pNext;
6900 }
6901 }
6902}
6903
6904/**
6905 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
6906 * @adapter: HDD adapter pointer
6907 *
6908 * This function loop through each adapter and enable roaming on each STA
6909 * device mode except the input adapter.
6910 * Note: On the input adapter no need to enable roaming because link got
6911 * disconnected on this.
6912 *
6913 * Return: None
6914 */
6915void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
6916{
6917 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6918 hdd_adapter_t *adapterIdx = NULL;
6919 hdd_adapter_list_node_t *adapterNode = NULL;
6920 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306921 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006922
6923 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
6924 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006925 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006926 cds_is_sta_active_connection_exists()) {
6927 hddLog(LOG1, FL("Disconnect received on STA sessionId(%d)"),
6928 adapter->sessionId);
6929 /*
6930 * Loop through adapter and enable roaming for each STA device
6931 * mode except the input adapter.
6932 */
6933 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
6934
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306935 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006936 adapterIdx = adapterNode->pAdapter;
6937
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006938 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006939 && adapter->sessionId != adapterIdx->sessionId) {
6940 hddLog(LOG1,
6941 FL("Enabling Roaming on sessionId(%d)"),
6942 adapterIdx->sessionId);
6943 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
6944 (adapterIdx),
6945 adapterIdx->sessionId,
6946 REASON_CONNECT);
6947 }
6948
6949 status = hdd_get_next_adapter(hdd_ctx,
6950 adapterNode,
6951 &pNext);
6952 adapterNode = pNext;
6953 }
6954 }
6955}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006956
6957void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
6958{
6959 struct sk_buff *skb;
6960 struct nlmsghdr *nlh;
6961 tAniMsgHdr *ani_hdr;
6962 void *nl_data = NULL;
6963 int flags = GFP_KERNEL;
6964
6965 if (in_interrupt() || irqs_disabled() || in_atomic())
6966 flags = GFP_ATOMIC;
6967
6968 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
6969
6970 if (skb == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306971 hddLog(QDF_TRACE_LEVEL_ERROR, FL("alloc_skb failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006972 return;
6973 }
6974
6975 nlh = (struct nlmsghdr *)skb->data;
6976 nlh->nlmsg_pid = 0; /* from kernel */
6977 nlh->nlmsg_flags = 0;
6978 nlh->nlmsg_seq = 0;
6979 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
6980
6981 ani_hdr = NLMSG_DATA(nlh);
6982 ani_hdr->type = type;
6983
6984 switch (type) {
6985 case WLAN_SVC_FW_CRASHED_IND:
6986 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006987 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07006988 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006989 ani_hdr->length = 0;
6990 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
6991 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
6992 break;
6993 case WLAN_SVC_WLAN_STATUS_IND:
6994 case WLAN_SVC_WLAN_VERSION_IND:
6995 case WLAN_SVC_DFS_CAC_START_IND:
6996 case WLAN_SVC_DFS_CAC_END_IND:
6997 case WLAN_SVC_DFS_RADAR_DETECT_IND:
6998 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
6999 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08007000 case WLAN_SVC_WLAN_TP_TX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007001 ani_hdr->length = len;
7002 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
7003 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
7004 memcpy(nl_data, data, len);
7005 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
7006 break;
7007
7008 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307009 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007010 FL("WLAN SVC: Attempt to send unknown nlink message %d"),
7011 type);
7012 kfree_skb(skb);
7013 return;
7014 }
7015
7016 nl_srv_bcast(skb);
7017
7018 return;
7019}
7020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007021#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7022void wlan_hdd_auto_shutdown_cb(void)
7023{
7024 hddLog(LOGE, FL("Wlan Idle. Sending Shutdown event.."));
7025 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
7026}
7027
7028void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
7029{
7030 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307031 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007032 hdd_adapter_t *adapter;
7033 bool ap_connected = false, sta_connected = false;
7034 tHalHandle hal_handle;
7035
7036 hal_handle = hdd_ctx->hHal;
7037 if (hal_handle == NULL)
7038 return;
7039
7040 if (hdd_ctx->config->WlanAutoShutdown == 0)
7041 return;
7042
7043 if (enable == false) {
7044 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307045 QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007046 hddLog(LOGE,
7047 FL("Failed to stop wlan auto shutdown timer"));
7048 }
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07007049 wlan_hdd_send_svc_nlink_msg(
7050 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007051 return;
7052 }
7053
7054 /* To enable shutdown timer check conncurrency */
7055 if (cds_concurrent_open_sessions_running()) {
7056 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
7057
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307058 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007059 adapter = adapterNode->pAdapter;
7060 if (adapter
7061 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007062 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007063 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
7064 conn_info.connState ==
7065 eConnectionState_Associated) {
7066 sta_connected = true;
7067 break;
7068 }
7069 }
7070 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007071 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007072 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
7073 bApActive == true) {
7074 ap_connected = true;
7075 break;
7076 }
7077 }
7078 status = hdd_get_next_adapter(hdd_ctx,
7079 adapterNode,
7080 &pNext);
7081 adapterNode = pNext;
7082 }
7083 }
7084
7085 if (ap_connected == true || sta_connected == true) {
7086 hddLog(LOG1,
7087 FL("CC Session active. Shutdown timer not enabled"));
7088 return;
7089 } else {
7090 if (sme_set_auto_shutdown_timer(hal_handle,
7091 hdd_ctx->config->
7092 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307093 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007094 hddLog(LOGE,
7095 FL("Failed to start wlan auto shutdown timer"));
7096 else
7097 hddLog(LOG1,
7098 FL("Auto Shutdown timer for %d seconds enabled"),
7099 hdd_ctx->config->WlanAutoShutdown);
7100
7101 }
7102}
7103#endif
7104
7105hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
7106 bool check_start_bss)
7107{
7108 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
7109 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307110 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007111 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
7112
7113 con_sap_adapter = NULL;
7114
7115 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307116 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007117 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007118 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
7119 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007120 adapter != this_sap_adapter) {
7121 if (check_start_bss) {
7122 if (test_bit(SOFTAP_BSS_STARTED,
7123 &adapter->event_flags)) {
7124 con_sap_adapter = adapter;
7125 break;
7126 }
7127 } else {
7128 con_sap_adapter = adapter;
7129 break;
7130 }
7131 }
7132 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
7133 adapterNode = pNext;
7134 }
7135
7136 return con_sap_adapter;
7137}
7138
7139#ifdef MSM_PLATFORM
7140void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
7141{
7142 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7143
Anurag Chouhan210db072016-02-22 18:42:15 +05307144 if (QDF_TIMER_STATE_RUNNING ==
7145 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007146 return;
7147
Anurag Chouhan210db072016-02-22 18:42:15 +05307148 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007149 hdd_ctx->config->busBandwidthComputeInterval);
7150}
7151
7152void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
7153{
7154 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307155 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007156 bool can_stop = true;
7157 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7158
Anurag Chouhan210db072016-02-22 18:42:15 +05307159 if (QDF_TIMER_STATE_RUNNING !=
7160 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007161 /* trying to stop timer, when not running is not good */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307162 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007163 FL("bus band width compute timer is not running"));
7164 return;
7165 }
7166
7167 if (cds_concurrent_open_sessions_running()) {
7168 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
7169
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307170 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007171 adapter = adapterNode->pAdapter;
7172 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007173 && (adapter->device_mode == QDF_STA_MODE
7174 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007175 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
7176 conn_info.connState ==
7177 eConnectionState_Associated) {
7178 can_stop = false;
7179 break;
7180 }
7181 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007182 && (adapter->device_mode == QDF_SAP_MODE
7183 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007184 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
7185 true) {
7186 can_stop = false;
7187 break;
7188 }
7189 status = hdd_get_next_adapter(hdd_ctx,
7190 adapterNode,
7191 &pNext);
7192 adapterNode = pNext;
7193 }
7194 }
7195
7196 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05307197 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007198}
7199#endif
7200
7201/**
7202 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
7203 * and sta's operating channel.
7204 * @sta_adapter: Describe the first argument to foobar.
7205 * @ap_adapter: Describe the second argument to foobar.
7206 * @roam_profile: Roam profile of AP to which STA wants to connect.
7207 * @concurrent_chnl_same: If both SAP and STA channels are same then
7208 * set this flag to true else false.
7209 *
7210 * This function checks the sap's operating channel and sta's operating channel.
7211 * if both are same then it will return false else it will restart the sap in
7212 * sta's channel and return true.
7213 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307214 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007215 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307216QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007217 hdd_adapter_t *ap_adapter,
7218 tCsrRoamProfile *roam_profile,
7219 tScanResultHandle *scan_cache,
7220 bool *concurrent_chnl_same)
7221{
7222 hdd_ap_ctx_t *hdd_ap_ctx;
7223 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307224 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007225 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007226 *concurrent_chnl_same = true;
7227
7228 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7229 status =
7230 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
7231 roam_profile,
7232 scan_cache,
7233 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307234 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007235 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007236 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
7237 if (hdd_ap_ctx->operatingChannel != channel_id) {
7238 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307239 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007240 FL("channels are different"));
7241 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007242 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007243 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
7244 if (hdd_ap_ctx->operatingChannel != channel_id) {
7245 *concurrent_chnl_same = false;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307246 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007247 FL("channels are different"));
7248 }
7249 }
7250 } else {
7251 /*
7252 * Lets handle worst case scenario here, Scan cache lookup is
7253 * failed so we have to stop the SAP to avoid any channel
7254 * discrepancy between SAP's channel and STA's channel.
7255 * Return the status as failure so caller function could know
7256 * that scan look up is failed.
7257 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307258 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007259 FL("Finding AP from scan cache failed"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307260 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007261 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307262 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007263}
7264
7265#ifdef WLAN_FEATURE_MBSSID
7266/**
7267 * wlan_hdd_stop_sap() - This function stops bss of SAP.
7268 * @ap_adapter: SAP adapter
7269 *
7270 * This function will process the stopping of sap adapter.
7271 *
7272 * Return: None
7273 */
7274void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
7275{
7276 hdd_ap_ctx_t *hdd_ap_ctx;
7277 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05307278 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007279 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007280
7281 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307282 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007283 FL("ap_adapter is NULL here"));
7284 return;
7285 }
7286
7287 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7288 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307289 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007290 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007292 mutex_lock(&hdd_ctx->sap_lock);
7293 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08007294 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007295 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
7296 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307297 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007298 FL("Now doing SAP STOPBSS"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307299 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307300 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007301 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05307302 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307303 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007304 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05307305 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007306 mutex_unlock(&hdd_ctx->sap_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307307 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007308 FL("SAP Stop Failed"));
7309 return;
7310 }
7311 }
7312 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08007313 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007314 ap_adapter->sessionId);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307315 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007316 FL("SAP Stop Success"));
7317 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307318 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007319 FL("Can't stop ap because its not started"));
7320 }
7321 mutex_unlock(&hdd_ctx->sap_lock);
7322 return;
7323}
7324
7325/**
7326 * wlan_hdd_start_sap() - this function starts bss of SAP.
7327 * @ap_adapter: SAP adapter
7328 *
7329 * This function will process the starting of sap adapter.
7330 *
7331 * Return: None
7332 */
7333void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
7334{
7335 hdd_ap_ctx_t *hdd_ap_ctx;
7336 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05307337 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007338 hdd_context_t *hdd_ctx;
7339 tsap_Config_t *sap_config;
7340
7341 if (NULL == ap_adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307342 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007343 FL("ap_adapter is NULL here"));
7344 return;
7345 }
7346
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007347 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07007348 hdd_err("SoftAp role has not been enabled");
7349 return;
7350 }
7351
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007352 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
7353 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7354 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
7355 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
7356
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307357 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007358 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307359
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007360 mutex_lock(&hdd_ctx->sap_lock);
7361 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
7362 goto end;
7363
7364 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
7365 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
7366 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
7367 goto end;
7368 }
7369
7370 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
7371 &hdd_ap_ctx->sapConfig,
7372 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307373 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007374 goto end;
7375
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307376 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007377 FL("Waiting for SAP to start"));
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307378 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007379 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05307380 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307381 hddLog(QDF_TRACE_LEVEL_ERROR, FL("SAP Start failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007382 goto end;
7383 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307384 hddLog(QDF_TRACE_LEVEL_INFO_HIGH, FL("SAP Start Success"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007385 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08007386 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007387 ap_adapter->sessionId);
7388 hostapd_state->bCommit = true;
7389
7390end:
7391 mutex_unlock(&hdd_ctx->sap_lock);
7392 return;
7393}
7394#endif
7395
7396/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08007397 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
7398 * mac scan config
7399 * @status: Status of set antenna mode
7400 *
7401 * Callback on setting the dual mac configuration
7402 *
7403 * Return: None
7404 */
7405void wlan_hdd_soc_set_antenna_mode_cb(
7406 enum set_antenna_mode_status status)
7407{
7408 hdd_context_t *hdd_ctx;
7409
7410 hdd_info("Status: %d", status);
7411
7412 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7413 if (0 != wlan_hdd_validate_context(hdd_ctx))
7414 return;
7415
7416 /* Signal the completion of set dual mac config */
7417 complete(&hdd_ctx->set_antenna_mode_cmpl);
7418}
7419
7420/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007421 * hdd_get_fw_version() - Get FW version
7422 * @hdd_ctx: pointer to HDD context.
7423 * @major_spid: FW version - major spid.
7424 * @minor_spid: FW version - minor spid
7425 * @ssid: FW version - ssid
7426 * @crmid: FW version - crmid
7427 *
7428 * This function is called to get the firmware build version stored
7429 * as part of the HDD context
7430 *
7431 * Return: None
7432 */
7433void hdd_get_fw_version(hdd_context_t *hdd_ctx,
7434 uint32_t *major_spid, uint32_t *minor_spid,
7435 uint32_t *siid, uint32_t *crmid)
7436{
7437 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
7438 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
7439 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
7440 *crmid = hdd_ctx->target_fw_version & 0x7fff;
7441}
7442
7443#ifdef QCA_CONFIG_SMP
7444/**
7445 * wlan_hdd_get_cpu() - get cpu_index
7446 *
7447 * Return: cpu_index
7448 */
7449int wlan_hdd_get_cpu(void)
7450{
7451 int cpu_index = get_cpu();
7452 put_cpu();
7453 return cpu_index;
7454}
7455#endif
7456
7457/**
7458 * hdd_get_fwpath() - get framework path
7459 *
7460 * This function is used to get the string written by
7461 * userspace to start the wlan driver
7462 *
7463 * Return: string
7464 */
7465const char *hdd_get_fwpath(void)
7466{
7467 return fwpath.string;
7468}
7469
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007470/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007471 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007472 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007473 * This function initilizes CDS global context with the help of cds_init. This
7474 * has to be the first function called after probe to get a valid global
7475 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007476 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007477 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007478 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007479int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007480{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007481 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007482 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007483
7484#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
7485 wlan_logging_sock_init_svc();
7486#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007487 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007488
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007489 if (p_cds_context == NULL) {
7490 hdd_alert("Failed to allocate CDS context");
7491 ret = -ENOMEM;
7492 goto err_out;
7493 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007494
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007495 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007496
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007497err_out:
7498 return ret;
7499}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007500
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007501/**
7502 * hdd_deinit() - Deinitialize Driver
7503 *
7504 * This function frees CDS global context with the help of cds_deinit. This
7505 * has to be the last function call in remove callback to free the global
7506 * context.
7507 */
7508void hdd_deinit(void)
7509{
7510 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007511
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007512#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
7513 wlan_logging_sock_deinit_svc();
7514#endif
7515}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007516
7517#ifdef QCA_WIFI_3_0_ADRASTEA
7518#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
7519#else
7520#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
7521#endif
7522
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007523/**
7524 * __hdd_module_init - Module init helper
7525 *
7526 * Module init helper function used by both module and static driver.
7527 *
7528 * Return: 0 for success, errno on failure
7529 */
7530static int __hdd_module_init(void)
7531{
7532 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007533
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007534 pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
7535 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007536
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07007537 pld_init();
7538
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307539 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007540
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007541 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007542
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007543 ret = wlan_hdd_register_driver();
7544 if (ret) {
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007545 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007546 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007547 }
7548
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307549 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007550
7551 return 0;
7552out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307553 qdf_wake_lock_destroy(&wlan_wake_lock);
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07007554 pld_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007555 return ret;
7556}
7557
7558/**
7559 * __hdd_module_exit - Module exit helper
7560 *
7561 * Module exit helper function used by both module and static driver.
7562 */
7563static void __hdd_module_exit(void)
7564{
7565 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
7566 QWLAN_VERSIONSTR);
7567
7568 wlan_hdd_unregister_driver();
7569
Anurag Chouhana37b5b72016-02-21 14:53:42 +05307570 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007571
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07007572 pld_deinit();
7573
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007574 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007575}
7576
7577/**
7578 * hdd_module_init() - Init Function
7579 *
7580 * This is the driver entry point (invoked when module is loaded using insmod)
7581 *
7582 * Return: 0 for success, non zero for failure
7583 */
7584#ifdef MODULE
7585static int __init hdd_module_init(void)
7586{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007587 return __hdd_module_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007588}
7589#else /* #ifdef MODULE */
7590static int __init hdd_module_init(void)
7591{
7592 /* Driver initialization is delayed to fwpath_changed_handler */
7593 return 0;
7594}
7595#endif /* #ifdef MODULE */
7596
7597/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007598 * hdd_module_exit() - Exit function
7599 *
7600 * This is the driver exit point (invoked when module is unloaded using rmmod)
7601 *
7602 * Return: None
7603 */
7604static void __exit hdd_module_exit(void)
7605{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007606 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007607}
7608
7609#ifdef MODULE
7610static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
7611{
7612 return param_set_copystring(kmessage, kp);
7613}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007614#else /* #ifdef MODULE */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007615
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007616/**
7617 * kickstart_driver() - driver entry point
7618 *
7619 * This is the driver entry point
7620 * - delayed driver initialization when driver is statically linked
7621 * - invoked when module parameter fwpath is modified from userspace to signal
7622 * initializing the WLAN driver or when con_mode is modified from userspace
7623 * to signal a switch in operating mode
7624 *
7625 * Return: 0 for success, non zero for failure
7626 */
7627static int kickstart_driver(void)
7628{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007629 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007630
7631 if (!wlan_hdd_inited) {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007632 ret = __hdd_module_init();
7633 wlan_hdd_inited = ret ? 0 : 1;
7634
7635 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007636 }
7637
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007638 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007639
7640 msleep(200);
7641
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007642 ret = __hdd_module_init();
7643
7644 wlan_hdd_inited = ret ? 0 : 1;
7645
7646 return ret;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007647}
7648
7649/**
7650 * fwpath_changed_handler() - Handler Function
7651 *
7652 * Handle changes to the fwpath parameter
7653 *
7654 * Return: 0 for success, non zero for failure
7655 */
7656static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
7657{
7658 int ret;
7659
7660 ret = param_set_copystring(kmessage, kp);
7661 if (0 == ret)
7662 ret = kickstart_driver();
7663 return ret;
7664}
7665
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007666#ifdef QCA_WIFI_FTM
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007667/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007668 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007669 *
7670 * Handler function for module param con_mode when it is changed by userspace
7671 * Dynamically linked - do nothing
7672 * Statically linked - exit and init driver, as in rmmod and insmod
7673 *
7674 * Return -
7675 */
7676static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
7677{
7678 int ret;
7679
7680 ret = param_set_int(kmessage, kp);
7681 if (0 == ret)
7682 ret = kickstart_driver();
7683 return ret;
7684}
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007685#endif /* QCA_WIFI_FTM */
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007686#endif /* #ifdef MODULE */
7687
7688/**
7689 * hdd_get_conparam() - driver exit point
7690 *
7691 * This is the driver exit point (invoked when module is unloaded using rmmod)
7692 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05307693 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007694 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05307695enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007696{
Anurag Chouhan6d760662016-02-20 16:05:43 +05307697 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007698}
7699
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007700void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007701{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007702 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08007703}
7704
Komal Seelamc11bb222016-01-27 18:57:10 +05307705#ifdef WLAN_FEATURE_LPSS
7706static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
7707{
7708 return hdd_ctx->config->enable_lpass_support;
7709}
7710#else
7711static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
7712{
7713 return false;
7714}
7715#endif
7716
7717/**
Komal Seelamec702b02016-02-24 18:42:16 +05307718 * hdd_update_ol_config - API to update ol configuration parameters
7719 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05307720 *
Komal Seelamc11bb222016-01-27 18:57:10 +05307721 * Return: void
7722 */
Komal Seelamec702b02016-02-24 18:42:16 +05307723static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05307724{
Komal Seelamec702b02016-02-24 18:42:16 +05307725 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307726 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05307727
Komal Seelamec702b02016-02-24 18:42:16 +05307728 if (!ol_ctx)
7729 return;
7730
7731 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
7732 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
7733 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
7734 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
7735 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
7736
7737 ol_init_ini_config(ol_ctx, &cfg);
7738}
7739
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007740#ifdef FEATURE_RUNTIME_PM
7741/**
7742 * hdd_populate_runtime_cfg() - populate runtime configuration
7743 * @hdd_ctx: hdd context
7744 * @cfg: pointer to the configuration memory being populated
7745 *
7746 * Return: void
7747 */
7748static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7749 struct hif_config_info *cfg)
7750{
7751 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
7752 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
7753}
7754#else
7755static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
7756 struct hif_config_info *cfg)
7757{
7758}
7759#endif
7760
Komal Seelamec702b02016-02-24 18:42:16 +05307761/**
7762 * hdd_update_hif_config - API to update HIF configuration parameters
7763 * @hdd_ctx: HDD Context
7764 *
7765 * Return: void
7766 */
7767static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
7768{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05307769 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05307770 struct hif_config_info cfg;
7771
7772 if (!scn)
7773 return;
7774
7775 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07007776 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05307777 hif_init_ini_config(scn, &cfg);
7778}
7779
7780/**
7781 * hdd_update_config() - Initialize driver per module ini parameters
7782 * @hdd_ctx: HDD Context
7783 *
7784 * API is used to initialize all driver per module configuration parameters
7785 * Return: void
7786 */
7787void hdd_update_config(hdd_context_t *hdd_ctx)
7788{
7789 hdd_update_ol_config(hdd_ctx);
7790 hdd_update_hif_config(hdd_ctx);
Komal Seelamc11bb222016-01-27 18:57:10 +05307791}
7792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007793/* Register the module init/exit functions */
7794module_init(hdd_module_init);
7795module_exit(hdd_module_exit);
7796
7797MODULE_LICENSE("Dual BSD/GPL");
7798MODULE_AUTHOR("Qualcomm Atheros, Inc.");
7799MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
7800
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007801#if !defined(MODULE) && defined(QCA_WIFI_FTM)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007802module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
7803 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08007804#else
7805module_param(con_mode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007806#endif
7807
7808module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
7809 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
7810
7811module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
7812
7813module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
7814
7815module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);