blob: e89eba40cb6317182a673fea1fa01054420628db [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
Jeff Johnson94be11c2016-08-15 15:39:25 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038/* Include Files */
39#include <wlan_hdd_includes.h>
40#include <cds_api.h>
41#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053042#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#ifdef WLAN_FEATURE_LPSS
44#include <cds_utils.h>
45#endif
46#include <linux/etherdevice.h>
47#include <linux/firmware.h>
48#include <wlan_hdd_tx_rx.h>
49#include <wni_api.h>
50#include <wlan_hdd_cfg.h>
51#include <wlan_ptt_sock_svc.h>
52#include <dbglog_host.h>
53#include <wlan_logging_sock_svc.h>
54#include <wlan_hdd_wowl.h>
55#include <wlan_hdd_misc.h>
56#include <wlan_hdd_wext.h>
57#include "wlan_hdd_trace.h"
58#include "wlan_hdd_ioctl.h"
59#include "wlan_hdd_ftm.h"
60#include "wlan_hdd_power.h"
61#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070062#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070065#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080066
67#include <net/addrconf.h>
68#include <linux/wireless.h>
69#include <net/cfg80211.h>
70#include <linux/inetdevice.h>
71#include <net/addrconf.h>
72#include "wlan_hdd_cfg80211.h"
73#include "wlan_hdd_ext_scan.h"
74#include "wlan_hdd_p2p.h"
75#include <linux/rtnetlink.h>
76#include "sap_api.h"
77#include <linux/semaphore.h>
78#include <linux/ctype.h>
79#include <linux/compat.h>
80#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081#include <soc/qcom/subsystem_restart.h>
82#endif
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -070083#include <soc/qcom/socinfo.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084#include <wlan_hdd_hostapd.h>
85#include <wlan_hdd_softap_tx_rx.h>
86#include "cfg_api.h"
87#include "qwlan_version.h"
88#include "wma_types.h"
89#include "wlan_hdd_tdls.h"
90#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053091#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080092#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070094#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080095#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096#include "wlan_hdd_nan.h"
97#include "wlan_hdd_debugfs.h"
98#include "wlan_hdd_driver_ops.h"
99#include "epping_main.h"
100#include "wlan_hdd_memdump.h"
101
102#include <wlan_hdd_ipa.h>
103#include "hif.h"
104#include "wma.h"
105#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700106#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530108#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700109#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530110#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700111#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530112#include "nan_api.h"
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -0700113#include <wlan_hdd_napi.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114
115#ifdef MODULE
116#define WLAN_MODULE_NAME module_name(THIS_MODULE)
117#else
118#define WLAN_MODULE_NAME "wlan"
119#endif
120
121#ifdef TIMER_MANAGER
122#define TIMER_MANAGER_STR " +TIMER_MANAGER"
123#else
124#define TIMER_MANAGER_STR ""
125#endif
126
127#ifdef MEMORY_DEBUG
128#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
129#else
130#define MEMORY_DEBUG_STR ""
131#endif
132
Arun Khandavallifae92942016-08-01 13:31:08 +0530133#ifndef MODULE
134static struct gwlan_loader *wlan_loader;
135static ssize_t wlan_boot_cb(struct kobject *kobj,
136 struct kobj_attribute *attr,
137 const char *buf, size_t count);
138struct gwlan_loader {
139 bool loaded_state;
140 struct kobject *boot_wlan_obj;
141 struct attribute_group *attr_group;
142};
143
144static struct kobj_attribute wlan_boot_attribute =
145 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
146
147static struct attribute *attrs[] = {
148 &wlan_boot_attribute.attr,
149 NULL,
150};
151
152#define MODULE_INITIALIZED 1
153#endif
154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155/* the Android framework expects this param even though we don't use it */
156#define BUF_LEN 20
157static char fwpath_buffer[BUF_LEN];
158static struct kparam_string fwpath = {
159 .string = fwpath_buffer,
160 .maxlen = BUF_LEN,
161};
162
163static char *country_code;
164static int enable_11d = -1;
165static int enable_dfs_chan_scan = -1;
166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167/*
168 * spinlock for synchronizing asynchronous request/response
169 * (full description of use in wlan_hdd_main.h)
170 */
171DEFINE_SPINLOCK(hdd_context_lock);
172
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800173#define WLAN_NLINK_CESIUM 30
174
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530175static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176
177#define WOW_MAX_FILTER_LISTS 1
178#define WOW_MAX_FILTERS_PER_LIST 4
179#define WOW_MIN_PATTERN_SIZE 6
180#define WOW_MAX_PATTERN_SIZE 64
181
182#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
183static const struct wiphy_wowlan_support wowlan_support_reg_init = {
184 .flags = WIPHY_WOWLAN_ANY |
185 WIPHY_WOWLAN_MAGIC_PKT |
186 WIPHY_WOWLAN_DISCONNECT |
187 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
188 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
189 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
190 WIPHY_WOWLAN_4WAY_HANDSHAKE |
191 WIPHY_WOWLAN_RFKILL_RELEASE,
192 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
193 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
194 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
195};
196#endif
197
198/* internal function declaration */
199
200struct sock *cesium_nl_srv_sock;
201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800202#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
203void wlan_hdd_auto_shutdown_cb(void);
204#endif
205
206/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530207 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
208 * @hdd_ctx: pointer to hdd_context_t
209 *
210 * Return: none
211 */
212void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
213{
214 hdd_adapter_t *adapter;
215 hdd_adapter_list_node_t *adapter_node, *next;
216 QDF_STATUS status = QDF_STATUS_SUCCESS;
217
218 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
219 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
220 adapter = adapter_node->pAdapter;
221 if (NULL != adapter)
222 hdd_send_rps_ind(adapter);
223 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
224 adapter_node = next;
225 }
226}
227
228/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
230 * @vdev_id: vdev_id
231 * @action: action type
232 * @reason: reason type
233 *
234 * Return: none
235 */
236void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
237 enum netif_action_type action, enum netif_reason_type reason)
238{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530239 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800240 hdd_adapter_t *adapter;
241
242 if (!hdd_ctx) {
243 hdd_err("hdd ctx is NULL");
244 return;
245 }
246 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
247
248 wlan_hdd_netif_queue_control(adapter, action, reason);
249 return;
250}
251
252/*
253 * Store WLAN driver version info in a global variable such that crash debugger
254 * can extract it from driver debug symbol and crashdump for post processing
255 */
256uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
257
258/**
259 * hdd_device_mode_to_string() - return string conversion of device mode
260 * @device_mode: device mode
261 *
262 * This utility function helps log string conversion of device mode.
263 *
264 * Return: string conversion of device mode, if match found;
265 * "Unknown" otherwise.
266 */
267const char *hdd_device_mode_to_string(uint8_t device_mode)
268{
269 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800270 CASE_RETURN_STRING(QDF_STA_MODE);
271 CASE_RETURN_STRING(QDF_SAP_MODE);
272 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
273 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
274 CASE_RETURN_STRING(QDF_FTM_MODE);
275 CASE_RETURN_STRING(QDF_IBSS_MODE);
276 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
277 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700278 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 default:
280 return "Unknown";
281 }
282}
283
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530284/**
285 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
286 * @adapter: HDD adapter
287 * @chan_number: Channel number
288 * @chan_bw: Bandwidth
289 *
290 * Checks if the given bandwidth is valid for the given channel number.
291 *
292 * Return: 0 for success, non-zero for failure
293 */
294int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
295 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800296 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530297{
298 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
299 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
300 bool found = false;
301 tHalHandle hal;
302
303 hal = WLAN_HDD_GET_HAL_CTX(adapter);
304 if (!hal) {
305 hdd_err("Invalid HAL context");
306 return -EINVAL;
307 }
308
309 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
310 hdd_err("No valid channel list");
311 return -EOPNOTSUPP;
312 }
313
314 for (i = 0; i < len; i++) {
315 if (chan[i] == chan_number) {
316 found = true;
317 break;
318 }
319 }
320
321 if (found == false) {
322 hdd_err("Channel not in driver's valid channel list");
323 return -EOPNOTSUPP;
324 }
325
326 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
327 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
328 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
329 return -EINVAL;
330 }
331
332 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
333 if (chan_bw == CH_WIDTH_80MHZ) {
334 hdd_err("BW80 not possible in 2.4GHz band");
335 return -EINVAL;
336 }
337 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
338 (chan_bw != CH_WIDTH_MAX)) {
339 hdd_err("Only BW20 possible on channel 14");
340 return -EINVAL;
341 }
342 }
343
344 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
345 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
346 (chan_bw != CH_WIDTH_MAX)) {
347 hdd_err("Only BW20 possible on channel 165");
348 return -EINVAL;
349 }
350 }
351
352 return 0;
353}
354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355static int __hdd_netdev_notifier_call(struct notifier_block *nb,
356 unsigned long state, void *data)
357{
358#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
359 struct netdev_notifier_info *dev_notif_info = data;
360 struct net_device *dev = dev_notif_info->dev;
361#else
362 struct net_device *dev = data;
363#endif
364 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
365 hdd_context_t *hdd_ctx;
366
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800367 ENTER_DEV(dev);
368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369 /* Make sure that this callback corresponds to our device. */
370 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
371 return NOTIFY_DONE;
372
373 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
374 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700375 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376 return NOTIFY_DONE;
377 }
378
379 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700380 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800381 return NOTIFY_DONE;
382 }
383
384 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
385 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700386 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530387 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 return NOTIFY_DONE;
389 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800390 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 return NOTIFY_DONE;
392
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700393 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394 dev->name, state);
395
396 switch (state) {
397 case NETDEV_REGISTER:
398 break;
399
400 case NETDEV_UNREGISTER:
401 break;
402
403 case NETDEV_UP:
404 sme_ch_avoid_update_req(hdd_ctx->hHal);
405 break;
406
407 case NETDEV_DOWN:
408 break;
409
410 case NETDEV_CHANGE:
411 if (true == adapter->isLinkUpSvcNeeded)
412 complete(&adapter->linkup_event_var);
413 break;
414
415 case NETDEV_GOING_DOWN:
416 if (adapter->scan_info.mScanPending != false) {
417 unsigned long rc;
418 INIT_COMPLETION(adapter->scan_info.
419 abortscan_event_var);
420 hdd_abort_mac_scan(adapter->pHddCtx,
421 adapter->sessionId,
422 eCSR_SCAN_ABORT_DEFAULT);
423 rc = wait_for_completion_timeout(
424 &adapter->scan_info.abortscan_event_var,
425 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
426 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700427 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 }
429 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700430 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431 }
432 break;
433
434 default:
435 break;
436 }
437
438 return NOTIFY_DONE;
439}
440
441/**
442 * hdd_netdev_notifier_call() - netdev notifier callback function
443 * @nb: pointer to notifier block
444 * @state: state
445 * @ndev: ndev pointer
446 *
447 * Return: 0 on success, error number otherwise.
448 */
449static int hdd_netdev_notifier_call(struct notifier_block *nb,
450 unsigned long state,
451 void *ndev)
452{
453 int ret;
454
455 cds_ssr_protect(__func__);
456 ret = __hdd_netdev_notifier_call(nb, state, ndev);
457 cds_ssr_unprotect(__func__);
458
459 return ret;
460}
461
462struct notifier_block hdd_netdev_notifier = {
463 .notifier_call = hdd_netdev_notifier_call,
464};
465
466/* variable to hold the insmod parameters */
467static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800468
469/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800470static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530472/**
473 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
474 * @ch_width: NL channel width
475 *
476 * Converts the NL channel width to the driver's internal representation
477 *
478 * Return: Converted channel width. In case of non matching NL channel width,
479 * CH_WIDTH_MAX will be returned.
480 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800481enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530482{
483 switch (ch_width) {
484 case NL80211_CHAN_WIDTH_20_NOHT:
485 case NL80211_CHAN_WIDTH_20:
486 return CH_WIDTH_20MHZ;
487 case NL80211_CHAN_WIDTH_40:
488 return CH_WIDTH_40MHZ;
489 break;
490 case NL80211_CHAN_WIDTH_80:
491 return CH_WIDTH_80MHZ;
492 case NL80211_CHAN_WIDTH_80P80:
493 return CH_WIDTH_80P80MHZ;
494 case NL80211_CHAN_WIDTH_160:
495 return CH_WIDTH_160MHZ;
496 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800497 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530498 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800499 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530500 default:
501 hdd_err("Invalid channel width %d, setting to default",
502 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800503 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530504 }
505}
506
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530507/* wlan_hdd_find_opclass() - Find operating class for a channel
508 * @hal: handler to HAL
509 * @channel: channel id
510 * @bw_offset: bandwidth offset
511 *
512 * Function invokes sme api to find the operating class
513 *
514 * Return: operating class
515 */
516uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
517 uint8_t bw_offset)
518{
519 uint8_t opclass = 0;
520
521 sme_get_opclass(hal, channel, bw_offset, &opclass);
522 return opclass;
523}
524
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530526 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800527 * @moduleId: Module whose trace level is being configured
528 * @bitmask: Bitmask of log levels to be enabled
529 *
530 * Called immediately after the cfg.ini is read in order to configure
531 * the desired trace levels.
532 *
533 * Return: None
534 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530535static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530537 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538
539 /*
540 * if the bitmask is the default value, then a bitmask was not
541 * specified in cfg.ini, so leave the logging level alone (it
542 * will remain at the "compiled in" default value)
543 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530544 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545 return;
546 }
547
548 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530549 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550
551 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530552 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 while (0 != bitmask) {
554 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530555 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 }
557 level++;
558 bitmask >>= 1;
559 }
560}
561
562/**
563 * wlan_hdd_validate_context() - check the HDD context
564 * @hdd_ctx: HDD context pointer
565 *
566 * Return: 0 if the context is valid. Error code otherwise
567 */
568int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
569{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800570 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530571 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 return -ENODEV;
573 }
574
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800575 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530576 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
577 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 return -EAGAIN;
579 }
580
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800581 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530582 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
583 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584 return -EAGAIN;
585 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +0530586
587 if (hdd_ctx->start_modules_in_progress ||
588 hdd_ctx->stop_modules_in_progress) {
589 hdd_err("%pS Start/Stop Modules in progress. Ignore!!!",
590 (void *)_RET_IP_);
591 return -EAGAIN;
592 }
593
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594 return 0;
595}
596
597void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
598{
599 hdd_adapter_t *adapter = NULL;
600 hdd_station_ctx_t *pHddStaCtx = NULL;
601 eCsrPhyMode phyMode;
602 struct hdd_config *cfg_param = NULL;
603
604 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700605 hdd_alert("HDD Context is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606 return;
607 }
608
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800609 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610 if (NULL == adapter) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700611 hdd_alert("adapter is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612 return;
613 }
614
615 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
616
617 cfg_param = hdd_ctx->config;
618 if (NULL == cfg_param) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700619 hdd_alert("cfg_params not available !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 return;
621 }
622
623 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
624
625 if (!hdd_ctx->isVHT80Allowed) {
626 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
627 (eCSR_DOT11_MODE_11ac == phyMode) ||
628 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700629 hdd_notice("Setting phymode to 11n!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
631 eCSR_DOT11_MODE_11n);
632 }
633 } else {
634 /*
635 * New country Supports 11ac as well resetting value back from
636 * .ini
637 */
638 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
639 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
640 dot11Mode));
641 return;
642 }
643
644 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
645 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
646 || (eCSR_CFG_DOT11_MODE_11AC ==
647 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530648 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649
650 /* need to issue a disconnect to CSR. */
651 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530652 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 adapter->sessionId,
654 eCSR_DISCONNECT_REASON_UNSPECIFIED);
655
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530656 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 unsigned long rc;
658
659 rc = wait_for_completion_timeout(
660 &adapter->disconnect_comp_var,
661 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
662 if (!rc)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700663 hdd_err("failure waiting for disconnect_comp_var");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 }
665 }
666}
667
668/**
669 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
670 * @hdd_adapter_t Hdd adapter.
671 *
672 * This function sets the IBSS power save config parameters to WMA
673 * which will send it to firmware if FW supports IBSS power save
674 * before vdev start.
675 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530676 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 * on failure.
678 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530679QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680{
681 int ret;
682 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
683
684 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700685 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530686 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 }
688
689 ret = wma_cli_set_command(adapter->sessionId,
690 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
691 hdd_ctx->config->ibssATIMWinSize,
692 VDEV_CMD);
693 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700694 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530695 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 }
697
698 ret = wma_cli_set_command(adapter->sessionId,
699 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
700 hdd_ctx->config->isIbssPowerSaveAllowed,
701 VDEV_CMD);
702 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700703 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
704 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530705 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 }
707
708 ret = wma_cli_set_command(adapter->sessionId,
709 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
710 hdd_ctx->config->
711 isIbssPowerCollapseAllowed, VDEV_CMD);
712 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700713 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
714 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530715 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 }
717
718 ret = wma_cli_set_command(adapter->sessionId,
719 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
720 hdd_ctx->config->isIbssAwakeOnTxRx,
721 VDEV_CMD);
722 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700723 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530724 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725 }
726
727 ret = wma_cli_set_command(adapter->sessionId,
728 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
729 hdd_ctx->config->ibssInactivityCount,
730 VDEV_CMD);
731 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700732 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530733 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800734 }
735
736 ret = wma_cli_set_command(adapter->sessionId,
737 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
738 hdd_ctx->config->ibssTxSpEndInactivityTime,
739 VDEV_CMD);
740 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700741 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
742 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530743 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744 }
745
746 ret = wma_cli_set_command(adapter->sessionId,
747 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
748 hdd_ctx->config->ibssPsWarmupTime,
749 VDEV_CMD);
750 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700751 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
752 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530753 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754 }
755
756 ret = wma_cli_set_command(adapter->sessionId,
757 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
758 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
759 VDEV_CMD);
760 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700761 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
762 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530763 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 }
765
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530766 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767}
768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769#define INTF_MACADDR_MASK 0x7
770
771/**
772 * hdd_update_macaddr() - update mac address
773 * @config: hdd configuration
774 * @hw_macaddr: mac address
775 *
776 * Mac address for multiple virtual interface is found as following
777 * i) The mac address of the first interface is just the actual hw mac address.
778 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
779 * define the mac address for the remaining interfaces and locally
780 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
781 * supported virtual interfaces, right now this is 0x07 (meaning 8
782 * interface).
783 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
784 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
785 *
786 * Return: None
787 */
788void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530789 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790{
791 int8_t i;
792 uint8_t macaddr_b3, tmp_br3;
793
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530794 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530795 QDF_MAC_ADDR_SIZE);
796 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530797 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530798 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 macaddr_b3 = config->intfMacAddr[i].bytes[3];
800 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
801 INTF_MACADDR_MASK;
802 macaddr_b3 += tmp_br3;
803
804 /* XOR-ing bit-24 of the mac address. This will give enough
805 * mac address range before collision
806 */
807 macaddr_b3 ^= (1 << 7);
808
809 /* Set locally administered bit */
810 config->intfMacAddr[i].bytes[0] |= 0x02;
811 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700812 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 MAC_ADDRESS_STR, i,
814 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
815 }
816}
817
818static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
819 struct wma_tgt_services *cfg)
820{
821 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822
823 /* Set up UAPSD */
824 config->apUapsdEnabled &= cfg->uapsd;
825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 /* 11AC mode support */
827 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
828 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
829 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830
831 /* ARP offload: override user setting if invalid */
832 config->fhostArpOffload &= cfg->arp_offload;
833
834#ifdef FEATURE_WLAN_SCAN_PNO
835 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700836 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837 if (cfg->pno_offload)
838 config->PnoOffload = true;
839#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840#ifdef FEATURE_WLAN_TDLS
841 config->fEnableTDLSSupport &= cfg->en_tdls;
Manjeet Singhfdd2ac72016-09-02 18:11:43 +0530842 config->fEnableTDLSOffChannel = config->fEnableTDLSOffChannel &&
843 cfg->en_tdls_offchan;
844 config->fEnableTDLSBufferSta = config->fEnableTDLSBufferSta &&
845 cfg->en_tdls_uapsd_buf_sta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
847 config->fEnableTDLSSleepSta = true;
848 } else {
849 config->fEnableTDLSSleepSta = false;
850 }
851#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852#ifdef WLAN_FEATURE_ROAM_OFFLOAD
853 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
854#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700855 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800856
857}
858
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700859/**
860 * hdd_update_vdev_nss() - sets the vdev nss
861 * @hdd_ctx: HDD context
862 *
863 * Sets the Nss per vdev type based on INI
864 *
865 * Return: None
866 */
867static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
868{
869 struct hdd_config *cfg_ini = hdd_ctx->config;
870 uint8_t max_supp_nss = 1;
871
872 if (cfg_ini->enable2x2)
873 max_supp_nss = 2;
874
875 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
876 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
877
878 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
879 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
880}
881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
883 struct wma_tgt_ht_cap *cfg)
884{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530885 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 uint32_t value, val32;
887 uint16_t val16;
888 struct hdd_config *pconfig = hdd_ctx->config;
889 tSirMacHTCapabilityInfo *phtCapInfo;
890 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
891 uint8_t enable_tx_stbc;
892
893 /* check and update RX STBC */
894 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
895 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
896
897 /* get the MPDU density */
898 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
899
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530900 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700901 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 value = 0;
903 }
904
905 /*
906 * MPDU density:
907 * override user's setting if value is larger
908 * than the one supported by target
909 */
910 if (value > cfg->mpdu_density) {
911 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
912 cfg->mpdu_density);
913
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530914 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700915 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 }
917
918 /* get the HT capability info */
919 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530920 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700921 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 return;
923 }
924 val16 = (uint16_t) val32;
925 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
926
927 /* Set the LDPC capability */
928 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
929
930 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
931 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
932
933 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
934 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
935
936 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
937 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
938
939 enable_tx_stbc = pconfig->enableTxSTBC;
940
941 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
942 pconfig->enable2x2 = 1;
943 } else {
944 pconfig->enable2x2 = 0;
945 enable_tx_stbc = 0;
946
947 /* 1x1 */
948 /* Update Rx Highest Long GI data Rate */
949 if (sme_cfg_set_int(hdd_ctx->hHal,
950 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700951 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530952 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700953 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954 }
955
956 /* Update Tx Highest Long GI data Rate */
957 if (sme_cfg_set_int
958 (hdd_ctx->hHal,
959 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700960 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530961 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700962 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 }
964 }
965 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
966 enable_tx_stbc = 0;
967 phtCapInfo->txSTBC = enable_tx_stbc;
968
969 val32 = val16;
970 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530971 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700972 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800973#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
974 value = SIZE_OF_SUPPORTED_MCS_SET;
975 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530976 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700977 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978
979 if (pconfig->enable2x2) {
980 for (value = 0; value < cfg->num_rf_chains; value++)
981 mcs_set[value] =
982 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
983
984 status =
985 sme_cfg_set_str(hdd_ctx->hHal,
986 WNI_CFG_SUPPORTED_MCS_SET,
987 mcs_set,
988 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530989 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700990 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 }
992 }
993#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
994}
995
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
997 struct wma_tgt_vht_cap *cfg)
998{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530999 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 uint32_t value = 0;
1001 struct hdd_config *pconfig = hdd_ctx->config;
1002 struct wiphy *wiphy = hdd_ctx->wiphy;
1003 struct ieee80211_supported_band *band_5g =
1004 wiphy->bands[IEEE80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001005 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006
1007 /* Get the current MPDU length */
1008 status =
1009 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
1010 &value);
1011
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301012 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001013 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001014 value = 0;
1015 }
1016
1017 /*
1018 * VHT max MPDU length:
1019 * override if user configured value is too high
1020 * that the target cannot support
1021 */
1022 if (value > cfg->vht_max_mpdu) {
1023 status = sme_cfg_set_int(hdd_ctx->hHal,
1024 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1025 cfg->vht_max_mpdu);
1026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301027 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001028 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001029 }
1030 }
1031
1032 /* Get the current supported chan width */
1033 status = sme_cfg_get_int(hdd_ctx->hHal,
1034 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1035 &value);
1036
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301037 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001038 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039 value = 0;
1040 }
1041
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001042 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1043 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1044
1045 if (pconfig->enable2x2)
1046 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1047
1048 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1049 QDF_STATUS_E_FAILURE) {
1050 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1051 }
1052
1053 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1054 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1055 if (pconfig->enable2x2)
1056 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1057
1058 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1059 QDF_STATUS_E_FAILURE) {
1060 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1061 }
1062
1063 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1064 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1065 if (pconfig->enable2x2)
1066 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1067
1068 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1069 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1070
1071 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1072 QDF_STATUS_E_FAILURE) {
1073 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1074 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001076 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001077 &value);
1078
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301079 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001080 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001081 value = 0;
1082 }
1083
1084 /* Set the LDPC capability */
1085 if (value && !cfg->vht_rx_ldpc) {
1086 status = sme_cfg_set_int(hdd_ctx->hHal,
1087 WNI_CFG_VHT_LDPC_CODING_CAP,
1088 cfg->vht_rx_ldpc);
1089
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301090 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001091 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092 }
1093 }
1094
1095 /* Get current GI 80 value */
1096 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1097 &value);
1098
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301099 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001100 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101 value = 0;
1102 }
1103
1104 /* set the Guard interval 80MHz */
1105 if (value && !cfg->vht_short_gi_80) {
1106 status = sme_cfg_set_int(hdd_ctx->hHal,
1107 WNI_CFG_VHT_SHORT_GI_80MHZ,
1108 cfg->vht_short_gi_80);
1109
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301110 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001111 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001112 }
1113 }
1114
1115 /* Get current GI 160 value */
1116 status = sme_cfg_get_int(hdd_ctx->hHal,
1117 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1118 &value);
1119
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301120 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001121 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001122 value = 0;
1123 }
1124
1125 /* Get VHT TX STBC cap */
1126 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1127
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301128 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001129 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130 value = 0;
1131 }
1132
1133 /* VHT TX STBC cap */
1134 if (value && !cfg->vht_tx_stbc) {
1135 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1136 cfg->vht_tx_stbc);
1137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301138 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001139 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 }
1141 }
1142
1143 /* Get VHT RX STBC cap */
1144 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1145
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301146 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001147 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 value = 0;
1149 }
1150
1151 /* VHT RX STBC cap */
1152 if (value && !cfg->vht_rx_stbc) {
1153 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1154 cfg->vht_rx_stbc);
1155
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301156 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001157 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158 }
1159 }
1160
1161 /* Get VHT SU Beamformer cap */
1162 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1163 &value);
1164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301165 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001166 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001167 value = 0;
1168 }
1169
1170 /* set VHT SU Beamformer cap */
1171 if (value && !cfg->vht_su_bformer) {
1172 status = sme_cfg_set_int(hdd_ctx->hHal,
1173 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1174 cfg->vht_su_bformer);
1175
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301176 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001177 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001178 }
1179 }
1180
1181 /* check and update SU BEAMFORMEE capabality */
1182 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1183 pconfig->enableTxBF = cfg->vht_su_bformee;
1184
1185 status = sme_cfg_set_int(hdd_ctx->hHal,
1186 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1187 pconfig->enableTxBF);
1188
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301189 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001190 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001191 }
1192
1193 /* Get VHT MU Beamformer cap */
1194 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1195 &value);
1196
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301197 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001198 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 value = 0;
1200 }
1201
1202 /* set VHT MU Beamformer cap */
1203 if (value && !cfg->vht_mu_bformer) {
1204 status = sme_cfg_set_int(hdd_ctx->hHal,
1205 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1206 cfg->vht_mu_bformer);
1207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301208 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001209 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210 }
1211 }
1212
1213 /* Get VHT MU Beamformee cap */
1214 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1215 &value);
1216
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301217 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001218 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 value = 0;
1220 }
1221
1222 /* set VHT MU Beamformee cap */
1223 if (value && !cfg->vht_mu_bformee) {
1224 status = sme_cfg_set_int(hdd_ctx->hHal,
1225 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1226 cfg->vht_mu_bformee);
1227
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301228 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001229 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 }
1231 }
1232
1233 /* Get VHT MAX AMPDU Len exp */
1234 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1235 &value);
1236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301237 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001238 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 value = 0;
1240 }
1241
1242 /*
1243 * VHT max AMPDU len exp:
1244 * override if user configured value is too high
1245 * that the target cannot support.
1246 * Even though Rome publish ampdu_len=7, it can
1247 * only support 4 because of some h/w bug.
1248 */
1249
1250 if (value > cfg->vht_max_ampdu_len_exp) {
1251 status = sme_cfg_set_int(hdd_ctx->hHal,
1252 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1253 cfg->vht_max_ampdu_len_exp);
1254
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301255 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001256 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 }
1258 }
1259
1260 /* Get VHT TXOP PS CAP */
1261 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1262
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301263 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001264 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 value = 0;
1266 }
1267
1268 /* set VHT TXOP PS cap */
1269 if (value && !cfg->vht_txop_ps) {
1270 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1271 cfg->vht_txop_ps);
1272
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301273 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001274 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001275 }
1276 }
1277
1278 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1279 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1280 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1281 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1282 else
1283 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1284
1285
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001286 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 band_5g->vht_cap.cap |=
1288 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001289 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001290 band_5g->vht_cap.cap |=
1291 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001292
1293 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1294 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1295
1296 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1297 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1298 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1299 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1300
1301 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1302 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1303
1304 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1305 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1306 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1307 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1308 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1309 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1310
1311 band_5g->vht_cap.cap |=
1312 (cfg->vht_max_ampdu_len_exp <<
1313 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1314
1315 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1316 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1317 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1318 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1319 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1320 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1321 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1322 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1323
1324 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1325 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1326
1327}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001328
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001329/**
1330 * hdd_generate_macaddr_auto() - Auto-generate mac address
1331 * @hdd_ctx: Pointer to the HDD context
1332 *
1333 * Auto-generate mac address using device serial number.
1334 * Keep the first 3 bytes of OUI as before and replace
1335 * the last 3 bytes with the lower 3 bytes of serial number.
1336 *
1337 * Return: 0 for success
1338 * Non zero failure code for errors
1339 */
1340static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1341{
1342 unsigned int serialno = 0;
1343 struct qdf_mac_addr mac_addr = {
1344 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1345 };
1346
1347 serialno = socinfo_get_serial_number();
1348 if (serialno == 0)
1349 return -EINVAL;
1350
1351 serialno &= 0x00ffffff;
1352
1353 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1354 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1355 mac_addr.bytes[5] = serialno & 0xff;
1356
1357 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1358 return 0;
1359}
1360
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301361/**
1362 * hdd_update_ra_rate_limit() - Update RA rate limit from target
1363 * configuration to cfg_ini in HDD
1364 * @hdd_ctx: Pointer to hdd_ctx
1365 * @cfg: target configuration
1366 *
1367 * Return: None
1368 */
1369#ifdef FEATURE_WLAN_RA_FILTERING
1370static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1371 struct wma_tgt_cfg *cfg)
1372{
1373 hdd_ctx->config->IsRArateLimitEnabled = cfg->is_ra_rate_limit_enabled;
1374}
1375#else
1376static void hdd_update_ra_rate_limit(hdd_context_t *hdd_ctx,
1377 struct wma_tgt_cfg *cfg)
1378{
1379}
1380#endif
1381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382void hdd_update_tgt_cfg(void *context, void *param)
1383{
1384 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1385 struct wma_tgt_cfg *cfg = param;
1386 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001387 struct cds_config_info *cds_cfg = cds_get_ini_config();
1388
1389 if (cds_cfg) {
1390 if (hdd_ctx->config->enable_sub_20_channel_width !=
1391 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1392 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1393 cds_cfg->sub_20_channel_width =
1394 WLAN_SUB_20_CH_WIDTH_NONE;
1395 } else {
1396 cds_cfg->sub_20_channel_width =
1397 hdd_ctx->config->enable_sub_20_channel_width;
1398 }
1399 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001400
1401 /* first store the INI band capability */
1402 temp_band_cap = hdd_ctx->config->nBandCapability;
1403
1404 hdd_ctx->config->nBandCapability = cfg->band_cap;
1405
1406 /* now overwrite the target band capability with INI
1407 setting if INI setting is a subset */
1408
1409 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1410 (temp_band_cap != eCSR_BAND_ALL))
1411 hdd_ctx->config->nBandCapability = temp_band_cap;
1412 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1413 (temp_band_cap != eCSR_BAND_ALL) &&
1414 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001415 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001416 }
1417
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001418 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001419 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1420 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1421 }
1422
1423 /* This can be extended to other configurations like ht, vht cap... */
1424
Anurag Chouhanc5548422016-02-24 18:33:27 +05301425 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1427 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001428 static struct qdf_mac_addr default_mac_addr = {
1429 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1430 };
1431 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1432 &default_mac_addr)) {
1433 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1434 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1435 MAC_ADDRESS_STR,
1436 MAC_ADDR_ARRAY(hdd_ctx->config->
1437 intfMacAddr[0].bytes));
1438 } else {
1439 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1440 MAC_ADDRESS_STR,
1441 MAC_ADDR_ARRAY(hdd_ctx->config->
1442 intfMacAddr[0].bytes));
1443 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444 }
1445
1446 hdd_ctx->target_fw_version = cfg->target_fw_version;
1447
1448 hdd_ctx->max_intf_count = cfg->max_intf_count;
1449
1450#ifdef WLAN_FEATURE_LPSS
1451 hdd_ctx->lpss_support = cfg->lpss_support;
1452#endif
1453
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001454 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1457 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1458
1459 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001462
1463 hdd_update_vdev_nss(hdd_ctx);
1464
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001465 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001466 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001467 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001468 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001469
1470 hdd_ctx->current_antenna_mode =
1471 (hdd_ctx->config->enable2x2 == 0x01) ?
1472 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1473 hdd_info("Init current antenna mode: %d",
1474 hdd_ctx->current_antenna_mode);
1475
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001476 hdd_info("Target BPF %d Host BPF %d",
1477 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1478 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1479 hdd_ctx->config->bpf_packet_filter_enable);
Anurag Chouhan04dbf6d2016-09-08 15:32:52 +05301480 hdd_update_ra_rate_limit(hdd_ctx, cfg);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301481
Arun Khandavallid454d422016-08-17 12:47:05 +05301482 /*
1483 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1484 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1485 * configure the STA mode wow pattern.
1486 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301487 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301488 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301489
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001490 /* Configure NAN datapath features */
1491 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492}
1493
1494/**
1495 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1496 * @context: HDD context pointer
1497 * @param: HDD radar indication pointer
1498 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001499 * This function is invoked in atomic context when a radar
1500 * is found on the SAP current operating channel and Data Tx
1501 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 * Actions: Stop the netif Tx queues,Indicate Radar present
1503 * in HDD context for future usage.
1504 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301505 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301507bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508{
1509 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1510 struct wma_dfs_radar_ind *hdd_radar_event =
1511 (struct wma_dfs_radar_ind *)param;
1512 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1513 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301514 QDF_STATUS status;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301515 hdd_ap_ctx_t *ap_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301517 if (!hdd_ctx || !hdd_radar_event ||
1518 hdd_ctx->config->disableDFSChSwitch)
1519 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520
1521 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001522 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301523 /*
1524 * Application already triggered channel switch
1525 * on current channel, so return here.
1526 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301527 return false;
1528 }
1529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001530 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301531 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001532 adapter = adapterNode->pAdapter;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301533 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1534 if ((QDF_SAP_MODE == adapter->device_mode ||
1535 QDF_P2P_GO_MODE == adapter->device_mode) &&
1536 (CHANNEL_STATE_DFS ==
1537 cds_get_channel_state(ap_ctx->operatingChannel))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1539 dfs_cac_block_tx = true;
Manishekar Chandrasekaran11ecd552016-08-31 12:44:05 +05301540 hdd_info("tx blocked for session:%d",
1541 adapter->sessionId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001542 }
1543
1544 status = hdd_get_next_adapter(hdd_ctx,
1545 adapterNode,
1546 &pNext);
1547 adapterNode = pNext;
1548 }
1549 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301550
1551 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001552}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001553
1554/**
1555 * hdd_is_valid_mac_address() - validate MAC address
1556 * @pMacAddr: Pointer to the input MAC address
1557 *
1558 * This function validates whether the given MAC address is valid or not
1559 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1560 * where X is the hexa decimal digit character and separated by ':'
1561 * This algorithm works even if MAC address is not separated by ':'
1562 *
1563 * This code checks given input string mac contains exactly 12 hexadecimal
1564 * digits and a separator colon : appears in the input string only after
1565 * an even number of hex digits.
1566 *
1567 * Return: 1 for valid and 0 for invalid
1568 */
1569bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1570{
1571 int xdigit = 0;
1572 int separator = 0;
1573 while (*pMacAddr) {
1574 if (isxdigit(*pMacAddr)) {
1575 xdigit++;
1576 } else if (':' == *pMacAddr) {
1577 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1578 break;
1579
1580 ++separator;
1581 } else {
1582 /* Invalid MAC found */
1583 return 0;
1584 }
1585 ++pMacAddr;
1586 }
1587 return xdigit == 12 && (separator == 5 || separator == 0);
1588}
1589
1590/**
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301591 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
1592 * @dev: Handle to struct net_device to be updated.
1593 *
1594 * Return: None
1595 */
1596static void hdd_mon_mode_ether_setup(struct net_device *dev)
1597{
1598 dev->header_ops = NULL;
1599 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1600 dev->hard_header_len = ETH_HLEN;
1601 dev->mtu = ETH_DATA_LEN;
1602 dev->addr_len = ETH_ALEN;
1603 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
1604 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
1605 dev->priv_flags |= IFF_TX_SKB_SHARING;
1606
1607 memset(dev->broadcast, 0xFF, ETH_ALEN);
1608}
1609
1610/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001611 * __hdd__mon_open() - HDD Open function
1612 * @dev: Pointer to net_device structure
1613 *
1614 * This is called in response to ifconfig up
1615 *
1616 * Return: 0 for success; non-zero for failure
1617 */
1618static int __hdd_mon_open(struct net_device *dev)
1619{
1620 int ret;
1621
1622 ENTER_DEV(dev);
Arun Khandavallif5c0e0c2016-09-07 20:39:21 +05301623 hdd_mon_mode_ether_setup(dev);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001624 ret = hdd_set_mon_rx_cb(dev);
1625 return ret;
1626}
1627
1628/**
1629 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1630 * @dev: Pointer to net_device structure
1631 *
1632 * This is called in response to ifconfig up
1633 *
1634 * Return: 0 for success; non-zero for failure
1635 */
1636int hdd_mon_open(struct net_device *dev)
1637{
1638 int ret;
1639
1640 cds_ssr_protect(__func__);
1641 ret = __hdd_mon_open(dev);
1642 cds_ssr_unprotect(__func__);
1643
1644 return ret;
1645}
1646
1647/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301648 * hdd_start_adapter() - Wrapper function for device specific adapter
1649 * @adapter: pointer to HDD adapter
1650 *
1651 * This function is called to start the device specific adapter for
1652 * the mode passed in the adapter's device_mode.
1653 *
1654 * Return: 0 for success; non-zero for failure
1655 */
1656int hdd_start_adapter(hdd_adapter_t *adapter)
1657{
1658
1659 int ret;
1660 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1661
1662 ENTER_DEV(adapter->dev);
1663 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1664
1665 switch (device_mode) {
1666 case QDF_P2P_CLIENT_MODE:
1667 case QDF_P2P_DEVICE_MODE:
1668 case QDF_OCB_MODE:
1669 case QDF_STA_MODE:
1670 case QDF_MONITOR_MODE:
1671 ret = hdd_start_station_adapter(adapter);
1672 if (ret)
1673 goto err_start_adapter;
1674 break;
1675 case QDF_P2P_GO_MODE:
1676 case QDF_SAP_MODE:
1677 ret = hdd_start_ap_adapter(adapter);
1678 if (ret)
1679 goto err_start_adapter;
1680 break;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05301681 case QDF_IBSS_MODE:
1682 /*
1683 * For IBSS interface is initialized as part of
1684 * hdd_init_station_mode()
1685 */
1686 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05301687 case QDF_FTM_MODE:
1688 ret = hdd_start_ftm_adapter(adapter);
1689 if (ret)
1690 goto err_start_adapter;
1691 break;
1692 default:
1693 hdd_err("Invalid session type %d", device_mode);
1694 QDF_ASSERT(0);
1695 goto err_start_adapter;
1696 }
1697 if (hdd_set_fw_params(adapter))
1698 hdd_err("Failed to set the FW params for the adapter!");
1699
1700 /*
1701 * Action frame registered in one adapter which will
1702 * applicable to all interfaces
1703 */
1704 wlan_hdd_cfg80211_register_frames(adapter);
1705 EXIT();
1706 return 0;
1707err_start_adapter:
1708 return -EINVAL;
1709}
1710
1711/**
1712 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1713 * @hdd_ctx: HDD context
1714 * @adapter: HDD adapter
1715 * @reinit: flag to indicate from SSR or normal path
1716 *
1717 * This function maintains the driver state machine it will be invoked from
1718 * startup, reinit and change interface. Depending on the driver state shall
1719 * perform the opening of the modules.
1720 *
1721 * Return: 0 for success; non-zero for failure
1722 */
1723int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1724 bool reinit)
1725{
1726 int ret;
1727 qdf_device_t qdf_dev;
1728 QDF_STATUS status;
1729 p_cds_contextType p_cds_context;
1730 bool unint = false;
1731 void *hif_ctx;
1732
1733 ENTER();
1734
1735 p_cds_context = cds_get_global_context();
1736 if (!p_cds_context) {
1737 hdd_err("Global Context is NULL");
1738 QDF_ASSERT(0);
1739 return -EINVAL;
1740 }
1741
1742 hdd_info("start modules called in state! :%d reinit: %d",
1743 hdd_ctx->driver_status, reinit);
1744
1745 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1746 if (!qdf_dev) {
1747 hdd_err("QDF Device Context is Invalid return");
1748 return -EINVAL;
1749 }
1750
1751 mutex_lock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301752 hdd_ctx->start_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05301753
1754 if (QDF_TIMER_STATE_RUNNING ==
1755 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1756
1757 hdd_set_idle_ps_config(hdd_ctx, false);
1758 hdd_info("Interface change Timer running Stop timer");
1759 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1760 }
1761
1762 switch (hdd_ctx->driver_status) {
1763 case DRIVER_MODULES_UNINITIALIZED:
1764 unint = true;
1765 /* Fall through dont add break here */
1766 case DRIVER_MODULES_CLOSED:
1767 if (!reinit && !unint) {
1768 ret = pld_power_on(qdf_dev->dev);
1769 if (ret) {
1770 hdd_err("Failed to Powerup the device: %d", ret);
1771 goto release_lock;
1772 }
1773 }
1774 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1775 qdf_dev->bus_type,
1776 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1777 HIF_ENABLE_TYPE_PROBE);
1778 if (ret) {
1779 hdd_err("Failed to open hif: %d", ret);
1780 goto power_down;
1781 }
1782
1783 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Arun Khandavalli1318b992016-08-09 11:04:57 +05301784 if (!hif_ctx) {
1785 hdd_err("hif context is null!!");
1786 goto power_down;
1787 }
1788
Arun Khandavallifae92942016-08-01 13:31:08 +05301789 status = ol_cds_init(qdf_dev, hif_ctx);
1790 if (status != QDF_STATUS_SUCCESS) {
1791 hdd_err("No Memory to Create BMI Context :%d", status);
1792 goto hif_close;
1793 }
1794
Arun Khandavallif6246632016-08-17 17:43:06 +05301795 ret = hdd_update_config(hdd_ctx);
1796 if (ret) {
1797 hdd_err("Failed to update configuration :%d", ret);
1798 goto ol_cds_free;
1799 }
1800
Arun Khandavallifae92942016-08-01 13:31:08 +05301801 status = cds_open();
1802 if (!QDF_IS_STATUS_SUCCESS(status)) {
1803 hdd_err("Failed to Open CDS: %d", status);
1804 goto ol_cds_free;
1805 }
1806
1807 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1808
1809 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1810
1811 status = cds_pre_enable(hdd_ctx->pcds_context);
1812 if (!QDF_IS_STATUS_SUCCESS(status)) {
1813 hdd_err("Failed to pre-enable CDS: %d", status);
1814 goto close;
1815 }
1816
1817 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1818 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1819 hdd_ftm_mc_process_msg);
1820 break;
1821 }
1822 if (unint) {
1823 hdd_info("In phase-1 initialization don't enable modules");
1824 break;
1825 }
1826 /* Fall through dont add break here */
1827 case DRIVER_MODULES_OPENED:
1828 if (!adapter) {
1829 hdd_alert("adapter is Null");
1830 goto close;
1831 }
1832 if (hdd_configure_cds(hdd_ctx, adapter)) {
1833 hdd_err("Failed to Enable cds modules");
1834 goto close;
1835 }
1836 hdd_info("Driver Modules Successfully Enabled");
1837 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1838 break;
1839 case DRIVER_MODULES_ENABLED:
1840 hdd_info("Driver modules already Enabled");
1841 break;
1842 default:
1843 hdd_err("WLAN start invoked in wrong state! :%d\n",
1844 hdd_ctx->driver_status);
1845 goto release_lock;
1846 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301847 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301848 mutex_unlock(&hdd_ctx->iface_change_lock);
1849 EXIT();
1850 return 0;
1851
1852close:
1853 cds_close(p_cds_context);
1854
1855ol_cds_free:
1856 ol_cds_free();
1857
1858hif_close:
1859 hdd_hif_close(p_cds_context->pHIFContext);
1860power_down:
1861 if (!reinit && !unint)
1862 pld_power_off(qdf_dev->dev);
1863release_lock:
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301864 hdd_ctx->start_modules_in_progress = false;
Arun Khandavallifae92942016-08-01 13:31:08 +05301865 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05301866 EXIT();
Arun Khandavallifae92942016-08-01 13:31:08 +05301867 return -EINVAL;
1868}
1869
1870/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871 * __hdd_open() - HDD Open function
1872 * @dev: Pointer to net_device structure
1873 *
1874 * This is called in response to ifconfig up
1875 *
1876 * Return: 0 for success; non-zero for failure
1877 */
1878static int __hdd_open(struct net_device *dev)
1879{
1880 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1881 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1882 int ret;
1883
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001884 ENTER_DEV(dev);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301885 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301886 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887
1888 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301889 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301891
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892
Arun Khandavallifae92942016-08-01 13:31:08 +05301893 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1894 if (ret) {
1895 hdd_err("Failed to start WLAN modules return");
1896 return -ret;
1897 }
1898
1899
1900 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1901 ret = hdd_start_adapter(adapter);
1902 if (ret) {
1903 hdd_err("Failed to start adapter :%d",
1904 adapter->device_mode);
1905 return ret;
1906 }
1907 }
1908
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1910 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301911 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912 /* Enable TX queues only when we are connected */
1913 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301914 WLAN_START_ALL_NETIF_QUEUE,
1915 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 }
1917
1918 return ret;
1919}
1920
Arun Khandavallifae92942016-08-01 13:31:08 +05301921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922/**
1923 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1924 * @dev: Pointer to net_device structure
1925 *
1926 * This is called in response to ifconfig up
1927 *
1928 * Return: 0 for success; non-zero for failure
1929 */
1930int hdd_open(struct net_device *dev)
1931{
1932 int ret;
1933
1934 cds_ssr_protect(__func__);
1935 ret = __hdd_open(dev);
1936 cds_ssr_unprotect(__func__);
1937
1938 return ret;
1939}
1940
1941/**
1942 * __hdd_stop() - HDD stop function
1943 * @dev: Pointer to net_device structure
1944 *
1945 * This is called in response to ifconfig down
1946 *
1947 * Return: 0 for success; non-zero for failure
1948 */
1949static int __hdd_stop(struct net_device *dev)
1950{
1951 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1952 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301953 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301955 bool close_modules = true;
1956 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001958 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301960 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001961 adapter->sessionId, adapter->device_mode));
1962
1963 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301964 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966
1967 /* Nothing to be done if the interface is not opened */
1968 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001969 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970 return -ENODEV;
1971 }
1972
1973 /* Make sure the interface is marked as closed */
1974 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001975 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976
1977 /*
1978 * Disable TX on the interface, after this hard_start_xmit() will not
1979 * be called on that interface
1980 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001981 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1983 WLAN_CONTROL_PATH);
1984
1985 /*
1986 * The interface is marked as down for outside world (aka kernel)
1987 * But the driver is pretty much alive inside. The driver needs to
1988 * tear down the existing connection on the netdev (session)
1989 * cleanup the data pipes and wait until the control plane is stabilized
1990 * for this interface. The call also needs to wait until the above
1991 * mentioned actions are completed before returning to the caller.
1992 * Notice that the hdd_stop_adapter is requested not to close the session
1993 * That is intentional to be able to scan if it is a STA/P2P interface
1994 */
Arun Khandavallifae92942016-08-01 13:31:08 +05301995 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996
1997 /* DeInit the adapter. This ensures datapath cleanup as well */
1998 hdd_deinit_adapter(hdd_ctx, adapter, true);
1999
Arun Khandavallifae92942016-08-01 13:31:08 +05302000
2001 /*
2002 * Find if any iface is up. If any iface is up then can't put device to
2003 * sleep/power save mode
2004 */
2005 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
2006 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
2007 if (test_bit(DEVICE_IFACE_OPENED,
2008 &adapternode->pAdapter->event_flags)) {
2009 hdd_info("Still other ifaces are up cannot close modules");
2010 close_modules = false;
2011 break;
2012 }
2013 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
2014 adapternode = next;
2015
2016 }
2017
2018 if (close_modules) {
2019 hdd_info("Closing all modules from the hdd_stop");
2020 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
2021 hdd_ctx->config->iface_change_wait_time
2022 * 50000);
2023 }
2024
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 EXIT();
2026 return 0;
2027}
2028
2029/**
2030 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
2031 * @dev: pointer to net_device structure
2032 *
2033 * This is called in response to ifconfig down
2034 *
2035 * Return: 0 for success and error number for failure
2036 */
2037int hdd_stop(struct net_device *dev)
2038{
2039 int ret;
2040
2041 cds_ssr_protect(__func__);
2042 ret = __hdd_stop(dev);
2043 cds_ssr_unprotect(__func__);
2044
2045 return ret;
2046}
2047
2048/**
2049 * __hdd_uninit() - HDD uninit function
2050 * @dev: Pointer to net_device structure
2051 *
2052 * This is called during the netdev unregister to uninitialize all data
2053 * associated with the device
2054 *
2055 * Return: None
2056 */
2057static void __hdd_uninit(struct net_device *dev)
2058{
2059 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2060
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002061 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062
2063 do {
2064 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002065 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 break;
2067 }
2068
2069 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002070 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 break;
2072 }
2073
2074 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002075 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 /*
2077 * we haven't validated all cases so let this go for
2078 * now
2079 */
2080 }
2081
2082 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2083
2084 /* after uninit our adapter structure will no longer be valid */
2085 adapter->dev = NULL;
2086 adapter->magic = 0;
2087 } while (0);
2088
2089 EXIT();
2090}
2091
2092/**
2093 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2094 * @dev: pointer to net_device structure
2095 *
2096 * This is called during the netdev unregister to uninitialize all data
2097 * associated with the device
2098 *
2099 * Return: none
2100 */
2101static void hdd_uninit(struct net_device *dev)
2102{
2103 cds_ssr_protect(__func__);
2104 __hdd_uninit(dev);
2105 cds_ssr_unprotect(__func__);
2106}
2107
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002108static int hdd_open_cesium_nl_sock(void)
2109{
2110#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2111 struct netlink_kernel_cfg cfg = {
2112 .groups = WLAN_NLINK_MCAST_GRP_ID,
2113 .input = NULL
2114 };
2115#endif
2116 int ret = 0;
2117
2118#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2119 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2120#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2121 THIS_MODULE,
2122#endif
2123 &cfg);
2124#else
2125 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2126 WLAN_NLINK_MCAST_GRP_ID,
2127 NULL, NULL, THIS_MODULE);
2128#endif
2129
2130 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002131 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002132 ret = -ECONNREFUSED;
2133 }
2134
2135 return ret;
2136}
2137
2138static void hdd_close_cesium_nl_sock(void)
2139{
2140 if (NULL != cesium_nl_srv_sock) {
2141 netlink_kernel_release(cesium_nl_srv_sock);
2142 cesium_nl_srv_sock = NULL;
2143 }
2144}
2145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002146/**
2147 * __hdd_set_mac_address() - set the user specified mac address
2148 * @dev: Pointer to the net device.
2149 * @addr: Pointer to the sockaddr.
2150 *
2151 * This function sets the user specified mac address using
2152 * the command ifconfig wlanX hw ether <mac adress>.
2153 *
2154 * Return: 0 for success, non zero for failure
2155 */
2156static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2157{
2158 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2159 hdd_context_t *hdd_ctx;
2160 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302161 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 int ret;
2163
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002164 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165
2166 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2167 ret = wlan_hdd_validate_context(hdd_ctx);
2168 if (0 != ret)
2169 return ret;
2170
2171 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2172 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2173
2174 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302175 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176}
2177
2178/**
2179 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2180 * function from SSR
2181 * @dev: pointer to net_device structure
2182 * @addr: Pointer to the sockaddr
2183 *
2184 * This function sets the user specified mac address using
2185 * the command ifconfig wlanX hw ether <mac adress>.
2186 *
2187 * Return: 0 for success.
2188 */
2189static int hdd_set_mac_address(struct net_device *dev, void *addr)
2190{
2191 int ret;
2192
2193 cds_ssr_protect(__func__);
2194 ret = __hdd_set_mac_address(dev, addr);
2195 cds_ssr_unprotect(__func__);
2196
2197 return ret;
2198}
2199
2200uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2201{
2202 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302203 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2205 break;
2206 }
2207
Anurag Chouhan6d760662016-02-20 16:05:43 +05302208 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209 return NULL;
2210
2211 hdd_ctx->config->intfAddrMask |= (1 << i);
2212 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2213}
2214
2215void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2216{
2217 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302218 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 if (!memcmp(releaseAddr,
2220 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2221 6)) {
2222 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2223 break;
2224 }
2225 }
2226 return;
2227}
2228
2229#ifdef WLAN_FEATURE_PACKET_FILTERING
2230/**
2231 * __hdd_set_multicast_list() - set the multicast address list
2232 * @dev: Pointer to the WLAN device.
2233 * @skb: Pointer to OS packet (sk_buff).
2234 *
2235 * This funciton sets the multicast address list.
2236 *
2237 * Return: None
2238 */
2239static void __hdd_set_multicast_list(struct net_device *dev)
2240{
2241 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2242 int mc_count;
2243 int i = 0, status;
2244 struct netdev_hw_addr *ha;
2245 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2246 static const uint8_t ipv6_router_solicitation[]
2247 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2248
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002249 ENTER_DEV(dev);
2250
Anurag Chouhan6d760662016-02-20 16:05:43 +05302251 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302252 return;
2253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302255 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002256 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257
2258 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002259 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260 adapter->mc_addr_list.mc_cnt = 0;
2261 } else {
2262 mc_count = netdev_mc_count(dev);
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302263 hdd_notice("mc_count : %u", mc_count);
2264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002265 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002266 hdd_notice("No free filter available; allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267 adapter->mc_addr_list.mc_cnt = 0;
2268 return;
2269 }
2270
2271 adapter->mc_addr_list.mc_cnt = mc_count;
2272
2273 netdev_for_each_mc_addr(ha, dev) {
Sachin Ahujaa69c72a2016-09-03 15:59:33 +05302274 hdd_notice("ha_addr[%d] "MAC_ADDRESS_STR,
2275 i, MAC_ADDR_ARRAY(ha->addr));
2276
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 if (i == mc_count)
2278 break;
2279 /*
2280 * Skip following addresses:
2281 * 1)IPv6 router solicitation address
2282 * 2)Any other address pattern if its set during
2283 * RXFILTER REMOVE driver command based on
2284 * addr_filter_pattern
2285 */
2286 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2287 ETH_ALEN)) ||
2288 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2289 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002290 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291 MAC_ADDR_ARRAY(ha->addr));
2292 adapter->mc_addr_list.mc_cnt--;
2293 continue;
2294 }
2295
2296 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2297 ETH_ALEN);
2298 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2299 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002300 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2302 i++;
2303 }
2304 }
2305 if (hdd_ctx->config->active_mode_offload) {
2306 hdd_info("enable mc filtering");
2307 wlan_hdd_set_mc_addr_list(adapter, true);
2308 } else {
2309 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2310 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302311 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 return;
2313}
2314
2315/**
2316 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2317 * @dev: pointer to net_device
2318 *
2319 * Return: none
2320 */
2321static void hdd_set_multicast_list(struct net_device *dev)
2322{
2323 cds_ssr_protect(__func__);
2324 __hdd_set_multicast_list(dev);
2325 cds_ssr_unprotect(__func__);
2326}
2327#endif
2328
2329/**
2330 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2331 * @dev: Pointer to the WLAN device.
2332 * @skb: Pointer to OS packet (sk_buff).
2333 *
2334 * This function is registered with the Linux OS for network
2335 * core to decide which queue to use first.
2336 *
2337 * Return: ac, Queue Index/access category corresponding to UP in IP header
2338 */
2339static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2340#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2341 , void *accel_priv
2342#endif
2343#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2344 , select_queue_fallback_t fallback
2345#endif
2346)
2347{
2348 return hdd_wmm_select_queue(dev, skb);
2349}
2350
2351static struct net_device_ops wlan_drv_ops = {
2352 .ndo_open = hdd_open,
2353 .ndo_stop = hdd_stop,
2354 .ndo_uninit = hdd_uninit,
2355 .ndo_start_xmit = hdd_hard_start_xmit,
2356 .ndo_tx_timeout = hdd_tx_timeout,
2357 .ndo_get_stats = hdd_get_stats,
2358 .ndo_do_ioctl = hdd_ioctl,
2359 .ndo_set_mac_address = hdd_set_mac_address,
2360 .ndo_select_queue = hdd_select_queue,
2361#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002363#endif
2364};
2365
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002366/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2367static struct net_device_ops wlan_mon_drv_ops = {
2368 .ndo_open = hdd_mon_open,
2369 .ndo_stop = hdd_stop,
2370 .ndo_get_stats = hdd_get_stats,
2371};
2372
2373/**
2374 * hdd_set_station_ops() - update net_device ops for monitor mode
2375 * @pWlanDev: Handle to struct net_device to be updated.
2376 * Return: None
2377 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378void hdd_set_station_ops(struct net_device *pWlanDev)
2379{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002380 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2381 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2382 else
2383 pWlanDev->netdev_ops = &wlan_drv_ops;
2384}
2385
2386/**
Ryan Hsu07495ea2016-01-21 15:25:39 -08002387 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2388 * @hdd_ctx: global hdd context
2389 * @macAddr: mac address to assign to the interface
2390 * @name: User-visible name of the interface
2391 *
2392 * hdd adapter pointer would point to the netdev->priv space, this function
2393 * would retrive the pointer, and setup the hdd adapter configuration.
2394 *
2395 * Return: the pointer to hdd adapter, otherwise NULL
2396 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002397static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2398 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002399 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 const char *name)
2401{
2402 struct net_device *pWlanDev = NULL;
2403 hdd_adapter_t *adapter = NULL;
2404 /*
2405 * cfg80211 initialization and registration....
2406 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002407 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2408#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2409 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002411 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2412 hdd_mon_mode_ether_setup : ether_setup),
2413 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414
2415 if (pWlanDev != NULL) {
2416
2417 /* Save the pointer to the net_device in the HDD adapter */
2418 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2419
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302420 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002421
2422 adapter->dev = pWlanDev;
2423 adapter->pHddCtx = hdd_ctx;
2424 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05302425 adapter->sessionId = HDD_SESSION_ID_INVALID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426
2427 init_completion(&adapter->session_open_comp_var);
2428 init_completion(&adapter->session_close_comp_var);
2429 init_completion(&adapter->disconnect_comp_var);
2430 init_completion(&adapter->linkup_event_var);
2431 init_completion(&adapter->cancel_rem_on_chan_var);
2432 init_completion(&adapter->rem_on_chan_ready_event);
2433 init_completion(&adapter->sta_authorized_event);
2434 init_completion(&adapter->offchannel_tx_event);
2435 init_completion(&adapter->tx_action_cnf_event);
2436#ifdef FEATURE_WLAN_TDLS
2437 init_completion(&adapter->tdls_add_station_comp);
2438 init_completion(&adapter->tdls_del_station_comp);
2439 init_completion(&adapter->tdls_mgmt_comp);
2440 init_completion(&adapter->tdls_link_establish_req_comp);
2441#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002442 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 init_completion(&adapter->change_country_code);
2444
2445
2446 init_completion(&adapter->scan_info.abortscan_event_var);
2447
2448 adapter->offloads_configured = false;
2449 adapter->isLinkUpSvcNeeded = false;
2450 adapter->higherDtimTransition = true;
2451 /* Init the net_device structure */
2452 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2453
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302454 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302456 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 sizeof(tSirMacAddr));
2458 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459
2460 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2461 pWlanDev->features |=
2462 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2463 pWlanDev->features |= NETIF_F_RXCSUM;
2464
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002465 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2466
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 hdd_set_station_ops(adapter->dev);
2468
2469 pWlanDev->destructor = free_netdev;
2470 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002471 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 adapter->wdev.wiphy = hdd_ctx->wiphy;
2473 adapter->wdev.netdev = pWlanDev;
2474 /* set pWlanDev's parent to underlying device */
2475 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2476 hdd_wmm_init(adapter);
2477 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302478 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 }
2480
2481 return adapter;
2482}
2483
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302484QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002485 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486{
2487 struct net_device *pWlanDev = adapter->dev;
2488 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
2489 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302490 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002492 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2494 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002495 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302496 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 }
2498 }
2499 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002500 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302501 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 }
2503 } else {
2504 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002505 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302506 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002507 }
2508 }
2509 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2510
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302511 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512}
2513
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002514QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515{
2516 hdd_adapter_t *adapter = pContext;
2517
2518 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002519 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302520 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 }
2522
2523 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002524 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302525 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 }
2527
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002528 /*
2529 * For NAN Data interface, the close session results in the final
2530 * indication to the userspace
2531 */
Rakesh Sunki3480f962016-08-29 17:29:53 -07002532 if (adapter->device_mode == QDF_NDI_MODE)
2533 hdd_ndp_session_end_handler(adapter);
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 /*
2538 * We can be blocked while waiting for scheduled work to be
2539 * flushed, and the adapter structure can potentially be freed, in
2540 * which case the magic will have been reset. So make sure the
2541 * magic is still good, and hence the adapter structure is still
2542 * valid, before signaling completion
2543 */
2544 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2545 complete(&adapter->session_close_comp_var);
2546
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302547 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548}
2549
Krunal Soni8c37e322016-02-03 16:08:37 -08002550/**
2551 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2552 * @adapter: pointer to device adapter
2553 * @type: type of interface
2554 *
2555 * This routine will check the mode of adapter and if it is required then it
2556 * will initialize the TDLS operations
2557 *
2558 * Return: QDF_STATUS
2559 */
2560#ifdef FEATURE_WLAN_TDLS
2561static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2562{
2563 if (QDF_IBSS_MODE != type) {
2564 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002565 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002566 return QDF_STATUS_E_FAILURE;
2567 }
2568 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2569 }
2570 return QDF_STATUS_SUCCESS;
2571}
2572#else
2573static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2574{
2575 return QDF_STATUS_SUCCESS;
2576}
2577#endif
2578
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302579QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580{
2581 struct net_device *pWlanDev = adapter->dev;
2582 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2583 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302584 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302585 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 uint32_t type, subType;
2587 unsigned long rc;
2588 int ret_val;
2589
2590 INIT_COMPLETION(adapter->session_open_comp_var);
2591 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002592 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302594 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002595 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596 goto error_sme_open;
2597 }
2598 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302599 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2601 (uint8_t *) &adapter->macAddressCurrent,
2602 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302603 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002604 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302605 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302606 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 goto error_sme_open;
2608 }
2609 /* Block on a completion variable. Can't wait forever though. */
2610 rc = wait_for_completion_timeout(
2611 &adapter->session_open_comp_var,
2612 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2613 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002614 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302616 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617 goto error_sme_open;
2618 }
2619
2620 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302621 qdf_ret_status = hdd_register_wext(pWlanDev);
2622 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002623 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302624 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302625 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 goto error_register_wext;
2627 }
2628 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002629 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2631
2632 /* Set the default operation channel */
2633 pHddStaCtx->conn_info.operationChannel =
2634 hdd_ctx->config->OperatingChannel;
2635
2636 /* Make the default Auth Type as OPEN */
2637 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2638
2639 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302640 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002641 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002642 status, status);
2643 goto error_init_txrx;
2644 }
2645
2646 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2647
2648 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302649 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002650 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651 status, status);
2652 goto error_wmm_init;
2653 }
2654
2655 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2656
2657 ret_val = wma_cli_set_command(adapter->sessionId,
2658 WMI_PDEV_PARAM_BURST_ENABLE,
2659 hdd_ctx->config->enableSifsBurst,
2660 PDEV_CMD);
2661
2662 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002663 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002664 ret_val);
2665 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002666 status = hdd_check_and_init_tdls(adapter, type);
2667 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302670 status = hdd_lro_enable(hdd_ctx, adapter);
2671 if (status != QDF_STATUS_SUCCESS)
2672 goto error_lro_enable;
2673
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302674 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05302676error_lro_enable:
2677 wlan_hdd_tdls_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678error_tdls_init:
2679 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2680 hdd_wmm_adapter_close(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681error_wmm_init:
2682 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2683 hdd_deinit_tx_rx(adapter);
2684error_init_txrx:
2685 hdd_unregister_wext(pWlanDev);
2686error_register_wext:
2687 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2688 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302689 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690 adapter->sessionId,
2691 hdd_sme_close_session_callback,
2692 adapter)) {
2693 unsigned long rc;
2694
2695 /*
2696 * Block on a completion variable.
2697 * Can't wait forever though.
2698 */
2699 rc = wait_for_completion_timeout(
2700 &adapter->session_close_comp_var,
2701 msecs_to_jiffies
2702 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2703 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002704 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 rc);
2706 }
2707 }
2708error_sme_open:
2709 return status;
2710}
2711
2712void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2713{
2714 hdd_cfg80211_state_t *cfgState;
2715
2716 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2717
2718 if (NULL != cfgState->buf) {
2719 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 rc = wait_for_completion_timeout(
2721 &adapter->tx_action_cnf_event,
2722 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2723 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002724 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302725 /*
2726 * Inform tx status as FAILURE to upper layer and free
2727 * cfgState->buf
2728 */
2729 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730 }
2731 }
2732 return;
2733}
2734
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302735/**
2736 * hdd_station_adapter_deinit() - De-initialize the station adapter
2737 * @hdd_ctx: global hdd context
2738 * @adapter: HDD adapter
2739 *
2740 * This function De-initializes the STA/P2P/OCB adapter.
2741 *
2742 * Return: None.
2743 */
2744void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2745 hdd_adapter_t *adapter)
2746{
2747 ENTER_DEV(adapter->dev);
2748
2749 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2750 hdd_deinit_tx_rx(adapter);
2751 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2752 }
2753
2754 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2755 hdd_wmm_adapter_close(adapter);
2756 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2757 }
2758
2759 hdd_cleanup_actionframe(hdd_ctx, adapter);
2760 wlan_hdd_tdls_exit(adapter);
2761
2762 EXIT();
2763}
2764
2765/**
2766 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2767 * @hdd_ctx: global hdd context
2768 * @adapter: HDD adapter
2769 * @rtnl_held: the rtnl lock hold flag
2770 * This function De-initializes the AP/P2PGo adapter.
2771 *
2772 * Return: None.
2773 */
2774void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2775 bool rtnl_held)
2776{
2777 ENTER_DEV(adapter->dev);
2778
2779 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2780 hdd_wmm_adapter_close(adapter);
2781 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2782 }
2783
2784 hdd_cleanup_actionframe(hdd_ctx, adapter);
2785
2786 hdd_unregister_hostapd(adapter, rtnl_held);
2787
2788 EXIT();
2789}
2790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2792 bool rtnl_held)
2793{
2794 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002797 case QDF_STA_MODE:
2798 case QDF_P2P_CLIENT_MODE:
2799 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 {
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302801 hdd_station_adapter_deinit(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002802 break;
2803 }
2804
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002805 case QDF_SAP_MODE:
2806 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 {
2808
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302809 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 break;
2811 }
2812
2813 default:
2814 break;
2815 }
2816
2817 EXIT();
2818}
2819
2820void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002821 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822{
2823 struct net_device *pWlanDev = NULL;
2824
2825 if (adapter)
2826 pWlanDev = adapter->dev;
2827 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002828 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 return;
2830 }
2831
Rajeev Kumardca5f812016-02-04 17:28:06 -08002832 hdd_debugfs_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002833 /*
2834 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2835 * the driver is almost closed and cannot handle either control
2836 * messages or data. However, unregister_netdevice() call above will
2837 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2838 * to close the active connections (basically excites control path) which
2839 * is not right. Setting this flag helps hdd_stop() to recognize that
2840 * the interface is closed and restricts any operations on that
2841 */
2842 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2843
2844 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2845 if (rtnl_held) {
2846 unregister_netdevice(pWlanDev);
2847 } else {
2848 unregister_netdev(pWlanDev);
2849 }
2850 /*
2851 * Note that the adapter is no longer valid at this point
2852 * since the memory has been reclaimed
2853 */
2854 }
2855}
2856
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302857QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002858 tSirMacAddr macAddr)
2859{
2860 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2861 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302862 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302864 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865 adapter = adapterNode->pAdapter;
2866 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302867 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002868 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302869 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 }
2871 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2872 adapterNode = pNext;
2873 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302874 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002875}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002876
Arun Khandavalli2358d522016-05-16 18:05:37 +05302877#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2878/**
2879 * hdd_set_fw_log_params() - Set log parameters to FW
2880 * @hdd_ctx: HDD Context
2881 * @adapter: HDD Adapter
2882 *
2883 * This function set the FW Debug log level based on the INI.
2884 *
2885 * Return: None
2886 */
2887static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2888 hdd_adapter_t *adapter)
2889{
2890 uint8_t count = 0, numentries = 0,
2891 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2892 uint32_t value = 0;
2893 int ret;
2894
Arun Khandavallifae92942016-08-01 13:31:08 +05302895 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
2896 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302897 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
2898 return;
2899 }
2900
Arun Khandavallifae92942016-08-01 13:31:08 +05302901 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05302902 hdd_ctx->fw_log_settings.dl_type =
2903 hdd_ctx->config->enableFwLogType;
2904 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302905 WMI_DBGLOG_TYPE,
2906 hdd_ctx->config->enableFwLogType,
2907 DBG_CMD);
2908 if (ret != 0)
2909 hdd_err("Failed to enable FW log type ret %d",
2910 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302911
2912 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05302913 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05302914 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302915 WMI_DBGLOG_LOG_LEVEL,
2916 hdd_ctx->config->enableFwLogLevel,
2917 DBG_CMD);
2918 if (ret != 0)
2919 hdd_err("Failed to enable FW log level ret %d",
2920 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302921
2922 hdd_string_to_u8_array(
2923 hdd_ctx->config->enableFwModuleLogLevel,
2924 moduleloglevel,
2925 &numentries,
2926 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2927
2928 while (count < numentries) {
2929 /*
2930 * FW module log level input string looks like
2931 * below:
2932 * gFwDebugModuleLoglevel=<FW Module ID>,
2933 * <Log Level>,...
2934 * For example:
2935 * gFwDebugModuleLoglevel=
2936 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
2937 * Above input string means :
2938 * For FW module ID 1 enable log level 0
2939 * For FW module ID 2 enable log level 1
2940 * For FW module ID 3 enable log level 2
2941 * For FW module ID 4 enable log level 3
2942 * For FW module ID 5 enable log level 4
2943 * For FW module ID 6 enable log level 5
2944 * For FW module ID 7 enable log level 6
2945 */
2946
Arun Khandavallifae92942016-08-01 13:31:08 +05302947 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05302948 * Module ID * 10 + Module Log level
2949 */
2950 value = ((moduleloglevel[count] * 10) +
2951 moduleloglevel[count + 1]);
2952 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302953 WMI_DBGLOG_MOD_LOG_LEVEL,
2954 value, DBG_CMD);
2955 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05302956 hdd_err("Failed to enable FW module log level %d ret %d",
2957 value, ret);
2958
2959 count += 2;
2960 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302961
Arun Khandavalli2358d522016-05-16 18:05:37 +05302962}
2963#else
2964static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2965 hdd_adapter_t *adapter)
2966{
2967}
2968
2969#endif
2970
2971/**
2972 * hdd_set_fw_params() - Set parameters to firmware
2973 * @adapter: HDD adapter
2974 *
2975 * This function Sets various parameters to fw once the
2976 * adapter is started.
2977 *
2978 * Return: 0 on success or errno on failure
2979 */
2980int hdd_set_fw_params(hdd_adapter_t *adapter)
2981{
2982 int ret;
2983 hdd_context_t *hdd_ctx;
2984
2985 ENTER_DEV(adapter->dev);
2986
2987 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2988 if (!hdd_ctx)
2989 return -EINVAL;
2990
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07002991 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) &&
Arun Khandavallifae92942016-08-01 13:31:08 +05302992 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302993#define HDD_DTIM_1CHAIN_RX_ID 0x5
2994#define HDD_SMPS_PARAM_VALUE_S 29
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07002995 /*
2996 * Disable DTIM 1 chain Rx when in 1x1,
2997 * we are passing two value
2998 * as param_id << 29 | param_value.
2999 * Below param_value = 0(disable)
3000 */
3001 ret = wma_cli_set_command(adapter->sessionId,
3002 WMI_STA_SMPS_PARAM_CMDID,
3003 HDD_DTIM_1CHAIN_RX_ID <<
3004 HDD_SMPS_PARAM_VALUE_S,
3005 VDEV_CMD);
3006 if (ret) {
3007 hdd_err("DTIM 1 chain set failed %d", ret);
3008 goto error;
3009 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303010
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003011 ret = wma_cli_set_command(adapter->sessionId,
3012 WMI_PDEV_PARAM_TX_CHAIN_MASK,
3013 hdd_ctx->config->txchainmask1x1,
3014 PDEV_CMD);
3015 if (ret) {
3016 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
3017 ret);
3018 goto error;
3019 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303020
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003021 ret = wma_cli_set_command(adapter->sessionId,
3022 WMI_PDEV_PARAM_RX_CHAIN_MASK,
3023 hdd_ctx->config->rxchainmask1x1,
3024 PDEV_CMD);
3025 if (ret) {
3026 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
3027 ret);
3028 goto error;
3029 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303030#undef HDD_DTIM_1CHAIN_RX_ID
3031#undef HDD_SMPS_PARAM_VALUE_S
Krishna Kumaar Natarajanaa938722016-08-21 23:18:53 -07003032 } else {
3033 hdd_info("FTM Mode or 2x2 mode - Do not set 1x1 params");
3034 }
3035
Arun Khandavallifae92942016-08-01 13:31:08 +05303036 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
3037 ret = wma_cli_set_command(adapter->sessionId,
3038 WMI_PDEV_PARAM_HYST_EN,
3039 hdd_ctx->config->enableMemDeepSleep,
3040 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05303041
Arun Khandavallifae92942016-08-01 13:31:08 +05303042 if (ret) {
3043 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
3044 ret);
3045 goto error;
3046 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05303047 }
3048
3049 hdd_set_fw_log_params(hdd_ctx, adapter);
3050
3051 EXIT();
3052 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05303053
Arun Khandavalli2358d522016-05-16 18:05:37 +05303054error:
3055 return -EINVAL;
3056}
3057
Ryan Hsu07495ea2016-01-21 15:25:39 -08003058/**
3059 * hdd_open_adapter() - open and setup the hdd adatper
3060 * @hdd_ctx: global hdd context
3061 * @session_type: type of the interface to be created
3062 * @iface_name: User-visible name of the interface
3063 * @macAddr: MAC address to assign to the interface
3064 * @name_assign_type: the name of assign type of the netdev
3065 * @rtnl_held: the rtnl lock hold flag
3066 *
3067 * This function open and setup the hdd adpater according to the device
3068 * type request, assign the name, the mac address assigned, and then prepared
3069 * the hdd related parameters, queue, lock and ready to start.
3070 *
3071 * Return: the pointer of hdd adapter, otherwise NULL.
3072 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003073hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3074 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003075 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003076 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003077{
3078 hdd_adapter_t *adapter = NULL;
3079 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303080 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003081 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003082
Arun Khandavallifae92942016-08-01 13:31:08 +05303083 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084
3085 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3086 /*
3087 * Max limit reached on the number of vdevs configured by the
3088 * host. Return error
3089 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303090 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3091 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 return NULL;
3093 }
3094
3095 if (macAddr == NULL) {
3096 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303097 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 return NULL;
3099 }
3100 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303101 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303102 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3103 " already exists",
3104 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 return NULL;
3106 }
3107
3108 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003109 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003110 /* Reset locally administered bit if the device mode is STA */
3111 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3112 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003113 case QDF_P2P_CLIENT_MODE:
3114 case QDF_P2P_DEVICE_MODE:
3115 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003116 case QDF_NDI_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003117 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3118 name_assign_type,
3119 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120
3121 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303122 hdd_err("failed to allocate adapter for session %d",
3123 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 return NULL;
3125 }
3126
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003127 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003129 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 else
3132 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3133
3134 adapter->device_mode = session_type;
3135
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303136 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003137 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303138 if (QDF_STATUS_SUCCESS != status)
3139 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303140 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003142 /*
3143 * Workqueue which gets scheduled in IPv4 notification
3144 * callback
3145 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3147 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148
3149#ifdef WLAN_NS_OFFLOAD
3150 /*
3151 * Workqueue which gets scheduled in IPv6
3152 * notification callback.
3153 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3155 hdd_ipv6_notifier_work_queue);
3156#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303158 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3160 goto err_lro_cleanup;
3161 }
3162
3163 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303164 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003165 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303166 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3167 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003171 case QDF_P2P_GO_MODE:
3172 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003173 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3174 name_assign_type,
3175 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303177 hdd_alert("failed to allocate adapter for session %d",
3178 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179 return NULL;
3180 }
3181
3182 adapter->wdev.iftype =
3183 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003184 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 NL80211_IFTYPE_P2P_GO;
3186 adapter->device_mode = session_type;
3187
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303189 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3191 goto err_free_netdev;
3192 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303193 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303195 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3196 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303199 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303200 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201 return NULL;
3202 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203
3204 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3205 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3206
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303207 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 /* Add it to the hdd's session list. */
3209 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303210 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303212 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213 } else {
3214 pHddAdapterNode->pAdapter = adapter;
3215 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3216 }
3217 }
3218
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303219 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 if (NULL != adapter) {
3221 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3222 adapter = NULL;
3223 }
3224 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303225 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003226 }
3227 return NULL;
3228 }
3229
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303230 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003231 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232
3233 /* Initialize the WoWL service */
3234 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003235 hdd_alert("hdd_init_wowl failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 goto err_lro_cleanup;
3237 }
3238
3239 /* Adapter successfully added. Increment the vdev count */
3240 hdd_ctx->current_intf_count++;
3241
Jeff Johnson5880d792016-08-15 13:32:30 -07003242 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 hdd_ctx->current_intf_count);
3244
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003245 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246 }
3247
Rajeev Kumardca5f812016-02-04 17:28:06 -08003248 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3249 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250
3251 return adapter;
3252
3253err_lro_cleanup:
3254 hdd_lro_disable(hdd_ctx, adapter);
3255err_free_netdev:
3256 free_netdev(adapter->dev);
3257 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
3258
3259 return NULL;
3260}
3261
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303262QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003263 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264{
3265 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267
3268 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303269 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003270 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271 status);
3272 return status;
3273 }
3274
3275 while (pCurrent->pAdapter != adapter) {
3276 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303277 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 break;
3279
3280 pCurrent = pNext;
3281 }
3282 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303283 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003284 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3286
3287 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303288 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 adapterNode = NULL;
3290
3291 /* Adapter removed. Decrement vdev count */
3292 if (hdd_ctx->current_intf_count != 0)
3293 hdd_ctx->current_intf_count--;
3294
3295 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303296 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003297 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303298 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299}
3300
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003301/**
3302 * hdd_close_all_adapters - Close all open adapters
3303 * @hdd_ctx: Hdd context
3304 * rtnl_held: True if RTNL lock held
3305 *
3306 * Close all open adapters.
3307 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303308 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003309 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303310QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311{
3312 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303313 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314
3315 ENTER();
3316
3317 do {
3318 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303319 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003320 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003321 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303322 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003323 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303324 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003325
3326 EXIT();
3327
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303328 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003329}
3330
3331void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3332{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303333 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003334 tSirUpdateIE updateIE;
3335 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003336 case QDF_STA_MODE:
3337 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003338 {
3339 hdd_station_ctx_t *pHddStaCtx =
3340 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003341 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342 break;
3343 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003344 case QDF_SAP_MODE:
3345 case QDF_P2P_GO_MODE:
3346 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003348 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349 break;
3350 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003351 case QDF_FTM_MODE:
3352 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353 default:
3354 /*
3355 * wlan_hdd_reset_prob_rspies should not have been called
3356 * for these kind of devices
3357 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003358 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003359 pHostapdAdapter->device_mode);
3360 return;
3361 }
3362
Anurag Chouhanc5548422016-02-24 18:33:27 +05303363 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003364 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3365 updateIE.ieBufferlength = 0;
3366 updateIE.pAdditionIEBuffer = NULL;
3367 updateIE.append = true;
3368 updateIE.notify = false;
3369 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3370 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003372 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373 }
3374}
3375
Peng Xu66162de2016-02-11 17:01:20 -08003376/**
3377 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3378 * @hdd_ctx: HDD context which is already NULL validated
3379 * @adapter: HDD adapter which is already NULL validated
3380 *
3381 * Close the SME session and wait for its completion, if needed.
3382 *
3383 * Return: None
3384 */
3385static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3386 hdd_adapter_t *adapter)
3387{
3388 unsigned long rc;
3389
3390 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3391 hdd_err("session is not opened:%d", adapter->sessionId);
3392 return;
3393 }
3394
3395 INIT_COMPLETION(adapter->session_close_comp_var);
3396 if (QDF_STATUS_SUCCESS ==
3397 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3398 hdd_sme_close_session_callback,
3399 adapter)) {
Arun Khandavalli9ad88f02016-09-01 19:03:37 +05303400 adapter->sessionId = HDD_SESSION_ID_INVALID;
Peng Xu66162de2016-02-11 17:01:20 -08003401 /*
3402 * Block on a completion variable. Can't wait
3403 * forever though.
3404 */
3405 rc = wait_for_completion_timeout(
3406 &adapter->session_close_comp_var,
3407 msecs_to_jiffies
3408 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3409 if (!rc)
3410 hdd_err("failure waiting for session_close_comp_var");
3411 }
3412}
3413
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303414QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 const bool bCloseSession)
3416{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303417 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3419 union iwreq_data wrqu;
3420 tSirUpdateIE updateIE;
3421 unsigned long rc;
3422
3423 ENTER();
3424
Jeff Johnson5880d792016-08-15 13:32:30 -07003425 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003426 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3427 WLAN_CONTROL_PATH);
3428 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003429 case QDF_STA_MODE:
3430 case QDF_P2P_CLIENT_MODE:
3431 case QDF_IBSS_MODE:
3432 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003433 case QDF_NDI_MODE:
3434 if ((QDF_NDI_MODE == adapter->device_mode) ||
3435 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3437 hdd_is_connecting(
3438 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003439 INIT_COMPLETION(adapter->disconnect_comp_var);
3440 /*
3441 * For NDI do not use pWextState from sta_ctx, if needed
3442 * extract from ndi_ctx.
3443 */
3444 if (QDF_NDI_MODE == adapter->device_mode)
3445 qdf_ret_status = sme_roam_disconnect(
3446 hdd_ctx->hHal,
3447 adapter->sessionId,
3448 eCSR_DISCONNECT_REASON_NDI_DELETE);
3449 else if (pWextState->roamProfile.BSSType ==
3450 eCSR_BSS_TYPE_START_IBSS)
3451 qdf_ret_status = sme_roam_disconnect(
3452 hdd_ctx->hHal,
3453 adapter->sessionId,
3454 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003456 qdf_ret_status = sme_roam_disconnect(
3457 hdd_ctx->hHal,
3458 adapter->sessionId,
3459 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003460 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303461 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462 rc = wait_for_completion_timeout(
3463 &adapter->disconnect_comp_var,
3464 msecs_to_jiffies
3465 (WLAN_WAIT_TIME_DISCONNECT));
3466 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003467 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468 }
3469 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003470 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471 }
3472 memset(&wrqu, '\0', sizeof(wrqu));
3473 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3474 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3475 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3476 NULL);
3477 } else {
Mahesh A Saptasagarebb47fa2016-07-21 18:11:38 +05303478 wlan_hdd_scan_abort(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003479 }
Himanshu Agarwal3d95b902016-08-24 16:27:03 +05303480 hdd_lro_disable(hdd_ctx, adapter);
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303481 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482
3483#ifdef WLAN_OPEN_SOURCE
3484 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3485#endif
3486
3487 hdd_deregister_tx_flow_control(adapter);
3488
3489#ifdef WLAN_NS_OFFLOAD
3490#ifdef WLAN_OPEN_SOURCE
3491 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3492#endif
3493#endif
3494
3495 /*
3496 * It is possible that the caller of this function does not
3497 * wish to close the session
3498 */
Peng Xu66162de2016-02-11 17:01:20 -08003499 if (true == bCloseSession)
3500 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003501 break;
3502
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003503 case QDF_SAP_MODE:
3504 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003506 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 /*
3508 * Before stopping the sap adapter, lets make sure there
3509 * is no sap restart work pending.
3510 */
3511 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003512 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003513 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514 }
3515 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003516 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3518
3519 hdd_deregister_tx_flow_control(adapter);
3520
3521 mutex_lock(&hdd_ctx->sap_lock);
3522 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303523 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303524 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525
3526 /* Stop Bss. */
3527#ifdef WLAN_FEATURE_MBSSID
3528 status = wlansap_stop_bss(
3529 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3530#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003531 status = wlansap_stop_bss(
3532 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533#endif
3534
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303535 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003536 hdd_hostapd_state_t *hostapd_state =
3537 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303538 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303539 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303540 qdf_status =
3541 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303542 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543 BSS_WAIT_TIMEOUT);
3544
Anurag Chouhance0dc992016-02-16 18:18:03 +05303545 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003546 hdd_err("failure waiting for wlansap_stop_bss %d",
3547 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548 }
3549 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003550 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 }
3552 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003553 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554 adapter->device_mode,
3555 adapter->sessionId);
3556
Anurag Chouhanc5548422016-02-24 18:33:27 +05303557 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003558 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559 updateIE.smeSessionId = adapter->sessionId;
3560 updateIE.ieBufferlength = 0;
3561 updateIE.pAdditionIEBuffer = NULL;
3562 updateIE.append = false;
3563 updateIE.notify = false;
3564 /* Probe bcn reset */
3565 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3566 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303567 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003568 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003569 }
3570 /* Assoc resp reset */
3571 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3572 &updateIE,
3573 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303574 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003575 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 }
3577 /* Reset WNI_CFG_PROBE_RSP Flags */
3578 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303579 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580 adapter->sessionCtx.ap.beacon = NULL;
3581 }
3582 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003583 if (true == bCloseSession)
3584 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003586 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3588 conn_info.staId[0]);
3589 break;
3590 default:
3591 break;
3592 }
3593
3594 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303595 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003596}
3597
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303598QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003599{
3600 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303601 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602 hdd_adapter_t *adapter;
3603
3604 ENTER();
3605
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303606 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3607
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3609
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303610 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 adapter = adapterNode->pAdapter;
3612 hdd_stop_adapter(hdd_ctx, adapter, true);
3613 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3614 adapterNode = pNext;
3615 }
3616
3617 EXIT();
3618
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303619 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620}
3621
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303622QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003623{
3624 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303625 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 hdd_adapter_t *adapter;
3627
3628 ENTER();
3629
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303630 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3633
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303634 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003636 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637 wlan_hdd_netif_queue_control(adapter,
3638 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3639 WLAN_CONTROL_PATH);
3640
3641 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3642
3643 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003644 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003645 adapter->sessionId);
3646 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3647 hdd_wmm_adapter_close(adapter);
3648 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3649 }
3650
3651 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3652 adapterNode = pNext;
3653 }
3654
3655 EXIT();
3656
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303657 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003658}
3659
Arun Khandavallifae92942016-08-01 13:31:08 +05303660/**
3661 * hdd_is_interface_up()- Checkfor interface up before ssr
3662 * @hdd_ctx: HDD context
3663 *
3664 * check if there are any wlan interfaces before SSR accordingly start
3665 * the interface.
3666 *
3667 * Return: 0 if interface was opened else false
3668 */
3669static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3670{
3671 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3672 return true;
3673 else
3674 return false;
3675}
3676
Anurag Chouhanc4092922016-09-08 15:56:11 +05303677#if defined CFG80211_CONNECT_BSS
3678#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
3679 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
3680struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3681 struct ieee80211_channel *channel,
3682 const u8 *bssid, const u8 *ssid,
3683 size_t ssid_len)
3684{
3685 return cfg80211_get_bss(wiphy, channel, bssid,
3686 ssid, ssid_len,
3687 WLAN_CAPABILITY_ESS,
3688 WLAN_CAPABILITY_ESS);
3689}
3690#else
3691struct cfg80211_bss *hdd_cfg80211_get_bss(struct wiphy *wiphy,
3692 struct ieee80211_channel *channel,
3693 const u8 *bssid, const u8 *ssid,
3694 size_t ssid_len)
3695{
3696 return cfg80211_get_bss(wiphy, channel, bssid,
3697 ssid, ssid_len,
3698 IEEE80211_BSS_TYPE_ESS,
3699 IEEE80211_PRIVACY_ANY);
3700}
3701#endif
3702#endif
3703
Abhishek Singha84d3952016-09-13 13:45:05 +05303704#if defined CFG80211_CONNECT_BSS
3705/**
3706 * hdd_connect_bss() - API to send connection status to supplicant
3707 * @dev: network device
3708 * @bssid: bssid to which we want to associate
3709 * @req_ie: Request Information Element
3710 * @req_ie_len: len of the req IE
3711 * @resp_ie: Response IE
3712 * @resp_ie_len: len of ht response IE
3713 * @status: status
3714 * @gfp: Kernel Flag
3715 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
3716 *
3717 * The API is a wrapper to send connection status to supplicant
3718 *
3719 * Return: Void
3720 */
3721#if defined CFG80211_CONNECT_TIMEOUT
3722static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3723 struct cfg80211_bss *bss, const u8 *req_ie,
3724 size_t req_ie_len, const u8 *resp_ie,
3725 size_t resp_ie_len, int status, gfp_t gfp,
3726 bool connect_timeout)
3727{
3728 if (connect_timeout)
3729 cfg80211_connect_timeout(dev, bssid, NULL, 0, GFP_KERNEL);
3730 else
3731 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3732 resp_ie, resp_ie_len, status, gfp);
3733}
3734#else
3735static void hdd_connect_bss(struct net_device *dev, const u8 *bssid,
3736 struct cfg80211_bss *bss, const u8 *req_ie,
3737 size_t req_ie_len, const u8 *resp_ie,
3738 size_t resp_ie_len, int status, gfp_t gfp,
3739 bool connect_timeout)
3740{
3741 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
3742 resp_ie, resp_ie_len, status, gfp);
3743}
3744#endif
Anurag Chouhanc4092922016-09-08 15:56:11 +05303745
3746/**
3747 * hdd_connect_result() - API to send connection status to supplicant
3748 * @dev: network device
3749 * @bssid: bssid to which we want to associate
3750 * @roam_info: information about connected bss
3751 * @req_ie: Request Information Element
3752 * @req_ie_len: len of the req IE
3753 * @resp_ie: Response IE
3754 * @resp_ie_len: len of ht response IE
3755 * @status: status
3756 * @gfp: Kernel Flag
Abhishek Singha84d3952016-09-13 13:45:05 +05303757 * @connect_timeout: If timed out waiting for Auth/Assoc/Probe resp
Anurag Chouhanc4092922016-09-08 15:56:11 +05303758 *
3759 * The API is a wrapper to send connection status to supplicant
3760 * and allow runtime suspend
3761 *
3762 * Return: Void
3763 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303764void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3765 tCsrRoamInfo *roam_info, const u8 *req_ie,
3766 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303767 size_t resp_ie_len, u16 status, gfp_t gfp,
3768 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303769{
3770 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
3771 struct cfg80211_bss *bss = NULL;
3772
3773 if (WLAN_STATUS_SUCCESS == status) {
3774 struct ieee80211_channel *chan;
3775 int freq;
3776 int chan_no = roam_info->pBssDesc->channelId;
3777
3778 if (chan_no <= 14)
3779 freq = ieee80211_channel_to_frequency(chan_no,
3780 IEEE80211_BAND_2GHZ);
3781 else
3782 freq = ieee80211_channel_to_frequency(chan_no,
3783 IEEE80211_BAND_5GHZ);
3784
3785 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
3786 bss = hdd_cfg80211_get_bss(padapter->wdev.wiphy, chan, bssid,
3787 roam_info->u.pConnectedProfile->SSID.ssId,
3788 roam_info->u.pConnectedProfile->SSID.length);
3789 }
Abhishek Singha84d3952016-09-13 13:45:05 +05303790 hdd_connect_bss(dev, bssid, bss, req_ie,
3791 req_ie_len, resp_ie, resp_ie_len,
3792 status, gfp, connect_timeout);
Anurag Chouhanc4092922016-09-08 15:56:11 +05303793}
3794#else
3795void hdd_connect_result(struct net_device *dev, const u8 *bssid,
3796 tCsrRoamInfo *roam_info, const u8 *req_ie,
3797 size_t req_ie_len, const u8 *resp_ie,
Abhishek Singha84d3952016-09-13 13:45:05 +05303798 size_t resp_ie_len, u16 status, gfp_t gfp,
3799 bool connect_timeout)
Anurag Chouhanc4092922016-09-08 15:56:11 +05303800{
3801 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
3802 resp_ie, resp_ie_len, status, gfp);
3803}
3804#endif
3805
3806
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303807QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808{
3809 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303810 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 hdd_adapter_t *adapter;
3812#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303813 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814#endif
3815 eConnectionState connState;
3816
3817 ENTER();
3818
3819 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303820 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821 adapter = adapterNode->pAdapter;
3822
Arun Khandavallifae92942016-08-01 13:31:08 +05303823 if (!hdd_is_interface_up(adapter))
3824 continue;
3825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 hdd_wmm_init(adapter);
3827
3828 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003829 case QDF_STA_MODE:
3830 case QDF_P2P_CLIENT_MODE:
3831 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003832
3833 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3834 ->conn_info.connState;
3835
3836 hdd_init_station_mode(adapter);
3837 /* Open the gates for HDD to receive Wext commands */
3838 adapter->isLinkUpSvcNeeded = false;
3839 adapter->scan_info.mScanPending = false;
3840
3841 /* Indicate disconnect event to supplicant if associated previously */
3842 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003843 eConnectionState_IbssConnected == connState ||
3844 eConnectionState_NotConnected == connState ||
3845 eConnectionState_IbssDisconnected == connState ||
3846 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 union iwreq_data wrqu;
3848 memset(&wrqu, '\0', sizeof(wrqu));
3849 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3850 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3851 wireless_send_event(adapter->dev, SIOCGIWAP,
3852 &wrqu, NULL);
3853 adapter->sessionCtx.station.
3854 hdd_ReassocScenario = false;
3855
3856 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05303857 wlan_hdd_cfg80211_indicate_disconnect(
3858 adapter->dev, false,
3859 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860 } else if (eConnectionState_Connecting == connState) {
3861 /*
3862 * Indicate connect failure to supplicant if we were in the
3863 * process of connecting
3864 */
Anurag Chouhanc4092922016-09-08 15:56:11 +05303865 hdd_connect_result(adapter->dev, NULL, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 NULL, 0, NULL, 0,
3867 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
Abhishek Singha84d3952016-09-13 13:45:05 +05303868 GFP_KERNEL, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869 }
3870
3871 hdd_register_tx_flow_control(adapter,
3872 hdd_tx_resume_timer_expired_handler,
3873 hdd_tx_resume_cb);
3874
3875 break;
3876
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003877 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 /* softAP can handle SSR */
3879 break;
3880
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003881 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07003883 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3885#else
Jeff Johnson5880d792016-08-15 13:32:30 -07003886 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003887 /* event supplicant to restart */
3888 cfg80211_del_sta(adapter->dev,
3889 (const u8 *)&bcastMac.bytes[0],
3890 GFP_KERNEL);
3891#endif
3892 break;
3893
3894 default:
3895 break;
3896 }
3897
3898 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3899 adapterNode = pNext;
3900 }
3901
3902 EXIT();
3903
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303904 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905}
3906
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303907QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908 hdd_adapter_list_node_t **padapterNode)
3909{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303910 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003911 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303912 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3913 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003914 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 return status;
3916}
3917
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303918QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003919 hdd_adapter_list_node_t *adapterNode,
3920 hdd_adapter_list_node_t **pNextAdapterNode)
3921{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303922 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003923 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303924 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3925 (qdf_list_node_t *) adapterNode,
3926 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003928 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 return status;
3930}
3931
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303932QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933 hdd_adapter_list_node_t *adapterNode)
3934{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303935 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003936 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303937 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003939 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003940 return status;
3941}
3942
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303943QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944 hdd_adapter_list_node_t **padapterNode)
3945{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303946 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003947 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303948 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3949 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003950 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951 return status;
3952}
3953
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303954QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955 hdd_adapter_list_node_t *adapterNode)
3956{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303957 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003958 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303959 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3960 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003961 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962 return status;
3963}
3964
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303965QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966 hdd_adapter_list_node_t *adapterNode)
3967{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303968 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003969 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303970 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3971 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003972 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 return status;
3974}
3975
3976hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3977 tSirMacAddr macAddr)
3978{
3979 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3980 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303981 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982
3983 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3984
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303985 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003986 adapter = adapterNode->pAdapter;
3987
3988 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303989 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990 macAddr, sizeof(tSirMacAddr))) {
3991 return adapter;
3992 }
3993 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3994 adapterNode = pNext;
3995 }
3996
3997 return NULL;
3998
3999}
4000
4001hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
4002 uint32_t vdev_id)
4003{
4004 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4005 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304006 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304008 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304010 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011 adapter = adapterNode->pAdapter;
4012
4013 if (adapter->sessionId == vdev_id)
4014 return adapter;
4015
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304016 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4018 adapterNode = pNext;
4019 }
4020
Jeff Johnson5880d792016-08-15 13:32:30 -07004021 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022
4023 return NULL;
4024}
4025
Abhishek Singh7996eb72015-12-30 17:24:02 +05304026/**
4027 * hdd_get_adapter_by_sme_session_id() - Return adapter with
4028 * the sessionid
4029 * @hdd_ctx: hdd context.
4030 * @sme_session_id: sme session is for the adapter to get.
4031 *
4032 * This function is used to get the adapter with provided session id
4033 *
4034 * Return: adapter pointer if found
4035 *
4036 */
4037hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
4038 uint32_t sme_session_id)
4039{
4040 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
4041 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304042 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05304043
4044
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304045 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05304046
4047 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304048 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05304049 adapter = adapter_node->pAdapter;
4050
4051 if (adapter &&
4052 adapter->sessionId == sme_session_id)
4053 return adapter;
4054
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304055 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05304056 hdd_get_next_adapter(hdd_ctx,
4057 adapter_node, &next);
4058 adapter_node = next;
4059 }
4060 return NULL;
4061}
4062
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004063/**
4064 * hdd_get_adapter() - to get adapter matching the mode
4065 * @hdd_ctx: hdd context
4066 * @mode: adapter mode
4067 *
4068 * This routine will return the pointer to adapter matching
4069 * with the passed mode.
4070 *
4071 * Return: pointer to adapter or null
4072 */
4073hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
4074 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075{
4076 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
4077 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304078 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079
4080 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4081
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304082 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 adapter = adapterNode->pAdapter;
4084
4085 if (adapter && (mode == adapter->device_mode))
4086 return adapter;
4087
4088 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4089 adapterNode = pNext;
4090 }
4091
4092 return NULL;
4093
4094}
4095
4096/**
4097 * hdd_get_operating_channel() - return operating channel of the device mode
4098 * @hdd_ctx: Pointer to the HDD context.
4099 * @mode: Device mode for which operating channel is required.
4100 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004101 * QDF_STA_MODE,
4102 * QDF_P2P_CLIENT_MODE,
4103 * QDF_SAP_MODE,
4104 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105 *
4106 * This API returns the operating channel of the requested device mode
4107 *
4108 * Return: channel number. "0" id the requested device is not found OR it is
4109 * not connected.
4110 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004111uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
4112 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113{
4114 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304115 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 hdd_adapter_t *adapter;
4117 uint8_t operatingChannel = 0;
4118
4119 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304121 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004122 adapter = adapterNode->pAdapter;
4123
4124 if (mode == adapter->device_mode) {
4125 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004126 case QDF_STA_MODE:
4127 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128 if (hdd_conn_is_connected
4129 (WLAN_HDD_GET_STATION_CTX_PTR
4130 (adapter))) {
4131 operatingChannel =
4132 (WLAN_HDD_GET_STATION_CTX_PTR
4133 (adapter))->conn_info.
4134 operationChannel;
4135 }
4136 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004137 case QDF_SAP_MODE:
4138 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 /* softap connection info */
4140 if (test_bit
4141 (SOFTAP_BSS_STARTED,
4142 &adapter->event_flags))
4143 operatingChannel =
4144 (WLAN_HDD_GET_AP_CTX_PTR
4145 (adapter))->operatingChannel;
4146 break;
4147 default:
4148 break;
4149 }
4150
4151 break; /* Found the device of interest. break the loop */
4152 }
4153
4154 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4155 adapterNode = pNext;
4156 }
4157 return operatingChannel;
4158}
4159
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304160static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161 hdd_ctx)
4162{
4163 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304164 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004165 hdd_adapter_t *adapter;
4166
4167 ENTER();
4168
4169 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4170
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304171 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004172 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004173 if ((adapter->device_mode == QDF_STA_MODE) ||
4174 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4175 (adapter->device_mode == QDF_IBSS_MODE) ||
4176 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4177 (adapter->device_mode == QDF_SAP_MODE) ||
4178 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004179 wlan_hdd_cfg80211_deregister_frames(adapter);
4180 hdd_unregister_wext(adapter->dev);
4181 }
4182 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4183 adapterNode = pNext;
4184 }
4185
4186 EXIT();
4187
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304188 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189}
4190
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304191QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192{
4193 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304194 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195 hdd_adapter_t *adapter;
4196
4197 ENTER();
4198
4199 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
4200
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304201 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004203 if ((adapter->device_mode == QDF_STA_MODE) ||
4204 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4205 (adapter->device_mode == QDF_IBSS_MODE) ||
4206 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4207 (adapter->device_mode == QDF_SAP_MODE) ||
4208 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4210 eCSR_SCAN_ABORT_DEFAULT);
4211 }
4212 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4213 adapterNode = pNext;
4214 }
4215
4216 EXIT();
4217
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304218 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219}
4220
4221#ifdef WLAN_NS_OFFLOAD
4222/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004223 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 * @hdd_ctx: Pointer to hdd context
4225 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004226 * Unregister for IPv6 address change notifications.
4227 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004228 * Return: None
4229 */
4230static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4231{
4232 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4233
4234 return;
4235}
4236
4237/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004238 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004239 * @hdd_ctx: Pointer to hdd context
4240 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004241 * Register for IPv6 address change notifications.
4242 *
4243 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004245static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246{
4247 int ret;
4248
4249 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4250 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004251 if (ret) {
4252 hdd_err("Failed to register IPv6 notifier: %d", ret);
4253 goto out;
4254 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004256 hdd_info("Registered IPv6 notifier");
4257out:
4258 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259}
4260#else
4261/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004262 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 * @hdd_ctx: Pointer to hdd context
4264 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004265 * Unregister for IPv6 address change notifications.
4266 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 * Return: None
4268 */
4269static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4270{
4271}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004272
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004273/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004274 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275 * @hdd_ctx: Pointer to hdd context
4276 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004277 * Register for IPv6 address change notifications.
4278 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 * Return: None
4280 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004281static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004282{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004283 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284}
4285#endif
4286
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304287#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4288/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004289 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304290 * @hdd_ctx: HDD context
4291 *
4292 * Activates the logging service
4293 *
4294 * Return: Zero in case of success, negative value otherwise
4295 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004296static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304297{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004298 int ret;
4299 struct hdd_config *config = hdd_ctx->config;
4300
4301 if (!config->wlanLoggingEnable)
4302 return 0;
4303
4304 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4305 config->wlanLoggingNumBuf);
4306 if (ret)
4307 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4308 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304309}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004310
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304311/**
4312 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4313 * @hdd_ctx: HDD context
4314 *
4315 * Deactivates the logging service
4316 *
4317 * Return: 0 on deactivating the logging service
4318 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004319static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304320{
4321 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4322 return wlan_logging_sock_deactivate_svc();
4323
4324 return 0;
4325}
4326#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004327static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304328{
4329 return 0;
4330}
4331
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004332static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304333{
4334 return 0;
4335}
4336#endif
4337
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004339 * hdd_register_notifiers - Register netdev notifiers.
4340 * @hdd_ctx: HDD context
4341 *
4342 * Register netdev notifiers like IPv4 and IPv6.
4343 *
4344 * Return: 0 on success and errno on failure
4345 */
4346static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4347{
4348 int ret;
4349
4350 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4351 if (ret) {
4352 hdd_err("register_netdevice_notifier failed: %d", ret);
4353 goto out;
4354 }
4355
4356 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4357 if (ret)
4358 goto unregister_notifier;
4359
4360 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4361 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4362 if (ret) {
4363 hdd_err("Failed to register IPv4 notifier: %d", ret);
4364 goto unregister_ip6_notifier;
4365 }
4366
4367 return 0;
4368
4369unregister_ip6_notifier:
4370 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4371unregister_notifier:
4372 unregister_netdevice_notifier(&hdd_netdev_notifier);
4373out:
4374 return ret;
4375
4376}
4377
4378/**
4379 * hdd_unregister_notifiers - Unregister netdev notifiers.
4380 * @hdd_ctx: HDD context
4381 *
4382 * Unregister netdev notifiers like IPv4 and IPv6.
4383 *
4384 * Return: None.
4385 */
4386static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4387{
4388 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4389
4390 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4391
4392 unregister_netdevice_notifier(&hdd_netdev_notifier);
4393}
4394
4395/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004396 * hdd_exit_netlink_services - Exit netlink services
4397 * @hdd_ctx: HDD context
4398 *
4399 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4400 * nl service.
4401 *
4402 * Return: None.
4403 */
4404static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4405{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004406 hdd_close_cesium_nl_sock();
4407
4408 ptt_sock_deactivate_svc();
4409
4410 nl_srv_exit();
4411}
4412
4413/**
4414 * hdd_init_netlink_services- Init netlink services
4415 * @hdd_ctx: HDD context
4416 *
4417 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4418 * nl service.
4419 *
4420 * Return: 0 on success and errno on failure.
4421 */
4422static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4423{
4424 int ret;
4425
Ryan Hsuceddceb2016-04-28 10:20:14 -07004426 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004427 if (ret) {
4428 hdd_alert("nl_srv_init failed: %d", ret);
4429 goto out;
4430 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004431 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004432
4433 ret = oem_activate_service(hdd_ctx);
4434 if (ret) {
4435 hdd_alert("oem_activate_service failed: %d", ret);
4436 goto err_nl_srv;
4437 }
4438
4439 ret = ptt_sock_activate_svc();
4440 if (ret) {
4441 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4442 goto err_nl_srv;
4443 }
4444
4445 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004446 if (ret)
4447 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004448
4449 ret = cnss_diag_activate_service();
4450 if (ret) {
4451 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4452 goto err_close_cesium;
4453 }
4454
4455 return 0;
4456
4457err_close_cesium:
4458 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004459 ptt_sock_deactivate_svc();
4460err_nl_srv:
4461 nl_srv_exit();
4462out:
4463 return ret;
4464}
4465
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004466#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4467/**
4468 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4469 * @hdd_ctx: HDD context.
4470 *
4471 * Destroy RX wakelock.
4472 *
4473 * Return: None.
4474 */
4475static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4476{
4477 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4478}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004479
4480/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004481 * hdd_rx_wake_lock_create() - Create RX wakelock
4482 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004483 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004484 * Create RX wakelock.
4485 *
4486 * Return: None.
4487 */
4488static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4489{
4490 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4491}
4492#else
4493static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { }
4494static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { }
4495#endif
4496
4497/**
4498 * hdd_roc_context_init() - Init ROC context
4499 * @hdd_ctx: HDD context.
4500 *
4501 * Initialize ROC context.
4502 *
4503 * Return: 0 on success and errno on failure.
4504 */
4505static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4506{
4507 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4508 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4509
4510 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4511
4512 return 0;
4513}
4514
4515/**
4516 * hdd_roc_context_destroy() - Destroy ROC context
4517 * @hdd_ctx: HDD context.
4518 *
4519 * Destroy roc list and flush the pending roc work.
4520 *
4521 * Return: None.
4522 */
4523static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4524{
4525 flush_delayed_work(&hdd_ctx->roc_req_work);
4526 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4527}
4528
4529/**
4530 * hdd_context_destroy() - Destroy HDD context
4531 * @hdd_ctx: HDD context to be destroyed.
4532 *
4533 * Free config and HDD context as well as destroy all the resources.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004534 *
4535 * Return: None
4536 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004537static void hdd_context_destroy(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004538{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304539 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004540 hdd_logging_sock_deactivate_svc(hdd_ctx);
4541
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004542 hdd_roc_context_destroy(hdd_ctx);
4543
4544 hdd_sap_context_destroy(hdd_ctx);
4545
4546 hdd_rx_wake_lock_destroy(hdd_ctx);
4547
4548 hdd_tdls_context_destroy(hdd_ctx);
4549
4550 hdd_scan_context_destroy(hdd_ctx);
4551
4552 qdf_list_destroy(&hdd_ctx->hddAdapters);
4553
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304554 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004555 hdd_ctx->config = NULL;
4556
4557 wiphy_free(hdd_ctx->wiphy);
4558}
4559
4560/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004561 * hdd_wlan_exit() - HDD WLAN exit function
4562 * @hdd_ctx: Pointer to the HDD Context
4563 *
4564 * This is the driver exit point (invoked during rmmod)
4565 *
4566 * Return: None
4567 */
4568void hdd_wlan_exit(hdd_context_t *hdd_ctx)
4569{
4570 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304571 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004572 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304573 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004574
4575 ENTER();
4576
Arun Khandavallifae92942016-08-01 13:31:08 +05304577 if (QDF_TIMER_STATE_RUNNING ==
4578 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4579 hdd_info("Stpp interface change timer");
4580 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 }
4582
Arun Khandavallifae92942016-08-01 13:31:08 +05304583 if (!QDF_IS_STATUS_SUCCESS
4584 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4585 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004586
Arun Khandavallifae92942016-08-01 13:31:08 +05304587
4588 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589
4590#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05304591 if (QDF_TIMER_STATE_RUNNING ==
4592 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
4593 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594 }
4595
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304596 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304597 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004598 hdd_err("Cannot deallocate Bus bandwidth timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599 }
4600#endif
4601
4602#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304603 if (QDF_TIMER_STATE_RUNNING ==
4604 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4605 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004606 }
4607
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304608 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304609 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004610 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004611 }
4612#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004613
Arun Khandavallifae92942016-08-01 13:31:08 +05304614 mutex_lock(&hdd_ctx->iface_change_lock);
4615 driver_status = hdd_ctx->driver_status;
4616 mutex_unlock(&hdd_ctx->iface_change_lock);
4617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004618 /*
4619 * Powersave Offload Case
4620 * Disable Idle Power Save Mode
4621 */
4622 hdd_set_idle_ps_config(hdd_ctx, false);
4623
Arun Khandavallifae92942016-08-01 13:31:08 +05304624 if (driver_status != DRIVER_MODULES_CLOSED) {
4625 hdd_unregister_wext_all_adapters(hdd_ctx);
4626 /*
4627 * Cancel any outstanding scan requests. We are about to close
4628 * all of our adapters, but an adapter structure is what SME
4629 * passes back to our callback function. Hence if there
4630 * are any outstanding scan requests then there is a
4631 * race condition between when the adapter is closed and
4632 * when the callback is invoked. We try to resolve that
4633 * race condition here by canceling any outstanding scans
4634 * before we close the adapters.
4635 * Note that the scans may be cancelled in an asynchronous
4636 * manner, so ideally there needs to be some kind of
4637 * synchronization. Rather than introduce a new
4638 * synchronization here, we will utilize the fact that we are
4639 * about to Request Full Power, and since that is synchronized,
4640 * the expectation is that by the time Request Full Power has
4641 * completed, all scans will be cancelled
4642 */
4643 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4644 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004645 }
4646
Arun Khandavallifae92942016-08-01 13:31:08 +05304647 hdd_wlan_stop_modules(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004648 /*
4649 * Close the scheduler before calling cds_close to make sure no thread
4650 * is scheduled after the each module close is called i.e after all the
4651 * data structures are freed.
4652 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304653 qdf_status = cds_sched_close(p_cds_context);
4654 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004655 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304656 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004657 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304659 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4660 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4661 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4662
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 /*
4664 * Close CDS
4665 * This frees pMac(HAL) context. There should not be any call
4666 * that requires pMac access after this.
4667 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668
4669 hdd_wlan_green_ap_deinit(hdd_ctx);
4670
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004671 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672
4673 hdd_ipa_cleanup(hdd_ctx);
4674
4675 /* Free up RoC request queue and flush workqueue */
4676 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677
Arun Khandavallifae92942016-08-01 13:31:08 +05304678
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304680 wlansap_global_deinit();
Nirav Shahed34b212016-04-25 10:59:16 +05304681 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304683 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004684
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004685 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
4686
Arun Khandavallifae92942016-08-01 13:31:08 +05304687 hdd_exit_netlink_services(hdd_ctx);
4688 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004689 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690}
4691
4692void __hdd_wlan_exit(void)
4693{
4694 hdd_context_t *hdd_ctx;
4695
4696 ENTER();
4697
Anurag Chouhan6d760662016-02-20 16:05:43 +05304698 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004700 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 EXIT();
4702 return;
4703 }
4704
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004705 /* Check IPA HW Pipe shutdown */
4706 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4707
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004708 memdump_deinit();
4709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 /* Do all the cleanup before deregistering the driver */
4711 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004712
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 EXIT();
4714}
4715
4716#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4717void hdd_skip_acs_scan_timer_handler(void *data)
4718{
4719 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4720
Jeff Johnson760350b2016-08-15 14:01:52 -07004721 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4723
4724 if (!hdd_ctx->hHal)
4725 return;
4726 sme_scan_flush_result(hdd_ctx->hHal);
4727}
4728#endif
4729
4730#ifdef QCA_HT_2040_COEX
4731/**
4732 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4733 * @adapter: pointer to adapter
4734 * @staId: station id
4735 * @macAddrSTA: station MAC address
4736 * @channel_type: channel type
4737 *
4738 * This function notifies FW with HT20/HT40 mode
4739 *
4740 * Return: 0 if successful, error number otherwise
4741 */
4742int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304743 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004744{
4745 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304746 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004747 hdd_context_t *hdd_ctx = NULL;
4748
4749 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4750
4751 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304752 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304754
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 if (!hdd_ctx->hHal)
4756 return -EINVAL;
4757
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304758 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004759 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304760 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004761 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 return -EINVAL;
4763 }
4764
4765 return 0;
4766}
4767#endif
4768
4769/**
4770 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4771 * @state: state
4772 *
4773 * This function notifies FW with modem power status
4774 *
4775 * Return: 0 if successful, error number otherwise
4776 */
4777int hdd_wlan_notify_modem_power_state(int state)
4778{
4779 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304780 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004781 hdd_context_t *hdd_ctx;
4782
Anurag Chouhan6d760662016-02-20 16:05:43 +05304783 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004784 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304785 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304787
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004788 if (!hdd_ctx->hHal)
4789 return -EINVAL;
4790
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304791 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4792 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004793 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794 state);
4795 return -EINVAL;
4796 }
4797 return 0;
4798}
4799
4800/**
4801 *
4802 * hdd_post_cds_enable_config() - HDD post cds start config helper
4803 * @adapter - Pointer to the HDD
4804 *
4805 * Return: None
4806 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304807QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304809 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004810
4811 /*
4812 * Send ready indication to the HDD. This will kick off the MAC
4813 * into a 'running' state and should kick off an initial scan.
4814 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304815 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4816 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004817 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
4818 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304819 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 }
4821
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304822 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823}
4824
4825/* wake lock APIs for HDD */
4826void hdd_prevent_suspend(uint32_t reason)
4827{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304828 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004829}
4830
4831void hdd_allow_suspend(uint32_t reason)
4832{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304833 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004834}
4835
4836void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
4837{
Anurag Chouhan01cfa4e2016-09-04 15:10:49 +05304838 cds_host_diag_log_work(&wlan_wake_lock, timeout, reason);
4839 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004840}
4841
4842/**
4843 * hdd_exchange_version_and_caps() - exchange version and capability with target
4844 * @hdd_ctx: Pointer to HDD context
4845 *
4846 * This is the HDD function to exchange version and capability information
4847 * between Host and Target
4848 *
4849 * This function gets reported version of FW.
4850 * It also finds the version of target headers used to compile the host;
4851 * It compares the above two and prints a warning if they are different;
4852 * It gets the SW and HW version string;
4853 * Finally, it exchanges capabilities between host and target i.e. host
4854 * and target exchange a msg indicating the features they support through a
4855 * bitmap
4856 *
4857 * Return: None
4858 */
4859void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4860{
4861
4862 tSirVersionType versionCompiled;
4863 tSirVersionType versionReported;
4864 tSirVersionString versionString;
4865 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304866 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867
4868 memset(&versionCompiled, 0, sizeof(versionCompiled));
4869 memset(&versionReported, 0, sizeof(versionReported));
4870
4871 /* retrieve and display WCNSS version information */
4872 do {
4873
4874 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4875 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304876 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004877 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878 break;
4879 }
4880
4881 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4882 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304883 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004884 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004885 break;
4886 }
4887
4888 if ((versionCompiled.major != versionReported.major) ||
4889 (versionCompiled.minor != versionReported.minor) ||
4890 (versionCompiled.version != versionReported.version) ||
4891 (versionCompiled.revision != versionReported.revision)) {
4892 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4893 "Host expected %u.%u.%u.%u\n",
4894 WLAN_MODULE_NAME,
4895 (int)versionReported.major,
4896 (int)versionReported.minor,
4897 (int)versionReported.version,
4898 (int)versionReported.revision,
4899 (int)versionCompiled.major,
4900 (int)versionCompiled.minor,
4901 (int)versionCompiled.version,
4902 (int)versionCompiled.revision);
4903 } else {
4904 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4905 WLAN_MODULE_NAME,
4906 (int)versionReported.major,
4907 (int)versionReported.minor,
4908 (int)versionReported.version,
4909 (int)versionReported.revision);
4910 }
4911
4912 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4913 versionString,
4914 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304915 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004916 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 break;
4918 }
4919
4920 pr_info("%s: WCNSS software version %s\n",
4921 WLAN_MODULE_NAME, versionString);
4922
4923 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4924 versionString,
4925 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304926 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07004927 hdd_alert("unable to retrieve WCNSS hardware version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 break;
4929 }
4930
4931 pr_info("%s: WCNSS hardware version %s\n",
4932 WLAN_MODULE_NAME, versionString);
4933
4934 /*
4935 * 1.Check if FW version is greater than 0.1.1.0. Only then
4936 * send host-FW capability exchange message
4937 * 2.Host-FW capability exchange message is only present on
4938 * target 1.1 so send the message only if it the target is 1.1
4939 * minor numbers for different target branches:
4940 * 0 -> (1.0)Mainline Build
4941 * 1 -> (1.1)Mainline Build
4942 * 2->(1.04) Stability Build
4943 */
4944 if (((versionReported.major > 0) || (versionReported.minor > 1)
4945 || ((versionReported.minor >= 1)
4946 && (versionReported.version >= 1)))
4947 && ((versionReported.major == 1)
4948 && (versionReported.minor >= 1)))
4949 fwFeatCapsMsgSupported = 1;
4950
4951 if (fwFeatCapsMsgSupported) {
4952 /*
4953 * Indicate if IBSS heartbeat monitoring needs to be
4954 * offloaded
4955 */
4956 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4957 sme_disable_feature_capablity
4958 (IBSS_HEARTBEAT_OFFLOAD);
4959 }
4960
4961 sme_feature_caps_exchange(hdd_ctx->hHal);
4962 }
4963
4964 } while (0);
4965
4966}
4967
4968/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304969QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970{
4971 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4972 hdd_ctx->reg.cc_src);
4973}
4974
4975/**
4976 * hdd_is_5g_supported() - check if hardware supports 5GHz
4977 * @hdd_ctx: Pointer to the hdd context
4978 *
4979 * HDD function to know if hardware supports 5GHz
4980 *
4981 * Return: true if hardware supports 5GHz
4982 */
4983bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4984{
4985 /*
4986 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4987 * then hardware support 5Ghz.
4988 */
4989 return true;
4990}
4991
Amar Singhale4f28ee2015-10-21 14:36:56 -07004992static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993{
4994 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07004995 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004996
4997 wiphy = hdd_ctx->wiphy;
4998
4999 /*
5000 * The channel information in
5001 * wiphy needs to be initialized before wiphy registration
5002 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005003 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
5004 if (ret_val) {
5005 hdd_alert("regulatory init failed");
5006 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 }
5008
5009#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5010 wiphy->wowlan = &wowlan_support_reg_init;
5011#else
5012 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
5013 WIPHY_WOWLAN_MAGIC_PKT |
5014 WIPHY_WOWLAN_DISCONNECT |
5015 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
5016 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
5017 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
5018 WIPHY_WOWLAN_4WAY_HANDSHAKE |
5019 WIPHY_WOWLAN_RFKILL_RELEASE;
5020
5021 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
5022 WOW_MAX_FILTERS_PER_LIST);
5023 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
5024 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
5025#endif
5026
5027 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07005028 ret_val = wlan_hdd_cfg80211_register(wiphy);
5029 if (0 > ret_val)
5030 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031
Amar Singhale4f28ee2015-10-21 14:36:56 -07005032 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033}
5034
Ravi Joshie2331e82015-07-01 18:18:54 -07005035/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07005036 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07005037 * @hdd_ctx - handle to hdd context
5038 * @tx_packets - transmit packet count
5039 * @rx_packets - receive packet count
5040 *
5041 * The function controls the bus bandwidth and dynamic control of
5042 * tcp delayed ack configuration
5043 *
5044 * Returns: None
5045 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005046#ifdef MSM_PLATFORM
Yuanyuan Liu13738502016-04-06 17:41:37 -07005047void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08005048 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005049{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08005051 uint64_t temp_rx = 0;
5052 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005053 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08005054 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
5055 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005056
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005058 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005060 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07005061 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07005062 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07005063 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07005064 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065
Mohit Khannae71e2262015-11-10 09:37:24 -08005066 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
5067 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005068
5069 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005070 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
5071 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07005073 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05305074 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05305075 if (hdd_ctx->hbw_requested) {
5076 pld_remove_pm_qos(hdd_ctx->parent_dev);
5077 hdd_ctx->hbw_requested = false;
5078 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05305079 if (cds_sched_handle_throughput_req(false))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005080 hdd_err("low bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305081 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05305082 if (!hdd_ctx->hbw_requested) {
5083 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
5084 hdd_ctx->hbw_requested = true;
5085 }
5086
Nirav Shah3bbfa512016-05-12 16:43:49 +05305087 if (cds_sched_handle_throughput_req(true))
Jeff Johnsonb7082ae2016-08-23 13:13:30 -07005088 hdd_err("high bandwidth set rx affinity fail");
Nirav Shah3bbfa512016-05-12 16:43:49 +05305089 }
Orhan K AKYILDIZ1481aff2016-05-16 12:40:13 -07005090 hdd_napi_apply_throughput_policy(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005091 }
Mohit Khannae71e2262015-11-10 09:37:24 -08005092
5093 /* fine-tuning parameters for RX Flows */
5094 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
5095
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005096 hdd_ctx->prev_rx = rx_packets;
5097 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08005098 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099 else
Mohit Khannae71e2262015-11-10 09:37:24 -08005100 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005101
Mohit Khannae71e2262015-11-10 09:37:24 -08005102 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
5103 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005104
5105 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07005106 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005107 next_rx_level, temp_rx);
5108 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07005109 /* Send throughput indication only if it is enabled.
5110 * Disabling tcp_del_ack will revert the tcp stack behavior
5111 * to default delayed ack. Note that this will disable the
5112 * dynamic delayed ack mechanism across the system
5113 */
5114 if (hdd_ctx->config->enable_tcp_delack)
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305115 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5116 WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117 &next_rx_level,
5118 sizeof(next_rx_level));
5119 }
5120
Mohit Khannae71e2262015-11-10 09:37:24 -08005121 /* fine-tuning parameters for TX Flows */
5122 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
5123 hdd_ctx->prev_tx = tx_packets;
5124 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
5125 next_tx_level = WLAN_SVC_TP_HIGH;
5126 else
5127 next_tx_level = WLAN_SVC_TP_LOW;
5128
5129 if (hdd_ctx->cur_tx_level != next_tx_level) {
5130 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
5131 next_tx_level, temp_tx);
5132 hdd_ctx->cur_tx_level = next_tx_level;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305133 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
5134 WLAN_SVC_WLAN_TP_TX_IND,
Mohit Khannae71e2262015-11-10 09:37:24 -08005135 &next_tx_level,
5136 sizeof(next_tx_level));
5137 }
5138
5139 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
5140 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005141 hdd_ctx->hdd_txrx_hist_idx++;
5142 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143}
5144
5145#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
5146static void hdd_bus_bw_compute_cbk(void *priv)
5147{
5148 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
5149 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305150 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05305151 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
5152 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005153 uint64_t total_tx = 0, total_rx = 0;
5154 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305155 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305156 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005157 bool connected = false;
5158 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
5159
5160 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305161 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005162 status =
5163 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
5164
5165 if (adapterNode->pAdapter == NULL)
5166 continue;
5167 adapter = adapterNode->pAdapter;
Manjeet Singh01327cc2016-09-03 12:14:25 +05305168 /*
5169 * Validate magic so we don't end up accessing
5170 * an invalid adapter.
5171 */
5172 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC)
5173 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005175 if ((adapter->device_mode == QDF_STA_MODE ||
5176 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
5178 != eConnectionState_Associated) {
5179
5180 continue;
5181 }
5182
Krunal Soni9b04c9b2016-03-10 13:08:05 -08005183 if ((adapter->device_mode == QDF_SAP_MODE ||
5184 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
5186
5187 continue;
5188 }
5189
5190 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
5191 adapter->prev_tx_packets);
5192 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
5193 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305194
5195 if (adapter->device_mode == QDF_SAP_MODE ||
5196 adapter->device_mode == QDF_P2P_GO_MODE ||
5197 adapter->device_mode == QDF_IBSS_MODE) {
5198
5199 ret = ol_get_intra_bss_fwd_pkts_count(
5200 adapter->sessionId,
5201 &fwd_tx_packets, &fwd_rx_packets);
5202 if (ret == A_OK) {
5203 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
5204 fwd_tx_packets,
5205 adapter->prev_fwd_tx_packets);
5206 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5207 fwd_tx_packets,
5208 adapter->prev_fwd_rx_packets);
5209 }
5210 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211
5212 total_rx += adapter->stats.rx_packets;
5213 total_tx += adapter->stats.tx_packets;
5214
5215 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5216 adapter->prev_tx_packets = adapter->stats.tx_packets;
5217 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305218 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5219 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5221 connected = true;
5222 }
5223
5224 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5225 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5226 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5227 rx_packets;
5228 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5229 tx_packets;
5230
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305231 /* add intra bss forwarded tx and rx packets */
5232 tx_packets += fwd_tx_packets_diff;
5233 rx_packets += fwd_rx_packets_diff;
5234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5236 tx_packets += (uint64_t)ipa_tx_packets;
5237 rx_packets += (uint64_t)ipa_rx_packets;
5238
5239 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005240 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 return;
5242 }
5243
Yuanyuan Liu13738502016-04-06 17:41:37 -07005244 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245
5246 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5247 hdd_ipa_uc_stat_request(adapter, 2);
5248
Anurag Chouhan210db072016-02-22 18:42:15 +05305249 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005250 hdd_ctx->config->busBandwidthComputeInterval);
5251}
5252#endif
5253
5254/**
Nirav Shahed34b212016-04-25 10:59:16 +05305255 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5256 * @hdd_ctx: hdd context
5257 *
5258 * Return: 0 for success or error code
5259 */
5260int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
5261{
5262 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5263 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5264 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005265 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305266 return -ENOMEM;
5267 }
5268 return 0;
5269}
5270
5271/**
5272 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5273 * @hdd_ctx: hdd context
5274 *
5275 * Return: none
5276 */
5277void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5278{
5279 if (hdd_ctx->hdd_txrx_hist) {
5280 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5281 hdd_ctx->hdd_txrx_hist = NULL;
5282 }
5283}
5284
Nirav Shahda008342016-05-17 18:50:40 +05305285static uint8_t *convert_level_to_string(uint32_t level)
5286{
5287 switch (level) {
5288 /* initialize the wlan sub system */
5289 case WLAN_SVC_TP_NONE:
5290 return "NONE";
5291 case WLAN_SVC_TP_LOW:
5292 return "LOW";
5293 case WLAN_SVC_TP_MEDIUM:
5294 return "MED";
5295 case WLAN_SVC_TP_HIGH:
5296 return "HIGH";
5297 default:
5298 return "INVAL";
5299 }
5300}
5301
Nirav Shahed34b212016-04-25 10:59:16 +05305302
5303/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5305 * @hdd_ctx: hdd context
5306 *
5307 * Return: none
5308 */
5309void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5310{
5311 int i;
5312
5313#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005314 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305315 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005316 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 hdd_ctx->config->busBandwidthHighThreshold,
5318 hdd_ctx->config->busBandwidthMediumThreshold,
5319 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005320 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305321 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005322 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005323 hdd_ctx->config->tcpDelackThresholdHigh,
5324 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005325 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305326 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005327#endif
5328
Jeff Johnson760350b2016-08-15 14:01:52 -07005329 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305330 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5331
Jeff Johnson760350b2016-08-15 14:01:52 -07005332 hdd_err("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 -08005333
5334 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005335 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5337 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5338 hdd_ctx->hdd_txrx_hist[i].total_tx,
5339 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305340 convert_level_to_string(
5341 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5342 convert_level_to_string(
5343 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5344 convert_level_to_string(
5345 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005346 }
5347 return;
5348}
5349
5350/**
5351 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5352 * @hdd_ctx: hdd context
5353 *
5354 * Return: none
5355 */
5356void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5357{
5358 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305359 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5360 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361}
5362
5363/**
5364 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5365 * @pHddCtx: hdd context
5366 *
5367 * Return: none
5368 */
5369void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5370{
5371
5372 hdd_adapter_t *adapter = NULL;
5373 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305374 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305376 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377
5378 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305379 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 adapter = adapter_node->pAdapter;
5381
Jeff Johnson760350b2016-08-15 14:01:52 -07005382 hdd_err("\nNetif queue operation statistics:");
5383 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305384 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005385 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305386 curr_time = qdf_system_ticks();
5387 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305388 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305389 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305390 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305391 unpause = adapter->total_unpause_time;
5392 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305393 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305394 pause = adapter->total_pause_time;
5395 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005396 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305397 qdf_system_ticks_to_msecs(total),
5398 qdf_system_ticks_to_msecs(pause),
5399 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005400 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005401
Nirav Shahda008342016-05-17 18:50:40 +05305402 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5403 qdf_time_t pause_delta = 0;
5404
5405 if (adapter->pause_map & (1 << i))
5406 pause_delta = delta;
5407
Jeff Johnson760350b2016-08-15 14:01:52 -07005408 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005409 hdd_reason_type_to_string(i),
5410 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305411 adapter->queue_oper_stats[i].unpause_count,
5412 qdf_system_ticks_to_msecs(
5413 adapter->queue_oper_stats[i].total_pause_time +
5414 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415 }
5416
Jeff Johnson760350b2016-08-15 14:01:52 -07005417 hdd_err("\nNetif queue operation history:");
5418 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305419 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5420
Jeff Johnson760350b2016-08-15 14:01:52 -07005421 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422
5423 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005424 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305425 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 adapter->queue_oper_history[i].time),
5427 hdd_action_type_to_string(
5428 adapter->queue_oper_history[i].netif_action),
5429 hdd_reason_type_to_string(
5430 adapter->queue_oper_history[i].netif_reason),
5431 adapter->queue_oper_history[i].pause_map);
5432 }
5433
5434 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5435 adapter_node = next;
5436 }
5437
5438
5439}
5440
5441/**
5442 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5443 * @hdd_ctx: hdd context
5444 *
5445 * Return: none
5446 */
5447void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5448{
5449 hdd_adapter_t *adapter = NULL;
5450 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305451 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452
5453 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305454 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455 adapter = adapter_node->pAdapter;
5456
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305457 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005458 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305459 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305461 adapter->history_index = 0;
5462 adapter->start_time = adapter->last_time = qdf_system_ticks();
5463 adapter->total_pause_time = 0;
5464 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005465 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5466 adapter_node = next;
5467 }
5468}
5469
5470/**
5471 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5472 * @halHandle: Hal handle
5473 * @pContext: Pointer to the context
5474 * @sessionId: Session ID
5475 * @scanId: Scan ID
5476 * @status: Status
5477 *
5478 * This is the callback to be executed when 11d scan is completed to flush out
5479 * the scan results
5480 *
5481 * 11d scan is done during driver load and is a passive scan on all
5482 * channels supported by the device, 11d scans may find some APs on
5483 * frequencies which are forbidden to be used in the regulatory domain
5484 * the device is operating in. If these APs are notified to the supplicant
5485 * it may try to connect to these APs, thus flush out all the scan results
5486 * which are present in SME after 11d scan is done.
5487 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305488 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305490static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005491 uint8_t sessionId, uint32_t scanId,
5492 eCsrScanStatus status)
5493{
5494 ENTER();
5495
5496 sme_scan_flush_result(halHandle);
5497
5498 EXIT();
5499
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305500 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501}
5502
5503#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5504/**
5505 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5506 * @hdd_ctx: hdd global context
5507 *
5508 * Return: none
5509 */
5510static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5511{
5512 uint8_t i;
5513
5514 mutex_init(&hdd_ctx->op_ctx.op_lock);
5515 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5516 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5517 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5518 }
5519}
5520#else
5521static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5522{
5523}
5524#endif
5525
5526#ifdef WLAN_FEATURE_FASTPATH
5527/**
5528 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5529 * @hdd_cfg: hdd config
5530 * @context: lower layer context
5531 *
5532 * Return: none
5533 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305534void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535 void *context)
5536{
5537 if (hdd_cfg->fastpath_enable)
5538 hif_enable_fastpath(context);
5539}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540#endif
5541
Yuanyuan Liu13738502016-04-06 17:41:37 -07005542#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005543/**
5544 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005545 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546 * @level: thermal level
5547 *
5548 * Change IPA data path to SW path when the thermal throttle level greater
5549 * than 0, and restore the original data path when throttle level is 0
5550 *
5551 * Return: none
5552 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005553static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005554{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005555 hdd_context_t *hdd_ctx = context;
5556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005557 /* Change IPA to SW path when throttle level greater than 0 */
5558 if (level > THROTTLE_LEVEL_0)
5559 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5560 else
5561 /* restore original concurrency mode */
5562 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5563}
5564
5565/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305566 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5567 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305568 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305570 * Get a safe channel to restart SAP. PCL already takes into account the
5571 * unsafe channels. So, the PCL is validated with the ACS range to provide
5572 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005573 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305574 * Return: Channel number to restart SAP in case of success. In case of any
5575 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005576 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305577static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5578 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305580 struct sir_pcl_list pcl;
5581 QDF_STATUS status;
5582 uint32_t i, j;
5583 tHalHandle *hal_handle;
5584 hdd_context_t *hdd_ctx;
5585 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305587 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5588 if (!hdd_ctx) {
5589 hdd_err("invalid HDD context");
5590 return INVALID_CHANNEL_ID;
5591 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305593 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5594 if (!hal_handle) {
5595 hdd_err("invalid HAL handle");
5596 return INVALID_CHANNEL_ID;
5597 }
5598
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305599 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5600 pcl.pcl_list, &pcl.pcl_len,
5601 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5602 if (QDF_IS_STATUS_ERROR(status)) {
5603 hdd_err("Get PCL failed");
5604 return INVALID_CHANNEL_ID;
5605 }
5606
5607 if (!pcl.pcl_len) {
5608 hdd_alert("pcl length is zero. this is not expected");
5609 return INVALID_CHANNEL_ID;
5610 }
5611
5612 hdd_info("start:%d end:%d",
5613 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5614 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5615
5616 /* PCL already takes unsafe channel into account */
5617 for (i = 0; i < pcl.pcl_len; i++) {
5618 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5619 if ((pcl.pcl_list[i] >=
5620 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5621 (pcl.pcl_list[i] <=
5622 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5623 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5624 return pcl.pcl_list[i];
5625 }
5626 }
5627
5628 hdd_info("no safe channel from PCL found in ACS range");
5629
5630 /* Try for safe channel from all valid channel */
5631 pcl.pcl_len = MAX_NUM_CHAN;
5632 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5633 &pcl.pcl_len);
5634 if (QDF_IS_STATUS_ERROR(status)) {
5635 hdd_err("error in getting valid channel list");
5636 return INVALID_CHANNEL_ID;
5637 }
5638
5639 for (i = 0; i < pcl.pcl_len; i++) {
5640 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5641 found = false;
5642 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
5643 if (cds_chan_to_freq(pcl.pcl_list[i]) ==
5644 hdd_ctx->unsafe_channel_list[j]) {
5645 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5646 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647 break;
5648 }
5649 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305650
5651 if (found)
5652 continue;
5653
5654 if ((pcl.pcl_list[i] >=
5655 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5656 (pcl.pcl_list[i] <=
5657 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5658 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5659 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 }
5661 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305662
5663 return INVALID_CHANNEL_ID;
5664}
5665
5666/**
5667 * hdd_restart_sap() - Restarts SAP on the given channel
5668 * @adapter: AP adapter
5669 * @channel: Channel
5670 *
5671 * Restarts the SAP interface by invoking the function which executes the
5672 * callback to perform channel switch using (E)CSA.
5673 *
5674 * Return: None
5675 */
5676void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
5677{
5678 hdd_ap_ctx_t *hdd_ap_ctx;
5679 tHalHandle *hal_handle;
5680
5681 if (!adapter) {
5682 hdd_err("invalid adapter");
5683 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305685
5686 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5687
5688 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5689 if (!hal_handle) {
5690 hdd_err("invalid HAL handle");
5691 return;
5692 }
5693
5694 hdd_ap_ctx->sapConfig.channel = channel;
5695 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5696 hdd_ap_ctx->sapConfig.ch_width_orig;
5697
5698 hdd_info("chan:%d width:%d",
5699 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5700
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005701 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305702 hdd_ap_ctx->sapConfig.sec_ch,
5703 &hdd_ap_ctx->sapConfig.ch_params);
5704
5705 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005706}
5707
5708/**
5709 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
5710 * @adapter: HDD adapter pointer
5711 * @indParam: Channel avoid notification parameter
5712 *
5713 * Avoid channel notification from FW handler.
5714 * FW will send un-safe channel list to avoid over wrapping.
5715 * hostapd should not use notified channel
5716 *
5717 * Return: None
5718 */
5719static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
5720{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 hdd_context_t *hdd_ctxt;
5722 tSirChAvoidIndType *ch_avoid_indi;
5723 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08005724 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
5725 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005726 uint16_t start_channel;
5727 uint16_t end_channel;
5728 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005729 tHddAvoidFreqList hdd_avoid_freq_list;
5730 uint32_t i;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305731 QDF_STATUS status;
5732 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
5733 hdd_adapter_t *adapter_temp;
5734 uint8_t restart_chan;
5735 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005736
5737 /* Basic sanity */
5738 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005739 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005740 return;
5741 }
5742
5743 hdd_ctxt = (hdd_context_t *) hdd_context;
5744 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
5745 cds_context = hdd_ctxt->pcds_context;
5746
5747 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07005748 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005749 ch_avoid_indi->avoid_range_count);
5750
5751 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305752 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
5754 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
5755 ch_avoid_indi->avoid_freq_range[i].start_freq;
5756 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
5757 ch_avoid_indi->avoid_freq_range[i].end_freq;
5758 }
5759 hdd_avoid_freq_list.avoidFreqRangeCount =
5760 ch_avoid_indi->avoid_range_count;
5761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005762 /* clear existing unsafe channel cache */
5763 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305764 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005765 sizeof(hdd_ctxt->unsafe_channel_list));
5766
5767 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
5768 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08005769 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005770 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771 break;
5772 }
5773
5774 start_channel = ieee80211_frequency_to_channel(
5775 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
5776 end_channel = ieee80211_frequency_to_channel(
5777 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07005778 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
5780 start_channel,
5781 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
5782 end_channel);
5783
5784 /* do not process frequency bands that are not mapped to
5785 * predefined channels
5786 */
5787 if (start_channel == 0 || end_channel == 0)
5788 continue;
5789
Amar Singhalb8d4f152016-02-10 10:21:43 -08005790 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5791 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005792 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005793 ch_avoid_indi->avoid_freq_range[
5794 range_loop].start_freq) {
5795 start_channel_idx = channel_loop;
5796 break;
5797 }
5798 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08005799 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5800 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005801 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005802 ch_avoid_indi->avoid_freq_range[
5803 range_loop].end_freq) {
5804 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07005805 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 ch_avoid_indi->avoid_freq_range[
5807 range_loop].end_freq)
5808 end_channel_idx--;
5809 break;
5810 }
5811 }
5812
Amar Singhalb8d4f152016-02-10 10:21:43 -08005813 if (start_channel_idx == INVALID_CHANNEL ||
5814 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005815 continue;
5816
5817 for (channel_loop = start_channel_idx; channel_loop <=
5818 end_channel_idx; channel_loop++) {
5819 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07005820 hdd_ctxt->unsafe_channel_count++] =
5821 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08005823 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005824 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005825 break;
5826 }
5827 }
5828 }
5829
Jeff Johnson34c88b72016-08-15 14:27:11 -07005830 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831 hdd_ctxt->unsafe_channel_count);
5832
Yuanyuan Liu13738502016-04-06 17:41:37 -07005833 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
5834 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005835 hdd_ctxt->unsafe_channel_count)) {
5836 hdd_err("Failed to set unsafe channel");
5837
5838 /* clear existing unsafe channel cache */
5839 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305840 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 sizeof(hdd_ctxt->unsafe_channel_list));
5842
5843 return;
5844 }
5845
5846 for (channel_loop = 0;
5847 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005848 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849 hdd_ctxt->unsafe_channel_list[channel_loop]);
5850 }
5851
Kondabattini, Ganeshcf7b60f2016-08-10 16:31:55 +05305852 /*
5853 * first update the unsafe channel list to the platform driver and
5854 * send the avoid freq event to the application
5855 */
5856 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
5857
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305858 if (!hdd_ctxt->unsafe_channel_count) {
5859 hdd_info("no unsafe channels - not restarting SAP");
5860 return;
5861 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305863 /* No channel change is done for fixed channel SAP.
5864 * Loop through all ACS SAP interfaces and change the channels for
5865 * the ones operating on unsafe channels.
5866 */
5867 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
5868 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5869 adapter_temp = adapter_node->pAdapter;
5870
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305871 if (!adapter_temp) {
5872 hdd_err("adapter is NULL, moving to next one");
5873 goto next_adapater;
5874 }
5875
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305876 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
5877 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
5878 hdd_info("skip device mode:%d acs:%d",
5879 adapter_temp->device_mode,
5880 adapter_temp->sessionCtx.ap.sapConfig.
5881 acs_cfg.acs_mode);
5882 goto next_adapater;
5883 }
5884
5885 found = false;
5886 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
5887 if (cds_chan_to_freq(
5888 adapter_temp->sessionCtx.ap.operatingChannel) ==
5889 hdd_ctxt->unsafe_channel_list[i]) {
5890 found = true;
5891 hdd_info("operating ch:%d is unsafe",
5892 adapter_temp->sessionCtx.ap.operatingChannel);
5893 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005894 }
5895 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305896
5897 if (!found) {
5898 hdd_info("ch:%d is safe. no need to change channel",
5899 adapter_temp->sessionCtx.ap.operatingChannel);
5900 goto next_adapater;
5901 }
5902
5903 restart_chan =
5904 hdd_get_safe_channel_from_pcl_and_acs_range(
5905 adapter_temp);
5906 if (!restart_chan) {
5907 hdd_alert("fail to restart SAP");
5908 } else {
5909 hdd_info("sending coex indication");
5910 wlan_hdd_send_svc_nlink_msg
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05305911 (hdd_ctxt->radio_index,
5912 WLAN_SVC_LTE_COEX_IND, NULL, 0);
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305913 hdd_restart_sap(adapter_temp, restart_chan);
5914 }
5915
5916next_adapater:
5917 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
5918 adapter_node = next;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 }
5920 return;
5921}
5922
5923/**
5924 * hdd_init_channel_avoidance() - Initialize channel avoidance
5925 * @hdd_ctx: HDD global context
5926 *
5927 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07005928 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 * down to the lower layers. Then subscribe to subsequent channel
5930 * avoidance events.
5931 *
5932 * Return: None
5933 */
5934static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5935{
5936 uint16_t unsafe_channel_count;
5937 int index;
5938
Yuanyuan Liu13738502016-04-06 17:41:37 -07005939 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
5940 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08005942 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943
Jeff Johnson34c88b72016-08-15 14:27:11 -07005944 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945 hdd_ctx->unsafe_channel_count);
5946
Anurag Chouhan6d760662016-02-20 16:05:43 +05305947 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08005948 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949
5950 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005951 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005952 hdd_ctx->unsafe_channel_list[index]);
5953
5954 }
5955
5956 /* Plug in avoid channel notification callback */
5957 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
5958}
5959#else
5960static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5961{
5962}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005963static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005964{
5965}
Yuanyuan Liu13738502016-04-06 17:41:37 -07005966#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967
5968/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08005969 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
5970 * user space
5971 * @frame_ind: Management frame data to be informed.
5972 *
5973 * This function is used to indicate management frame to
5974 * user space
5975 *
5976 * Return: None
5977 *
5978 */
5979void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
5980{
5981 hdd_context_t *hdd_ctx = NULL;
5982 hdd_adapter_t *adapter = NULL;
5983 void *cds_context = NULL;
5984 int i;
5985
5986 /* Get the global VOSS context.*/
5987 cds_context = cds_get_global_context();
5988 if (!cds_context) {
5989 hdd_err("Global CDS context is Null");
5990 return;
5991 }
5992 /* Get the HDD context.*/
5993 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
5994
5995 if (0 != wlan_hdd_validate_context(hdd_ctx))
5996 return;
5997
5998 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
5999 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
6000 adapter =
6001 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
6002 if (adapter)
6003 break;
6004 }
6005 } else {
6006 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
6007 frame_ind->sessionId);
6008 }
6009
6010 if ((NULL != adapter) &&
6011 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
6012 __hdd_indicate_mgmt_frame(adapter,
6013 frame_ind->frame_len,
6014 frame_ind->frameBuf,
6015 frame_ind->frameType,
6016 frame_ind->rxChan,
6017 frame_ind->rxRssi);
6018 return;
6019}
6020
6021/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006022 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
6023 * @hdd_ctx: HDD context
6024 *
6025 * Disables all the dual mac features like DBS, Agile DFS etc.
6026 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306027 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006028 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306029static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030{
6031 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306032 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006033
6034 if (!hdd_ctx) {
6035 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306036 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006037 }
6038
Arun Khandavallid4349a92016-07-25 11:10:43 +05306039 if (hdd_ctx->config->dual_mac_feature_disable)
6040 return QDF_STATUS_SUCCESS;
6041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006042 cfg.scan_config = 0;
6043 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05306044 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006045
6046 hdd_debug("Disabling all dual mac features...");
6047
6048 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306049 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006050 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
6051 return status;
6052 }
6053
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306054 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006055}
6056
6057/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006058 * hdd_override_ini_config - Override INI config
6059 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006060 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006061 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006062 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006063 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006064 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006065static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006066{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006067
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006068 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
6069 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
6070 hdd_notice("Module enable_dfs_chan_scan set to %d",
6071 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006072 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006073 if (0 == enable_11d || 1 == enable_11d) {
6074 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
6075 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006076 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006077}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006078
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006079/**
6080 * hdd_set_trace_level_for_each - Set trace level for each INI config
6081 * @hdd_ctx - HDD context
6082 *
6083 * Set trace level for each module based on INI config.
6084 *
6085 * Return: None
6086 */
6087static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
6088{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306089 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
6090 hdd_ctx->config->qdf_trace_enable_wdi);
6091 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
6092 hdd_ctx->config->qdf_trace_enable_hdd);
6093 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
6094 hdd_ctx->config->qdf_trace_enable_sme);
6095 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
6096 hdd_ctx->config->qdf_trace_enable_pe);
6097 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
6098 hdd_ctx->config->qdf_trace_enable_wma);
6099 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
6100 hdd_ctx->config->qdf_trace_enable_sys);
6101 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
6102 hdd_ctx->config->qdf_trace_enable_qdf);
6103 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
6104 hdd_ctx->config->qdf_trace_enable_sap);
6105 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
6106 hdd_ctx->config->qdf_trace_enable_hdd_sap);
6107 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
6108 hdd_ctx->config->qdf_trace_enable_bmi);
6109 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
6110 hdd_ctx->config->qdf_trace_enable_cfg);
6111 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
6112 hdd_ctx->config->qdf_trace_enable_epping);
6113 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
6114 hdd_ctx->config->qdf_trace_enable_qdf_devices);
6115 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05306116 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306117 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
6118 hdd_ctx->config->qdf_trace_enable_htc);
6119 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
6120 hdd_ctx->config->qdf_trace_enable_hif);
6121 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
6122 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
6123 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
6124 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05306125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006126 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006127}
6128
6129/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006130 * hdd_context_init() - Initialize HDD context
6131 * @hdd_ctx: HDD context.
6132 *
6133 * Initialize HDD context along with all the feature specific contexts.
6134 *
6135 * return: 0 on success and errno on failure.
6136 */
6137static int hdd_context_init(hdd_context_t *hdd_ctx)
6138{
6139 int ret;
6140
6141 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
6142 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
6143
6144 hdd_init_ll_stats_ctx();
6145
6146 init_completion(&hdd_ctx->mc_sus_event_var);
6147 init_completion(&hdd_ctx->ready_to_suspend);
6148
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306149 hdd_init_bpf_completion();
6150
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006151 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306152 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006153 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05306154
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006155 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
6156
6157 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
6158
6159 ret = hdd_scan_context_init(hdd_ctx);
6160 if (ret)
6161 goto list_destroy;
6162
6163 hdd_tdls_context_init(hdd_ctx);
6164
6165 hdd_rx_wake_lock_create(hdd_ctx);
6166
6167 ret = hdd_sap_context_init(hdd_ctx);
6168 if (ret)
6169 goto scan_destroy;
6170
6171 ret = hdd_roc_context_init(hdd_ctx);
6172 if (ret)
6173 goto sap_destroy;
6174
6175 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
6176
6177 hdd_init_offloaded_packets_ctx(hdd_ctx);
6178
6179 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
6180 hdd_ctx->config);
6181 if (ret)
6182 goto roc_destroy;
6183
6184 return 0;
6185
6186roc_destroy:
6187 hdd_roc_context_destroy(hdd_ctx);
6188
6189sap_destroy:
6190 hdd_sap_context_destroy(hdd_ctx);
6191
6192scan_destroy:
6193 hdd_scan_context_destroy(hdd_ctx);
6194 hdd_rx_wake_lock_destroy(hdd_ctx);
6195 hdd_tdls_context_destroy(hdd_ctx);
6196
6197list_destroy:
6198 qdf_list_destroy(&hdd_ctx->hddAdapters);
6199 return ret;
6200}
6201
6202/**
6203 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05306204 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006205 *
6206 * Allocate and initialize HDD context. HDD context is allocated as part of
6207 * wiphy allocation and then context is initialized.
6208 *
6209 * Return: HDD context on success and ERR_PTR on failure
6210 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306211hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006212{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306213 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006214 int ret = 0;
6215 hdd_context_t *hdd_ctx;
6216 v_CONTEXT_t p_cds_context;
6217
6218 ENTER();
6219
6220 p_cds_context = cds_get_global_context();
6221 if (p_cds_context == NULL) {
6222 hdd_alert("Failed to get CDS global context");
6223 ret = -EINVAL;
6224 goto err_out;
6225 }
6226
6227 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6228
6229 if (hdd_ctx == NULL) {
6230 ret = -ENOMEM;
6231 goto err_out;
6232 }
6233
6234 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006235 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006236
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306237 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006238 if (hdd_ctx->config == NULL) {
6239 hdd_alert("Failed to alloc memory for HDD config!");
6240 ret = -ENOMEM;
6241 goto err_free_hdd_context;
6242 }
6243
6244 /* Read and parse the qcom_cfg.ini file */
6245 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306246 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306247 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006248 WLAN_INI_FILE);
6249 ret = -EINVAL;
6250 goto err_free_config;
6251 }
6252
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006253 hdd_ctx->configuredMcastBcastFilter =
6254 hdd_ctx->config->mcastBcastFilterSetting;
6255
6256 hdd_notice("Setting configuredMcastBcastFilter: %d",
6257 hdd_ctx->config->mcastBcastFilterSetting);
6258
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306259 if (hdd_ctx->config->fhostNSOffload)
6260 hdd_ctx->ns_offload_enable = true;
6261
Abhishek Singh5ea86532016-04-27 14:10:53 +05306262 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6263
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006264 hdd_override_ini_config(hdd_ctx);
6265
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006266 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006267
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006268 ret = hdd_context_init(hdd_ctx);
6269
6270 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006271 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006272
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006273
Yuanyuan Liu13738502016-04-06 17:41:37 -07006274 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6275 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006276
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006277
6278 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306279 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006280
Anurag Chouhan6d760662016-02-20 16:05:43 +05306281 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006282 goto skip_multicast_logging;
6283
6284 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6285
Nirav Shahed34b212016-04-25 10:59:16 +05306286 status = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6287 if (status)
6288 goto err_free_config;
6289
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006290 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6291 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306292 goto err_free_histogram;
6293
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006294
6295 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306296 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006297 * levels of the code need not be set when the logger thread
6298 * is not enabled.
6299 */
6300 if (cds_is_multicast_logging())
6301 wlan_logging_set_log_level();
6302
6303skip_multicast_logging:
6304 hdd_set_trace_level_for_each(hdd_ctx);
6305
6306 return hdd_ctx;
6307
Nirav Shahed34b212016-04-25 10:59:16 +05306308err_free_histogram:
6309 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6310
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006311err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306312 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006313
6314err_free_hdd_context:
6315 wiphy_free(hdd_ctx->wiphy);
6316
6317err_out:
6318 return ERR_PTR(ret);
6319}
6320
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006321#ifdef WLAN_OPEN_P2P_INTERFACE
6322/**
6323 * hdd_open_p2p_interface - Open P2P interface
6324 * @hdd_ctx: HDD context
6325 * @rtnl_held: True if RTNL lock held
6326 *
6327 * Open P2P interface during probe. This function called to open the P2P
6328 * interface at probe along with STA interface.
6329 *
6330 * Return: 0 on success and errno on failure
6331 */
6332static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6333{
6334 hdd_adapter_t *adapter;
6335 uint8_t *p2p_dev_addr;
6336
6337 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6338 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306339 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006340 hdd_ctx->config->intfMacAddr[0].bytes,
6341 sizeof(tSirMacAddr));
6342
6343 /*
6344 * Generate the P2P Device Address. This consists of
6345 * the device's primary MAC address with the locally
6346 * administered bit set.
6347 */
6348 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6349 } else {
6350 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6351 if (p2p_dev_addr == NULL) {
6352 hdd_alert("Failed to allocate mac_address for p2p_device");
6353 return -ENOSPC;
6354 }
6355
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306356 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306357 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006358 }
6359
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006360 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006361 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006362 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006363
6364 if (NULL == adapter) {
6365 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6366 return -ENOSPC;
6367 }
6368
6369 return 0;
6370}
6371#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306372static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006373 bool rtnl_held)
6374{
6375 return 0;
6376}
6377#endif
6378
6379/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306380 * hdd_start_station_adapter()- Start the Station Adapter
6381 * @adapter: HDD adapter
6382 *
6383 * This function initializes the adapter for the station mode.
6384 *
6385 * Return: 0 on success or errno on failure.
6386 */
6387int hdd_start_station_adapter(hdd_adapter_t *adapter)
6388{
6389 QDF_STATUS status;
6390
6391 ENTER_DEV(adapter->dev);
6392
6393 status = hdd_init_station_mode(adapter);
6394
6395 if (QDF_STATUS_SUCCESS != status) {
6396 hdd_err("Error Initializing station mode: %d", status);
6397 return qdf_status_to_os_return(status);
6398 }
6399
Arun Khandavallifae92942016-08-01 13:31:08 +05306400 hdd_register_tx_flow_control(adapter,
6401 hdd_tx_resume_timer_expired_handler,
6402 hdd_tx_resume_cb);
6403
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306404 EXIT();
6405 return 0;
6406}
6407
6408/**
6409 * hdd_start_ap_adapter()- Start AP Adapter
6410 * @adapter: HDD adapter
6411 *
6412 * This function initializes the adapter for the AP mode.
6413 *
6414 * Return: 0 on success errno on failure.
6415 */
6416int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6417{
6418 QDF_STATUS status;
6419
6420 ENTER();
6421
6422 status = hdd_init_ap_mode(adapter);
6423
6424 if (QDF_STATUS_SUCCESS != status) {
6425 hdd_err("Error Initializing the AP mode: %d", status);
6426 return qdf_status_to_os_return(status);
6427 }
6428
Arun Khandavallifae92942016-08-01 13:31:08 +05306429 hdd_register_tx_flow_control(adapter,
6430 hdd_softap_tx_resume_timer_expired_handler,
6431 hdd_softap_tx_resume_cb);
6432
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306433 EXIT();
6434 return 0;
6435}
6436
6437/**
6438 * hdd_start_ftm_adapter()- Start FTM adapter
6439 * @adapter: HDD adapter
6440 *
6441 * This function initializes the adapter for the FTM mode.
6442 *
6443 * Return: 0 on success or errno on failure.
6444 */
6445int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6446{
6447 QDF_STATUS qdf_status;
6448
6449 ENTER_DEV(adapter->dev);
6450
6451 qdf_status = hdd_init_tx_rx(adapter);
6452
6453 if (QDF_STATUS_SUCCESS != qdf_status) {
6454 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6455 return qdf_status_to_os_return(qdf_status);
6456 }
6457
6458 return 0;
6459 EXIT();
6460}
6461
6462/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006463 * hdd_open_interfaces - Open all required interfaces
6464 * hdd_ctx: HDD context
6465 * rtnl_held: True if RTNL lock is held
6466 *
6467 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6468 *
6469 * Return: Primary adapter on success and PTR_ERR on failure
6470 */
6471static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6472 bool rtnl_held)
6473{
6474 hdd_adapter_t *adapter = NULL;
6475 hdd_adapter_t *adapter_11p = NULL;
6476 int ret;
6477
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006478 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306479 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006480 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006481 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006482 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006483
6484 if (adapter == NULL)
6485 return ERR_PTR(-ENOSPC);
6486
6487 return adapter;
6488 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006489 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006490 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006491 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006492
6493 if (adapter == NULL)
6494 return ERR_PTR(-ENOSPC);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006495 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6496 if (ret)
6497 goto err_close_adapter;
6498
6499 /* Open 802.11p Interface */
6500 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006501 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006502 "wlanocb%d",
6503 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006504 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006505 if (adapter_11p == NULL) {
6506 hdd_err("Failed to open 802.11p interface");
6507 goto err_close_adapter;
6508 }
6509 }
6510
6511 return adapter;
6512
6513err_close_adapter:
6514 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6515 return ERR_PTR(ret);
6516}
6517
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006518/**
6519 * hdd_update_country_code - Update country code
6520 * @hdd_ctx: HDD context
6521 * @adapter: Primary adapter context
6522 *
6523 * Update country code based on module parameter country_code at SME and wait
6524 * for the settings to take effect.
6525 *
6526 * Return: 0 on success and errno on failure
6527 */
6528static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6529 hdd_adapter_t *adapter)
6530{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306531 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006532 int ret = 0;
6533 unsigned long rc;
6534
6535 if (country_code == NULL)
6536 return 0;
6537
6538 INIT_COMPLETION(adapter->change_country_code);
6539
6540 status = sme_change_country_code(hdd_ctx->hHal,
6541 wlan_hdd_change_country_code_callback,
6542 country_code, adapter,
6543 hdd_ctx->pcds_context, eSIR_TRUE,
6544 eSIR_TRUE);
6545
6546
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306547 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006548 hdd_err("SME Change Country code from module param fail ret=%d",
6549 ret);
6550 return -EINVAL;
6551 }
6552
6553 rc = wait_for_completion_timeout(&adapter->change_country_code,
6554 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6555 if (!rc) {
6556 hdd_err("SME while setting country code timed out");
6557 ret = -ETIMEDOUT;
6558 }
6559
6560 return ret;
6561}
6562
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306563#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6564/**
6565 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6566 * @cds_cfg: CDS Configuration
6567 * @hdd_ctx: Pointer to hdd context
6568 *
6569 * Return: none
6570 */
6571static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6572 *cds_cfg,
6573 hdd_context_t *hdd_ctx)
6574{
6575 cds_cfg->tx_flow_stop_queue_th =
6576 hdd_ctx->config->TxFlowStopQueueThreshold;
6577 cds_cfg->tx_flow_start_queue_offset =
6578 hdd_ctx->config->TxFlowStartQueueOffset;
6579}
6580#else
6581static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6582 *cds_cfg,
6583 hdd_context_t *hdd_ctx)
6584{
6585}
6586#endif
6587
6588#ifdef FEATURE_WLAN_RA_FILTERING
6589/**
6590 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6591 * @cds_cfg: CDS Configuration
6592 * @hdd_ctx: Pointer to hdd context
6593 *
6594 * Return: none
6595 */
6596inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6597 hdd_context_t *hdd_ctx)
6598{
6599 cds_cfg->ra_ratelimit_interval =
6600 hdd_ctx->config->RArateLimitInterval;
6601 cds_cfg->is_ra_ratelimit_enabled =
6602 hdd_ctx->config->IsRArateLimitEnabled;
6603}
6604#else
6605inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6606 hdd_context_t *hdd_ctx)
6607{
6608}
6609#endif
6610
6611/**
6612 * hdd_update_cds_config() - API to update cds configuration parameters
6613 * @hdd_ctx: HDD Context
6614 *
6615 * Return: 0 for Success, errno on failure
6616 */
6617int hdd_update_cds_config(hdd_context_t *hdd_ctx)
6618{
6619 struct cds_config_info *cds_cfg;
6620
6621 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6622 if (!cds_cfg) {
6623 hdd_err("failed to allocate cds config");
6624 return -ENOMEM;
6625 }
6626
6627 qdf_mem_zero(cds_cfg, sizeof(*cds_cfg));
6628
6629 /* UMA is supported in hardware for performing the
6630 * frame translation 802.11 <-> 802.3
6631 */
6632 cds_cfg->frame_xln_reqd = 1;
6633 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
6634 cds_cfg->powersave_offload_enabled =
6635 hdd_ctx->config->enablePowersaveOffload;
6636 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
6637 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
6638 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
6639 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
6640 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
6641
6642 /* Here ol_ini_info is used to store ini status of arp offload
6643 * ns offload and others. Currently 1st bit is used for arp
6644 * off load and 2nd bit for ns offload currently, rest bits are unused
6645 */
6646 if (hdd_ctx->config->fhostArpOffload)
6647 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
6648 if (hdd_ctx->config->fhostNSOffload)
6649 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
6650
6651 /*
6652 * Copy the DFS Phyerr Filtering Offload status.
6653 * This parameter reflects the value of the
6654 * dfs_phyerr_filter_offload flag as set in the ini.
6655 */
6656 cds_cfg->dfs_phyerr_filter_offload =
6657 hdd_ctx->config->fDfsPhyerrFilterOffload;
6658 if (hdd_ctx->config->ssdp)
6659 cds_cfg->ssdp = hdd_ctx->config->ssdp;
6660
6661 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
6662 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
6663
6664 cds_cfg->ap_maxoffload_reorderbuffs =
6665 hdd_ctx->config->apMaxOffloadReorderBuffs;
6666
6667 cds_cfg->ap_disable_intrabss_fwd =
6668 hdd_ctx->config->apDisableIntraBssFwd;
6669
6670 cds_cfg->dfs_pri_multiplier =
6671 hdd_ctx->config->dfsRadarPriMultiplier;
6672 cds_cfg->reorder_offload =
6673 hdd_ctx->config->reorderOffloadSupport;
6674
6675 /* IPA micro controller data path offload resource config item */
6676 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
6677 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
6678 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
6679 cds_cfg->uc_rxind_ringcount =
6680 hdd_ctx->config->IpaUcRxIndRingCount;
6681 cds_cfg->uc_tx_partition_base =
6682 hdd_ctx->config->IpaUcTxPartitionBase;
6683 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
6684
6685 cds_cfg->ip_tcp_udp_checksum_offload =
6686 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05306687 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306688 cds_cfg->ce_classify_enabled =
6689 hdd_ctx->config->ce_classify_enabled;
Dustin Brownd3fc9ee2016-09-14 13:57:27 -07006690 cds_cfg->bpf_packet_filter_enable =
6691 hdd_ctx->config->bpf_packet_filter_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306692 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
6693 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
6694 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07006695 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Manjunathappa Prakashfff753c2016-09-01 19:34:56 -07006696 cds_cfg->flow_steering_enabled = hdd_ctx->config->flow_steering_enable;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306697
6698 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
6699 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
6700 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
6701
6702 cds_init_ini_config(cds_cfg);
6703 return 0;
6704}
6705
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006706/**
6707 * hdd_init_thermal_info - Initialize thermal level
6708 * @hdd_ctx: HDD context
6709 *
6710 * Initialize thermal level at SME layer and set the thermal level callback
6711 * which would be called when a configured thermal threshold is hit.
6712 *
6713 * Return: 0 on success and errno on failure
6714 */
6715static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
6716{
6717 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306718 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006719
6720 thermal_param.smeThermalMgmtEnabled =
6721 hdd_ctx->config->thermalMitigationEnable;
6722 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
6723
Poddar, Siddarth83905022016-04-16 17:56:08 -07006724 thermal_param.sme_throttle_duty_cycle_tbl[0] =
6725 hdd_ctx->config->throttle_dutycycle_level0;
6726 thermal_param.sme_throttle_duty_cycle_tbl[1] =
6727 hdd_ctx->config->throttle_dutycycle_level1;
6728 thermal_param.sme_throttle_duty_cycle_tbl[2] =
6729 hdd_ctx->config->throttle_dutycycle_level2;
6730 thermal_param.sme_throttle_duty_cycle_tbl[3] =
6731 hdd_ctx->config->throttle_dutycycle_level3;
6732
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006733 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
6734 hdd_ctx->config->thermalTempMinLevel0;
6735 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
6736 hdd_ctx->config->thermalTempMaxLevel0;
6737 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
6738 hdd_ctx->config->thermalTempMinLevel1;
6739 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
6740 hdd_ctx->config->thermalTempMaxLevel1;
6741 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
6742 hdd_ctx->config->thermalTempMinLevel2;
6743 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
6744 hdd_ctx->config->thermalTempMaxLevel2;
6745 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
6746 hdd_ctx->config->thermalTempMinLevel3;
6747 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
6748 hdd_ctx->config->thermalTempMaxLevel3;
6749
6750 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
6751
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306752 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05306753 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006754
6755 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
6756 hdd_set_thermal_level_cb);
6757
6758 return 0;
6759
6760}
6761
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006762#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
6763/**
6764 * hdd_hold_rtnl_lock - Hold RTNL lock
6765 *
6766 * Hold RTNL lock
6767 *
6768 * Return: True if held and false otherwise
6769 */
6770static inline bool hdd_hold_rtnl_lock(void)
6771{
6772 rtnl_lock();
6773 return true;
6774}
6775
6776/**
6777 * hdd_release_rtnl_lock - Release RTNL lock
6778 *
6779 * Release RTNL lock
6780 *
6781 * Return: None
6782 */
6783static inline void hdd_release_rtnl_lock(void)
6784{
6785 rtnl_unlock();
6786}
6787#else
6788static inline bool hdd_hold_rtnl_lock(void) { return false; }
6789static inline void hdd_release_rtnl_lock(void) { }
6790#endif
6791
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006792#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006793
6794/**
6795 * hdd_process_pktlog_command() - process pktlog command
6796 * @hdd_ctx: hdd context
6797 * @set_value: value set by user
6798 *
6799 * Return: 0 for success or error.
6800 */
6801int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value)
6802{
6803 int ret;
6804 bool enable;
6805 uint8_t user_triggered = 0;
6806
6807 ret = wlan_hdd_validate_context(hdd_ctx);
6808 if (0 != ret)
6809 return ret;
6810
6811 hdd_info("set pktlog %d", set_value);
6812
6813 if (set_value > 2) {
6814 hdd_err("invalid pktlog value %d", set_value);
6815 return -EINVAL;
6816 }
6817
6818 /*
6819 * set_value = 0 then disable packetlog
6820 * set_value = 1 enable packetlog forcefully
6821 * set_vlaue = 2 then disable packetlog if disabled through ini or
6822 * enable packetlog with AUTO type.
6823 */
6824 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
6825 true : false;
6826
6827 if (1 == set_value) {
6828 enable = true;
6829 user_triggered = 1;
6830 }
6831
6832 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered);
6833}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006834/**
6835 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
6836 * @hdd_ctx: HDD context
6837 * @enable: Flag to enable/disable
6838 *
6839 * Return: 0 on success; error number otherwise
6840 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006841int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
6842 uint8_t user_triggered)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006843{
6844 struct sir_wifi_start_log start_log;
6845 QDF_STATUS status;
6846
6847 start_log.ring_id = RING_ID_PER_PACKET_STATS;
6848 start_log.verbose_level =
6849 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006850 start_log.ini_triggered = cds_is_packet_log_enabled();
6851 start_log.user_triggered = user_triggered;
6852
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006853 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
6854 if (!QDF_IS_STATUS_SUCCESS(status)) {
6855 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
6856 EXIT();
6857 return -EINVAL;
6858 }
6859
6860 return 0;
6861}
6862#endif /* REMOVE_PKT_LOG */
6863
6864
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05306865#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
6866/**
6867 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
6868 * switch without restart
6869 *
6870 * Registers callback function to change the operating channel of SAP by using
6871 * channel switch announcements instead of restarting SAP.
6872 *
6873 * Return: QDF_STATUS
6874 */
6875QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
6876{
6877 QDF_STATUS status;
6878
6879 status = cds_register_sap_restart_channel_switch_cb(
6880 (void *)hdd_sap_restart_with_channel_switch);
6881 if (!QDF_IS_STATUS_SUCCESS(status))
6882 hdd_err("restart cb registration failed");
6883
6884 return status;
6885}
6886#endif
6887
Komal Seelam92fff912016-03-24 11:51:41 +05306888#ifdef CONFIG_CNSS
6889/**
6890 * hdd_get_cnss_wlan_mac_buff() - API to query platform driver for MAC address
6891 * @dev: Device Pointer
6892 * @num: Number of Valid Mac address
6893 *
6894 * Return: Pointer to MAC address buffer
6895 */
6896static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6897{
6898 return cnss_common_get_wlan_mac_address(dev, num);
6899}
6900#else
6901static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6902{
6903 *num = 0;
6904 return NULL;
6905}
6906#endif
6907
6908/**
6909 * hdd_populate_random_mac_addr() - API to populate random mac addresses
6910 * @hdd_ctx: HDD Context
6911 * @num: Number of random mac addresses needed
6912 *
6913 * Generate random addresses using bit manipulation on the base mac address
6914 *
6915 * Return: None
6916 */
6917static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
6918{
6919 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
6920 uint32_t iter;
6921 struct hdd_config *ini = hdd_ctx->config;
6922 uint8_t *buf = NULL;
6923 uint8_t macaddr_b3, tmp_br3;
6924 uint8_t *src = ini->intfMacAddr[0].bytes;
6925
6926 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
6927 buf = ini->intfMacAddr[iter].bytes;
6928 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
6929 macaddr_b3 = buf[3];
6930 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
6931 INTF_MACADDR_MASK;
6932 macaddr_b3 += tmp_br3;
6933 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
6934 buf[0] |= 0x02;
6935 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07006936 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05306937 }
6938}
6939
6940/**
6941 * hdd_cnss_wlan_mac() - API to get mac addresses from cnss platform driver
6942 * @hdd_ctx: HDD Context
6943 *
6944 * API to get mac addresses from platform driver and update the driver
6945 * structures and configure FW with the base mac address.
6946 * Return: int
6947 */
6948static int hdd_cnss_wlan_mac(hdd_context_t *hdd_ctx)
6949{
6950 uint32_t no_of_mac_addr, iter;
6951 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
6952 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
6953 uint8_t *addr, *buf;
6954 struct device *dev = hdd_ctx->parent_dev;
6955 struct hdd_config *ini = hdd_ctx->config;
6956 tSirMacAddr mac_addr;
6957 QDF_STATUS status;
6958
6959 addr = hdd_get_cnss_wlan_mac_buff(dev, &no_of_mac_addr);
6960
6961 if (no_of_mac_addr == 0 || !addr) {
6962 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
6963 return -EINVAL;
6964 }
6965
6966 if (no_of_mac_addr > max_mac_addr)
6967 no_of_mac_addr = max_mac_addr;
6968
6969 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
6970
6971 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
6972 buf = ini->intfMacAddr[iter].bytes;
6973 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006974 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05306975 }
6976
6977 status = sme_set_custom_mac_addr(mac_addr);
6978
6979 if (!QDF_IS_STATUS_SUCCESS(status))
6980 return -EAGAIN;
6981 if (no_of_mac_addr < max_mac_addr)
6982 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
6983 no_of_mac_addr);
6984 return 0;
6985}
6986
6987/**
6988 * hdd_initialize_mac_address() - API to get wlan mac addresses
6989 * @hdd_ctx: HDD Context
6990 *
6991 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
6992 * is provisioned with mac addresses, driver uses it, else it will use
6993 * wlan_mac.bin to update HW MAC addresses.
6994 *
6995 * Return: None
6996 */
6997static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
6998{
6999 QDF_STATUS status;
7000 int ret;
7001
7002 ret = hdd_cnss_wlan_mac(hdd_ctx);
7003 if (ret == 0)
7004 return;
7005
7006 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
7007
7008 status = hdd_update_mac_config(hdd_ctx);
7009
7010 if (!QDF_IS_STATUS_SUCCESS(status))
7011 hdd_warn("can't update mac config, using MAC from ini file");
7012}
7013
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007014/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07007015 * hdd_tsf_init() - Initialize the TSF synchronization interface
7016 * @hdd_ctx: HDD global context
7017 *
7018 * When TSF synchronization via GPIO is supported by the driver and
7019 * has been enabled in the configuration file, this function plumbs
7020 * the GPIO value down to firmware via SME.
7021 *
7022 * Return: None
7023 */
7024#ifdef WLAN_FEATURE_TSF
7025static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7026{
7027 QDF_STATUS status;
7028
7029 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
7030 return;
7031
7032 status = sme_set_tsf_gpio(hdd_ctx->hHal,
7033 hdd_ctx->config->tsf_gpio_pin);
7034 if (!QDF_IS_STATUS_SUCCESS(status))
7035 hdd_err("Set tsf GPIO failed, status: %d", status);
7036}
7037#else
7038static void hdd_tsf_init(hdd_context_t *hdd_ctx)
7039{
7040}
7041#endif
7042
7043/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07007044 * hdd_pre_enable_configure() - Configurations prior to cds_enable
7045 * @hdd_ctx: HDD context
7046 *
7047 * Pre configurations to be done at lower layer before calling cds enable.
7048 *
7049 * Return: 0 on success and errno on failure.
7050 */
7051static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
7052{
7053 int ret;
7054 QDF_STATUS status;
7055 tSirRetStatus hal_status;
7056
7057 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
7058
7059 /*
7060 * Set 802.11p config
7061 * TODO-OCB: This has been temporarily added here to ensure this
7062 * parameter is set in CSR when we init the channel list. This should
7063 * be removed once the 5.9 GHz channels are added to the regulatory
7064 * domain.
7065 */
7066 hdd_set_dot11p_config(hdd_ctx);
7067
7068 /*
7069 * Note that the cds_pre_enable() sequence triggers the cfg download.
7070 * The cfg download must occur before we update the SME config
7071 * since the SME config operation must access the cfg database
7072 */
7073 status = hdd_set_sme_config(hdd_ctx);
7074
7075 if (QDF_STATUS_SUCCESS != status) {
7076 hdd_alert("Failed hdd_set_sme_config: %d", status);
7077 ret = qdf_status_to_os_return(status);
7078 goto out;
7079 }
7080
7081 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
7082 hdd_ctx->config->tx_chain_mask_1ss,
7083 PDEV_CMD);
7084 if (0 != ret) {
7085 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
7086 goto out;
7087 }
7088
7089 hdd_program_country_code(hdd_ctx);
7090
7091 status = hdd_set_sme_chan_list(hdd_ctx);
7092 if (status != QDF_STATUS_SUCCESS) {
7093 hdd_alert("Failed to init channel list: %d", status);
7094 ret = qdf_status_to_os_return(status);
7095 goto out;
7096 }
7097
7098 /* Apply the cfg.ini to cfg.dat */
7099 if (!hdd_update_config_dat(hdd_ctx)) {
7100 hdd_alert("config update failed");
7101 ret = -EINVAL;
7102 goto out;
7103 }
7104
Komal Seelam92fff912016-03-24 11:51:41 +05307105 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta07998752016-04-28 12:35:33 -07007106
7107 /*
7108 * Set the MAC Address Currently this is used by HAL to add self sta.
7109 * Remove this once self sta is added as part of session open.
7110 */
7111 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
7112 hdd_ctx->config->intfMacAddr[0].bytes,
7113 sizeof(hdd_ctx->config->intfMacAddr[0]));
7114
7115 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
7116 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
7117 hal_status, hal_status);
7118 ret = -EINVAL;
7119 goto out;
7120 }
7121
7122 hdd_init_channel_avoidance(hdd_ctx);
7123
7124out:
7125 return ret;
7126}
7127
7128/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007129 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
7130 * @context_ptr - hdd context pointer
7131 * @event_ptr - event structure pointer
7132 *
7133 * This is the p2p listen offload stop event handler, it sends vendor
7134 * event back to supplicant to notify the stop reason.
7135 *
7136 * Return: None
7137 */
7138static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
7139 void *event_ptr)
7140{
7141 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
7142 struct sir_p2p_lo_event *evt = event_ptr;
7143 struct sk_buff *vendor_event;
7144
7145 ENTER();
7146
7147 if (hdd_ctx == NULL) {
7148 hdd_err("Invalid HDD context pointer");
7149 return;
7150 }
7151
7152 vendor_event =
7153 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
7154 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
7155 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
7156 GFP_KERNEL);
7157
7158 if (!vendor_event) {
7159 hdd_err("cfg80211_vendor_event_alloc failed");
7160 return;
7161 }
7162
7163 if (nla_put_u32(vendor_event,
7164 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
7165 evt->reason_code)) {
7166 hdd_err("nla put failed");
7167 kfree_skb(vendor_event);
7168 return;
7169 }
7170
7171 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
7172}
7173
7174/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307175 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
7176 * @hdd_ctx: HDD context
7177 *
7178 * This function sends the adaptive dwell time config configuration to the
7179 * firmware via WMA
7180 *
7181 * Return: 0 - success, < 0 - failure
7182 */
7183static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
7184{
7185 QDF_STATUS status;
7186 struct adaptive_dwelltime_params dwelltime_params;
7187
7188 dwelltime_params.is_enabled =
7189 hdd_ctx->config->adaptive_dwell_mode_enabled;
7190 dwelltime_params.dwelltime_mode =
7191 hdd_ctx->config->global_adapt_dwelltime_mode;
7192 dwelltime_params.lpf_weight =
7193 hdd_ctx->config->adapt_dwell_lpf_weight;
7194 dwelltime_params.passive_mon_intval =
7195 hdd_ctx->config->adapt_dwell_passive_mon_intval;
7196 dwelltime_params.wifi_act_threshold =
7197 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
7198
7199 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
7200 &dwelltime_params);
7201
7202 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
7203 if (!QDF_IS_STATUS_SUCCESS(status)) {
7204 hdd_err("Failed to send Adaptive Dwelltime configuration!");
7205 return -EAGAIN;
7206 }
7207 return 0;
7208}
7209
Arun Khandavallid4349a92016-07-25 11:10:43 +05307210#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7211/**
7212 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
7213 * @hdd_ctx: HDD context
7214 *
7215 * Set auto shutdown callback to get indications from firmware to indicate
7216 * userspace to shutdown WLAN after a configured amount of inactivity.
7217 *
7218 * Return: 0 on success and errno on failure.
7219 */
7220static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7221{
7222 QDF_STATUS status;
7223
7224 if (!hdd_ctx->config->WlanAutoShutdown)
7225 return 0;
7226
7227 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7228 wlan_hdd_auto_shutdown_cb);
7229 if (status != QDF_STATUS_SUCCESS)
7230 hdd_err("Auto shutdown feature could not be enabled: %d",
7231 status);
7232
7233 return qdf_status_to_os_return(status);
7234}
7235#else
7236static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7237{
7238 return 0;
7239}
7240#endif
7241
7242/**
7243 * hdd_features_init() - Init features
7244 * @hdd_ctx: HDD context
7245 * @adapter: Primary adapter context
7246 *
7247 * Initialize features and their feature context after WLAN firmware is up.
7248 *
7249 * Return: 0 on success and errno on failure.
7250 */
7251static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7252{
7253 tSirTxPowerLimit hddtxlimit;
7254 QDF_STATUS status;
7255 int ret;
7256
7257 ENTER();
7258
7259 ret = hdd_update_country_code(hdd_ctx, adapter);
7260 if (ret) {
7261 hdd_err("Failed to update country code: %d", ret);
7262 goto out;
7263 }
7264
7265 /* FW capabilities received, Set the Dot11 mode */
7266 sme_setdef_dot11mode(hdd_ctx->hHal);
7267
Arun Khandavallid4349a92016-07-25 11:10:43 +05307268
7269 if (hdd_ctx->config->fIsImpsEnabled)
7270 hdd_set_idle_ps_config(hdd_ctx, true);
7271 else
7272 hdd_set_idle_ps_config(hdd_ctx, false);
7273
7274 if (hdd_lro_init(hdd_ctx))
7275 hdd_err("Unable to initialize LRO in fw");
7276
7277 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7278 hdd_err("Unable to send adaptive dwelltime setting to FW");
7279
7280 ret = hdd_init_thermal_info(hdd_ctx);
7281 if (ret) {
7282 hdd_err("Error while initializing thermal information");
7283 goto deregister_frames;
7284 }
7285
7286 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7287 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7288 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7289 if (!QDF_IS_STATUS_SUCCESS(status))
7290 hdd_err("Error setting txlimit in sme: %d", status);
7291
7292 hdd_tsf_init(hdd_ctx);
7293
7294 if (hdd_ctx->config->dual_mac_feature_disable) {
7295 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7296 if (status != QDF_STATUS_SUCCESS) {
7297 hdd_err("Failed to disable dual mac features");
7298 goto deregister_frames;
7299 }
7300 }
7301
7302 ret = hdd_register_cb(hdd_ctx);
7303 if (ret) {
7304 hdd_err("Failed to register HDD callbacks!");
7305 goto deregister_frames;
7306 }
7307
7308 if (hdd_ctx->config->dual_mac_feature_disable) {
7309 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7310 if (status != QDF_STATUS_SUCCESS) {
7311 hdd_err("Failed to disable dual mac features");
7312 goto deregister_cb;
7313 }
7314 }
7315
7316 /* register P2P Listen Offload event callback */
7317 if (wma_is_p2p_lo_capable())
7318 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7319 wlan_hdd_p2p_lo_event_callback);
7320
7321 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7322
7323 if (ret)
7324 goto deregister_cb;
7325
7326 EXIT();
7327 return 0;
7328
7329deregister_cb:
7330 hdd_deregister_cb(hdd_ctx);
7331deregister_frames:
7332 wlan_hdd_cfg80211_deregister_frames(adapter);
7333out:
7334 return -EINVAL;
7335
7336}
7337
7338
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307339/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307340 * hdd_configure_cds() - Configure cds modules
7341 * @hdd_ctx: HDD context
7342 * @adapter: Primary adapter context
7343 *
7344 * Enable Cds modules after WLAN firmware is up.
7345 *
7346 * Return: 0 on success and errno on failure.
7347 */
7348int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7349{
7350 int ret;
7351 QDF_STATUS status;
7352 /* structure of function pointers to be used by CDS */
7353 struct cds_sme_cbacks sme_cbacks;
7354
7355 ret = hdd_pre_enable_configure(hdd_ctx);
7356 if (ret) {
7357 hdd_err("Failed to pre-configure cds");
7358 goto out;
7359 }
7360
7361 /*
7362 * Start CDS which starts up the SME/MAC/HAL modules and everything
7363 * else
7364 */
7365 status = cds_enable(hdd_ctx->pcds_context);
7366
7367 if (!QDF_IS_STATUS_SUCCESS(status)) {
7368 hdd_alert("cds_enable failed");
7369 goto out;
7370 }
7371
7372 status = hdd_post_cds_enable_config(hdd_ctx);
7373 if (!QDF_IS_STATUS_SUCCESS(status)) {
7374 hdd_alert("hdd_post_cds_enable_config failed");
7375 goto out;
7376 }
7377
7378 ret = hdd_features_init(hdd_ctx, adapter);
7379 if (ret)
7380 goto out;
7381
7382 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7383 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7384 status = cds_init_policy_mgr(&sme_cbacks);
7385 if (!QDF_IS_STATUS_SUCCESS(status)) {
7386 hdd_err("Policy manager initialization failed");
7387 goto out;
7388 }
7389
7390 return 0;
7391out:
7392 return -EINVAL;
7393}
7394
7395/**
7396 * hdd_deconfigure_cds() -De-Configure cds
7397 * @hdd_ctx: HDD context
7398 *
7399 * Deconfigure Cds modules before WLAN firmware is down.
7400 *
7401 * Return: 0 on success and errno on failure.
7402 */
7403int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
7404{
7405 QDF_STATUS qdf_status;
7406
7407 ENTER();
7408 /* De-register the SME callbacks */
7409 hdd_deregister_cb(hdd_ctx);
7410
7411 /* De-init Policy Manager */
7412 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7413 hdd_err("Failed to deinit policy manager");
7414 /* Proceed and complete the clean up */
7415 return -EINVAL;
7416 }
7417
7418 qdf_status = cds_disable(hdd_ctx->pcds_context);
7419 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7420 hdd_err("Failed to Disable the CDS Modules! :%d",
7421 qdf_status);
7422 return -EINVAL;
7423 }
7424
7425 EXIT();
7426 return 0;
7427}
7428
7429
7430/**
7431 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7432 * @hdd_ctx: HDD context
7433 * @shutdown: flag to indicate from SSR or normal path
7434 *
7435 * This function maintains the driver state machine it will be invoked from
7436 * exit, shutdown and con_mode change handler. Depending on the driver state
7437 * shall perform the stopping/closing of the modules.
7438 *
7439 * Return: 0 for success; non-zero for failure
7440 */
7441int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
7442{
7443 void *hif_ctx;
7444 qdf_device_t qdf_ctx;
7445 QDF_STATUS qdf_status;
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307446 int ret = 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05307447 p_cds_sched_context cds_sched_context = NULL;
7448
7449 ENTER();
7450
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307451
Arun Khandavallifae92942016-08-01 13:31:08 +05307452 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7453 if (!qdf_ctx) {
7454 hdd_err("QDF device context NULL");
7455 return -EINVAL;
7456 }
7457
7458 cds_sched_context = get_cds_sched_ctxt();
7459 if (!cds_sched_context) {
7460 hdd_err("cds scheduler context NULL");
7461 return -EINVAL;
7462 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307463 mutex_lock(&hdd_ctx->iface_change_lock);
7464 hdd_ctx->stop_modules_in_progress = true;
Arun Khandavallifae92942016-08-01 13:31:08 +05307465
7466 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7467
7468 switch (hdd_ctx->driver_status) {
7469 case DRIVER_MODULES_UNINITIALIZED:
7470 hdd_info("Modules not initialized just return");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307471 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307472 case DRIVER_MODULES_CLOSED:
7473 hdd_info("Modules already closed");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307474 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307475 case DRIVER_MODULES_ENABLED:
7476 if (hdd_deconfigure_cds(hdd_ctx)) {
7477 hdd_alert("Failed to de-configure CDS");
7478 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307479 ret = -EINVAL;
7480 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307481 }
7482 hdd_info("successfully Disabled the CDS modules!");
7483 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7484 break;
7485 case DRIVER_MODULES_OPENED:
7486 hdd_info("Closing CDS modules!");
7487 break;
7488 default:
7489 hdd_err("Trying to stop wlan in a wrong state: %d",
7490 hdd_ctx->driver_status);
7491 QDF_ASSERT(0);
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307492 ret = -EINVAL;
7493 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307494 }
7495
7496 qdf_status = cds_close(hdd_ctx->pcds_context);
7497 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7498 hdd_warn("Failed to stop CDS:%d", qdf_status);
7499 QDF_ASSERT(0);
7500 }
7501 /* Clean up message queues of TX, RX and MC thread */
7502 cds_sched_flush_mc_mqs(cds_sched_context);
7503
7504 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
7505 if (!hif_ctx) {
7506 hdd_err("Hif context is Null");
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307507 ret = -EINVAL;
7508 goto done;
Arun Khandavallifae92942016-08-01 13:31:08 +05307509 }
7510
7511 hdd_hif_close(hif_ctx);
7512
7513 ol_cds_free();
7514
7515 if (!shutdown) {
7516 ret = pld_power_off(qdf_ctx->dev);
7517 if (ret)
7518 hdd_err("CNSS power down failed put device into Low power mode:%d",
7519 ret);
7520 }
7521 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
7522
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307523done:
7524 hdd_ctx->stop_modules_in_progress = false;
7525 mutex_unlock(&hdd_ctx->iface_change_lock);
Arun Khandavallifae92942016-08-01 13:31:08 +05307526 EXIT();
7527
Arun Khandavallia172c3e2016-08-26 17:33:13 +05307528 return ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307529
7530}
7531
7532/**
7533 * hdd_iface_change_callback() - Function invoked when stop modules expires
7534 * @priv: pointer to hdd context
7535 *
7536 * This function is invoked when the timer waiting for the interface change
7537 * expires, it shall cut-down the power to wlan and stop all the modules.
7538 *
7539 * Return: void
7540 */
7541static void hdd_iface_change_callback(void *priv)
7542{
7543 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
7544 int ret;
7545 int status = wlan_hdd_validate_context(hdd_ctx);
7546
7547 if (status)
7548 return;
7549
7550 ENTER();
7551 hdd_info("Interface change timer expired close the modules!");
Arun Khandavallifae92942016-08-01 13:31:08 +05307552 ret = hdd_wlan_stop_modules(hdd_ctx, false);
7553 if (ret)
7554 hdd_alert("Failed to stop modules");
Arun Khandavallifae92942016-08-01 13:31:08 +05307555 EXIT();
7556}
7557
7558/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007559 * hdd_wlan_startup() - HDD init function
7560 * @dev: Pointer to the underlying device
7561 *
7562 * This is the driver startup code executed once a WLAN device has been detected
7563 *
7564 * Return: 0 for success, < 0 for failure
7565 */
Arun Khandavallifae92942016-08-01 13:31:08 +05307566int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007567{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307568 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007569 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007570 hdd_context_t *hdd_ctx = NULL;
7571 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307572 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007573 bool rtnl_held;
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05307574 int set_value;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007575
7576 ENTER();
7577
Arun Khandavallifae92942016-08-01 13:31:08 +05307578 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007579
7580 if (IS_ERR(hdd_ctx))
7581 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007582
Arun Khandavallifae92942016-08-01 13:31:08 +05307583 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
7584 hdd_iface_change_callback, (void *)hdd_ctx);
7585
7586 mutex_init(&hdd_ctx->iface_change_lock);
7587
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007588 ret = hdd_init_netlink_services(hdd_ctx);
7589 if (ret)
7590 goto err_hdd_free_context;
7591
Arun Khandavallifae92942016-08-01 13:31:08 +05307592 hdd_wlan_green_ap_init(hdd_ctx);
7593
Arun Khandavallifae92942016-08-01 13:31:08 +05307594 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
7595 if (ret) {
7596 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007597 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007598 }
7599
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007600 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007601
Anurag Chouhan6d760662016-02-20 16:05:43 +05307602 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007603
7604 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007605 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05307606 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007607 }
7608
Prashanth Bhatta07998752016-04-28 12:35:33 -07007609 ret = hdd_wiphy_init(hdd_ctx);
7610 if (ret) {
7611 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05307612 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007613 }
7614
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05307615 if (hdd_ctx->config->enable_dp_trace)
7616 qdf_dp_trace_init();
7617
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307618 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007619 goto err_wiphy_unregister;
7620
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08007621
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007622 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007623
Arun Khandavallifae92942016-08-01 13:31:08 +05307624
7625 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007626
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007627 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007628 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007629 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05307630 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007631 }
7632
Arun Khandavallifae92942016-08-01 13:31:08 +05307633 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007634 /*
7635 * target hw version/revision would only be retrieved after firmware
7636 * donwload
7637 */
7638 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
7639 &hdd_ctx->target_hw_revision,
7640 &hdd_ctx->target_hw_name);
7641
7642 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05307643 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007644
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007645 hdd_release_rtnl_lock();
7646 rtnl_held = false;
7647
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007648#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05307649 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307650 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007651 hdd_skip_acs_scan_timer_handler,
7652 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307653 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07007654 hdd_err("Failed to init ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007655#endif
7656
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007657#ifdef MSM_PLATFORM
7658 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05307659 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307660 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007661 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
7662#endif
7663
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007664 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
7665 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
7666 hdd_ctx->target_hw_version,
7667 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007668
Nirav Shahbd36b062016-07-18 11:12:59 +05307669 if (hdd_ctx->rps)
7670 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07007671
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007672
7673 if (cds_is_packet_log_enabled())
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007674 hdd_pktlog_enable_disable(hdd_ctx, true, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007675
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007676 ret = hdd_register_notifiers(hdd_ctx);
7677 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05307678 goto err_debugfs_exit;
7679
7680 status = wlansap_global_init();
7681 if (QDF_IS_STATUS_ERROR(status))
7682 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007683
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007684 memdump_init();
7685
Arun Khandavallifae92942016-08-01 13:31:08 +05307686 if (hdd_ctx->config->fIsImpsEnabled)
7687 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307688
Manjeet Singhe7ecb7c2016-09-03 12:34:53 +05307689 if (hdd_ctx->config->sifs_burst_duration) {
7690 set_value = (SIFS_BURST_DUR_MULTIPLIER) *
7691 hdd_ctx->config->sifs_burst_duration;
7692
7693 if ((set_value > 0) && (set_value <= SIFS_BURST_DUR_MAX))
7694 wma_cli_set_command(0, (int)WMI_PDEV_PARAM_BURST_DUR,
7695 set_value, PDEV_CMD);
7696 }
7697
Arun Khandavallifae92942016-08-01 13:31:08 +05307698 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
7699 hdd_ctx->config->iface_change_wait_time * 5000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007700 goto success;
7701
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007702err_debugfs_exit:
7703 hdd_debugfs_exit(adapter);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007704 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007705
Arun Khandavallid4349a92016-07-25 11:10:43 +05307706 if (rtnl_held)
7707 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007708
Yun Park6a46ad82016-01-04 16:48:19 -08007709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007710err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007711 wiphy_unregister(hdd_ctx->wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05307712 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007713
Arun Khandavallifae92942016-08-01 13:31:08 +05307714err_ipa_cleanup:
7715 hdd_ipa_cleanup(hdd_ctx);
7716
7717err_stop_modules:
7718 hdd_wlan_stop_modules(hdd_ctx, false);
7719
7720
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007721 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307722 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007723 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307724 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007725 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007726
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007727err_exit_nl_srv:
7728 hdd_exit_netlink_services(hdd_ctx);
7729
7730 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7731 hdd_err("Failed to deinit policy manager");
7732 /* Proceed and complete the clean up */
7733 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307734 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007735err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05307736 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
7737 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007738 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307739 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007741 return -EIO;
7742
7743success:
7744 EXIT();
7745 return 0;
7746}
7747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007748/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307749 * hdd_wlan_update_target_info() - update target type info
7750 * @hdd_ctx: HDD context
7751 * @context: hif context
7752 *
7753 * Update target info received from firmware in hdd context
7754 * Return:None
7755 */
7756
7757void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
7758{
7759 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
7760
7761 if (!tgt_info) {
7762 hdd_err("Target info is Null");
7763 return;
7764 }
7765
7766 hdd_ctx->target_type = tgt_info->target_type;
7767}
7768
7769/**
7770 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307771 * @hdd_ctx: HDD context
7772 *
7773 * Register the HDD callbacks to CDS/SME.
7774 *
7775 * Return: 0 for success or Error code for failure
7776 */
7777int hdd_register_cb(hdd_context_t *hdd_ctx)
7778{
7779 QDF_STATUS status;
7780 int ret = 0;
7781
7782 ENTER();
7783
7784 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
7785
7786 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
7787 hdd_send_oem_data_rsp_msg);
7788
7789 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
7790 wlan_hdd_cfg80211_fw_mem_dump_cb);
7791 if (!QDF_IS_STATUS_SUCCESS(status)) {
7792 hdd_err("Failed to register memdump callback");
7793 ret = -EINVAL;
7794 return ret;
7795 }
Deepthi Gowrid5a58fe2016-09-03 16:01:28 +05307796 sme_register_mgmt_frame_ind_callback(hdd_ctx->hHal,
7797 hdd_indicate_mgmt_frame);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307798 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
7799 sme_nan_register_callback(hdd_ctx->hHal,
7800 wlan_hdd_cfg80211_nan_callback);
7801 sme_stats_ext_register_callback(hdd_ctx->hHal,
7802 wlan_hdd_cfg80211_stats_ext_callback);
7803
7804 sme_ext_scan_register_callback(hdd_ctx->hHal,
7805 wlan_hdd_cfg80211_extscan_callback);
7806
7807 status = cds_register_sap_restart_channel_switch_cb(
7808 (void *)hdd_sap_restart_with_channel_switch);
7809 if (!QDF_IS_STATUS_SUCCESS(status)) {
7810 hdd_err("restart cb registration failed");
7811 ret = -EINVAL;
7812 return ret;
7813 }
7814
7815 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
7816 hdd_rssi_threshold_breached);
7817
7818 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
7819 hdd_get_bpf_offload_cb);
7820 if (!QDF_IS_STATUS_SUCCESS(status)) {
7821 hdd_err("set bpf offload callback failed");
7822 ret = -EINVAL;
7823 return ret;
7824 }
7825
7826 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
7827 wlan_hdd_cfg80211_link_layer_stats_callback);
7828
7829 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
7830
7831 EXIT();
7832
7833 return ret;
7834}
7835
7836/**
7837 * hdd_deregister_cb() - De-Register HDD callbacks.
7838 * @hdd_ctx: HDD context
7839 *
7840 * De-Register the HDD callbacks to CDS/SME.
7841 *
7842 * Return: void
7843 */
7844void hdd_deregister_cb(hdd_context_t *hdd_ctx)
7845{
7846 QDF_STATUS status;
7847
7848 ENTER();
7849
7850 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
7851 if (!QDF_IS_STATUS_SUCCESS(status))
7852 hdd_err("De-register of dcc stats callback failed: %d",
7853 status);
7854
7855 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
7856 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
7857 if (!QDF_IS_STATUS_SUCCESS(status))
7858 hdd_err("De-register bpf offload callback failed: %d",
7859 status);
7860 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
7861
7862 status = cds_deregister_sap_restart_channel_switch_cb();
7863 if (!QDF_IS_STATUS_SUCCESS(status))
7864 hdd_err("De-register restart cb registration failed: %d",
7865 status);
7866
7867 sme_stats_ext_register_callback(hdd_ctx->hHal,
7868 wlan_hdd_cfg80211_stats_ext_callback);
7869
7870 sme_nan_deregister_callback(hdd_ctx->hHal);
7871 status = sme_reset_tsfcb(hdd_ctx->hHal);
7872 if (!QDF_IS_STATUS_SUCCESS(status))
7873 hdd_err("Failed to de-register tsfcb the callback:%d",
7874 status);
7875 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
7876 if (!QDF_IS_STATUS_SUCCESS(status))
7877 hdd_err("Failed to de-register the fw mem dump callback: %d",
7878 status);
7879
7880 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
7881 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
7882
7883 EXIT();
7884}
7885
7886/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007887 * hdd_softap_sta_deauth() - handle deauth req from HDD
7888 * @adapter: Pointer to the HDD
7889 * @enable: bool value
7890 *
7891 * This to take counter measure to handle deauth req from HDD
7892 *
7893 * Return: None
7894 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307895QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007896 struct tagCsrDelStaParams *pDelStaParams)
7897{
7898#ifndef WLAN_FEATURE_MBSSID
7899 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7900#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307901 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007902
7903 ENTER();
7904
Jeff Johnson34c88b72016-08-15 14:27:11 -07007905 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007906 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7907
7908 /* Ignore request to deauth bcmc station */
7909 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307910 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007911
7912#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307913 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007914 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7915 pDelStaParams);
7916#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307917 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007918#endif
7919
7920 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307921 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007922}
7923
7924/**
7925 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
7926 * @adapter: Pointer to the HDD
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05307927 * @p_del_sta_params: pointer to station deletion parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007928 *
7929 * This to take counter measure to handle deauth req from HDD
7930 *
7931 * Return: None
7932 */
7933void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05307934 struct tagCsrDelStaParams *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007935{
7936#ifndef WLAN_FEATURE_MBSSID
7937 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7938#endif
7939
7940 ENTER();
7941
Jeff Johnson34c88b72016-08-15 14:27:11 -07007942 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007943 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7944
7945 /* Ignore request to disassoc bcmc station */
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05307946 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007947 return;
7948
7949#ifdef WLAN_FEATURE_MBSSID
7950 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05307951 pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007952#else
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +05307953 wlansap_disassoc_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007954#endif
7955}
7956
7957void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
7958 bool enable)
7959{
7960#ifndef WLAN_FEATURE_MBSSID
7961 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7962#endif
7963
7964 ENTER();
7965
Jeff Johnson34c88b72016-08-15 14:27:11 -07007966 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007967 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7968
7969#ifdef WLAN_FEATURE_MBSSID
7970 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7971 (bool) enable);
7972#else
7973 wlansap_set_counter_measure(p_cds_context, (bool) enable);
7974#endif
7975}
7976
7977/**
7978 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
7979 * @hdd_ctx: HDD Context
7980 *
7981 * API to find if there is any STA or P2P-Client is connected
7982 *
7983 * Return: true if connected; false otherwise
7984 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307985QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007986{
7987 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
7988}
7989
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007990/**
7991 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
7992 * @adapter: HDD adapter pointer
7993 *
7994 * This function loop through each adapter and disable roaming on each STA
7995 * device mode except the input adapter.
7996 *
7997 * Note: On the input adapter roaming is not enabled yet hence no need to
7998 * disable.
7999 *
8000 * Return: None
8001 */
8002void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
8003{
8004 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8005 hdd_adapter_t *adapterIdx = NULL;
8006 hdd_adapter_list_node_t *adapterNode = NULL;
8007 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308008 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008009
8010 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8011 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008012 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008013 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008014 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008015 adapter->sessionId);
8016 /*
8017 * Loop through adapter and disable roaming for each STA device
8018 * mode except the input adapter.
8019 */
8020 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8021
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308022 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008023 adapterIdx = adapterNode->pAdapter;
8024
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008025 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008026 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008027 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008028 adapterIdx->sessionId);
8029 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
8030 (adapterIdx),
8031 adapterIdx->sessionId, 0);
8032 }
8033
8034 status = hdd_get_next_adapter(hdd_ctx,
8035 adapterNode,
8036 &pNext);
8037 adapterNode = pNext;
8038 }
8039 }
8040}
8041
8042/**
8043 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
8044 * @adapter: HDD adapter pointer
8045 *
8046 * This function loop through each adapter and enable roaming on each STA
8047 * device mode except the input adapter.
8048 * Note: On the input adapter no need to enable roaming because link got
8049 * disconnected on this.
8050 *
8051 * Return: None
8052 */
8053void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
8054{
8055 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8056 hdd_adapter_t *adapterIdx = NULL;
8057 hdd_adapter_list_node_t *adapterNode = NULL;
8058 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308059 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008060
8061 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
8062 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008063 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008064 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008065 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008066 adapter->sessionId);
8067 /*
8068 * Loop through adapter and enable roaming for each STA device
8069 * mode except the input adapter.
8070 */
8071 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8072
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308073 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008074 adapterIdx = adapterNode->pAdapter;
8075
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008076 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008077 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008078 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008079 adapterIdx->sessionId);
8080 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
8081 (adapterIdx),
8082 adapterIdx->sessionId,
8083 REASON_CONNECT);
8084 }
8085
8086 status = hdd_get_next_adapter(hdd_ctx,
8087 adapterNode,
8088 &pNext);
8089 adapterNode = pNext;
8090 }
8091 }
8092}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008093
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308094void wlan_hdd_send_svc_nlink_msg(int radio, int type, void *data, int len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008095{
8096 struct sk_buff *skb;
8097 struct nlmsghdr *nlh;
8098 tAniMsgHdr *ani_hdr;
8099 void *nl_data = NULL;
8100 int flags = GFP_KERNEL;
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308101 struct radio_index_tlv *radio_info;
8102 int tlv_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008103
8104 if (in_interrupt() || irqs_disabled() || in_atomic())
8105 flags = GFP_ATOMIC;
8106
8107 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
8108
8109 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07008110 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008111 return;
8112 }
8113
8114 nlh = (struct nlmsghdr *)skb->data;
8115 nlh->nlmsg_pid = 0; /* from kernel */
8116 nlh->nlmsg_flags = 0;
8117 nlh->nlmsg_seq = 0;
8118 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8119
8120 ani_hdr = NLMSG_DATA(nlh);
8121 ani_hdr->type = type;
8122
8123 switch (type) {
8124 case WLAN_SVC_FW_CRASHED_IND:
8125 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008126 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008127 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008128 ani_hdr->length = 0;
8129 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8130 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8131 break;
8132 case WLAN_SVC_WLAN_STATUS_IND:
8133 case WLAN_SVC_WLAN_VERSION_IND:
8134 case WLAN_SVC_DFS_CAC_START_IND:
8135 case WLAN_SVC_DFS_CAC_END_IND:
8136 case WLAN_SVC_DFS_RADAR_DETECT_IND:
8137 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
8138 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08008139 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05308140 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008141 ani_hdr->length = len;
8142 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
8143 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
8144 memcpy(nl_data, data, len);
8145 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
8146 break;
8147
8148 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07008149 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008150 type);
8151 kfree_skb(skb);
8152 return;
8153 }
8154
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308155 /*
8156 * Add radio index at the end of the svc event in TLV format to maintain
8157 * the backward compatibility with userspace applications.
8158 */
8159
8160 tlv_len = 0;
8161
8162 if ((sizeof(*ani_hdr) + len + sizeof(struct radio_index_tlv))
8163 < WLAN_NL_MAX_PAYLOAD) {
8164 radio_info = (struct radio_index_tlv *)((char *) ani_hdr +
8165 sizeof(*ani_hdr) + len);
8166 radio_info->type = (unsigned short) WLAN_SVC_WLAN_RADIO_INDEX;
8167 radio_info->length = (unsigned short) sizeof(radio_info->radio);
8168 radio_info->radio = radio;
8169 tlv_len = sizeof(*radio_info);
8170 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
8171 "Added radio index tlv - radio index %d",
8172 radio_info->radio);
8173 }
8174
8175 nlh->nlmsg_len += tlv_len;
8176 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len + tlv_len));
8177
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008178 nl_srv_bcast(skb);
8179
8180 return;
8181}
8182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008183#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
8184void wlan_hdd_auto_shutdown_cb(void)
8185{
Mahesh Kumar Kalikot Veetild214d552016-09-14 15:15:49 -07008186 hdd_context_t *hdd_ctx = cds_get_global_context();
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308187
8188 if (!hdd_ctx)
8189 return;
8190
Jeff Johnson28f8a772016-08-15 15:30:36 -07008191 hdd_err("Wlan Idle. Sending Shutdown event..");
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308192 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
8193 WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008194}
8195
8196void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
8197{
8198 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308199 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008200 hdd_adapter_t *adapter;
8201 bool ap_connected = false, sta_connected = false;
8202 tHalHandle hal_handle;
8203
8204 hal_handle = hdd_ctx->hHal;
8205 if (hal_handle == NULL)
8206 return;
8207
8208 if (hdd_ctx->config->WlanAutoShutdown == 0)
8209 return;
8210
8211 if (enable == false) {
8212 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308213 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008214 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008215 }
Kondabattini, Ganesh96ac37b2016-09-02 23:12:15 +05308216 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07008217 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008218 return;
8219 }
8220
8221 /* To enable shutdown timer check conncurrency */
8222 if (cds_concurrent_open_sessions_running()) {
8223 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8224
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308225 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008226 adapter = adapterNode->pAdapter;
8227 if (adapter
8228 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008229 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008230 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8231 conn_info.connState ==
8232 eConnectionState_Associated) {
8233 sta_connected = true;
8234 break;
8235 }
8236 }
8237 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008238 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008239 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
8240 bApActive == true) {
8241 ap_connected = true;
8242 break;
8243 }
8244 }
8245 status = hdd_get_next_adapter(hdd_ctx,
8246 adapterNode,
8247 &pNext);
8248 adapterNode = pNext;
8249 }
8250 }
8251
8252 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008253 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008254 return;
8255 } else {
8256 if (sme_set_auto_shutdown_timer(hal_handle,
8257 hdd_ctx->config->
8258 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308259 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07008260 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008261 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008262 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008263 hdd_ctx->config->WlanAutoShutdown);
8264
8265 }
8266}
8267#endif
8268
8269hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8270 bool check_start_bss)
8271{
8272 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8273 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308274 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008275 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8276
8277 con_sap_adapter = NULL;
8278
8279 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308280 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008281 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008282 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8283 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008284 adapter != this_sap_adapter) {
8285 if (check_start_bss) {
8286 if (test_bit(SOFTAP_BSS_STARTED,
8287 &adapter->event_flags)) {
8288 con_sap_adapter = adapter;
8289 break;
8290 }
8291 } else {
8292 con_sap_adapter = adapter;
8293 break;
8294 }
8295 }
8296 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8297 adapterNode = pNext;
8298 }
8299
8300 return con_sap_adapter;
8301}
8302
8303#ifdef MSM_PLATFORM
8304void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8305{
8306 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8307
Anurag Chouhan210db072016-02-22 18:42:15 +05308308 if (QDF_TIMER_STATE_RUNNING ==
8309 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008310 return;
8311
Anurag Chouhan210db072016-02-22 18:42:15 +05308312 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008313 hdd_ctx->config->busBandwidthComputeInterval);
8314}
8315
8316void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8317{
8318 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308319 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008320 bool can_stop = true;
8321 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8322
Anurag Chouhan210db072016-02-22 18:42:15 +05308323 if (QDF_TIMER_STATE_RUNNING !=
8324 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008325 /* trying to stop timer, when not running is not good */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008326 hdd_err("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008327 return;
8328 }
8329
8330 if (cds_concurrent_open_sessions_running()) {
8331 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8332
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308333 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008334 adapter = adapterNode->pAdapter;
8335 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008336 && (adapter->device_mode == QDF_STA_MODE
8337 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008338 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8339 conn_info.connState ==
8340 eConnectionState_Associated) {
8341 can_stop = false;
8342 break;
8343 }
8344 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008345 && (adapter->device_mode == QDF_SAP_MODE
8346 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008347 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8348 true) {
8349 can_stop = false;
8350 break;
8351 }
8352 status = hdd_get_next_adapter(hdd_ctx,
8353 adapterNode,
8354 &pNext);
8355 adapterNode = pNext;
8356 }
8357 }
8358
8359 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05308360 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008361}
8362#endif
8363
8364/**
8365 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8366 * and sta's operating channel.
8367 * @sta_adapter: Describe the first argument to foobar.
8368 * @ap_adapter: Describe the second argument to foobar.
8369 * @roam_profile: Roam profile of AP to which STA wants to connect.
8370 * @concurrent_chnl_same: If both SAP and STA channels are same then
8371 * set this flag to true else false.
8372 *
8373 * This function checks the sap's operating channel and sta's operating channel.
8374 * if both are same then it will return false else it will restart the sap in
8375 * sta's channel and return true.
8376 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308377 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008378 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308379QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008380 hdd_adapter_t *ap_adapter,
8381 tCsrRoamProfile *roam_profile,
8382 tScanResultHandle *scan_cache,
8383 bool *concurrent_chnl_same)
8384{
8385 hdd_ap_ctx_t *hdd_ap_ctx;
8386 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308387 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008388 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008389 *concurrent_chnl_same = true;
8390
8391 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8392 status =
8393 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8394 roam_profile,
8395 scan_cache,
8396 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308397 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008398 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008399 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8400 if (hdd_ap_ctx->operatingChannel != channel_id) {
8401 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008402 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008403 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008404 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008405 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8406 if (hdd_ap_ctx->operatingChannel != channel_id) {
8407 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008408 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008409 }
8410 }
8411 } else {
8412 /*
8413 * Lets handle worst case scenario here, Scan cache lookup is
8414 * failed so we have to stop the SAP to avoid any channel
8415 * discrepancy between SAP's channel and STA's channel.
8416 * Return the status as failure so caller function could know
8417 * that scan look up is failed.
8418 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008419 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308420 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008421 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308422 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008423}
8424
8425#ifdef WLAN_FEATURE_MBSSID
8426/**
8427 * wlan_hdd_stop_sap() - This function stops bss of SAP.
8428 * @ap_adapter: SAP adapter
8429 *
8430 * This function will process the stopping of sap adapter.
8431 *
8432 * Return: None
8433 */
8434void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
8435{
8436 hdd_ap_ctx_t *hdd_ap_ctx;
8437 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308438 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008439 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008440
8441 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008442 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008443 return;
8444 }
8445
8446 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8447 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308448 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008449 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008451 mutex_lock(&hdd_ctx->sap_lock);
8452 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08008453 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008454 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
8455 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008456 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308457 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308458 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008459 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05308460 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308461 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008462 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308463 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008464 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008465 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008466 return;
8467 }
8468 }
8469 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008470 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008471 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008472 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008473 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008474 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008475 }
8476 mutex_unlock(&hdd_ctx->sap_lock);
8477 return;
8478}
8479
8480/**
8481 * wlan_hdd_start_sap() - this function starts bss of SAP.
8482 * @ap_adapter: SAP adapter
8483 *
8484 * This function will process the starting of sap adapter.
8485 *
8486 * Return: None
8487 */
8488void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
8489{
8490 hdd_ap_ctx_t *hdd_ap_ctx;
8491 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308492 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008493 hdd_context_t *hdd_ctx;
8494 tsap_Config_t *sap_config;
8495
8496 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008497 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008498 return;
8499 }
8500
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008501 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07008502 hdd_err("SoftAp role has not been enabled");
8503 return;
8504 }
8505
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008506 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
8507 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8508 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8509 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
8510
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308511 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008512 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308513
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008514 mutex_lock(&hdd_ctx->sap_lock);
8515 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
8516 goto end;
8517
8518 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008519 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008520 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
8521 goto end;
8522 }
8523
8524 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
8525 &hdd_ap_ctx->sapConfig,
8526 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308527 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008528 goto end;
8529
Jeff Johnson28f8a772016-08-15 15:30:36 -07008530 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308531 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008532 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308533 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008534 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008535 goto end;
8536 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07008537 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008538 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008539 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008540 ap_adapter->sessionId);
8541 hostapd_state->bCommit = true;
8542
8543end:
8544 mutex_unlock(&hdd_ctx->sap_lock);
8545 return;
8546}
8547#endif
8548
8549/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08008550 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
8551 * mac scan config
8552 * @status: Status of set antenna mode
8553 *
8554 * Callback on setting the dual mac configuration
8555 *
8556 * Return: None
8557 */
8558void wlan_hdd_soc_set_antenna_mode_cb(
8559 enum set_antenna_mode_status status)
8560{
8561 hdd_context_t *hdd_ctx;
8562
8563 hdd_info("Status: %d", status);
8564
8565 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8566 if (0 != wlan_hdd_validate_context(hdd_ctx))
8567 return;
8568
8569 /* Signal the completion of set dual mac config */
8570 complete(&hdd_ctx->set_antenna_mode_cmpl);
8571}
8572
8573/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008574 * hdd_get_fw_version() - Get FW version
8575 * @hdd_ctx: pointer to HDD context.
8576 * @major_spid: FW version - major spid.
8577 * @minor_spid: FW version - minor spid
8578 * @ssid: FW version - ssid
8579 * @crmid: FW version - crmid
8580 *
8581 * This function is called to get the firmware build version stored
8582 * as part of the HDD context
8583 *
8584 * Return: None
8585 */
8586void hdd_get_fw_version(hdd_context_t *hdd_ctx,
8587 uint32_t *major_spid, uint32_t *minor_spid,
8588 uint32_t *siid, uint32_t *crmid)
8589{
8590 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
8591 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
8592 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
8593 *crmid = hdd_ctx->target_fw_version & 0x7fff;
8594}
8595
8596#ifdef QCA_CONFIG_SMP
8597/**
8598 * wlan_hdd_get_cpu() - get cpu_index
8599 *
8600 * Return: cpu_index
8601 */
8602int wlan_hdd_get_cpu(void)
8603{
8604 int cpu_index = get_cpu();
8605 put_cpu();
8606 return cpu_index;
8607}
8608#endif
8609
8610/**
8611 * hdd_get_fwpath() - get framework path
8612 *
8613 * This function is used to get the string written by
8614 * userspace to start the wlan driver
8615 *
8616 * Return: string
8617 */
8618const char *hdd_get_fwpath(void)
8619{
8620 return fwpath.string;
8621}
8622
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008623/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008624 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008625 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008626 * This function initilizes CDS global context with the help of cds_init. This
8627 * has to be the first function called after probe to get a valid global
8628 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008629 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008630 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008631 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008632int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008633{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008634 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008635 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008636
8637#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8638 wlan_logging_sock_init_svc();
8639#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008640 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008641
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008642 if (p_cds_context == NULL) {
8643 hdd_alert("Failed to allocate CDS context");
8644 ret = -ENOMEM;
8645 goto err_out;
8646 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008647
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008648 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008649
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008650err_out:
8651 return ret;
8652}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008653
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008654/**
8655 * hdd_deinit() - Deinitialize Driver
8656 *
8657 * This function frees CDS global context with the help of cds_deinit. This
8658 * has to be the last function call in remove callback to free the global
8659 * context.
8660 */
8661void hdd_deinit(void)
8662{
8663 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008664
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008665#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8666 wlan_logging_sock_deinit_svc();
8667#endif
8668}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008669
8670#ifdef QCA_WIFI_3_0_ADRASTEA
8671#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
8672#else
8673#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
8674#endif
8675
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008676/**
8677 * __hdd_module_init - Module init helper
8678 *
8679 * Module init helper function used by both module and static driver.
8680 *
8681 * Return: 0 for success, errno on failure
8682 */
8683static int __hdd_module_init(void)
8684{
8685 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008686
Arun Khandavallifae92942016-08-01 13:31:08 +05308687 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008688 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008689
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008690 pld_init();
8691
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308692 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008693
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008694 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008695
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008696 ret = wlan_hdd_register_driver();
8697 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07008698 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
8699 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008700 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008701 }
8702
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308703 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008704
8705 return 0;
8706out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308707 qdf_wake_lock_destroy(&wlan_wake_lock);
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008708 pld_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008709 return ret;
8710}
8711
8712/**
8713 * __hdd_module_exit - Module exit helper
8714 *
8715 * Module exit helper function used by both module and static driver.
8716 */
8717static void __hdd_module_exit(void)
8718{
8719 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
8720 QWLAN_VERSIONSTR);
8721
8722 wlan_hdd_unregister_driver();
8723
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308724 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008725
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008726 pld_deinit();
8727
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008728 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008729}
8730
Arun Khandavallifae92942016-08-01 13:31:08 +05308731#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008732/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308733 * wlan_boot_cb() - Wlan boot callback
8734 * @kobj: object whose directory we're creating the link in.
8735 * @attr: attribute the user is interacting with
8736 * @buff: the buffer containing the user data
8737 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008738 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308739 * This callback is invoked when the fs is ready to start the
8740 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008741 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308742 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008743 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308744static ssize_t wlan_boot_cb(struct kobject *kobj,
8745 struct kobj_attribute *attr,
8746 const char *buf,
8747 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008748{
Arun Khandavallifae92942016-08-01 13:31:08 +05308749
8750 int ret = 0;
8751
8752 if (wlan_loader->loaded_state) {
8753 pr_info("Wlan driver already initialized");
8754 return 0;
8755 }
8756
8757
8758 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8759 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8760
8761 if (__hdd_module_init()) {
8762 pr_err("%s: Failed to register handler\n", __func__);
8763 ret = -EINVAL;
8764 } else
8765 wlan_loader->loaded_state = MODULE_INITIALIZED;
8766
8767 return count;
8768
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008769}
Arun Khandavallifae92942016-08-01 13:31:08 +05308770
8771/**
8772 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
8773 * ready
8774 *
8775 * This is creates the syfs entry boot_wlan. Which shall be invoked
8776 * when the filesystem is ready.
8777 *
8778 * Return: None
8779 */
8780static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008781{
Arun Khandavallifae92942016-08-01 13:31:08 +05308782 int ret = -EINVAL;
8783
8784 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
8785 if (!wlan_loader) {
8786 pr_err("%s: memory alloc failed\n", __func__);
8787 ret = -ENOMEM;
8788 return ret;
8789 }
8790
8791 wlan_loader->boot_wlan_obj = NULL;
8792 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
8793 GFP_KERNEL);
8794 if (!wlan_loader->attr_group) {
8795 pr_err("%s: malloc attr_group failed\n", __func__);
8796 ret = -ENOMEM;
8797 goto error_return;
8798 }
8799
8800 wlan_loader->loaded_state = 0;
8801 wlan_loader->attr_group->attrs = attrs;
8802
8803 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
8804 kernel_kobj);
8805 if (!wlan_loader->boot_wlan_obj) {
8806 pr_err("%s: sysfs create and add failed\n", __func__);
8807 ret = -ENOMEM;
8808 goto error_return;
8809 }
8810
8811 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
8812 wlan_loader->attr_group);
8813 if (ret) {
8814 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
8815 goto error_return;
8816 }
8817
8818 return 0;
8819
8820error_return:
8821
8822 if (wlan_loader->boot_wlan_obj) {
8823 kobject_del(wlan_loader->boot_wlan_obj);
8824 wlan_loader->boot_wlan_obj = NULL;
8825 }
8826
8827 return ret;
8828}
8829
8830/**
8831 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
8832 *
8833 * Return: 0 on success or errno on failure
8834 */
8835static int wlan_deinit_sysfs(void)
8836{
8837
8838 if (!wlan_loader) {
8839 hdd_alert("wlan loader context is Null!");
8840 return -EINVAL;
8841 }
8842
8843 if (wlan_loader->boot_wlan_obj) {
8844 sysfs_remove_group(wlan_loader->boot_wlan_obj,
8845 wlan_loader->attr_group);
8846 kobject_del(wlan_loader->boot_wlan_obj);
8847 wlan_loader->boot_wlan_obj = NULL;
8848 }
8849
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008850 return 0;
8851}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008852
Arun Khandavallifae92942016-08-01 13:31:08 +05308853#endif
8854
8855#ifdef MODULE
8856/**
8857 * __hdd_module_init - Module init helper
8858 *
8859 * Module init helper function used by both module and static driver.
8860 *
8861 * Return: 0 for success, errno on failure
8862 */
8863static int hdd_module_init(void)
8864{
8865 int ret = 0;
8866
8867 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8868 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8869
8870 if (__hdd_module_init()) {
8871 pr_err("%s: Failed to register handler\n", __func__);
8872 ret = -EINVAL;
8873 }
8874
8875 return ret;
8876}
8877#else
8878static int __init hdd_module_init(void)
8879{
8880 int ret = -EINVAL;
8881
8882 ret = wlan_init_sysfs();
8883 if (!ret)
8884 pr_err("Failed to create sysfs entry for loading wlan");
8885
8886 return ret;
8887}
8888#endif
8889
8890
8891#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008892/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008893 * hdd_module_exit() - Exit function
8894 *
8895 * This is the driver exit point (invoked when module is unloaded using rmmod)
8896 *
8897 * Return: None
8898 */
8899static void __exit hdd_module_exit(void)
8900{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008901 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008902}
Arun Khandavallifae92942016-08-01 13:31:08 +05308903#else
8904static void __exit hdd_module_exit(void)
8905{
8906 __hdd_module_exit();
8907 wlan_deinit_sysfs();
8908}
8909#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008910
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008911static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
8912{
8913 return param_set_copystring(kmessage, kp);
8914}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008915
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008916
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008917/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08008918 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008919 *
8920 * Handler function for module param con_mode when it is changed by userspace
8921 * Dynamically linked - do nothing
8922 * Statically linked - exit and init driver, as in rmmod and insmod
8923 *
8924 * Return -
8925 */
8926static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
8927{
8928 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308929 hdd_context_t *hdd_ctx;
8930 hdd_adapter_t *adapter;
8931 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8932 QDF_STATUS status;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008933
Arun Khandavallifae92942016-08-01 13:31:08 +05308934 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008935 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05308936
8937 if (!qdf_dev) {
8938 hdd_err("qdf device context is Null return!");
8939 return -EINVAL;
8940 }
8941
8942 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8943 if (!hdd_ctx) {
8944 hdd_err("Hdd context Null return!");
8945 return -EINVAL;
8946 }
Arun Khandavallia172c3e2016-08-26 17:33:13 +05308947
Arun Khandavallifae92942016-08-01 13:31:08 +05308948 ret = hdd_wlan_stop_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +05308949 if (ret) {
8950 hdd_err("Stop wlan modules failed");
8951 return -EINVAL;
8952 }
8953
8954 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
8955 if (!adapter) {
8956 hdd_err("Failed to get station adapter");
8957 return -EINVAL;
8958 }
8959
8960 if (con_mode == QDF_GLOBAL_FTM_MODE) {
8961 adapter->device_mode = QDF_FTM_MODE;
8962 hdd_set_conparam(QDF_GLOBAL_FTM_MODE);
8963 } else if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
8964 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
8965 adapter->device_mode = QDF_MONITOR_MODE;
8966 hdd_set_conparam(QDF_GLOBAL_MONITOR_MODE);
8967 hdd_set_station_ops(adapter->dev);
8968 } else if (con_mode == QDF_GLOBAL_EPPING_MODE) {
8969 hdd_set_conparam(QDF_GLOBAL_EPPING_MODE);
8970 status = epping_open();
8971 if (status != QDF_STATUS_SUCCESS) {
8972 hdd_err("Failed to open in eeping mode: %d", status);
8973 return -EINVAL;
8974 }
8975 ret = epping_enable(qdf_dev->dev);
8976 if (ret) {
8977 hdd_err("Failed to enable in epping mode : %d", ret);
8978 epping_close();
8979 return -EINVAL;
8980 }
8981 hdd_info("epping mode successfully enabled");
8982 return 0;
8983 } else {
8984 hdd_info("Con mode not supported");
8985 return -EINVAL;
8986 }
8987
8988 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
8989 if (ret) {
8990 hdd_err("Start wlan modules failed: %d", ret);
8991 return -EINVAL;
8992 }
8993
8994 if (hdd_start_adapter(adapter)) {
8995 hdd_err("Failed to start %s adapter", kmessage);
8996 return -EINVAL;
8997 } else {
8998 hdd_info("Mode successfully changed to %s", kmessage);
8999 ret = 0;
9000 }
9001
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009002 return ret;
9003}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009004
9005/**
9006 * hdd_get_conparam() - driver exit point
9007 *
9008 * This is the driver exit point (invoked when module is unloaded using rmmod)
9009 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05309010 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009011 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309012enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009013{
Anurag Chouhan6d760662016-02-20 16:05:43 +05309014 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009015}
9016
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009017void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009018{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08009019 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08009020}
9021
Komal Seelamc11bb222016-01-27 18:57:10 +05309022#ifdef WLAN_FEATURE_LPSS
9023static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
9024{
9025 return hdd_ctx->config->enable_lpass_support;
9026}
9027#else
9028static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
9029{
9030 return false;
9031}
9032#endif
9033
9034/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309035 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
9036 * @hdd_ctx: HDD context
9037 *
9038 * Cleans up the pre cac interface, if it exists
9039 *
9040 * Return: None
9041 */
9042void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
9043{
9044 uint8_t session_id;
9045 QDF_STATUS status;
9046 struct hdd_adapter_s *precac_adapter;
9047
9048 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
9049 if (QDF_IS_STATUS_ERROR(status)) {
9050 hdd_err("failed to get pre cac vdev id");
9051 return;
9052 }
9053
9054 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
9055 if (!precac_adapter) {
9056 hdd_err("invalid pre cac adapater");
9057 return;
9058 }
9059
9060 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
9061 wlan_hdd_sap_pre_cac_failure,
9062 (void *)precac_adapter);
9063 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
9064
9065}
9066
9067/**
Komal Seelamec702b02016-02-24 18:42:16 +05309068 * hdd_update_ol_config - API to update ol configuration parameters
9069 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05309070 *
Komal Seelamc11bb222016-01-27 18:57:10 +05309071 * Return: void
9072 */
Komal Seelamec702b02016-02-24 18:42:16 +05309073static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05309074{
Komal Seelamec702b02016-02-24 18:42:16 +05309075 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309076 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05309077
Komal Seelamec702b02016-02-24 18:42:16 +05309078 if (!ol_ctx)
9079 return;
9080
9081 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
9082 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
9083 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
9084 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
9085 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
9086
9087 ol_init_ini_config(ol_ctx, &cfg);
9088}
9089
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009090#ifdef FEATURE_RUNTIME_PM
9091/**
9092 * hdd_populate_runtime_cfg() - populate runtime configuration
9093 * @hdd_ctx: hdd context
9094 * @cfg: pointer to the configuration memory being populated
9095 *
9096 * Return: void
9097 */
9098static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9099 struct hif_config_info *cfg)
9100{
9101 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
9102 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
9103}
9104#else
9105static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
9106 struct hif_config_info *cfg)
9107{
9108}
9109#endif
9110
Komal Seelamec702b02016-02-24 18:42:16 +05309111/**
9112 * hdd_update_hif_config - API to update HIF configuration parameters
9113 * @hdd_ctx: HDD Context
9114 *
9115 * Return: void
9116 */
9117static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
9118{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05309119 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05309120 struct hif_config_info cfg;
9121
9122 if (!scn)
9123 return;
9124
9125 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07009126 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05309127 hif_init_ini_config(scn, &cfg);
9128}
9129
9130/**
9131 * hdd_update_config() - Initialize driver per module ini parameters
9132 * @hdd_ctx: HDD Context
9133 *
9134 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309135 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05309136 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309137int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05309138{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309139 int ret;
9140
Komal Seelamec702b02016-02-24 18:42:16 +05309141 hdd_update_ol_config(hdd_ctx);
9142 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05309143 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
9144 ret = hdd_update_cds_config_ftm(hdd_ctx);
9145 else
9146 ret = hdd_update_cds_config(hdd_ctx);
9147
9148 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05309149}
9150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009151/* Register the module init/exit functions */
9152module_init(hdd_module_init);
9153module_exit(hdd_module_exit);
9154
9155MODULE_LICENSE("Dual BSD/GPL");
9156MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9157MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009159module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9160 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009161
9162module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
9163 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
9164
9165module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
9166
9167module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
9168
9169module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);