blob: 6e9f51b1d012c135db893c1f38fe7d58d449e6fa [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_main.c
30 *
31 * WLAN Host Device Driver implementation
32 *
33 */
34
35/* Include Files */
36#include <wlan_hdd_includes.h>
37#include <cds_api.h>
38#include <cds_sched.h>
Arun Khandavallifae92942016-08-01 13:31:08 +053039#include <linux/cpu.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#ifdef WLAN_FEATURE_LPSS
41#include <cds_utils.h>
42#endif
43#include <linux/etherdevice.h>
44#include <linux/firmware.h>
45#include <wlan_hdd_tx_rx.h>
46#include <wni_api.h>
47#include <wlan_hdd_cfg.h>
48#include <wlan_ptt_sock_svc.h>
49#include <dbglog_host.h>
50#include <wlan_logging_sock_svc.h>
51#include <wlan_hdd_wowl.h>
52#include <wlan_hdd_misc.h>
53#include <wlan_hdd_wext.h>
54#include "wlan_hdd_trace.h"
55#include "wlan_hdd_ioctl.h"
56#include "wlan_hdd_ftm.h"
57#include "wlan_hdd_power.h"
58#include "wlan_hdd_stats.h"
Prashanth Bhatta527fd752016-04-28 12:35:23 -070059#include "wlan_hdd_scan.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070062#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063
64#include <net/addrconf.h>
65#include <linux/wireless.h>
66#include <net/cfg80211.h>
67#include <linux/inetdevice.h>
68#include <net/addrconf.h>
69#include "wlan_hdd_cfg80211.h"
70#include "wlan_hdd_ext_scan.h"
71#include "wlan_hdd_p2p.h"
72#include <linux/rtnetlink.h>
73#include "sap_api.h"
74#include <linux/semaphore.h>
75#include <linux/ctype.h>
76#include <linux/compat.h>
77#ifdef MSM_PLATFORM
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078#include <soc/qcom/subsystem_restart.h>
79#endif
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -070080#include <soc/qcom/socinfo.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081#include <wlan_hdd_hostapd.h>
82#include <wlan_hdd_softap_tx_rx.h>
83#include "cfg_api.h"
84#include "qwlan_version.h"
85#include "wma_types.h"
86#include "wlan_hdd_tdls.h"
87#ifdef FEATURE_WLAN_CH_AVOID
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +053088#include "cds_regdomain.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080089#include "cdp_txrx_flow_ctrl_v2.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080090#endif /* FEATURE_WLAN_CH_AVOID */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070091#include "pld_common.h"
Tushnim Bhattacharyya15596cf2016-02-12 11:57:02 -080092#include "wlan_hdd_ocb.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "wlan_hdd_nan.h"
94#include "wlan_hdd_debugfs.h"
95#include "wlan_hdd_driver_ops.h"
96#include "epping_main.h"
97#include "wlan_hdd_memdump.h"
98
99#include <wlan_hdd_ipa.h>
100#include "hif.h"
101#include "wma.h"
102#include "cds_concurrency.h"
Manikandan Mohandcc21ba2016-03-15 14:31:56 -0700103#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104#include "wlan_hdd_green_ap.h"
Komal Seelamec702b02016-02-24 18:42:16 +0530105#include "bmi.h"
Amar Singhale4f28ee2015-10-21 14:36:56 -0700106#include <wlan_hdd_regulatory.h>
Himanshu Agarwal11c874a2016-05-06 18:35:29 +0530107#include "ol_rx_fwd.h"
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700108#include "wlan_hdd_lpass.h"
Arun Khandavalli4b55da72016-07-19 19:55:01 +0530109#include "nan_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110
111#ifdef MODULE
112#define WLAN_MODULE_NAME module_name(THIS_MODULE)
113#else
114#define WLAN_MODULE_NAME "wlan"
115#endif
116
117#ifdef TIMER_MANAGER
118#define TIMER_MANAGER_STR " +TIMER_MANAGER"
119#else
120#define TIMER_MANAGER_STR ""
121#endif
122
123#ifdef MEMORY_DEBUG
124#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
125#else
126#define MEMORY_DEBUG_STR ""
127#endif
128
Arun Khandavallifae92942016-08-01 13:31:08 +0530129#ifndef MODULE
130static struct gwlan_loader *wlan_loader;
131static ssize_t wlan_boot_cb(struct kobject *kobj,
132 struct kobj_attribute *attr,
133 const char *buf, size_t count);
134struct gwlan_loader {
135 bool loaded_state;
136 struct kobject *boot_wlan_obj;
137 struct attribute_group *attr_group;
138};
139
140static struct kobj_attribute wlan_boot_attribute =
141 __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb);
142
143static struct attribute *attrs[] = {
144 &wlan_boot_attribute.attr,
145 NULL,
146};
147
148#define MODULE_INITIALIZED 1
149#endif
150
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151/* the Android framework expects this param even though we don't use it */
152#define BUF_LEN 20
153static char fwpath_buffer[BUF_LEN];
154static struct kparam_string fwpath = {
155 .string = fwpath_buffer,
156 .maxlen = BUF_LEN,
157};
158
159static char *country_code;
160static int enable_11d = -1;
161static int enable_dfs_chan_scan = -1;
162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163/*
164 * spinlock for synchronizing asynchronous request/response
165 * (full description of use in wlan_hdd_main.h)
166 */
167DEFINE_SPINLOCK(hdd_context_lock);
168
Rajeev Kumar8e3e2832015-11-06 16:02:54 -0800169#define WLAN_NLINK_CESIUM 30
170
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530171static qdf_wake_lock_t wlan_wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172
173#define WOW_MAX_FILTER_LISTS 1
174#define WOW_MAX_FILTERS_PER_LIST 4
175#define WOW_MIN_PATTERN_SIZE 6
176#define WOW_MAX_PATTERN_SIZE 64
177
178#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
179static const struct wiphy_wowlan_support wowlan_support_reg_init = {
180 .flags = WIPHY_WOWLAN_ANY |
181 WIPHY_WOWLAN_MAGIC_PKT |
182 WIPHY_WOWLAN_DISCONNECT |
183 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
184 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
185 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
186 WIPHY_WOWLAN_4WAY_HANDSHAKE |
187 WIPHY_WOWLAN_RFKILL_RELEASE,
188 .n_patterns = WOW_MAX_FILTER_LISTS * WOW_MAX_FILTERS_PER_LIST,
189 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
190 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
191};
192#endif
193
194/* internal function declaration */
195
196struct sock *cesium_nl_srv_sock;
197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
199void wlan_hdd_auto_shutdown_cb(void);
200#endif
201
202/**
Nirav Shahbd36b062016-07-18 11:12:59 +0530203 * hdd_set_rps_cpu_mask - set RPS CPU mask for interfaces
204 * @hdd_ctx: pointer to hdd_context_t
205 *
206 * Return: none
207 */
208void hdd_set_rps_cpu_mask(hdd_context_t *hdd_ctx)
209{
210 hdd_adapter_t *adapter;
211 hdd_adapter_list_node_t *adapter_node, *next;
212 QDF_STATUS status = QDF_STATUS_SUCCESS;
213
214 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
215 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
216 adapter = adapter_node->pAdapter;
217 if (NULL != adapter)
218 hdd_send_rps_ind(adapter);
219 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
220 adapter_node = next;
221 }
222}
223
224/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 * wlan_hdd_txrx_pause_cb() - pause callback from txrx layer
226 * @vdev_id: vdev_id
227 * @action: action type
228 * @reason: reason type
229 *
230 * Return: none
231 */
232void wlan_hdd_txrx_pause_cb(uint8_t vdev_id,
233 enum netif_action_type action, enum netif_reason_type reason)
234{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530235 hdd_context_t *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236 hdd_adapter_t *adapter;
237
238 if (!hdd_ctx) {
239 hdd_err("hdd ctx is NULL");
240 return;
241 }
242 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
243
244 wlan_hdd_netif_queue_control(adapter, action, reason);
245 return;
246}
247
248/*
249 * Store WLAN driver version info in a global variable such that crash debugger
250 * can extract it from driver debug symbol and crashdump for post processing
251 */
252uint8_t g_wlan_driver_version[] = QWLAN_VERSIONSTR;
253
254/**
255 * hdd_device_mode_to_string() - return string conversion of device mode
256 * @device_mode: device mode
257 *
258 * This utility function helps log string conversion of device mode.
259 *
260 * Return: string conversion of device mode, if match found;
261 * "Unknown" otherwise.
262 */
263const char *hdd_device_mode_to_string(uint8_t device_mode)
264{
265 switch (device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800266 CASE_RETURN_STRING(QDF_STA_MODE);
267 CASE_RETURN_STRING(QDF_SAP_MODE);
268 CASE_RETURN_STRING(QDF_P2P_CLIENT_MODE);
269 CASE_RETURN_STRING(QDF_P2P_GO_MODE);
270 CASE_RETURN_STRING(QDF_FTM_MODE);
271 CASE_RETURN_STRING(QDF_IBSS_MODE);
272 CASE_RETURN_STRING(QDF_P2P_DEVICE_MODE);
273 CASE_RETURN_STRING(QDF_OCB_MODE);
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700274 CASE_RETURN_STRING(QDF_NDI_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275 default:
276 return "Unknown";
277 }
278}
279
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530280/**
281 * hdd_validate_channel_and_bandwidth() - Validate the channel-bandwidth combo
282 * @adapter: HDD adapter
283 * @chan_number: Channel number
284 * @chan_bw: Bandwidth
285 *
286 * Checks if the given bandwidth is valid for the given channel number.
287 *
288 * Return: 0 for success, non-zero for failure
289 */
290int hdd_validate_channel_and_bandwidth(hdd_adapter_t *adapter,
291 uint32_t chan_number,
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800292 enum phy_ch_width chan_bw)
Chandrasekaran, Manishekar794a0982016-01-12 19:42:20 +0530293{
294 uint8_t chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
295 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN, i;
296 bool found = false;
297 tHalHandle hal;
298
299 hal = WLAN_HDD_GET_HAL_CTX(adapter);
300 if (!hal) {
301 hdd_err("Invalid HAL context");
302 return -EINVAL;
303 }
304
305 if (0 != sme_cfg_get_str(hal, WNI_CFG_VALID_CHANNEL_LIST, chan, &len)) {
306 hdd_err("No valid channel list");
307 return -EOPNOTSUPP;
308 }
309
310 for (i = 0; i < len; i++) {
311 if (chan[i] == chan_number) {
312 found = true;
313 break;
314 }
315 }
316
317 if (found == false) {
318 hdd_err("Channel not in driver's valid channel list");
319 return -EOPNOTSUPP;
320 }
321
322 if ((!CDS_IS_CHANNEL_24GHZ(chan_number)) &&
323 (!CDS_IS_CHANNEL_5GHZ(chan_number))) {
324 hdd_err("CH %d is not in 2.4GHz or 5GHz", chan_number);
325 return -EINVAL;
326 }
327
328 if (CDS_IS_CHANNEL_24GHZ(chan_number)) {
329 if (chan_bw == CH_WIDTH_80MHZ) {
330 hdd_err("BW80 not possible in 2.4GHz band");
331 return -EINVAL;
332 }
333 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 14) &&
334 (chan_bw != CH_WIDTH_MAX)) {
335 hdd_err("Only BW20 possible on channel 14");
336 return -EINVAL;
337 }
338 }
339
340 if (CDS_IS_CHANNEL_5GHZ(chan_number)) {
341 if ((chan_bw != CH_WIDTH_20MHZ) && (chan_number == 165) &&
342 (chan_bw != CH_WIDTH_MAX)) {
343 hdd_err("Only BW20 possible on channel 165");
344 return -EINVAL;
345 }
346 }
347
348 return 0;
349}
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351static int __hdd_netdev_notifier_call(struct notifier_block *nb,
352 unsigned long state, void *data)
353{
354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
355 struct netdev_notifier_info *dev_notif_info = data;
356 struct net_device *dev = dev_notif_info->dev;
357#else
358 struct net_device *dev = data;
359#endif
360 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
361 hdd_context_t *hdd_ctx;
362
Jeff Johnson3c3994a2016-02-11 08:12:30 -0800363 ENTER_DEV(dev);
364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 /* Make sure that this callback corresponds to our device. */
366 if ((strncmp(dev->name, "wlan", 4)) && (strncmp(dev->name, "p2p", 3)))
367 return NOTIFY_DONE;
368
369 if ((adapter->magic != WLAN_HDD_ADAPTER_MAGIC) &&
370 (adapter->dev != dev)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700371 hdd_err("device adapter is not matching!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800372 return NOTIFY_DONE;
373 }
374
375 if (!dev->ieee80211_ptr) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700376 hdd_err("ieee80211_ptr is NULL!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 return NOTIFY_DONE;
378 }
379
380 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
381 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700382 hdd_alert("HDD Context Null Pointer");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530383 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 return NOTIFY_DONE;
385 }
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800386 if (cds_is_driver_recovering())
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 return NOTIFY_DONE;
388
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700389 hdd_notice("%s New Net Device State = %lu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 dev->name, state);
391
392 switch (state) {
393 case NETDEV_REGISTER:
394 break;
395
396 case NETDEV_UNREGISTER:
397 break;
398
399 case NETDEV_UP:
400 sme_ch_avoid_update_req(hdd_ctx->hHal);
401 break;
402
403 case NETDEV_DOWN:
404 break;
405
406 case NETDEV_CHANGE:
407 if (true == adapter->isLinkUpSvcNeeded)
408 complete(&adapter->linkup_event_var);
409 break;
410
411 case NETDEV_GOING_DOWN:
412 if (adapter->scan_info.mScanPending != false) {
413 unsigned long rc;
414 INIT_COMPLETION(adapter->scan_info.
415 abortscan_event_var);
416 hdd_abort_mac_scan(adapter->pHddCtx,
417 adapter->sessionId,
418 eCSR_SCAN_ABORT_DEFAULT);
419 rc = wait_for_completion_timeout(
420 &adapter->scan_info.abortscan_event_var,
421 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
422 if (!rc) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700423 hdd_err("Timeout occurred while waiting for abortscan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 }
425 } else {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700426 hdd_notice("Scan is not Pending from user");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800427 }
428 break;
429
430 default:
431 break;
432 }
433
434 return NOTIFY_DONE;
435}
436
437/**
438 * hdd_netdev_notifier_call() - netdev notifier callback function
439 * @nb: pointer to notifier block
440 * @state: state
441 * @ndev: ndev pointer
442 *
443 * Return: 0 on success, error number otherwise.
444 */
445static int hdd_netdev_notifier_call(struct notifier_block *nb,
446 unsigned long state,
447 void *ndev)
448{
449 int ret;
450
451 cds_ssr_protect(__func__);
452 ret = __hdd_netdev_notifier_call(nb, state, ndev);
453 cds_ssr_unprotect(__func__);
454
455 return ret;
456}
457
458struct notifier_block hdd_netdev_notifier = {
459 .notifier_call = hdd_netdev_notifier_call,
460};
461
462/* variable to hold the insmod parameters */
463static int con_mode;
Prashanth Bhatta05aaf012015-12-10 17:34:24 -0800464
465/* Variable to hold connection mode including module parameter con_mode */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466static int curr_con_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530468/**
469 * hdd_map_nl_chan_width() - Map NL channel width to internal representation
470 * @ch_width: NL channel width
471 *
472 * Converts the NL channel width to the driver's internal representation
473 *
474 * Return: Converted channel width. In case of non matching NL channel width,
475 * CH_WIDTH_MAX will be returned.
476 */
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800477enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width)
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530478{
479 switch (ch_width) {
480 case NL80211_CHAN_WIDTH_20_NOHT:
481 case NL80211_CHAN_WIDTH_20:
482 return CH_WIDTH_20MHZ;
483 case NL80211_CHAN_WIDTH_40:
484 return CH_WIDTH_40MHZ;
485 break;
486 case NL80211_CHAN_WIDTH_80:
487 return CH_WIDTH_80MHZ;
488 case NL80211_CHAN_WIDTH_80P80:
489 return CH_WIDTH_80P80MHZ;
490 case NL80211_CHAN_WIDTH_160:
491 return CH_WIDTH_160MHZ;
492 case NL80211_CHAN_WIDTH_5:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800493 return CH_WIDTH_5MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530494 case NL80211_CHAN_WIDTH_10:
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800495 return CH_WIDTH_10MHZ;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530496 default:
497 hdd_err("Invalid channel width %d, setting to default",
498 ch_width);
Kiran Kumar Lokere13644672016-02-29 15:40:10 -0800499 return CH_WIDTH_INVALID;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +0530500 }
501}
502
Masti, Narayanraddic4a7ab82015-11-25 15:41:10 +0530503/* wlan_hdd_find_opclass() - Find operating class for a channel
504 * @hal: handler to HAL
505 * @channel: channel id
506 * @bw_offset: bandwidth offset
507 *
508 * Function invokes sme api to find the operating class
509 *
510 * Return: operating class
511 */
512uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
513 uint8_t bw_offset)
514{
515 uint8_t opclass = 0;
516
517 sme_get_opclass(hal, channel, bw_offset, &opclass);
518 return opclass;
519}
520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530522 * hdd_qdf_trace_enable() - configure initial QDF Trace enable
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523 * @moduleId: Module whose trace level is being configured
524 * @bitmask: Bitmask of log levels to be enabled
525 *
526 * Called immediately after the cfg.ini is read in order to configure
527 * the desired trace levels.
528 *
529 * Return: None
530 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532{
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530533 QDF_TRACE_LEVEL level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534
535 /*
536 * if the bitmask is the default value, then a bitmask was not
537 * specified in cfg.ini, so leave the logging level alone (it
538 * will remain at the "compiled in" default value)
539 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530540 if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 return;
542 }
543
544 /* a mask was specified. start by disabling all logging */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530545 qdf_trace_set_value(moduleId, QDF_TRACE_LEVEL_NONE, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546
547 /* now cycle through the bitmask until all "set" bits are serviced */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530548 level = QDF_TRACE_LEVEL_FATAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 while (0 != bitmask) {
550 if (bitmask & 1) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530551 qdf_trace_set_value(moduleId, level, 1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552 }
553 level++;
554 bitmask >>= 1;
555 }
556}
557
558/**
559 * wlan_hdd_validate_context() - check the HDD context
560 * @hdd_ctx: HDD context pointer
561 *
562 * Return: 0 if the context is valid. Error code otherwise
563 */
564int wlan_hdd_validate_context(hdd_context_t *hdd_ctx)
565{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 if (NULL == hdd_ctx || NULL == hdd_ctx->config) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530567 hdd_err("%pS HDD context is Null", (void *)_RET_IP_);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568 return -ENODEV;
569 }
570
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800571 if (cds_is_driver_recovering()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530572 hdd_err("%pS Recovery in Progress. State: 0x%x Ignore!!!",
573 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574 return -EAGAIN;
575 }
576
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800577 if (cds_is_load_or_unload_in_progress()) {
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530578 hdd_err("%pS Unloading/Loading in Progress. Ignore!!!: 0x%x",
579 (void *)_RET_IP_, cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 return -EAGAIN;
581 }
582 return 0;
583}
584
585void hdd_checkandupdate_phymode(hdd_context_t *hdd_ctx)
586{
587 hdd_adapter_t *adapter = NULL;
588 hdd_station_ctx_t *pHddStaCtx = NULL;
589 eCsrPhyMode phyMode;
590 struct hdd_config *cfg_param = NULL;
591
592 if (NULL == hdd_ctx) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700593 hdd_alert("HDD Context is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594 return;
595 }
596
Krunal Soni9b04c9b2016-03-10 13:08:05 -0800597 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 if (NULL == adapter) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700599 hdd_alert("adapter is null !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800600 return;
601 }
602
603 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
604
605 cfg_param = hdd_ctx->config;
606 if (NULL == cfg_param) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700607 hdd_alert("cfg_params not available !!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608 return;
609 }
610
611 phyMode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
612
613 if (!hdd_ctx->isVHT80Allowed) {
614 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
615 (eCSR_DOT11_MODE_11ac == phyMode) ||
616 (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700617 hdd_notice("Setting phymode to 11n!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
619 eCSR_DOT11_MODE_11n);
620 }
621 } else {
622 /*
623 * New country Supports 11ac as well resetting value back from
624 * .ini
625 */
626 sme_set_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter),
627 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->
628 dot11Mode));
629 return;
630 }
631
632 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
633 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode)
634 || (eCSR_CFG_DOT11_MODE_11AC ==
635 pHddStaCtx->conn_info.dot11Mode))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530636 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637
638 /* need to issue a disconnect to CSR. */
639 INIT_COMPLETION(adapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530640 qdf_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641 adapter->sessionId,
642 eCSR_DISCONNECT_REASON_UNSPECIFIED);
643
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530644 if (QDF_STATUS_SUCCESS == qdf_status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645 unsigned long rc;
646
647 rc = wait_for_completion_timeout(
648 &adapter->disconnect_comp_var,
649 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
650 if (!rc)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700651 hdd_err("failure waiting for disconnect_comp_var");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 }
653 }
654}
655
656/**
657 * hdd_set_ibss_power_save_params() - update IBSS Power Save params to WMA.
658 * @hdd_adapter_t Hdd adapter.
659 *
660 * This function sets the IBSS power save config parameters to WMA
661 * which will send it to firmware if FW supports IBSS power save
662 * before vdev start.
663 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530664 * Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 * on failure.
666 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530667QDF_STATUS hdd_set_ibss_power_save_params(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668{
669 int ret;
670 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
671
672 if (hdd_ctx == NULL) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700673 hdd_err("HDD context is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530674 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 }
676
677 ret = wma_cli_set_command(adapter->sessionId,
678 WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE,
679 hdd_ctx->config->ibssATIMWinSize,
680 VDEV_CMD);
681 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700682 hdd_err("WMA_VDEV_IBSS_SET_ATIM_WINDOW_SIZE failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530683 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 }
685
686 ret = wma_cli_set_command(adapter->sessionId,
687 WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED,
688 hdd_ctx->config->isIbssPowerSaveAllowed,
689 VDEV_CMD);
690 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700691 hdd_err("WMA_VDEV_IBSS_SET_POWER_SAVE_ALLOWED failed %d",
692 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530693 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 }
695
696 ret = wma_cli_set_command(adapter->sessionId,
697 WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED,
698 hdd_ctx->config->
699 isIbssPowerCollapseAllowed, VDEV_CMD);
700 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700701 hdd_err("WMA_VDEV_IBSS_SET_POWER_COLLAPSE_ALLOWED failed %d",
702 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530703 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 }
705
706 ret = wma_cli_set_command(adapter->sessionId,
707 WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX,
708 hdd_ctx->config->isIbssAwakeOnTxRx,
709 VDEV_CMD);
710 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700711 hdd_err("WMA_VDEV_IBSS_SET_AWAKE_ON_TX_RX failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530712 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 }
714
715 ret = wma_cli_set_command(adapter->sessionId,
716 WMA_VDEV_IBSS_SET_INACTIVITY_TIME,
717 hdd_ctx->config->ibssInactivityCount,
718 VDEV_CMD);
719 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700720 hdd_err("WMA_VDEV_IBSS_SET_INACTIVITY_TIME failed %d", ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530721 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 }
723
724 ret = wma_cli_set_command(adapter->sessionId,
725 WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME,
726 hdd_ctx->config->ibssTxSpEndInactivityTime,
727 VDEV_CMD);
728 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700729 hdd_err("WMA_VDEV_IBSS_SET_TXSP_END_INACTIVITY_TIME failed %d",
730 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530731 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800732 }
733
734 ret = wma_cli_set_command(adapter->sessionId,
735 WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS,
736 hdd_ctx->config->ibssPsWarmupTime,
737 VDEV_CMD);
738 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700739 hdd_err("WMA_VDEV_IBSS_PS_SET_WARMUP_TIME_SECS failed %d",
740 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530741 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800742 }
743
744 ret = wma_cli_set_command(adapter->sessionId,
745 WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW,
746 hdd_ctx->config->ibssPs1RxChainInAtimEnable,
747 VDEV_CMD);
748 if (0 != ret) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700749 hdd_err("WMA_VDEV_IBSS_PS_SET_1RX_CHAIN_IN_ATIM_WINDOW failed %d",
750 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530751 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800752 }
753
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530754 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755}
756
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800757#define INTF_MACADDR_MASK 0x7
758
759/**
760 * hdd_update_macaddr() - update mac address
761 * @config: hdd configuration
762 * @hw_macaddr: mac address
763 *
764 * Mac address for multiple virtual interface is found as following
765 * i) The mac address of the first interface is just the actual hw mac address.
766 * ii) MSM 3 or 4 bits of byte5 of the actual mac address are used to
767 * define the mac address for the remaining interfaces and locally
768 * admistered bit is set. INTF_MACADDR_MASK is based on the number of
769 * supported virtual interfaces, right now this is 0x07 (meaning 8
770 * interface).
771 * Byte[3] of second interface will be hw_macaddr[3](bit5..7) + 1,
772 * for third interface it will be hw_macaddr[3](bit5..7) + 2, etc.
773 *
774 * Return: None
775 */
776void hdd_update_macaddr(struct hdd_config *config,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530777 struct qdf_mac_addr hw_macaddr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778{
779 int8_t i;
780 uint8_t macaddr_b3, tmp_br3;
781
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530782 qdf_mem_copy(config->intfMacAddr[0].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530783 QDF_MAC_ADDR_SIZE);
784 for (i = 1; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530785 qdf_mem_copy(config->intfMacAddr[i].bytes, hw_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530786 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787 macaddr_b3 = config->intfMacAddr[i].bytes[3];
788 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + i) &
789 INTF_MACADDR_MASK;
790 macaddr_b3 += tmp_br3;
791
792 /* XOR-ing bit-24 of the mac address. This will give enough
793 * mac address range before collision
794 */
795 macaddr_b3 ^= (1 << 7);
796
797 /* Set locally administered bit */
798 config->intfMacAddr[i].bytes[0] |= 0x02;
799 config->intfMacAddr[i].bytes[3] = macaddr_b3;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700800 hdd_notice("config->intfMacAddr[%d]: "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800801 MAC_ADDRESS_STR, i,
802 MAC_ADDR_ARRAY(config->intfMacAddr[i].bytes));
803 }
804}
805
806static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
807 struct wma_tgt_services *cfg)
808{
809 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810
811 /* Set up UAPSD */
812 config->apUapsdEnabled &= cfg->uapsd;
813
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 /* 11AC mode support */
815 if ((config->dot11Mode == eHDD_DOT11_MODE_11ac ||
816 config->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) && !cfg->en_11ac)
817 config->dot11Mode = eHDD_DOT11_MODE_AUTO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818
819 /* ARP offload: override user setting if invalid */
820 config->fhostArpOffload &= cfg->arp_offload;
821
822#ifdef FEATURE_WLAN_SCAN_PNO
823 /* PNO offload */
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700824 hdd_info("PNO Capability in f/w = %d", cfg->pno_offload);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 if (cfg->pno_offload)
826 config->PnoOffload = true;
827#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828#ifdef FEATURE_WLAN_TDLS
829 config->fEnableTDLSSupport &= cfg->en_tdls;
830 config->fEnableTDLSOffChannel &= cfg->en_tdls_offchan;
831 config->fEnableTDLSBufferSta &= cfg->en_tdls_uapsd_buf_sta;
832 if (config->fTDLSUapsdMask && cfg->en_tdls_uapsd_sleep_sta) {
833 config->fEnableTDLSSleepSta = true;
834 } else {
835 config->fEnableTDLSSleepSta = false;
836 }
837#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838#ifdef WLAN_FEATURE_ROAM_OFFLOAD
839 config->isRoamOffloadEnabled &= cfg->en_roam_offload;
840#endif
Krishna Kumaar Natarajan052c6e62015-09-28 15:32:55 -0700841 sme_update_tgt_services(hdd_ctx->hHal, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842
843}
844
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700845/**
846 * hdd_update_vdev_nss() - sets the vdev nss
847 * @hdd_ctx: HDD context
848 *
849 * Sets the Nss per vdev type based on INI
850 *
851 * Return: None
852 */
853static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
854{
855 struct hdd_config *cfg_ini = hdd_ctx->config;
856 uint8_t max_supp_nss = 1;
857
858 if (cfg_ini->enable2x2)
859 max_supp_nss = 2;
860
861 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
862 cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
863
864 sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
865 cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
866}
867
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
869 struct wma_tgt_ht_cap *cfg)
870{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530871 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800872 uint32_t value, val32;
873 uint16_t val16;
874 struct hdd_config *pconfig = hdd_ctx->config;
875 tSirMacHTCapabilityInfo *phtCapInfo;
876 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
877 uint8_t enable_tx_stbc;
878
879 /* check and update RX STBC */
880 if (pconfig->enableRxSTBC && !cfg->ht_rx_stbc)
881 pconfig->enableRxSTBC = cfg->ht_rx_stbc;
882
883 /* get the MPDU density */
884 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY, &value);
885
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530886 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700887 hdd_err("could not get MPDU DENSITY");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 value = 0;
889 }
890
891 /*
892 * MPDU density:
893 * override user's setting if value is larger
894 * than the one supported by target
895 */
896 if (value > cfg->mpdu_density) {
897 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_MPDU_DENSITY,
898 cfg->mpdu_density);
899
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530900 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700901 hdd_alert("could not set MPDU DENSITY to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 }
903
904 /* get the HT capability info */
905 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530906 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700907 hdd_err("could not get HT capability info");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908 return;
909 }
910 val16 = (uint16_t) val32;
911 phtCapInfo = (tSirMacHTCapabilityInfo *) &val16;
912
913 /* Set the LDPC capability */
914 phtCapInfo->advCodingCap = cfg->ht_rx_ldpc;
915
916 if (pconfig->ShortGI20MhzEnable && !cfg->ht_sgi_20)
917 pconfig->ShortGI20MhzEnable = cfg->ht_sgi_20;
918
919 if (pconfig->ShortGI40MhzEnable && !cfg->ht_sgi_40)
920 pconfig->ShortGI40MhzEnable = cfg->ht_sgi_40;
921
922 hdd_ctx->num_rf_chains = cfg->num_rf_chains;
923 hdd_ctx->ht_tx_stbc_supported = cfg->ht_tx_stbc;
924
925 enable_tx_stbc = pconfig->enableTxSTBC;
926
927 if (pconfig->enable2x2 && (cfg->num_rf_chains == 2)) {
928 pconfig->enable2x2 = 1;
929 } else {
930 pconfig->enable2x2 = 0;
931 enable_tx_stbc = 0;
932
933 /* 1x1 */
934 /* Update Rx Highest Long GI data Rate */
935 if (sme_cfg_set_int(hdd_ctx->hHal,
936 WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700937 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530938 == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700939 hdd_err("Could not pass on WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940 }
941
942 /* Update Tx Highest Long GI data Rate */
943 if (sme_cfg_set_int
944 (hdd_ctx->hHal,
945 WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700946 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530947 QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700948 hdd_err("VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 }
950 }
951 if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
952 enable_tx_stbc = 0;
953 phtCapInfo->txSTBC = enable_tx_stbc;
954
955 val32 = val16;
956 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, val32);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530957 if (status != QDF_STATUS_SUCCESS)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700958 hdd_alert("could not set HT capability to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959#define WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES 0xff
960 value = SIZE_OF_SUPPORTED_MCS_SET;
961 if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530962 &value) == QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700963 hdd_notice("Read MCS rate set");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800964
965 if (pconfig->enable2x2) {
966 for (value = 0; value < cfg->num_rf_chains; value++)
967 mcs_set[value] =
968 WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES;
969
970 status =
971 sme_cfg_set_str(hdd_ctx->hHal,
972 WNI_CFG_SUPPORTED_MCS_SET,
973 mcs_set,
974 SIZE_OF_SUPPORTED_MCS_SET);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530975 if (status == QDF_STATUS_E_FAILURE)
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700976 hdd_alert("could not set MCS SET to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800977 }
978 }
979#undef WLAN_HDD_RX_MCS_ALL_NSTREAM_RATES
980}
981
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
983 struct wma_tgt_vht_cap *cfg)
984{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530985 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986 uint32_t value = 0;
987 struct hdd_config *pconfig = hdd_ctx->config;
988 struct wiphy *wiphy = hdd_ctx->wiphy;
989 struct ieee80211_supported_band *band_5g =
990 wiphy->bands[IEEE80211_BAND_5GHZ];
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -0700991 uint32_t temp = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992
993 /* Get the current MPDU length */
994 status =
995 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MAX_MPDU_LENGTH,
996 &value);
997
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530998 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -0700999 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 value = 0;
1001 }
1002
1003 /*
1004 * VHT max MPDU length:
1005 * override if user configured value is too high
1006 * that the target cannot support
1007 */
1008 if (value > cfg->vht_max_mpdu) {
1009 status = sme_cfg_set_int(hdd_ctx->hHal,
1010 WNI_CFG_VHT_MAX_MPDU_LENGTH,
1011 cfg->vht_max_mpdu);
1012
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301013 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001014 hdd_alert("could not set VHT MAX MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015 }
1016 }
1017
1018 /* Get the current supported chan width */
1019 status = sme_cfg_get_int(hdd_ctx->hHal,
1020 WNI_CFG_VHT_SUPPORTED_CHAN_WIDTH_SET,
1021 &value);
1022
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301023 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001024 hdd_err("could not get MPDU LENGTH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025 value = 0;
1026 }
1027
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001028 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
1029 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1030
1031 if (pconfig->enable2x2)
1032 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1033
1034 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
1035 QDF_STATUS_E_FAILURE) {
1036 hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
1037 }
1038
1039 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
1040 temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
1041 if (pconfig->enable2x2)
1042 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
1043
1044 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
1045 QDF_STATUS_E_FAILURE) {
1046 hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
1047 }
1048
1049 sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
1050 temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
1051 if (pconfig->enable2x2)
1052 temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
1053
1054 hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
1055 pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
1056
1057 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
1058 QDF_STATUS_E_FAILURE) {
1059 hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
1060 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001061 /* Get the current RX LDPC setting */
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07001062 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 &value);
1064
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301065 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001066 hdd_err("could not get VHT LDPC CODING CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067 value = 0;
1068 }
1069
1070 /* Set the LDPC capability */
1071 if (value && !cfg->vht_rx_ldpc) {
1072 status = sme_cfg_set_int(hdd_ctx->hHal,
1073 WNI_CFG_VHT_LDPC_CODING_CAP,
1074 cfg->vht_rx_ldpc);
1075
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301076 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001077 hdd_alert("could not set VHT LDPC CODING CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 }
1079 }
1080
1081 /* Get current GI 80 value */
1082 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
1083 &value);
1084
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301085 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001086 hdd_err("could not get SHORT GI 80MHZ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001087 value = 0;
1088 }
1089
1090 /* set the Guard interval 80MHz */
1091 if (value && !cfg->vht_short_gi_80) {
1092 status = sme_cfg_set_int(hdd_ctx->hHal,
1093 WNI_CFG_VHT_SHORT_GI_80MHZ,
1094 cfg->vht_short_gi_80);
1095
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301096 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001097 hdd_alert("could not set SHORT GI 80MHZ to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001098 }
1099 }
1100
1101 /* Get current GI 160 value */
1102 status = sme_cfg_get_int(hdd_ctx->hHal,
1103 WNI_CFG_VHT_SHORT_GI_160_AND_80_PLUS_80MHZ,
1104 &value);
1105
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301106 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001107 hdd_err("could not get SHORT GI 80 & 160");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 value = 0;
1109 }
1110
1111 /* Get VHT TX STBC cap */
1112 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC, &value);
1113
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301114 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001115 hdd_err("could not get VHT TX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001116 value = 0;
1117 }
1118
1119 /* VHT TX STBC cap */
1120 if (value && !cfg->vht_tx_stbc) {
1121 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXSTBC,
1122 cfg->vht_tx_stbc);
1123
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301124 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001125 hdd_alert("could not set the VHT TX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126 }
1127 }
1128
1129 /* Get VHT RX STBC cap */
1130 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC, &value);
1131
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301132 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001133 hdd_err("could not get VHT RX STBC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 value = 0;
1135 }
1136
1137 /* VHT RX STBC cap */
1138 if (value && !cfg->vht_rx_stbc) {
1139 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RXSTBC,
1140 cfg->vht_rx_stbc);
1141
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301142 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001143 hdd_alert("could not set the VHT RX STBC to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 }
1145 }
1146
1147 /* Get VHT SU Beamformer cap */
1148 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1149 &value);
1150
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301151 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001152 hdd_err("could not get VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153 value = 0;
1154 }
1155
1156 /* set VHT SU Beamformer cap */
1157 if (value && !cfg->vht_su_bformer) {
1158 status = sme_cfg_set_int(hdd_ctx->hHal,
1159 WNI_CFG_VHT_SU_BEAMFORMER_CAP,
1160 cfg->vht_su_bformer);
1161
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301162 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001163 hdd_alert("could not set VHT SU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001164 }
1165 }
1166
1167 /* check and update SU BEAMFORMEE capabality */
1168 if (pconfig->enableTxBF && !cfg->vht_su_bformee)
1169 pconfig->enableTxBF = cfg->vht_su_bformee;
1170
1171 status = sme_cfg_set_int(hdd_ctx->hHal,
1172 WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
1173 pconfig->enableTxBF);
1174
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301175 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001176 hdd_alert("could not set VHT SU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001177 }
1178
1179 /* Get VHT MU Beamformer cap */
1180 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1181 &value);
1182
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301183 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001184 hdd_err("could not get VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001185 value = 0;
1186 }
1187
1188 /* set VHT MU Beamformer cap */
1189 if (value && !cfg->vht_mu_bformer) {
1190 status = sme_cfg_set_int(hdd_ctx->hHal,
1191 WNI_CFG_VHT_MU_BEAMFORMER_CAP,
1192 cfg->vht_mu_bformer);
1193
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301194 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001195 hdd_alert("could not set the VHT MU BEAMFORMER CAP to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196 }
1197 }
1198
1199 /* Get VHT MU Beamformee cap */
1200 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1201 &value);
1202
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301203 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001204 hdd_err("could not get VHT MU BEAMFORMEE CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205 value = 0;
1206 }
1207
1208 /* set VHT MU Beamformee cap */
1209 if (value && !cfg->vht_mu_bformee) {
1210 status = sme_cfg_set_int(hdd_ctx->hHal,
1211 WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
1212 cfg->vht_mu_bformee);
1213
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301214 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001215 hdd_alert("could not set VHT MU BEAMFORMER CAP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 }
1217 }
1218
1219 /* Get VHT MAX AMPDU Len exp */
1220 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1221 &value);
1222
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301223 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001224 hdd_err("could not get VHT AMPDU LEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 value = 0;
1226 }
1227
1228 /*
1229 * VHT max AMPDU len exp:
1230 * override if user configured value is too high
1231 * that the target cannot support.
1232 * Even though Rome publish ampdu_len=7, it can
1233 * only support 4 because of some h/w bug.
1234 */
1235
1236 if (value > cfg->vht_max_ampdu_len_exp) {
1237 status = sme_cfg_set_int(hdd_ctx->hHal,
1238 WNI_CFG_VHT_AMPDU_LEN_EXPONENT,
1239 cfg->vht_max_ampdu_len_exp);
1240
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301241 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001242 hdd_alert("could not set the VHT AMPDU LEN EXP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243 }
1244 }
1245
1246 /* Get VHT TXOP PS CAP */
1247 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS, &value);
1248
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301249 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001250 hdd_err("could not get VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 value = 0;
1252 }
1253
1254 /* set VHT TXOP PS cap */
1255 if (value && !cfg->vht_txop_ps) {
1256 status = sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TXOP_PS,
1257 cfg->vht_txop_ps);
1258
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301259 if (status == QDF_STATUS_E_FAILURE) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001260 hdd_alert("could not set the VHT TXOP PS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 }
1262 }
1263
1264 if (WMI_VHT_CAP_MAX_MPDU_LEN_11454 == cfg->vht_max_mpdu)
1265 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1266 else if (WMI_VHT_CAP_MAX_MPDU_LEN_7935 == cfg->vht_max_mpdu)
1267 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1268 else
1269 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1270
1271
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001272 if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_80P80MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001273 band_5g->vht_cap.cap |=
1274 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
Amar Singhal90aaa6a2016-03-01 16:53:37 -08001275 else if (cfg->supp_chan_width & (1 << eHT_CHANNEL_WIDTH_160MHZ))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276 band_5g->vht_cap.cap |=
1277 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001278
1279 if (cfg->vht_rx_ldpc & WMI_VHT_CAP_RX_LDPC)
1280 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
1281
1282 if (cfg->vht_short_gi_80 & WMI_VHT_CAP_SGI_80MHZ)
1283 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1284 if (cfg->vht_short_gi_160 & WMI_VHT_CAP_SGI_160MHZ)
1285 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1286
1287 if (cfg->vht_tx_stbc & WMI_VHT_CAP_TX_STBC)
1288 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
1289
1290 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_1SS)
1291 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1292 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_2SS)
1293 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_2;
1294 if (cfg->vht_rx_stbc & WMI_VHT_CAP_RX_STBC_3SS)
1295 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_3;
1296
1297 band_5g->vht_cap.cap |=
1298 (cfg->vht_max_ampdu_len_exp <<
1299 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1300
1301 if (cfg->vht_su_bformer & WMI_VHT_CAP_SU_BFORMER)
1302 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1303 if (cfg->vht_su_bformee & WMI_VHT_CAP_SU_BFORMEE)
1304 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1305 if (cfg->vht_mu_bformer & WMI_VHT_CAP_MU_BFORMER)
1306 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1307 if (cfg->vht_mu_bformee & WMI_VHT_CAP_MU_BFORMEE)
1308 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1309
1310 if (cfg->vht_txop_ps & WMI_VHT_CAP_TXOP_PS)
1311 band_5g->vht_cap.cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1312
1313}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001314
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001315/**
1316 * hdd_generate_macaddr_auto() - Auto-generate mac address
1317 * @hdd_ctx: Pointer to the HDD context
1318 *
1319 * Auto-generate mac address using device serial number.
1320 * Keep the first 3 bytes of OUI as before and replace
1321 * the last 3 bytes with the lower 3 bytes of serial number.
1322 *
1323 * Return: 0 for success
1324 * Non zero failure code for errors
1325 */
1326static int hdd_generate_macaddr_auto(hdd_context_t *hdd_ctx)
1327{
1328 unsigned int serialno = 0;
1329 struct qdf_mac_addr mac_addr = {
1330 {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00}
1331 };
1332
1333 serialno = socinfo_get_serial_number();
1334 if (serialno == 0)
1335 return -EINVAL;
1336
1337 serialno &= 0x00ffffff;
1338
1339 mac_addr.bytes[3] = (serialno >> 16) & 0xff;
1340 mac_addr.bytes[4] = (serialno >> 8) & 0xff;
1341 mac_addr.bytes[5] = serialno & 0xff;
1342
1343 hdd_update_macaddr(hdd_ctx->config, mac_addr);
1344 return 0;
1345}
1346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347void hdd_update_tgt_cfg(void *context, void *param)
1348{
1349 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1350 struct wma_tgt_cfg *cfg = param;
1351 uint8_t temp_band_cap;
Naveen Rawat64e477e2016-05-20 10:34:56 -07001352 struct cds_config_info *cds_cfg = cds_get_ini_config();
1353
1354 if (cds_cfg) {
1355 if (hdd_ctx->config->enable_sub_20_channel_width !=
1356 WLAN_SUB_20_CH_WIDTH_NONE && !cfg->sub_20_support) {
1357 hdd_err("User requested sub 20 MHz channel width but unsupported by FW.");
1358 cds_cfg->sub_20_channel_width =
1359 WLAN_SUB_20_CH_WIDTH_NONE;
1360 } else {
1361 cds_cfg->sub_20_channel_width =
1362 hdd_ctx->config->enable_sub_20_channel_width;
1363 }
1364 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365
1366 /* first store the INI band capability */
1367 temp_band_cap = hdd_ctx->config->nBandCapability;
1368
1369 hdd_ctx->config->nBandCapability = cfg->band_cap;
1370
1371 /* now overwrite the target band capability with INI
1372 setting if INI setting is a subset */
1373
1374 if ((hdd_ctx->config->nBandCapability == eCSR_BAND_ALL) &&
1375 (temp_band_cap != eCSR_BAND_ALL))
1376 hdd_ctx->config->nBandCapability = temp_band_cap;
1377 else if ((hdd_ctx->config->nBandCapability != eCSR_BAND_ALL) &&
1378 (temp_band_cap != eCSR_BAND_ALL) &&
1379 (hdd_ctx->config->nBandCapability != temp_band_cap)) {
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001380 hdd_warn("ini BandCapability not supported by the target");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 }
1382
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001383 if (!cds_is_driver_recovering()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 hdd_ctx->reg.reg_domain = cfg->reg_domain;
1385 hdd_ctx->reg.eeprom_rd_ext = cfg->eeprom_rd_ext;
1386 }
1387
1388 /* This can be extended to other configurations like ht, vht cap... */
1389
Anurag Chouhanc5548422016-02-24 18:33:27 +05301390 if (!qdf_is_macaddr_zero(&cfg->hw_macaddr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001391 hdd_update_macaddr(hdd_ctx->config, cfg->hw_macaddr);
1392 } else {
Yuanyuan Liu5bdfad72016-07-21 10:33:04 -07001393 static struct qdf_mac_addr default_mac_addr = {
1394 {0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}
1395 };
1396 if (qdf_is_macaddr_equal(&hdd_ctx->config->intfMacAddr[0],
1397 &default_mac_addr)) {
1398 if (hdd_generate_macaddr_auto(hdd_ctx) != 0)
1399 hdd_err("Fail to auto-generate MAC, using MAC from ini file "
1400 MAC_ADDRESS_STR,
1401 MAC_ADDR_ARRAY(hdd_ctx->config->
1402 intfMacAddr[0].bytes));
1403 } else {
1404 hdd_err("Invalid MAC passed from target, using MAC from ini file "
1405 MAC_ADDRESS_STR,
1406 MAC_ADDR_ARRAY(hdd_ctx->config->
1407 intfMacAddr[0].bytes));
1408 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001409 }
1410
1411 hdd_ctx->target_fw_version = cfg->target_fw_version;
1412
1413 hdd_ctx->max_intf_count = cfg->max_intf_count;
1414
1415#ifdef WLAN_FEATURE_LPSS
1416 hdd_ctx->lpss_support = cfg->lpss_support;
1417#endif
1418
Ryan Hsu3c8f79f2015-12-02 16:45:09 -08001419 hdd_wlan_set_egap_support(hdd_ctx, cfg);
1420
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001421 hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
1422 hdd_update_tgt_services(hdd_ctx, &cfg->services);
1423
1424 hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
1425
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426 hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
Tushnim Bhattacharyyaf44a9d82016-07-05 10:52:06 -07001427
1428 hdd_update_vdev_nss(hdd_ctx);
1429
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001430 hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
Krunal Sonie3531942016-04-12 17:43:53 -07001431 hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
Jeff Johnsonb8969cb2016-08-15 12:38:19 -07001432 hdd_info("fine_time_meas_cap: 0x%x",
Krishna Kumaar Natarajan1ae49112015-11-24 21:43:22 -08001433 hdd_ctx->config->fine_time_meas_cap);
Archana Ramachandran393f3792015-11-13 17:13:21 -08001434
1435 hdd_ctx->current_antenna_mode =
1436 (hdd_ctx->config->enable2x2 == 0x01) ?
1437 HDD_ANTENNA_MODE_2X2 : HDD_ANTENNA_MODE_1X1;
1438 hdd_info("Init current antenna mode: %d",
1439 hdd_ctx->current_antenna_mode);
1440
Rajeev Kumardd3bc602016-08-16 14:21:05 -07001441 hdd_info("Target BPF %d Host BPF %d",
1442 cfg->bpf_enabled, hdd_ctx->config->bpf_packet_filter_enable);
1443 hdd_ctx->bpf_enabled = (cfg->bpf_enabled &&
1444 hdd_ctx->config->bpf_packet_filter_enable);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301445
Arun Khandavallid454d422016-08-17 12:47:05 +05301446 /*
1447 * If BPF is enabled, maxWowFilters set to WMA_STA_WOW_DEFAULT_PTRN_MAX
1448 * because we need atleast WMA_STA_WOW_DEFAULT_PTRN_MAX free slots to
1449 * configure the STA mode wow pattern.
1450 */
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301451 if (hdd_ctx->bpf_enabled)
Arun Khandavallid454d422016-08-17 12:47:05 +05301452 hdd_ctx->config->maxWoWFilters = WMA_STA_WOW_DEFAULT_PTRN_MAX;
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05301453
Deepak Dhamdhere13230d32016-05-26 00:46:53 -07001454 /* Configure NAN datapath features */
1455 hdd_nan_datapath_target_config(hdd_ctx, cfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456}
1457
1458/**
1459 * hdd_dfs_indicate_radar() - handle radar detection on current SAP channel
1460 * @context: HDD context pointer
1461 * @param: HDD radar indication pointer
1462 *
Sandeep Puligillaa8d4eec2016-06-30 15:13:11 -07001463 * This function is invoked in atomic context when a radar
1464 * is found on the SAP current operating channel and Data Tx
1465 * from netif has to be stopped to honor the DFS regulations.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 * Actions: Stop the netif Tx queues,Indicate Radar present
1467 * in HDD context for future usage.
1468 *
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301469 * Return: true to allow radar indication to host else false
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301471bool hdd_dfs_indicate_radar(void *context, void *param)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472{
1473 hdd_context_t *hdd_ctx = (hdd_context_t *) context;
1474 struct wma_dfs_radar_ind *hdd_radar_event =
1475 (struct wma_dfs_radar_ind *)param;
1476 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1477 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301478 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001479
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301480 if (!hdd_ctx || !hdd_radar_event ||
1481 hdd_ctx->config->disableDFSChSwitch)
1482 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001483
1484 if (true == hdd_radar_event->dfs_radar_status) {
Arif Hussain2a7c1f32016-07-18 14:24:36 -07001485 if (qdf_atomic_inc_return(&hdd_ctx->dfs_radar_found) > 1) {
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301486 /*
1487 * Application already triggered channel switch
1488 * on current channel, so return here.
1489 */
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301490 return false;
1491 }
1492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001493 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301494 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08001496 if (QDF_SAP_MODE == adapter->device_mode ||
1497 QDF_P2P_GO_MODE == adapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
1499 dfs_cac_block_tx = true;
1500 }
1501
1502 status = hdd_get_next_adapter(hdd_ctx,
1503 adapterNode,
1504 &pNext);
1505 adapterNode = pNext;
1506 }
1507 }
Edhar, Mahesh Kumar695468e2015-10-19 12:06:20 +05301508
1509 return true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001510}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511
1512/**
1513 * hdd_is_valid_mac_address() - validate MAC address
1514 * @pMacAddr: Pointer to the input MAC address
1515 *
1516 * This function validates whether the given MAC address is valid or not
1517 * Expected MAC address is of the format XX:XX:XX:XX:XX:XX
1518 * where X is the hexa decimal digit character and separated by ':'
1519 * This algorithm works even if MAC address is not separated by ':'
1520 *
1521 * This code checks given input string mac contains exactly 12 hexadecimal
1522 * digits and a separator colon : appears in the input string only after
1523 * an even number of hex digits.
1524 *
1525 * Return: 1 for valid and 0 for invalid
1526 */
1527bool hdd_is_valid_mac_address(const uint8_t *pMacAddr)
1528{
1529 int xdigit = 0;
1530 int separator = 0;
1531 while (*pMacAddr) {
1532 if (isxdigit(*pMacAddr)) {
1533 xdigit++;
1534 } else if (':' == *pMacAddr) {
1535 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
1536 break;
1537
1538 ++separator;
1539 } else {
1540 /* Invalid MAC found */
1541 return 0;
1542 }
1543 ++pMacAddr;
1544 }
1545 return xdigit == 12 && (separator == 5 || separator == 0);
1546}
1547
1548/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07001549 * __hdd__mon_open() - HDD Open function
1550 * @dev: Pointer to net_device structure
1551 *
1552 * This is called in response to ifconfig up
1553 *
1554 * Return: 0 for success; non-zero for failure
1555 */
1556static int __hdd_mon_open(struct net_device *dev)
1557{
1558 int ret;
1559
1560 ENTER_DEV(dev);
1561 ret = hdd_set_mon_rx_cb(dev);
1562 return ret;
1563}
1564
1565/**
1566 * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR
1567 * @dev: Pointer to net_device structure
1568 *
1569 * This is called in response to ifconfig up
1570 *
1571 * Return: 0 for success; non-zero for failure
1572 */
1573int hdd_mon_open(struct net_device *dev)
1574{
1575 int ret;
1576
1577 cds_ssr_protect(__func__);
1578 ret = __hdd_mon_open(dev);
1579 cds_ssr_unprotect(__func__);
1580
1581 return ret;
1582}
1583
1584/**
Arun Khandavallifae92942016-08-01 13:31:08 +05301585 * hdd_start_adapter() - Wrapper function for device specific adapter
1586 * @adapter: pointer to HDD adapter
1587 *
1588 * This function is called to start the device specific adapter for
1589 * the mode passed in the adapter's device_mode.
1590 *
1591 * Return: 0 for success; non-zero for failure
1592 */
1593int hdd_start_adapter(hdd_adapter_t *adapter)
1594{
1595
1596 int ret;
1597 enum tQDF_ADAPTER_MODE device_mode = adapter->device_mode;
1598
1599 ENTER_DEV(adapter->dev);
1600 hdd_info("Start_adapter for mode : %d", adapter->device_mode);
1601
1602 switch (device_mode) {
1603 case QDF_P2P_CLIENT_MODE:
1604 case QDF_P2P_DEVICE_MODE:
1605 case QDF_OCB_MODE:
1606 case QDF_STA_MODE:
1607 case QDF_MONITOR_MODE:
1608 ret = hdd_start_station_adapter(adapter);
1609 if (ret)
1610 goto err_start_adapter;
1611 break;
1612 case QDF_P2P_GO_MODE:
1613 case QDF_SAP_MODE:
1614 ret = hdd_start_ap_adapter(adapter);
1615 if (ret)
1616 goto err_start_adapter;
1617 break;
1618 case QDF_FTM_MODE:
1619 ret = hdd_start_ftm_adapter(adapter);
1620 if (ret)
1621 goto err_start_adapter;
1622 break;
1623 default:
1624 hdd_err("Invalid session type %d", device_mode);
1625 QDF_ASSERT(0);
1626 goto err_start_adapter;
1627 }
1628 if (hdd_set_fw_params(adapter))
1629 hdd_err("Failed to set the FW params for the adapter!");
1630
1631 /*
1632 * Action frame registered in one adapter which will
1633 * applicable to all interfaces
1634 */
1635 wlan_hdd_cfg80211_register_frames(adapter);
1636 EXIT();
1637 return 0;
1638err_start_adapter:
1639 return -EINVAL;
1640}
1641
1642/**
1643 * hdd_wlan_start_modules() - Single driver state machine for starting modules
1644 * @hdd_ctx: HDD context
1645 * @adapter: HDD adapter
1646 * @reinit: flag to indicate from SSR or normal path
1647 *
1648 * This function maintains the driver state machine it will be invoked from
1649 * startup, reinit and change interface. Depending on the driver state shall
1650 * perform the opening of the modules.
1651 *
1652 * Return: 0 for success; non-zero for failure
1653 */
1654int hdd_wlan_start_modules(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
1655 bool reinit)
1656{
1657 int ret;
1658 qdf_device_t qdf_dev;
1659 QDF_STATUS status;
1660 p_cds_contextType p_cds_context;
1661 bool unint = false;
1662 void *hif_ctx;
1663
1664 ENTER();
1665
1666 p_cds_context = cds_get_global_context();
1667 if (!p_cds_context) {
1668 hdd_err("Global Context is NULL");
1669 QDF_ASSERT(0);
1670 return -EINVAL;
1671 }
1672
1673 hdd_info("start modules called in state! :%d reinit: %d",
1674 hdd_ctx->driver_status, reinit);
1675
1676 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1677 if (!qdf_dev) {
1678 hdd_err("QDF Device Context is Invalid return");
1679 return -EINVAL;
1680 }
1681
1682 mutex_lock(&hdd_ctx->iface_change_lock);
1683
1684 if (QDF_TIMER_STATE_RUNNING ==
1685 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
1686
1687 hdd_set_idle_ps_config(hdd_ctx, false);
1688 hdd_info("Interface change Timer running Stop timer");
1689 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
1690 }
1691
1692 switch (hdd_ctx->driver_status) {
1693 case DRIVER_MODULES_UNINITIALIZED:
1694 unint = true;
1695 /* Fall through dont add break here */
1696 case DRIVER_MODULES_CLOSED:
1697 if (!reinit && !unint) {
1698 ret = pld_power_on(qdf_dev->dev);
1699 if (ret) {
1700 hdd_err("Failed to Powerup the device: %d", ret);
1701 goto release_lock;
1702 }
1703 }
1704 ret = hdd_hif_open(qdf_dev->dev, qdf_dev->drv_hdl, qdf_dev->bid,
1705 qdf_dev->bus_type,
1706 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
1707 HIF_ENABLE_TYPE_PROBE);
1708 if (ret) {
1709 hdd_err("Failed to open hif: %d", ret);
1710 goto power_down;
1711 }
1712
1713 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
1714 status = ol_cds_init(qdf_dev, hif_ctx);
1715 if (status != QDF_STATUS_SUCCESS) {
1716 hdd_err("No Memory to Create BMI Context :%d", status);
1717 goto hif_close;
1718 }
1719
1720 status = cds_open();
1721 if (!QDF_IS_STATUS_SUCCESS(status)) {
1722 hdd_err("Failed to Open CDS: %d", status);
1723 goto ol_cds_free;
1724 }
1725
1726 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
1727
1728 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
1729
1730 status = cds_pre_enable(hdd_ctx->pcds_context);
1731 if (!QDF_IS_STATUS_SUCCESS(status)) {
1732 hdd_err("Failed to pre-enable CDS: %d", status);
1733 goto close;
1734 }
1735
1736 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1737 sme_register_ftm_msg_processor(hdd_ctx->hHal,
1738 hdd_ftm_mc_process_msg);
1739 break;
1740 }
1741 if (unint) {
1742 hdd_info("In phase-1 initialization don't enable modules");
1743 break;
1744 }
1745 /* Fall through dont add break here */
1746 case DRIVER_MODULES_OPENED:
1747 if (!adapter) {
1748 hdd_alert("adapter is Null");
1749 goto close;
1750 }
1751 if (hdd_configure_cds(hdd_ctx, adapter)) {
1752 hdd_err("Failed to Enable cds modules");
1753 goto close;
1754 }
1755 hdd_info("Driver Modules Successfully Enabled");
1756 hdd_ctx->driver_status = DRIVER_MODULES_ENABLED;
1757 break;
1758 case DRIVER_MODULES_ENABLED:
1759 hdd_info("Driver modules already Enabled");
1760 break;
1761 default:
1762 hdd_err("WLAN start invoked in wrong state! :%d\n",
1763 hdd_ctx->driver_status);
1764 goto release_lock;
1765 }
1766 mutex_unlock(&hdd_ctx->iface_change_lock);
1767 EXIT();
1768 return 0;
1769
1770close:
1771 cds_close(p_cds_context);
1772
1773ol_cds_free:
1774 ol_cds_free();
1775
1776hif_close:
1777 hdd_hif_close(p_cds_context->pHIFContext);
1778power_down:
1779 if (!reinit && !unint)
1780 pld_power_off(qdf_dev->dev);
1781release_lock:
1782 mutex_unlock(&hdd_ctx->iface_change_lock);
1783 return -EINVAL;
1784}
1785
1786/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001787 * __hdd_open() - HDD Open function
1788 * @dev: Pointer to net_device structure
1789 *
1790 * This is called in response to ifconfig up
1791 *
1792 * Return: 0 for success; non-zero for failure
1793 */
1794static int __hdd_open(struct net_device *dev)
1795{
1796 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1797 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1798 int ret;
1799
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001800 ENTER_DEV(dev);
1801
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301802 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
Arun Khandavallifae92942016-08-01 13:31:08 +05301803 adapter->sessionId, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804
1805 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301806 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001807 return ret;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301808
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809
Arun Khandavallifae92942016-08-01 13:31:08 +05301810 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
1811 if (ret) {
1812 hdd_err("Failed to start WLAN modules return");
1813 return -ret;
1814 }
1815
1816
1817 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
1818 ret = hdd_start_adapter(adapter);
1819 if (ret) {
1820 hdd_err("Failed to start adapter :%d",
1821 adapter->device_mode);
1822 return ret;
1823 }
1824 }
1825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1827 if (hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Arun Khandavallifae92942016-08-01 13:31:08 +05301828 hdd_info("Enabling Tx Queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001829 /* Enable TX queues only when we are connected */
1830 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05301831 WLAN_START_ALL_NETIF_QUEUE,
1832 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001833 }
1834
1835 return ret;
1836}
1837
Arun Khandavallifae92942016-08-01 13:31:08 +05301838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839/**
1840 * hdd_open() - Wrapper function for __hdd_open to protect it from SSR
1841 * @dev: Pointer to net_device structure
1842 *
1843 * This is called in response to ifconfig up
1844 *
1845 * Return: 0 for success; non-zero for failure
1846 */
1847int hdd_open(struct net_device *dev)
1848{
1849 int ret;
1850
1851 cds_ssr_protect(__func__);
1852 ret = __hdd_open(dev);
1853 cds_ssr_unprotect(__func__);
1854
1855 return ret;
1856}
1857
1858/**
1859 * __hdd_stop() - HDD stop function
1860 * @dev: Pointer to net_device structure
1861 *
1862 * This is called in response to ifconfig down
1863 *
1864 * Return: 0 for success; non-zero for failure
1865 */
1866static int __hdd_stop(struct net_device *dev)
1867{
1868 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1869 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05301870 hdd_adapter_list_node_t *adapternode = NULL, *next = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05301872 bool close_modules = true;
1873 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001875 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301877 MTRACE(qdf_trace(QDF_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 adapter->sessionId, adapter->device_mode));
1879
1880 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301881 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883
1884 /* Nothing to be done if the interface is not opened */
1885 if (false == test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001886 hdd_err("NETDEV Interface is not OPENED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 return -ENODEV;
1888 }
1889
1890 /* Make sure the interface is marked as closed */
1891 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
Jeff Johnson1346fab2016-08-15 13:09:42 -07001892 hdd_notice("Disabling OS Tx queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893
1894 /*
1895 * Disable TX on the interface, after this hard_start_xmit() will not
1896 * be called on that interface
1897 */
Jeff Johnson1346fab2016-08-15 13:09:42 -07001898 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
1900 WLAN_CONTROL_PATH);
1901
1902 /*
1903 * The interface is marked as down for outside world (aka kernel)
1904 * But the driver is pretty much alive inside. The driver needs to
1905 * tear down the existing connection on the netdev (session)
1906 * cleanup the data pipes and wait until the control plane is stabilized
1907 * for this interface. The call also needs to wait until the above
1908 * mentioned actions are completed before returning to the caller.
1909 * Notice that the hdd_stop_adapter is requested not to close the session
1910 * That is intentional to be able to scan if it is a STA/P2P interface
1911 */
Arun Khandavallifae92942016-08-01 13:31:08 +05301912 hdd_stop_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913
1914 /* DeInit the adapter. This ensures datapath cleanup as well */
1915 hdd_deinit_adapter(hdd_ctx, adapter, true);
1916
Arun Khandavallifae92942016-08-01 13:31:08 +05301917
1918 /*
1919 * Find if any iface is up. If any iface is up then can't put device to
1920 * sleep/power save mode
1921 */
1922 status = hdd_get_front_adapter(hdd_ctx, &adapternode);
1923 while ((NULL != adapternode) && (QDF_STATUS_SUCCESS == status)) {
1924 if (test_bit(DEVICE_IFACE_OPENED,
1925 &adapternode->pAdapter->event_flags)) {
1926 hdd_info("Still other ifaces are up cannot close modules");
1927 close_modules = false;
1928 break;
1929 }
1930 status = hdd_get_next_adapter(hdd_ctx, adapternode, &next);
1931 adapternode = next;
1932
1933 }
1934
1935 if (close_modules) {
1936 hdd_info("Closing all modules from the hdd_stop");
1937 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
1938 hdd_ctx->config->iface_change_wait_time
1939 * 50000);
1940 }
1941
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 EXIT();
1943 return 0;
1944}
1945
1946/**
1947 * hdd_stop() - Wrapper function for __hdd_stop to protect it from SSR
1948 * @dev: pointer to net_device structure
1949 *
1950 * This is called in response to ifconfig down
1951 *
1952 * Return: 0 for success and error number for failure
1953 */
1954int hdd_stop(struct net_device *dev)
1955{
1956 int ret;
1957
1958 cds_ssr_protect(__func__);
1959 ret = __hdd_stop(dev);
1960 cds_ssr_unprotect(__func__);
1961
1962 return ret;
1963}
1964
1965/**
1966 * __hdd_uninit() - HDD uninit function
1967 * @dev: Pointer to net_device structure
1968 *
1969 * This is called during the netdev unregister to uninitialize all data
1970 * associated with the device
1971 *
1972 * Return: None
1973 */
1974static void __hdd_uninit(struct net_device *dev)
1975{
1976 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1977
Jeff Johnson3c3994a2016-02-11 08:12:30 -08001978 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979
1980 do {
1981 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001982 hdd_alert("Invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 break;
1984 }
1985
1986 if (NULL == adapter->pHddCtx) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001987 hdd_alert("NULL hdd_ctx");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 break;
1989 }
1990
1991 if (dev != adapter->dev) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07001992 hdd_alert("Invalid device reference");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 /*
1994 * we haven't validated all cases so let this go for
1995 * now
1996 */
1997 }
1998
1999 hdd_deinit_adapter(adapter->pHddCtx, adapter, true);
2000
2001 /* after uninit our adapter structure will no longer be valid */
2002 adapter->dev = NULL;
2003 adapter->magic = 0;
2004 } while (0);
2005
2006 EXIT();
2007}
2008
2009/**
2010 * hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
2011 * @dev: pointer to net_device structure
2012 *
2013 * This is called during the netdev unregister to uninitialize all data
2014 * associated with the device
2015 *
2016 * Return: none
2017 */
2018static void hdd_uninit(struct net_device *dev)
2019{
2020 cds_ssr_protect(__func__);
2021 __hdd_uninit(dev);
2022 cds_ssr_unprotect(__func__);
2023}
2024
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002025static int hdd_open_cesium_nl_sock(void)
2026{
2027#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2028 struct netlink_kernel_cfg cfg = {
2029 .groups = WLAN_NLINK_MCAST_GRP_ID,
2030 .input = NULL
2031 };
2032#endif
2033 int ret = 0;
2034
2035#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
2036 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2037#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
2038 THIS_MODULE,
2039#endif
2040 &cfg);
2041#else
2042 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
2043 WLAN_NLINK_MCAST_GRP_ID,
2044 NULL, NULL, THIS_MODULE);
2045#endif
2046
2047 if (cesium_nl_srv_sock == NULL) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002048 hdd_err("NLINK: cesium netlink_kernel_create failed");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002049 ret = -ECONNREFUSED;
2050 }
2051
2052 return ret;
2053}
2054
2055static void hdd_close_cesium_nl_sock(void)
2056{
2057 if (NULL != cesium_nl_srv_sock) {
2058 netlink_kernel_release(cesium_nl_srv_sock);
2059 cesium_nl_srv_sock = NULL;
2060 }
2061}
2062
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063/**
2064 * __hdd_set_mac_address() - set the user specified mac address
2065 * @dev: Pointer to the net device.
2066 * @addr: Pointer to the sockaddr.
2067 *
2068 * This function sets the user specified mac address using
2069 * the command ifconfig wlanX hw ether <mac adress>.
2070 *
2071 * Return: 0 for success, non zero for failure
2072 */
2073static int __hdd_set_mac_address(struct net_device *dev, void *addr)
2074{
2075 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2076 hdd_context_t *hdd_ctx;
2077 struct sockaddr *psta_mac_addr = addr;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302078 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 int ret;
2080
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002081 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082
2083 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2084 ret = wlan_hdd_validate_context(hdd_ctx);
2085 if (0 != ret)
2086 return ret;
2087
2088 memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
2089 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
2090
2091 EXIT();
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302092 return qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093}
2094
2095/**
2096 * hdd_set_mac_address() - Wrapper function to protect __hdd_set_mac_address()
2097 * function from SSR
2098 * @dev: pointer to net_device structure
2099 * @addr: Pointer to the sockaddr
2100 *
2101 * This function sets the user specified mac address using
2102 * the command ifconfig wlanX hw ether <mac adress>.
2103 *
2104 * Return: 0 for success.
2105 */
2106static int hdd_set_mac_address(struct net_device *dev, void *addr)
2107{
2108 int ret;
2109
2110 cds_ssr_protect(__func__);
2111 ret = __hdd_set_mac_address(dev, addr);
2112 cds_ssr_unprotect(__func__);
2113
2114 return ret;
2115}
2116
2117uint8_t *wlan_hdd_get_intf_addr(hdd_context_t *hdd_ctx)
2118{
2119 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302120 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002121 if (0 == ((hdd_ctx->config->intfAddrMask) & (1 << i)))
2122 break;
2123 }
2124
Anurag Chouhan6d760662016-02-20 16:05:43 +05302125 if (QDF_MAX_CONCURRENCY_PERSONA == i)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002126 return NULL;
2127
2128 hdd_ctx->config->intfAddrMask |= (1 << i);
2129 return &hdd_ctx->config->intfMacAddr[i].bytes[0];
2130}
2131
2132void wlan_hdd_release_intf_addr(hdd_context_t *hdd_ctx, uint8_t *releaseAddr)
2133{
2134 int i;
Anurag Chouhan6d760662016-02-20 16:05:43 +05302135 for (i = 0; i < QDF_MAX_CONCURRENCY_PERSONA; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002136 if (!memcmp(releaseAddr,
2137 &hdd_ctx->config->intfMacAddr[i].bytes[0],
2138 6)) {
2139 hdd_ctx->config->intfAddrMask &= ~(1 << i);
2140 break;
2141 }
2142 }
2143 return;
2144}
2145
2146#ifdef WLAN_FEATURE_PACKET_FILTERING
2147/**
2148 * __hdd_set_multicast_list() - set the multicast address list
2149 * @dev: Pointer to the WLAN device.
2150 * @skb: Pointer to OS packet (sk_buff).
2151 *
2152 * This funciton sets the multicast address list.
2153 *
2154 * Return: None
2155 */
2156static void __hdd_set_multicast_list(struct net_device *dev)
2157{
2158 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2159 int mc_count;
2160 int i = 0, status;
2161 struct netdev_hw_addr *ha;
2162 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2163 static const uint8_t ipv6_router_solicitation[]
2164 = {0x33, 0x33, 0x00, 0x00, 0x00, 0x02};
2165
Jeff Johnson3c3994a2016-02-11 08:12:30 -08002166 ENTER_DEV(dev);
2167
Anurag Chouhan6d760662016-02-20 16:05:43 +05302168 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Mukul Sharma51c44942015-10-30 19:30:19 +05302169 return;
2170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302172 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174
2175 if (dev->flags & IFF_ALLMULTI) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002176 hdd_notice("allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177 adapter->mc_addr_list.mc_cnt = 0;
2178 } else {
2179 mc_count = netdev_mc_count(dev);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002180 hdd_notice("mc_count = %u", mc_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002182 hdd_notice("No free filter available; allow all multicast frames");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 adapter->mc_addr_list.mc_cnt = 0;
2184 return;
2185 }
2186
2187 adapter->mc_addr_list.mc_cnt = mc_count;
2188
2189 netdev_for_each_mc_addr(ha, dev) {
2190 if (i == mc_count)
2191 break;
2192 /*
2193 * Skip following addresses:
2194 * 1)IPv6 router solicitation address
2195 * 2)Any other address pattern if its set during
2196 * RXFILTER REMOVE driver command based on
2197 * addr_filter_pattern
2198 */
2199 if ((!memcmp(ha->addr, ipv6_router_solicitation,
2200 ETH_ALEN)) ||
2201 (adapter->addr_filter_pattern && (!memcmp(ha->addr,
2202 &adapter->addr_filter_pattern, 1)))) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08002203 hdd_info("MC/BC filtering Skip addr ="MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204 MAC_ADDR_ARRAY(ha->addr));
2205 adapter->mc_addr_list.mc_cnt--;
2206 continue;
2207 }
2208
2209 memset(&(adapter->mc_addr_list.addr[i][0]), 0,
2210 ETH_ALEN);
2211 memcpy(&(adapter->mc_addr_list.addr[i][0]), ha->addr,
2212 ETH_ALEN);
Jeff Johnson1346fab2016-08-15 13:09:42 -07002213 hdd_notice("mlist[%d] = " MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 MAC_ADDR_ARRAY(adapter->mc_addr_list.addr[i]));
2215 i++;
2216 }
2217 }
2218 if (hdd_ctx->config->active_mode_offload) {
2219 hdd_info("enable mc filtering");
2220 wlan_hdd_set_mc_addr_list(adapter, true);
2221 } else {
2222 hdd_info("skip mc filtering enable it during cfg80211 suspend");
2223 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302224 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 return;
2226}
2227
2228/**
2229 * hdd_set_multicast_list() - SSR wrapper function for __hdd_set_multicast_list
2230 * @dev: pointer to net_device
2231 *
2232 * Return: none
2233 */
2234static void hdd_set_multicast_list(struct net_device *dev)
2235{
2236 cds_ssr_protect(__func__);
2237 __hdd_set_multicast_list(dev);
2238 cds_ssr_unprotect(__func__);
2239}
2240#endif
2241
2242/**
2243 * hdd_select_queue() - used by Linux OS to decide which queue to use first
2244 * @dev: Pointer to the WLAN device.
2245 * @skb: Pointer to OS packet (sk_buff).
2246 *
2247 * This function is registered with the Linux OS for network
2248 * core to decide which queue to use first.
2249 *
2250 * Return: ac, Queue Index/access category corresponding to UP in IP header
2251 */
2252static uint16_t hdd_select_queue(struct net_device *dev, struct sk_buff *skb
2253#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
2254 , void *accel_priv
2255#endif
2256#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2257 , select_queue_fallback_t fallback
2258#endif
2259)
2260{
2261 return hdd_wmm_select_queue(dev, skb);
2262}
2263
2264static struct net_device_ops wlan_drv_ops = {
2265 .ndo_open = hdd_open,
2266 .ndo_stop = hdd_stop,
2267 .ndo_uninit = hdd_uninit,
2268 .ndo_start_xmit = hdd_hard_start_xmit,
2269 .ndo_tx_timeout = hdd_tx_timeout,
2270 .ndo_get_stats = hdd_get_stats,
2271 .ndo_do_ioctl = hdd_ioctl,
2272 .ndo_set_mac_address = hdd_set_mac_address,
2273 .ndo_select_queue = hdd_select_queue,
2274#ifdef WLAN_FEATURE_PACKET_FILTERING
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 .ndo_set_rx_mode = hdd_set_multicast_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276#endif
2277};
2278
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002279/* Monitor mode net_device_ops, doesnot Tx and most of operations. */
2280static struct net_device_ops wlan_mon_drv_ops = {
2281 .ndo_open = hdd_mon_open,
2282 .ndo_stop = hdd_stop,
2283 .ndo_get_stats = hdd_get_stats,
2284};
2285
2286/**
2287 * hdd_set_station_ops() - update net_device ops for monitor mode
2288 * @pWlanDev: Handle to struct net_device to be updated.
2289 * Return: None
2290 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291void hdd_set_station_ops(struct net_device *pWlanDev)
2292{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002293 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
2294 pWlanDev->netdev_ops = &wlan_mon_drv_ops;
2295 else
2296 pWlanDev->netdev_ops = &wlan_drv_ops;
2297}
2298
2299/**
2300 * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device.
2301 * @dev: Handle to struct net_device to be updated.
2302 *
2303 * Return: None
2304 */
2305static void hdd_mon_mode_ether_setup(struct net_device *dev)
2306{
2307 dev->header_ops = NULL;
2308 dev->type = ARPHRD_IEEE80211_RADIOTAP;
2309 dev->hard_header_len = ETH_HLEN;
2310 dev->mtu = ETH_DATA_LEN;
2311 dev->addr_len = ETH_ALEN;
2312 dev->tx_queue_len = 1000; /* Ethernet wants good queues */
2313 dev->flags = IFF_BROADCAST|IFF_MULTICAST;
2314 dev->priv_flags |= IFF_TX_SKB_SHARING;
2315
2316 memset(dev->broadcast, 0xFF, ETH_ALEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317}
2318
Ryan Hsu07495ea2016-01-21 15:25:39 -08002319/**
2320 * hdd_alloc_station_adapter() - allocate the station hdd adapter
2321 * @hdd_ctx: global hdd context
2322 * @macAddr: mac address to assign to the interface
2323 * @name: User-visible name of the interface
2324 *
2325 * hdd adapter pointer would point to the netdev->priv space, this function
2326 * would retrive the pointer, and setup the hdd adapter configuration.
2327 *
2328 * Return: the pointer to hdd adapter, otherwise NULL
2329 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
2331 tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002332 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 const char *name)
2334{
2335 struct net_device *pWlanDev = NULL;
2336 hdd_adapter_t *adapter = NULL;
2337 /*
2338 * cfg80211 initialization and registration....
2339 */
Ryan Hsu07495ea2016-01-21 15:25:39 -08002340 pWlanDev = alloc_netdev_mq(sizeof(hdd_adapter_t), name,
2341#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
2342 name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07002344 (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ?
2345 hdd_mon_mode_ether_setup : ether_setup),
2346 NUM_TX_QUEUES);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347
2348 if (pWlanDev != NULL) {
2349
2350 /* Save the pointer to the net_device in the HDD adapter */
2351 adapter = (hdd_adapter_t *) netdev_priv(pWlanDev);
2352
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302353 qdf_mem_zero(adapter, sizeof(hdd_adapter_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354
2355 adapter->dev = pWlanDev;
2356 adapter->pHddCtx = hdd_ctx;
2357 adapter->magic = WLAN_HDD_ADAPTER_MAGIC;
2358
2359 init_completion(&adapter->session_open_comp_var);
2360 init_completion(&adapter->session_close_comp_var);
2361 init_completion(&adapter->disconnect_comp_var);
2362 init_completion(&adapter->linkup_event_var);
2363 init_completion(&adapter->cancel_rem_on_chan_var);
2364 init_completion(&adapter->rem_on_chan_ready_event);
2365 init_completion(&adapter->sta_authorized_event);
2366 init_completion(&adapter->offchannel_tx_event);
2367 init_completion(&adapter->tx_action_cnf_event);
2368#ifdef FEATURE_WLAN_TDLS
2369 init_completion(&adapter->tdls_add_station_comp);
2370 init_completion(&adapter->tdls_del_station_comp);
2371 init_completion(&adapter->tdls_mgmt_comp);
2372 init_completion(&adapter->tdls_link_establish_req_comp);
2373#endif
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08002374 init_completion(&adapter->ibss_peer_info_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 init_completion(&adapter->change_country_code);
2376
2377
2378 init_completion(&adapter->scan_info.abortscan_event_var);
2379
2380 adapter->offloads_configured = false;
2381 adapter->isLinkUpSvcNeeded = false;
2382 adapter->higherDtimTransition = true;
2383 /* Init the net_device structure */
2384 strlcpy(pWlanDev->name, name, IFNAMSIZ);
2385
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302386 qdf_mem_copy(pWlanDev->dev_addr, (void *)macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387 sizeof(tSirMacAddr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302388 qdf_mem_copy(adapter->macAddressCurrent.bytes, macAddr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389 sizeof(tSirMacAddr));
2390 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391
2392 if (hdd_ctx->config->enable_ip_tcp_udp_checksum_offload)
2393 pWlanDev->features |=
2394 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
2395 pWlanDev->features |= NETIF_F_RXCSUM;
2396
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002397 hdd_set_tso_flags(hdd_ctx, pWlanDev);
2398
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002399 hdd_set_station_ops(adapter->dev);
2400
2401 pWlanDev->destructor = free_netdev;
2402 pWlanDev->ieee80211_ptr = &adapter->wdev;
Mohit Khannaee9e80f2015-11-10 11:32:49 -08002403 pWlanDev->tx_queue_len = HDD_NETDEV_TX_QUEUE_LEN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404 adapter->wdev.wiphy = hdd_ctx->wiphy;
2405 adapter->wdev.netdev = pWlanDev;
2406 /* set pWlanDev's parent to underlying device */
2407 SET_NETDEV_DEV(pWlanDev, hdd_ctx->parent_dev);
2408 hdd_wmm_init(adapter);
2409 spin_lock_init(&adapter->pause_map_lock);
Nirav Shah617cff92016-04-25 10:24:24 +05302410 adapter->start_time = adapter->last_time = qdf_system_ticks();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 }
2412
2413 return adapter;
2414}
2415
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302416QDF_STATUS hdd_register_interface(hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002417 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418{
2419 struct net_device *pWlanDev = adapter->dev;
2420 /* hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station; */
2421 /* hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX( adapter ); */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302422 /* QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002424 if (rtnl_held) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
2426 if (dev_alloc_name(pWlanDev, pWlanDev->name) < 0) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002427 hdd_err("Failed:dev_alloc_name");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302428 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 }
2430 }
2431 if (register_netdevice(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002432 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302433 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 }
2435 } else {
2436 if (register_netdev(pWlanDev)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002437 hdd_err("Failed:register_netdev");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302438 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 }
2440 }
2441 set_bit(NET_DEVICE_REGISTERED, &adapter->event_flags);
2442
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302443 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444}
2445
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07002446QDF_STATUS hdd_sme_close_session_callback(void *pContext)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447{
2448 hdd_adapter_t *adapter = pContext;
2449
2450 if (NULL == adapter) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002451 hdd_alert("NULL adapter");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302452 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 }
2454
2455 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002456 hdd_alert("Invalid magic");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302457 return QDF_STATUS_NOT_INITIALIZED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 }
2459
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07002460 /*
2461 * For NAN Data interface, the close session results in the final
2462 * indication to the userspace
2463 */
2464 hdd_ndp_session_end_handler(adapter);
2465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 clear_bit(SME_SESSION_OPENED, &adapter->event_flags);
2467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 /*
2469 * We can be blocked while waiting for scheduled work to be
2470 * flushed, and the adapter structure can potentially be freed, in
2471 * which case the magic will have been reset. So make sure the
2472 * magic is still good, and hence the adapter structure is still
2473 * valid, before signaling completion
2474 */
2475 if (WLAN_HDD_ADAPTER_MAGIC == adapter->magic)
2476 complete(&adapter->session_close_comp_var);
2477
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302478 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479}
2480
Krunal Soni8c37e322016-02-03 16:08:37 -08002481/**
2482 * hdd_check_and_init_tdls() - check and init TDLS operation for desired mode
2483 * @adapter: pointer to device adapter
2484 * @type: type of interface
2485 *
2486 * This routine will check the mode of adapter and if it is required then it
2487 * will initialize the TDLS operations
2488 *
2489 * Return: QDF_STATUS
2490 */
2491#ifdef FEATURE_WLAN_TDLS
2492static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2493{
2494 if (QDF_IBSS_MODE != type) {
2495 if (0 != wlan_hdd_tdls_init(adapter)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002496 hdd_err("wlan_hdd_tdls_init failed");
Krunal Soni8c37e322016-02-03 16:08:37 -08002497 return QDF_STATUS_E_FAILURE;
2498 }
2499 set_bit(TDLS_INIT_DONE, &adapter->event_flags);
2500 }
2501 return QDF_STATUS_SUCCESS;
2502}
2503#else
2504static QDF_STATUS hdd_check_and_init_tdls(hdd_adapter_t *adapter, uint32_t type)
2505{
2506 return QDF_STATUS_SUCCESS;
2507}
2508#endif
2509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302510QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002511{
2512 struct net_device *pWlanDev = adapter->dev;
2513 hdd_station_ctx_t *pHddStaCtx = &adapter->sessionCtx.station;
2514 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302515 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302516 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 uint32_t type, subType;
2518 unsigned long rc;
2519 int ret_val;
2520
2521 INIT_COMPLETION(adapter->session_open_comp_var);
2522 sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
Kiran Kumar Lokere666bf852016-05-02 12:23:02 -07002523 sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302525 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002526 hdd_err("failed to get vdev type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 goto error_sme_open;
2528 }
2529 /* Open a SME session for future operation */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302530 qdf_ret_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002531 sme_open_session(hdd_ctx->hHal, hdd_sme_roam_callback, adapter,
2532 (uint8_t *) &adapter->macAddressCurrent,
2533 &adapter->sessionId, type, subType);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302534 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002535 hdd_alert("sme_open_session() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302536 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302537 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 goto error_sme_open;
2539 }
2540 /* Block on a completion variable. Can't wait forever though. */
2541 rc = wait_for_completion_timeout(
2542 &adapter->session_open_comp_var,
2543 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2544 if (!rc) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002545 hdd_alert("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 rc);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302547 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 goto error_sme_open;
2549 }
2550
2551 /* Register wireless extensions */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302552 qdf_ret_status = hdd_register_wext(pWlanDev);
2553 if (QDF_STATUS_SUCCESS != qdf_ret_status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002554 hdd_alert("hdd_register_wext() failed, status code %08d [x%08x]",
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05302555 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302556 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 goto error_register_wext;
2558 }
2559 /* Set the Connection State to Not Connected */
Jeff Johnson1346fab2016-08-15 13:09:42 -07002560 hdd_notice("Set HDD connState to eConnectionState_NotConnected");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2562
2563 /* Set the default operation channel */
2564 pHddStaCtx->conn_info.operationChannel =
2565 hdd_ctx->config->OperatingChannel;
2566
2567 /* Make the default Auth Type as OPEN */
2568 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
2569
2570 status = hdd_init_tx_rx(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302571 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002572 hdd_alert("hdd_init_tx_rx() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573 status, status);
2574 goto error_init_txrx;
2575 }
2576
2577 set_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2578
2579 status = hdd_wmm_adapter_init(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302580 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002581 hdd_alert("hdd_wmm_adapter_init() failed, status code %08d [x%08x]",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 status, status);
2583 goto error_wmm_init;
2584 }
2585
2586 set_bit(WMM_INIT_DONE, &adapter->event_flags);
2587
2588 ret_val = wma_cli_set_command(adapter->sessionId,
2589 WMI_PDEV_PARAM_BURST_ENABLE,
2590 hdd_ctx->config->enableSifsBurst,
2591 PDEV_CMD);
2592
2593 if (0 != ret_val) {
Jeff Johnson1346fab2016-08-15 13:09:42 -07002594 hdd_err("WMI_PDEV_PARAM_BURST_ENABLE set failed %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 ret_val);
2596 }
Krunal Soni8c37e322016-02-03 16:08:37 -08002597 status = hdd_check_and_init_tdls(adapter, type);
2598 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 goto error_tdls_init;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302601 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602
2603#ifdef FEATURE_WLAN_TDLS
2604error_tdls_init:
2605 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2606 hdd_wmm_adapter_close(adapter);
2607#endif
2608error_wmm_init:
2609 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2610 hdd_deinit_tx_rx(adapter);
2611error_init_txrx:
2612 hdd_unregister_wext(pWlanDev);
2613error_register_wext:
2614 if (test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
2615 INIT_COMPLETION(adapter->session_close_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302616 if (QDF_STATUS_SUCCESS == sme_close_session(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617 adapter->sessionId,
2618 hdd_sme_close_session_callback,
2619 adapter)) {
2620 unsigned long rc;
2621
2622 /*
2623 * Block on a completion variable.
2624 * Can't wait forever though.
2625 */
2626 rc = wait_for_completion_timeout(
2627 &adapter->session_close_comp_var,
2628 msecs_to_jiffies
2629 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2630 if (rc <= 0)
Jeff Johnson1346fab2016-08-15 13:09:42 -07002631 hdd_err("Session is not opened within timeout period code %ld",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002632 rc);
2633 }
2634 }
2635error_sme_open:
2636 return status;
2637}
2638
2639void hdd_cleanup_actionframe(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
2640{
2641 hdd_cfg80211_state_t *cfgState;
2642
2643 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
2644
2645 if (NULL != cfgState->buf) {
2646 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647 rc = wait_for_completion_timeout(
2648 &adapter->tx_action_cnf_event,
2649 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
2650 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07002651 hdd_err("HDD Wait for Action Confirmation Failed!!");
Masti, Narayanraddif8f6e7e2015-08-25 10:22:46 +05302652 /*
2653 * Inform tx status as FAILURE to upper layer and free
2654 * cfgState->buf
2655 */
2656 hdd_send_action_cnf(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 }
2658 }
2659 return;
2660}
2661
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302662/**
2663 * hdd_station_adapter_deinit() - De-initialize the station adapter
2664 * @hdd_ctx: global hdd context
2665 * @adapter: HDD adapter
2666 *
2667 * This function De-initializes the STA/P2P/OCB adapter.
2668 *
2669 * Return: None.
2670 */
2671void hdd_station_adapter_deinit(hdd_context_t *hdd_ctx,
2672 hdd_adapter_t *adapter)
2673{
2674 ENTER_DEV(adapter->dev);
2675
2676 if (test_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags)) {
2677 hdd_deinit_tx_rx(adapter);
2678 clear_bit(INIT_TX_RX_SUCCESS, &adapter->event_flags);
2679 }
2680
2681 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2682 hdd_wmm_adapter_close(adapter);
2683 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2684 }
2685
2686 hdd_cleanup_actionframe(hdd_ctx, adapter);
2687 wlan_hdd_tdls_exit(adapter);
2688
2689 EXIT();
2690}
2691
2692/**
2693 * hdd_ap_adapter_deinit() - De-initialize the ap adapter
2694 * @hdd_ctx: global hdd context
2695 * @adapter: HDD adapter
2696 * @rtnl_held: the rtnl lock hold flag
2697 * This function De-initializes the AP/P2PGo adapter.
2698 *
2699 * Return: None.
2700 */
2701void hdd_ap_adapter_deinit(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2702 bool rtnl_held)
2703{
2704 ENTER_DEV(adapter->dev);
2705
2706 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
2707 hdd_wmm_adapter_close(adapter);
2708 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
2709 }
2710
2711 hdd_cleanup_actionframe(hdd_ctx, adapter);
2712
2713 hdd_unregister_hostapd(adapter, rtnl_held);
2714
2715 EXIT();
2716}
2717
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718void hdd_deinit_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2719 bool rtnl_held)
2720{
2721 ENTER();
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302722
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002724 case QDF_STA_MODE:
2725 case QDF_P2P_CLIENT_MODE:
2726 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727 {
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302728 hdd_station_adapter_deinit(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729 break;
2730 }
2731
Krunal Soni9b04c9b2016-03-10 13:08:05 -08002732 case QDF_SAP_MODE:
2733 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002734 {
2735
Arun Khandavalli7e857c32016-06-26 12:07:16 +05302736 hdd_ap_adapter_deinit(hdd_ctx, adapter, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737 break;
2738 }
2739
2740 default:
2741 break;
2742 }
2743
2744 EXIT();
2745}
2746
2747void hdd_cleanup_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08002748 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749{
2750 struct net_device *pWlanDev = NULL;
2751
2752 if (adapter)
2753 pWlanDev = adapter->dev;
2754 else {
Jeff Johnson5880d792016-08-15 13:32:30 -07002755 hdd_err("adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 return;
2757 }
2758
2759 hdd_lro_disable(hdd_ctx, adapter);
Rajeev Kumardca5f812016-02-04 17:28:06 -08002760 hdd_debugfs_exit(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 /*
2762 * The adapter is marked as closed. When hdd_wlan_exit() call returns,
2763 * the driver is almost closed and cannot handle either control
2764 * messages or data. However, unregister_netdevice() call above will
2765 * eventually invoke hdd_stop (ndo_close) driver callback, which attempts
2766 * to close the active connections (basically excites control path) which
2767 * is not right. Setting this flag helps hdd_stop() to recognize that
2768 * the interface is closed and restricts any operations on that
2769 */
2770 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
2771
2772 if (test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags)) {
2773 if (rtnl_held) {
2774 unregister_netdevice(pWlanDev);
2775 } else {
2776 unregister_netdev(pWlanDev);
2777 }
2778 /*
2779 * Note that the adapter is no longer valid at this point
2780 * since the memory has been reclaimed
2781 */
2782 }
2783}
2784
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302785QDF_STATUS hdd_check_for_existing_macaddr(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786 tSirMacAddr macAddr)
2787{
2788 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
2789 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302790 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302792 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 adapter = adapterNode->pAdapter;
2794 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302795 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 macAddr, sizeof(tSirMacAddr))) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302797 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798 }
2799 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
2800 adapterNode = pNext;
2801 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302802 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002803}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002804
Arun Khandavalli2358d522016-05-16 18:05:37 +05302805#ifdef CONFIG_FW_LOGS_BASED_ON_INI
2806/**
2807 * hdd_set_fw_log_params() - Set log parameters to FW
2808 * @hdd_ctx: HDD Context
2809 * @adapter: HDD Adapter
2810 *
2811 * This function set the FW Debug log level based on the INI.
2812 *
2813 * Return: None
2814 */
2815static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2816 hdd_adapter_t *adapter)
2817{
2818 uint8_t count = 0, numentries = 0,
2819 moduleloglevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
2820 uint32_t value = 0;
2821 int ret;
2822
Arun Khandavallifae92942016-08-01 13:31:08 +05302823 if (QDF_GLOBAL_FTM_MODE == cds_get_conparam() ||
2824 (!hdd_ctx->config->enable_fw_log)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302825 hdd_info("enable_fw_log not enabled in INI or in FTM mode return");
2826 return;
2827 }
2828
Arun Khandavallifae92942016-08-01 13:31:08 +05302829 /* Enable FW logs based on INI configuration */
Arun Khandavalli2358d522016-05-16 18:05:37 +05302830 hdd_ctx->fw_log_settings.dl_type =
2831 hdd_ctx->config->enableFwLogType;
2832 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302833 WMI_DBGLOG_TYPE,
2834 hdd_ctx->config->enableFwLogType,
2835 DBG_CMD);
2836 if (ret != 0)
2837 hdd_err("Failed to enable FW log type ret %d",
2838 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302839
2840 hdd_ctx->fw_log_settings.dl_loglevel =
Arun Khandavallifae92942016-08-01 13:31:08 +05302841 hdd_ctx->config->enableFwLogLevel;
Arun Khandavalli2358d522016-05-16 18:05:37 +05302842 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302843 WMI_DBGLOG_LOG_LEVEL,
2844 hdd_ctx->config->enableFwLogLevel,
2845 DBG_CMD);
2846 if (ret != 0)
2847 hdd_err("Failed to enable FW log level ret %d",
2848 ret);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302849
2850 hdd_string_to_u8_array(
2851 hdd_ctx->config->enableFwModuleLogLevel,
2852 moduleloglevel,
2853 &numentries,
2854 FW_MODULE_LOG_LEVEL_STRING_LENGTH);
2855
2856 while (count < numentries) {
2857 /*
2858 * FW module log level input string looks like
2859 * below:
2860 * gFwDebugModuleLoglevel=<FW Module ID>,
2861 * <Log Level>,...
2862 * For example:
2863 * gFwDebugModuleLoglevel=
2864 * 1,0,2,1,3,2,4,3,5,4,6,5,7,6
2865 * Above input string means :
2866 * For FW module ID 1 enable log level 0
2867 * For FW module ID 2 enable log level 1
2868 * For FW module ID 3 enable log level 2
2869 * For FW module ID 4 enable log level 3
2870 * For FW module ID 5 enable log level 4
2871 * For FW module ID 6 enable log level 5
2872 * For FW module ID 7 enable log level 6
2873 */
2874
Arun Khandavallifae92942016-08-01 13:31:08 +05302875 /* FW expects WMI command value =
Arun Khandavalli2358d522016-05-16 18:05:37 +05302876 * Module ID * 10 + Module Log level
2877 */
2878 value = ((moduleloglevel[count] * 10) +
2879 moduleloglevel[count + 1]);
2880 ret = wma_cli_set_command(adapter->sessionId,
Arun Khandavallifae92942016-08-01 13:31:08 +05302881 WMI_DBGLOG_MOD_LOG_LEVEL,
2882 value, DBG_CMD);
2883 if (ret != 0)
Arun Khandavalli2358d522016-05-16 18:05:37 +05302884 hdd_err("Failed to enable FW module log level %d ret %d",
2885 value, ret);
2886
2887 count += 2;
2888 }
Arun Khandavallifae92942016-08-01 13:31:08 +05302889
Arun Khandavalli2358d522016-05-16 18:05:37 +05302890}
2891#else
2892static void hdd_set_fw_log_params(hdd_context_t *hdd_ctx,
2893 hdd_adapter_t *adapter)
2894{
2895}
2896
2897#endif
2898
2899/**
2900 * hdd_set_fw_params() - Set parameters to firmware
2901 * @adapter: HDD adapter
2902 *
2903 * This function Sets various parameters to fw once the
2904 * adapter is started.
2905 *
2906 * Return: 0 on success or errno on failure
2907 */
2908int hdd_set_fw_params(hdd_adapter_t *adapter)
2909{
2910 int ret;
2911 hdd_context_t *hdd_ctx;
2912
2913 ENTER_DEV(adapter->dev);
2914
2915 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2916 if (!hdd_ctx)
2917 return -EINVAL;
2918
Arun Khandavallifae92942016-08-01 13:31:08 +05302919 if ((cds_get_conparam() != QDF_GLOBAL_FTM_MODE) ||
2920 (!hdd_ctx->config->enable2x2)) {
Arun Khandavalli2358d522016-05-16 18:05:37 +05302921 hdd_info("enable2x2 not enabled in INI or in FTM mode return");
2922 return 0;
2923 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05302924#define HDD_DTIM_1CHAIN_RX_ID 0x5
2925#define HDD_SMPS_PARAM_VALUE_S 29
2926
2927 /*
2928 * Disable DTIM 1 chain Rx when in 1x1,
2929 * we are passing two value
2930 * as param_id << 29 | param_value.
2931 * Below param_value = 0(disable)
2932 */
2933 ret = wma_cli_set_command(adapter->sessionId,
2934 WMI_STA_SMPS_PARAM_CMDID,
2935 HDD_DTIM_1CHAIN_RX_ID <<
2936 HDD_SMPS_PARAM_VALUE_S,
2937 VDEV_CMD);
2938 if (ret) {
2939 hdd_err("DTIM 1 chain set failed %d", ret);
2940 goto error;
2941 }
2942
2943 ret = wma_cli_set_command(adapter->sessionId,
2944 WMI_PDEV_PARAM_TX_CHAIN_MASK,
2945 hdd_ctx->config->txchainmask1x1,
2946 PDEV_CMD);
2947 if (ret) {
2948 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK set failed %d",
2949 ret);
2950 goto error;
2951 }
2952
2953 ret = wma_cli_set_command(adapter->sessionId,
2954 WMI_PDEV_PARAM_RX_CHAIN_MASK,
2955 hdd_ctx->config->rxchainmask1x1,
2956 PDEV_CMD);
2957 if (ret) {
2958 hdd_err("WMI_PDEV_PARAM_RX_CHAIN_MASK set failed %d",
2959 ret);
2960 goto error;
2961 }
2962#undef HDD_DTIM_1CHAIN_RX_ID
2963#undef HDD_SMPS_PARAM_VALUE_S
Arun Khandavallifae92942016-08-01 13:31:08 +05302964 if (QDF_GLOBAL_FTM_MODE != cds_get_conparam()) {
2965 ret = wma_cli_set_command(adapter->sessionId,
2966 WMI_PDEV_PARAM_HYST_EN,
2967 hdd_ctx->config->enableMemDeepSleep,
2968 PDEV_CMD);
Arun Khandavalli2358d522016-05-16 18:05:37 +05302969
Arun Khandavallifae92942016-08-01 13:31:08 +05302970 if (ret) {
2971 hdd_err("WMI_PDEV_PARAM_HYST_EN set failed %d",
2972 ret);
2973 goto error;
2974 }
Arun Khandavalli2358d522016-05-16 18:05:37 +05302975 }
2976
2977 hdd_set_fw_log_params(hdd_ctx, adapter);
2978
2979 EXIT();
2980 return 0;
Arun Khandavallifae92942016-08-01 13:31:08 +05302981
Arun Khandavalli2358d522016-05-16 18:05:37 +05302982error:
2983 return -EINVAL;
2984}
2985
Ryan Hsu07495ea2016-01-21 15:25:39 -08002986/**
2987 * hdd_open_adapter() - open and setup the hdd adatper
2988 * @hdd_ctx: global hdd context
2989 * @session_type: type of the interface to be created
2990 * @iface_name: User-visible name of the interface
2991 * @macAddr: MAC address to assign to the interface
2992 * @name_assign_type: the name of assign type of the netdev
2993 * @rtnl_held: the rtnl lock hold flag
2994 *
2995 * This function open and setup the hdd adpater according to the device
2996 * type request, assign the name, the mac address assigned, and then prepared
2997 * the hdd related parameters, queue, lock and ready to start.
2998 *
2999 * Return: the pointer of hdd adapter, otherwise NULL.
3000 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type,
3002 const char *iface_name, tSirMacAddr macAddr,
Ryan Hsu07495ea2016-01-21 15:25:39 -08003003 unsigned char name_assign_type,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003004 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005{
3006 hdd_adapter_t *adapter = NULL;
3007 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303008 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003009 hdd_cfg80211_state_t *cfgState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010
Arun Khandavallifae92942016-08-01 13:31:08 +05303011 hdd_info("iface(%s) type(%d)", iface_name, session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012
3013 if (hdd_ctx->current_intf_count >= hdd_ctx->max_intf_count) {
3014 /*
3015 * Max limit reached on the number of vdevs configured by the
3016 * host. Return error
3017 */
Arun Khandavallifae92942016-08-01 13:31:08 +05303018 hdd_err("Unable to add virtual intf: currentVdevCnt=%d,hostConfiguredVdevCnt=%d",
3019 hdd_ctx->current_intf_count, hdd_ctx->max_intf_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003020 return NULL;
3021 }
3022
3023 if (macAddr == NULL) {
3024 /* Not received valid macAddr */
Arun Khandavallifae92942016-08-01 13:31:08 +05303025 hdd_err("Unable to add virtual intf: Not able to get valid mac address");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003026 return NULL;
3027 }
3028 status = hdd_check_for_existing_macaddr(hdd_ctx, macAddr);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303029 if (QDF_STATUS_E_FAILURE == status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303030 hdd_err("Duplicate MAC addr: " MAC_ADDRESS_STR
3031 " already exists",
3032 MAC_ADDR_ARRAY(macAddr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 return NULL;
3034 }
3035
3036 switch (session_type) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003037 case QDF_STA_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 /* Reset locally administered bit if the device mode is STA */
3039 WLAN_HDD_RESET_LOCALLY_ADMINISTERED_BIT(macAddr);
3040 /* fall through */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003041 case QDF_P2P_CLIENT_MODE:
3042 case QDF_P2P_DEVICE_MODE:
3043 case QDF_OCB_MODE:
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003044 case QDF_NDI_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003045 adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr,
3046 name_assign_type,
3047 iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048
3049 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303050 hdd_err("failed to allocate adapter for session %d",
3051 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003052 return NULL;
3053 }
3054
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003055 if (QDF_P2P_CLIENT_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003057 else if (QDF_P2P_DEVICE_MODE == session_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003058 adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 else
3060 adapter->wdev.iftype = NL80211_IFTYPE_STATION;
3061
3062 adapter->device_mode = session_type;
3063
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303064 if (QDF_NDI_MODE == session_type) {
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07003065 status = hdd_init_nan_data_mode(adapter);
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303066 if (QDF_STATUS_SUCCESS != status)
3067 goto err_free_netdev;
Arun Khandavalli7e857c32016-06-26 12:07:16 +05303068 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003069
3070 hdd_lro_enable(hdd_ctx, adapter);
3071
3072 /*
3073 * Workqueue which gets scheduled in IPv4 notification
3074 * callback
3075 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003076 INIT_WORK(&adapter->ipv4NotifierWorkQueue,
3077 hdd_ipv4_notifier_work_queue);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078
3079#ifdef WLAN_NS_OFFLOAD
3080 /*
3081 * Workqueue which gets scheduled in IPv6
3082 * notification callback.
3083 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003084 INIT_WORK(&adapter->ipv6NotifierWorkQueue,
3085 hdd_ipv6_notifier_work_queue);
3086#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 status = hdd_register_interface(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303088 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3090 goto err_lro_cleanup;
3091 }
3092
3093 /* Stop the Interface TX queue. */
Arun Khandavallifae92942016-08-01 13:31:08 +05303094 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003095 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303096 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3097 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003098 break;
Arun Khandavallifae92942016-08-01 13:31:08 +05303099
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003101 case QDF_P2P_GO_MODE:
3102 case QDF_SAP_MODE:
Ryan Hsu07495ea2016-01-21 15:25:39 -08003103 adapter = hdd_wlan_create_ap_dev(hdd_ctx, macAddr,
3104 name_assign_type,
3105 (uint8_t *) iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003106 if (NULL == adapter) {
Arun Khandavallifae92942016-08-01 13:31:08 +05303107 hdd_alert("failed to allocate adapter for session %d",
3108 session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003109 return NULL;
3110 }
3111
3112 adapter->wdev.iftype =
3113 (session_type ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003114 QDF_SAP_MODE) ? NL80211_IFTYPE_AP :
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 NL80211_IFTYPE_P2P_GO;
3116 adapter->device_mode = session_type;
3117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118 status = hdd_register_hostapd(adapter, rtnl_held);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303119 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120 hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held);
3121 goto err_free_netdev;
3122 }
Arun Khandavallifae92942016-08-01 13:31:08 +05303123 hdd_info("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 wlan_hdd_netif_queue_control(adapter,
Arun Khandavallifae92942016-08-01 13:31:08 +05303125 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3126 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003127 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 default:
Arun Khandavallifae92942016-08-01 13:31:08 +05303129 hdd_alert("Invalid session type %d", session_type);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303130 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003131 return NULL;
3132 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003133
3134 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
3135 mutex_init(&cfgState->remain_on_chan_ctx_lock);
3136
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303137 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 /* Add it to the hdd's session list. */
3139 pHddAdapterNode =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303140 qdf_mem_malloc(sizeof(hdd_adapter_list_node_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 if (NULL == pHddAdapterNode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303142 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003143 } else {
3144 pHddAdapterNode->pAdapter = adapter;
3145 status = hdd_add_adapter_back(hdd_ctx, pHddAdapterNode);
3146 }
3147 }
3148
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303149 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 if (NULL != adapter) {
3151 hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
3152 adapter = NULL;
3153 }
3154 if (NULL != pHddAdapterNode) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303155 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 }
3157 return NULL;
3158 }
3159
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303160 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003161 cds_set_concurrency_mode(session_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162
3163 /* Initialize the WoWL service */
3164 if (!hdd_init_wowl(adapter)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003165 hdd_alert("hdd_init_wowl failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 goto err_lro_cleanup;
3167 }
3168
3169 /* Adapter successfully added. Increment the vdev count */
3170 hdd_ctx->current_intf_count++;
3171
Jeff Johnson5880d792016-08-15 13:32:30 -07003172 hdd_debug("current_intf_count=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003173 hdd_ctx->current_intf_count);
3174
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003175 cds_check_and_restart_sap_with_non_dfs_acs();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 }
3177
Rajeev Kumardca5f812016-02-04 17:28:06 -08003178 if (QDF_STATUS_SUCCESS != hdd_debugfs_init(adapter))
3179 hdd_err("Interface %s wow debug_fs init failed", iface_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180
3181 return adapter;
3182
3183err_lro_cleanup:
3184 hdd_lro_disable(hdd_ctx, adapter);
3185err_free_netdev:
3186 free_netdev(adapter->dev);
3187 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
3188
3189 return NULL;
3190}
3191
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303192QDF_STATUS hdd_close_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003193 bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194{
3195 hdd_adapter_list_node_t *adapterNode, *pCurrent, *pNext;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303196 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197
3198 status = hdd_get_front_adapter(hdd_ctx, &pCurrent);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303199 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003200 hdd_warn("adapter list empty %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201 status);
3202 return status;
3203 }
3204
3205 while (pCurrent->pAdapter != adapter) {
3206 status = hdd_get_next_adapter(hdd_ctx, pCurrent, &pNext);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303207 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208 break;
3209
3210 pCurrent = pNext;
3211 }
3212 adapterNode = pCurrent;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303213 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003214 cds_clear_concurrency_mode(adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 hdd_cleanup_adapter(hdd_ctx, adapterNode->pAdapter, rtnl_held);
3216
3217 hdd_remove_adapter(hdd_ctx, adapterNode);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303218 qdf_mem_free(adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219 adapterNode = NULL;
3220
3221 /* Adapter removed. Decrement vdev count */
3222 if (hdd_ctx->current_intf_count != 0)
3223 hdd_ctx->current_intf_count--;
3224
3225 /* Fw will take care incase of concurrency */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303226 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303228 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229}
3230
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003231/**
3232 * hdd_close_all_adapters - Close all open adapters
3233 * @hdd_ctx: Hdd context
3234 * rtnl_held: True if RTNL lock held
3235 *
3236 * Close all open adapters.
3237 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303238 * Return: QDF status code
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003239 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303240QDF_STATUS hdd_close_all_adapters(hdd_context_t *hdd_ctx, bool rtnl_held)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241{
3242 hdd_adapter_list_node_t *pHddAdapterNode;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303243 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
3245 ENTER();
3246
3247 do {
3248 status = hdd_remove_front_adapter(hdd_ctx, &pHddAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303249 if (pHddAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250 hdd_cleanup_adapter(hdd_ctx, pHddAdapterNode->pAdapter,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08003251 rtnl_held);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303252 qdf_mem_free(pHddAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303254 } while (NULL != pHddAdapterNode && QDF_STATUS_E_EMPTY != status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255
3256 EXIT();
3257
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303258 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003259}
3260
3261void wlan_hdd_reset_prob_rspies(hdd_adapter_t *pHostapdAdapter)
3262{
Anurag Chouhan6d760662016-02-20 16:05:43 +05303263 struct qdf_mac_addr *bssid = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264 tSirUpdateIE updateIE;
3265 switch (pHostapdAdapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003266 case QDF_STA_MODE:
3267 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003268 {
3269 hdd_station_ctx_t *pHddStaCtx =
3270 WLAN_HDD_GET_STATION_CTX_PTR(pHostapdAdapter);
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003271 bssid = &pHddStaCtx->conn_info.bssId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 break;
3273 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003274 case QDF_SAP_MODE:
3275 case QDF_P2P_GO_MODE:
3276 case QDF_IBSS_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 {
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003278 bssid = &pHostapdAdapter->macAddressCurrent;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 break;
3280 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003281 case QDF_FTM_MODE:
3282 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003283 default:
3284 /*
3285 * wlan_hdd_reset_prob_rspies should not have been called
3286 * for these kind of devices
3287 */
Jeff Johnson5880d792016-08-15 13:32:30 -07003288 hdd_err("Unexpected request for the current device type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 pHostapdAdapter->device_mode);
3290 return;
3291 }
3292
Anurag Chouhanc5548422016-02-24 18:33:27 +05303293 qdf_copy_macaddr(&updateIE.bssid, bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294 updateIE.smeSessionId = pHostapdAdapter->sessionId;
3295 updateIE.ieBufferlength = 0;
3296 updateIE.pAdditionIEBuffer = NULL;
3297 updateIE.append = true;
3298 updateIE.notify = false;
3299 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pHostapdAdapter),
3300 &updateIE,
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303301 eUPDATE_IE_PROBE_RESP) == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003302 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003303 }
3304}
3305
Peng Xu66162de2016-02-11 17:01:20 -08003306/**
3307 * hdd_wait_for_sme_close_sesion() - Close and wait for SME session close
3308 * @hdd_ctx: HDD context which is already NULL validated
3309 * @adapter: HDD adapter which is already NULL validated
3310 *
3311 * Close the SME session and wait for its completion, if needed.
3312 *
3313 * Return: None
3314 */
3315static void hdd_wait_for_sme_close_sesion(hdd_context_t *hdd_ctx,
3316 hdd_adapter_t *adapter)
3317{
3318 unsigned long rc;
3319
3320 if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
3321 hdd_err("session is not opened:%d", adapter->sessionId);
3322 return;
3323 }
3324
3325 INIT_COMPLETION(adapter->session_close_comp_var);
3326 if (QDF_STATUS_SUCCESS ==
3327 sme_close_session(hdd_ctx->hHal, adapter->sessionId,
3328 hdd_sme_close_session_callback,
3329 adapter)) {
3330 /*
3331 * Block on a completion variable. Can't wait
3332 * forever though.
3333 */
3334 rc = wait_for_completion_timeout(
3335 &adapter->session_close_comp_var,
3336 msecs_to_jiffies
3337 (WLAN_WAIT_TIME_SESSIONOPENCLOSE));
3338 if (!rc)
3339 hdd_err("failure waiting for session_close_comp_var");
3340 }
3341}
3342
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303343QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344 const bool bCloseSession)
3345{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303346 QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
3348 union iwreq_data wrqu;
3349 tSirUpdateIE updateIE;
3350 unsigned long rc;
3351
3352 ENTER();
3353
Jeff Johnson5880d792016-08-15 13:32:30 -07003354 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355 wlan_hdd_netif_queue_control(adapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
3356 WLAN_CONTROL_PATH);
3357 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003358 case QDF_STA_MODE:
3359 case QDF_P2P_CLIENT_MODE:
3360 case QDF_IBSS_MODE:
3361 case QDF_P2P_DEVICE_MODE:
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003362 case QDF_NDI_MODE:
3363 if ((QDF_NDI_MODE == adapter->device_mode) ||
3364 hdd_conn_is_connected(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003365 WLAN_HDD_GET_STATION_CTX_PTR(adapter)) ||
3366 hdd_is_connecting(
3367 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003368 INIT_COMPLETION(adapter->disconnect_comp_var);
3369 /*
3370 * For NDI do not use pWextState from sta_ctx, if needed
3371 * extract from ndi_ctx.
3372 */
3373 if (QDF_NDI_MODE == adapter->device_mode)
3374 qdf_ret_status = sme_roam_disconnect(
3375 hdd_ctx->hHal,
3376 adapter->sessionId,
3377 eCSR_DISCONNECT_REASON_NDI_DELETE);
3378 else if (pWextState->roamProfile.BSSType ==
3379 eCSR_BSS_TYPE_START_IBSS)
3380 qdf_ret_status = sme_roam_disconnect(
3381 hdd_ctx->hHal,
3382 adapter->sessionId,
3383 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003384 else
Deepak Dhamdhere13983f22016-05-31 19:06:09 -07003385 qdf_ret_status = sme_roam_disconnect(
3386 hdd_ctx->hHal,
3387 adapter->sessionId,
3388 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 /* success implies disconnect command got queued up successfully */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303390 if (qdf_ret_status == QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391 rc = wait_for_completion_timeout(
3392 &adapter->disconnect_comp_var,
3393 msecs_to_jiffies
3394 (WLAN_WAIT_TIME_DISCONNECT));
3395 if (!rc) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003396 hdd_err("wait on disconnect_comp_var failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003397 }
3398 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003399 hdd_err("failed to post disconnect event to SME");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 }
3401 memset(&wrqu, '\0', sizeof(wrqu));
3402 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3403 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3404 wireless_send_event(adapter->dev, SIOCGIWAP, &wrqu,
3405 NULL);
3406 } else {
3407 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
3408 eCSR_SCAN_ABORT_DEFAULT);
3409 }
Abhishek Singh1e94d7a2015-11-30 17:26:54 +05303410 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003411
3412#ifdef WLAN_OPEN_SOURCE
3413 cancel_work_sync(&adapter->ipv4NotifierWorkQueue);
3414#endif
3415
3416 hdd_deregister_tx_flow_control(adapter);
3417
3418#ifdef WLAN_NS_OFFLOAD
3419#ifdef WLAN_OPEN_SOURCE
3420 cancel_work_sync(&adapter->ipv6NotifierWorkQueue);
3421#endif
3422#endif
3423
3424 /*
3425 * It is possible that the caller of this function does not
3426 * wish to close the session
3427 */
Peng Xu66162de2016-02-11 17:01:20 -08003428 if (true == bCloseSession)
3429 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 break;
3431
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003432 case QDF_SAP_MODE:
3433 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003434 if (hdd_ctx->config->conc_custom_rule1 &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003435 (QDF_SAP_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 /*
3437 * Before stopping the sap adapter, lets make sure there
3438 * is no sap restart work pending.
3439 */
3440 cds_flush_work(&hdd_ctx->sap_start_work);
Jeff Johnson5880d792016-08-15 13:32:30 -07003441 hdd_info("Canceled the pending SAP restart work");
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003442 cds_change_sap_restart_required_status(false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003443 }
3444 /* Any softap specific cleanup here... */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003445 if (adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003446 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
3447
3448 hdd_deregister_tx_flow_control(adapter);
3449
3450 mutex_lock(&hdd_ctx->sap_lock);
3451 if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303452 QDF_STATUS status;
Anurag Chouhance0dc992016-02-16 18:18:03 +05303453 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454
3455 /* Stop Bss. */
3456#ifdef WLAN_FEATURE_MBSSID
3457 status = wlansap_stop_bss(
3458 WLAN_HDD_GET_SAP_CTX_PTR(adapter));
3459#else
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003460 status = wlansap_stop_bss(
3461 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462#endif
3463
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303464 if (QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465 hdd_hostapd_state_t *hostapd_state =
3466 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303467 qdf_event_reset(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303468 qdf_stop_bss_event);
Anurag Chouhance0dc992016-02-16 18:18:03 +05303469 qdf_status =
3470 qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05303471 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472 BSS_WAIT_TIMEOUT);
3473
Anurag Chouhance0dc992016-02-16 18:18:03 +05303474 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003475 hdd_err("failure waiting for wlansap_stop_bss %d",
3476 qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 }
3478 } else {
Jeff Johnson5880d792016-08-15 13:32:30 -07003479 hdd_err("failure in wlansap_stop_bss");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 }
3481 clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08003482 cds_decr_session_set_pcl(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 adapter->device_mode,
3484 adapter->sessionId);
3485
Anurag Chouhanc5548422016-02-24 18:33:27 +05303486 qdf_copy_macaddr(&updateIE.bssid,
Srinivas Girigowda8b983962015-11-18 22:14:34 -08003487 &adapter->macAddressCurrent);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488 updateIE.smeSessionId = adapter->sessionId;
3489 updateIE.ieBufferlength = 0;
3490 updateIE.pAdditionIEBuffer = NULL;
3491 updateIE.append = false;
3492 updateIE.notify = false;
3493 /* Probe bcn reset */
3494 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3495 &updateIE, eUPDATE_IE_PROBE_BCN)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303496 == QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003497 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 }
3499 /* Assoc resp reset */
3500 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
3501 &updateIE,
3502 eUPDATE_IE_ASSOC_RESP) ==
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303503 QDF_STATUS_E_FAILURE) {
Jeff Johnson5880d792016-08-15 13:32:30 -07003504 hdd_err("Could not pass on ASSOC_RSP data to PE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003505 }
3506 /* Reset WNI_CFG_PROBE_RSP Flags */
3507 wlan_hdd_reset_prob_rspies(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303508 qdf_mem_free(adapter->sessionCtx.ap.beacon);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003509 adapter->sessionCtx.ap.beacon = NULL;
3510 }
3511 mutex_unlock(&hdd_ctx->sap_lock);
Peng Xu66162de2016-02-11 17:01:20 -08003512 if (true == bCloseSession)
3513 hdd_wait_for_sme_close_sesion(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003515 case QDF_OCB_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 ol_txrx_clear_peer(WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
3517 conn_info.staId[0]);
3518 break;
3519 default:
3520 break;
3521 }
3522
3523 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303524 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525}
3526
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303527QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528{
3529 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303530 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 hdd_adapter_t *adapter;
3532
3533 ENTER();
3534
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303535 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3538
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303539 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 adapter = adapterNode->pAdapter;
3541 hdd_stop_adapter(hdd_ctx, adapter, true);
3542 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3543 adapterNode = pNext;
3544 }
3545
3546 EXIT();
3547
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303548 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549}
3550
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303551QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552{
3553 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303554 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555 hdd_adapter_t *adapter;
3556
3557 ENTER();
3558
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05303559 cds_flush_work(&hdd_ctx->sap_pre_cac_work);
3560
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3562
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303563 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003564 adapter = adapterNode->pAdapter;
Jeff Johnson5880d792016-08-15 13:32:30 -07003565 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 wlan_hdd_netif_queue_control(adapter,
3567 WLAN_NETIF_TX_DISABLE_N_CARRIER,
3568 WLAN_CONTROL_PATH);
3569
3570 adapter->sessionCtx.station.hdd_ReassocScenario = false;
3571
3572 hdd_deinit_tx_rx(adapter);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08003573 cds_decr_session_set_pcl(adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574 adapter->sessionId);
3575 if (test_bit(WMM_INIT_DONE, &adapter->event_flags)) {
3576 hdd_wmm_adapter_close(adapter);
3577 clear_bit(WMM_INIT_DONE, &adapter->event_flags);
3578 }
3579
3580 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3581 adapterNode = pNext;
3582 }
3583
3584 EXIT();
3585
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303586 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587}
3588
Arun Khandavallifae92942016-08-01 13:31:08 +05303589/**
3590 * hdd_is_interface_up()- Checkfor interface up before ssr
3591 * @hdd_ctx: HDD context
3592 *
3593 * check if there are any wlan interfaces before SSR accordingly start
3594 * the interface.
3595 *
3596 * Return: 0 if interface was opened else false
3597 */
3598static bool hdd_is_interface_up(hdd_adapter_t *adapter)
3599{
3600 if (test_bit(DEVICE_IFACE_OPENED, &adapter->event_flags))
3601 return true;
3602 else
3603 return false;
3604}
3605
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303606QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607{
3608 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303609 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 hdd_adapter_t *adapter;
3611#ifndef MSM_PLATFORM
Anurag Chouhan6d760662016-02-20 16:05:43 +05303612 struct qdf_mac_addr bcastMac = QDF_MAC_ADDR_BROADCAST_INITIALIZER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613#endif
3614 eConnectionState connState;
3615
3616 ENTER();
3617
3618 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303619 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620 adapter = adapterNode->pAdapter;
3621
Arun Khandavallifae92942016-08-01 13:31:08 +05303622 if (!hdd_is_interface_up(adapter))
3623 continue;
3624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 hdd_wmm_init(adapter);
3626
3627 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003628 case QDF_STA_MODE:
3629 case QDF_P2P_CLIENT_MODE:
3630 case QDF_P2P_DEVICE_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003631
3632 connState = (WLAN_HDD_GET_STATION_CTX_PTR(adapter))
3633 ->conn_info.connState;
3634
3635 hdd_init_station_mode(adapter);
3636 /* Open the gates for HDD to receive Wext commands */
3637 adapter->isLinkUpSvcNeeded = false;
3638 adapter->scan_info.mScanPending = false;
3639
3640 /* Indicate disconnect event to supplicant if associated previously */
3641 if (eConnectionState_Associated == connState ||
Yue Macd961442015-10-20 16:15:31 -07003642 eConnectionState_IbssConnected == connState ||
3643 eConnectionState_NotConnected == connState ||
3644 eConnectionState_IbssDisconnected == connState ||
3645 eConnectionState_Disconnecting == connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646 union iwreq_data wrqu;
3647 memset(&wrqu, '\0', sizeof(wrqu));
3648 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3649 memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3650 wireless_send_event(adapter->dev, SIOCGIWAP,
3651 &wrqu, NULL);
3652 adapter->sessionCtx.station.
3653 hdd_ReassocScenario = false;
3654
3655 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05303656 wlan_hdd_cfg80211_indicate_disconnect(
3657 adapter->dev, false,
3658 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 } else if (eConnectionState_Connecting == connState) {
3660 /*
3661 * Indicate connect failure to supplicant if we were in the
3662 * process of connecting
3663 */
3664 cfg80211_connect_result(adapter->dev, NULL,
3665 NULL, 0, NULL, 0,
3666 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
3667 GFP_KERNEL);
3668 }
3669
3670 hdd_register_tx_flow_control(adapter,
3671 hdd_tx_resume_timer_expired_handler,
3672 hdd_tx_resume_cb);
3673
3674 break;
3675
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003676 case QDF_SAP_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003677 /* softAP can handle SSR */
3678 break;
3679
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003680 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681#ifdef MSM_PLATFORM
Jeff Johnson5880d792016-08-15 13:32:30 -07003682 hdd_err("[SSR] send stop ap to supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003683 cfg80211_ap_stopped(adapter->dev, GFP_KERNEL);
3684#else
Jeff Johnson5880d792016-08-15 13:32:30 -07003685 hdd_err("[SSR] send restart supplicant");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 /* event supplicant to restart */
3687 cfg80211_del_sta(adapter->dev,
3688 (const u8 *)&bcastMac.bytes[0],
3689 GFP_KERNEL);
3690#endif
3691 break;
3692
3693 default:
3694 break;
3695 }
3696
3697 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3698 adapterNode = pNext;
3699 }
3700
3701 EXIT();
3702
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303703 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003704}
3705
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303706QDF_STATUS hdd_get_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 hdd_adapter_list_node_t **padapterNode)
3708{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303709 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003710 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303711 status = qdf_list_peek_front(&hdd_ctx->hddAdapters,
3712 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003713 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003714 return status;
3715}
3716
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303717QDF_STATUS hdd_get_next_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003718 hdd_adapter_list_node_t *adapterNode,
3719 hdd_adapter_list_node_t **pNextAdapterNode)
3720{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303721 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003722 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303723 status = qdf_list_peek_next(&hdd_ctx->hddAdapters,
3724 (qdf_list_node_t *) adapterNode,
3725 (qdf_list_node_t **) pNextAdapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003727 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003728 return status;
3729}
3730
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303731QDF_STATUS hdd_remove_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 hdd_adapter_list_node_t *adapterNode)
3733{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303734 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003735 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303736 status = qdf_list_remove_node(&hdd_ctx->hddAdapters,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 &adapterNode->node);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003738 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 return status;
3740}
3741
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303742QDF_STATUS hdd_remove_front_adapter(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743 hdd_adapter_list_node_t **padapterNode)
3744{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303745 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003746 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303747 status = qdf_list_remove_front(&hdd_ctx->hddAdapters,
3748 (qdf_list_node_t **) padapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003749 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750 return status;
3751}
3752
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303753QDF_STATUS hdd_add_adapter_back(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003754 hdd_adapter_list_node_t *adapterNode)
3755{
Anurag Chouhanffb21542016-02-17 14:33:03 +05303756 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003757 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303758 status = qdf_list_insert_back(&hdd_ctx->hddAdapters,
3759 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003760 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761 return status;
3762}
3763
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303764QDF_STATUS hdd_add_adapter_front(hdd_context_t *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765 hdd_adapter_list_node_t *adapterNode)
3766{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303767 QDF_STATUS status;
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003768 qdf_spin_lock_bh(&hdd_ctx->hdd_adapter_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05303769 status = qdf_list_insert_front(&hdd_ctx->hddAdapters,
3770 (qdf_list_node_t *) adapterNode);
Rajeev Kumardd4dd082016-02-25 12:24:32 -08003771 qdf_spin_unlock_bh(&hdd_ctx->hdd_adapter_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772 return status;
3773}
3774
3775hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *hdd_ctx,
3776 tSirMacAddr macAddr)
3777{
3778 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3779 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303780 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003781
3782 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3783
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303784 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 adapter = adapterNode->pAdapter;
3786
3787 if (adapter
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303788 && !qdf_mem_cmp(adapter->macAddressCurrent.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003789 macAddr, sizeof(tSirMacAddr))) {
3790 return adapter;
3791 }
3792 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3793 adapterNode = pNext;
3794 }
3795
3796 return NULL;
3797
3798}
3799
3800hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *hdd_ctx,
3801 uint32_t vdev_id)
3802{
3803 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3804 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303805 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303807 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303809 while ((NULL != adapterNode) && (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 adapter = adapterNode->pAdapter;
3811
3812 if (adapter->sessionId == vdev_id)
3813 return adapter;
3814
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303815 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3817 adapterNode = pNext;
3818 }
3819
Jeff Johnson5880d792016-08-15 13:32:30 -07003820 hdd_err("vdev_id %d does not exist with host", vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821
3822 return NULL;
3823}
3824
Abhishek Singh7996eb72015-12-30 17:24:02 +05303825/**
3826 * hdd_get_adapter_by_sme_session_id() - Return adapter with
3827 * the sessionid
3828 * @hdd_ctx: hdd context.
3829 * @sme_session_id: sme session is for the adapter to get.
3830 *
3831 * This function is used to get the adapter with provided session id
3832 *
3833 * Return: adapter pointer if found
3834 *
3835 */
3836hdd_adapter_t *hdd_get_adapter_by_sme_session_id(hdd_context_t *hdd_ctx,
3837 uint32_t sme_session_id)
3838{
3839 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3840 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303841 QDF_STATUS qdf_status;
Abhishek Singh7996eb72015-12-30 17:24:02 +05303842
3843
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303844 qdf_status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Abhishek Singh7996eb72015-12-30 17:24:02 +05303845
3846 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303847 (QDF_STATUS_SUCCESS == qdf_status)) {
Abhishek Singh7996eb72015-12-30 17:24:02 +05303848 adapter = adapter_node->pAdapter;
3849
3850 if (adapter &&
3851 adapter->sessionId == sme_session_id)
3852 return adapter;
3853
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303854 qdf_status =
Abhishek Singh7996eb72015-12-30 17:24:02 +05303855 hdd_get_next_adapter(hdd_ctx,
3856 adapter_node, &next);
3857 adapter_node = next;
3858 }
3859 return NULL;
3860}
3861
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003862/**
3863 * hdd_get_adapter() - to get adapter matching the mode
3864 * @hdd_ctx: hdd context
3865 * @mode: adapter mode
3866 *
3867 * This routine will return the pointer to adapter matching
3868 * with the passed mode.
3869 *
3870 * Return: pointer to adapter or null
3871 */
3872hdd_adapter_t *hdd_get_adapter(hdd_context_t *hdd_ctx,
3873 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874{
3875 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
3876 hdd_adapter_t *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303877 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878
3879 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3880
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303881 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 adapter = adapterNode->pAdapter;
3883
3884 if (adapter && (mode == adapter->device_mode))
3885 return adapter;
3886
3887 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3888 adapterNode = pNext;
3889 }
3890
3891 return NULL;
3892
3893}
3894
3895/**
3896 * hdd_get_operating_channel() - return operating channel of the device mode
3897 * @hdd_ctx: Pointer to the HDD context.
3898 * @mode: Device mode for which operating channel is required.
3899 * Suported modes:
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003900 * QDF_STA_MODE,
3901 * QDF_P2P_CLIENT_MODE,
3902 * QDF_SAP_MODE,
3903 * QDF_P2P_GO_MODE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003904 *
3905 * This API returns the operating channel of the requested device mode
3906 *
3907 * Return: channel number. "0" id the requested device is not found OR it is
3908 * not connected.
3909 */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003910uint8_t hdd_get_operating_channel(hdd_context_t *hdd_ctx,
3911 enum tQDF_ADAPTER_MODE mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912{
3913 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303914 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 hdd_adapter_t *adapter;
3916 uint8_t operatingChannel = 0;
3917
3918 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3919
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303920 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921 adapter = adapterNode->pAdapter;
3922
3923 if (mode == adapter->device_mode) {
3924 switch (adapter->device_mode) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003925 case QDF_STA_MODE:
3926 case QDF_P2P_CLIENT_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927 if (hdd_conn_is_connected
3928 (WLAN_HDD_GET_STATION_CTX_PTR
3929 (adapter))) {
3930 operatingChannel =
3931 (WLAN_HDD_GET_STATION_CTX_PTR
3932 (adapter))->conn_info.
3933 operationChannel;
3934 }
3935 break;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003936 case QDF_SAP_MODE:
3937 case QDF_P2P_GO_MODE:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938 /* softap connection info */
3939 if (test_bit
3940 (SOFTAP_BSS_STARTED,
3941 &adapter->event_flags))
3942 operatingChannel =
3943 (WLAN_HDD_GET_AP_CTX_PTR
3944 (adapter))->operatingChannel;
3945 break;
3946 default:
3947 break;
3948 }
3949
3950 break; /* Found the device of interest. break the loop */
3951 }
3952
3953 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3954 adapterNode = pNext;
3955 }
3956 return operatingChannel;
3957}
3958
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303959static inline QDF_STATUS hdd_unregister_wext_all_adapters(hdd_context_t *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960 hdd_ctx)
3961{
3962 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303963 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003964 hdd_adapter_t *adapter;
3965
3966 ENTER();
3967
3968 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3969
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303970 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08003972 if ((adapter->device_mode == QDF_STA_MODE) ||
3973 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
3974 (adapter->device_mode == QDF_IBSS_MODE) ||
3975 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
3976 (adapter->device_mode == QDF_SAP_MODE) ||
3977 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 wlan_hdd_cfg80211_deregister_frames(adapter);
3979 hdd_unregister_wext(adapter->dev);
3980 }
3981 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
3982 adapterNode = pNext;
3983 }
3984
3985 EXIT();
3986
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303987 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988}
3989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303990QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003991{
3992 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303993 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994 hdd_adapter_t *adapter;
3995
3996 ENTER();
3997
3998 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
3999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304000 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004002 if ((adapter->device_mode == QDF_STA_MODE) ||
4003 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
4004 (adapter->device_mode == QDF_IBSS_MODE) ||
4005 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
4006 (adapter->device_mode == QDF_SAP_MODE) ||
4007 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 hdd_abort_mac_scan(hdd_ctx, adapter->sessionId,
4009 eCSR_SCAN_ABORT_DEFAULT);
4010 }
4011 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
4012 adapterNode = pNext;
4013 }
4014
4015 EXIT();
4016
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304017 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018}
4019
4020#ifdef WLAN_NS_OFFLOAD
4021/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004022 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 * @hdd_ctx: Pointer to hdd context
4024 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004025 * Unregister for IPv6 address change notifications.
4026 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 * Return: None
4028 */
4029static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4030{
4031 unregister_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
4032
4033 return;
4034}
4035
4036/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004037 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004038 * @hdd_ctx: Pointer to hdd context
4039 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004040 * Register for IPv6 address change notifications.
4041 *
4042 * Return: 0 on success and errno on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004044static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045{
4046 int ret;
4047
4048 hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
4049 ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier);
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004050 if (ret) {
4051 hdd_err("Failed to register IPv6 notifier: %d", ret);
4052 goto out;
4053 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004054
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004055 hdd_info("Registered IPv6 notifier");
4056out:
4057 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004058}
4059#else
4060/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004061 * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062 * @hdd_ctx: Pointer to hdd context
4063 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004064 * Unregister for IPv6 address change notifications.
4065 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 * Return: None
4067 */
4068static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx)
4069{
4070}
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004071
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004073 * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004074 * @hdd_ctx: Pointer to hdd context
4075 *
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004076 * Register for IPv6 address change notifications.
4077 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078 * Return: None
4079 */
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004080static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081{
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004082 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083}
4084#endif
4085
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304086#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4087/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004088 * hdd_logging_sock_activate_svc() - Activate logging
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304089 * @hdd_ctx: HDD context
4090 *
4091 * Activates the logging service
4092 *
4093 * Return: Zero in case of success, negative value otherwise
4094 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004095static int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304096{
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004097 int ret;
4098 struct hdd_config *config = hdd_ctx->config;
4099
4100 if (!config->wlanLoggingEnable)
4101 return 0;
4102
4103 ret = wlan_logging_sock_activate_svc(config->wlanLoggingFEToConsole,
4104 config->wlanLoggingNumBuf);
4105 if (ret)
4106 hdd_err("wlan_logging_sock_activate_svc failed: %d", ret);
4107 return ret;
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304108}
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004109
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304110/**
4111 * wlan_hdd_logging_sock_deactivate_svc() - Deactivate logging
4112 * @hdd_ctx: HDD context
4113 *
4114 * Deactivates the logging service
4115 *
4116 * Return: 0 on deactivating the logging service
4117 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004118static int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304119{
4120 if (hdd_ctx && hdd_ctx->config->wlanLoggingEnable)
4121 return wlan_logging_sock_deactivate_svc();
4122
4123 return 0;
4124}
4125#else
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004126static inline int hdd_logging_sock_activate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304127{
4128 return 0;
4129}
4130
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004131static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx)
Chandrasekaran, Manishekar3cc29cb2016-01-16 17:28:11 +05304132{
4133 return 0;
4134}
4135#endif
4136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137/**
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004138 * hdd_register_notifiers - Register netdev notifiers.
4139 * @hdd_ctx: HDD context
4140 *
4141 * Register netdev notifiers like IPv4 and IPv6.
4142 *
4143 * Return: 0 on success and errno on failure
4144 */
4145static int hdd_register_notifiers(hdd_context_t *hdd_ctx)
4146{
4147 int ret;
4148
4149 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4150 if (ret) {
4151 hdd_err("register_netdevice_notifier failed: %d", ret);
4152 goto out;
4153 }
4154
4155 ret = hdd_wlan_register_ip6_notifier(hdd_ctx);
4156 if (ret)
4157 goto unregister_notifier;
4158
4159 hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
4160 ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4161 if (ret) {
4162 hdd_err("Failed to register IPv4 notifier: %d", ret);
4163 goto unregister_ip6_notifier;
4164 }
4165
4166 return 0;
4167
4168unregister_ip6_notifier:
4169 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4170unregister_notifier:
4171 unregister_netdevice_notifier(&hdd_netdev_notifier);
4172out:
4173 return ret;
4174
4175}
4176
4177/**
4178 * hdd_unregister_notifiers - Unregister netdev notifiers.
4179 * @hdd_ctx: HDD context
4180 *
4181 * Unregister netdev notifiers like IPv4 and IPv6.
4182 *
4183 * Return: None.
4184 */
4185static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx)
4186{
4187 hdd_wlan_unregister_ip6_notifier(hdd_ctx);
4188
4189 unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier);
4190
4191 unregister_netdevice_notifier(&hdd_netdev_notifier);
4192}
4193
4194/**
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004195 * hdd_exit_netlink_services - Exit netlink services
4196 * @hdd_ctx: HDD context
4197 *
4198 * Exit netlink services like cnss_diag, cesium netlink socket, ptt socket and
4199 * nl service.
4200 *
4201 * Return: None.
4202 */
4203static void hdd_exit_netlink_services(hdd_context_t *hdd_ctx)
4204{
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004205 hdd_close_cesium_nl_sock();
4206
4207 ptt_sock_deactivate_svc();
4208
4209 nl_srv_exit();
4210}
4211
4212/**
4213 * hdd_init_netlink_services- Init netlink services
4214 * @hdd_ctx: HDD context
4215 *
4216 * Init netlink services like cnss_diag, cesium netlink socket, ptt socket and
4217 * nl service.
4218 *
4219 * Return: 0 on success and errno on failure.
4220 */
4221static int hdd_init_netlink_services(hdd_context_t *hdd_ctx)
4222{
4223 int ret;
4224
Ryan Hsuceddceb2016-04-28 10:20:14 -07004225 ret = wlan_hdd_nl_init(hdd_ctx);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004226 if (ret) {
4227 hdd_alert("nl_srv_init failed: %d", ret);
4228 goto out;
4229 }
Ryan Hsuceddceb2016-04-28 10:20:14 -07004230 cds_set_radio_index(hdd_ctx->radio_index);
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004231
4232 ret = oem_activate_service(hdd_ctx);
4233 if (ret) {
4234 hdd_alert("oem_activate_service failed: %d", ret);
4235 goto err_nl_srv;
4236 }
4237
4238 ret = ptt_sock_activate_svc();
4239 if (ret) {
4240 hdd_alert("ptt_sock_activate_svc failed: %d", ret);
4241 goto err_nl_srv;
4242 }
4243
4244 ret = hdd_open_cesium_nl_sock();
Ryan Hsu5e2e2052016-04-28 10:19:38 -07004245 if (ret)
4246 hdd_warn("hdd_open_cesium_nl_sock failed");
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004247
4248 ret = cnss_diag_activate_service();
4249 if (ret) {
4250 hdd_alert("cnss_diag_activate_service failed: %d", ret);
4251 goto err_close_cesium;
4252 }
4253
4254 return 0;
4255
4256err_close_cesium:
4257 hdd_close_cesium_nl_sock();
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004258 ptt_sock_deactivate_svc();
4259err_nl_srv:
4260 nl_srv_exit();
4261out:
4262 return ret;
4263}
4264
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004265#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4266/**
4267 * hdd_rx_wake_lock_destroy() - Destroy RX wakelock
4268 * @hdd_ctx: HDD context.
4269 *
4270 * Destroy RX wakelock.
4271 *
4272 * Return: None.
4273 */
4274static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx)
4275{
4276 qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock);
4277}
Prashanth Bhatta6a6a5552016-02-01 13:49:29 -08004278
4279/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004280 * hdd_rx_wake_lock_create() - Create RX wakelock
4281 * @hdd_ctx: HDD context.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004282 *
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004283 * Create RX wakelock.
4284 *
4285 * Return: None.
4286 */
4287static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx)
4288{
4289 qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock");
4290}
4291#else
4292static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { }
4293static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { }
4294#endif
4295
4296/**
4297 * hdd_roc_context_init() - Init ROC context
4298 * @hdd_ctx: HDD context.
4299 *
4300 * Initialize ROC context.
4301 *
4302 * Return: 0 on success and errno on failure.
4303 */
4304static int hdd_roc_context_init(hdd_context_t *hdd_ctx)
4305{
4306 qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock);
4307 qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY);
4308
4309 INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue);
4310
4311 return 0;
4312}
4313
4314/**
4315 * hdd_roc_context_destroy() - Destroy ROC context
4316 * @hdd_ctx: HDD context.
4317 *
4318 * Destroy roc list and flush the pending roc work.
4319 *
4320 * Return: None.
4321 */
4322static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx)
4323{
4324 flush_delayed_work(&hdd_ctx->roc_req_work);
4325 qdf_list_destroy(&hdd_ctx->hdd_roc_req_q);
4326}
4327
4328/**
4329 * hdd_context_destroy() - Destroy HDD context
4330 * @hdd_ctx: HDD context to be destroyed.
4331 *
4332 * Free config and HDD context as well as destroy all the resources.
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004333 *
4334 * Return: None
4335 */
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004336static void hdd_context_destroy(hdd_context_t *hdd_ctx)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004337{
Anurag Chouhan6d760662016-02-20 16:05:43 +05304338 if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004339 hdd_logging_sock_deactivate_svc(hdd_ctx);
4340
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004341 hdd_roc_context_destroy(hdd_ctx);
4342
4343 hdd_sap_context_destroy(hdd_ctx);
4344
4345 hdd_rx_wake_lock_destroy(hdd_ctx);
4346
4347 hdd_tdls_context_destroy(hdd_ctx);
4348
4349 hdd_scan_context_destroy(hdd_ctx);
4350
4351 qdf_list_destroy(&hdd_ctx->hddAdapters);
4352
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304353 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004354 hdd_ctx->config = NULL;
4355
4356 wiphy_free(hdd_ctx->wiphy);
4357}
4358
4359/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 * hdd_wlan_exit() - HDD WLAN exit function
4361 * @hdd_ctx: Pointer to the HDD Context
4362 *
4363 * This is the driver exit point (invoked during rmmod)
4364 *
4365 * Return: None
4366 */
4367void hdd_wlan_exit(hdd_context_t *hdd_ctx)
4368{
4369 v_CONTEXT_t p_cds_context = hdd_ctx->pcds_context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304370 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004371 struct wiphy *wiphy = hdd_ctx->wiphy;
Arun Khandavallifae92942016-08-01 13:31:08 +05304372 int driver_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373
4374 ENTER();
4375
Arun Khandavallifae92942016-08-01 13:31:08 +05304376 if (QDF_TIMER_STATE_RUNNING ==
4377 qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer)) {
4378 hdd_info("Stpp interface change timer");
4379 qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004380 }
4381
Arun Khandavallifae92942016-08-01 13:31:08 +05304382 if (!QDF_IS_STATUS_SUCCESS
4383 (qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer)))
4384 hdd_err("Cannot delete interface change timer");
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07004385
Arun Khandavallifae92942016-08-01 13:31:08 +05304386
4387 hdd_unregister_notifiers(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388
4389#ifdef MSM_PLATFORM
Anurag Chouhan210db072016-02-22 18:42:15 +05304390 if (QDF_TIMER_STATE_RUNNING ==
4391 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
4392 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393 }
4394
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304395 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304396 (qdf_mc_timer_destroy(&hdd_ctx->bus_bw_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004397 hdd_err("Cannot deallocate Bus bandwidth timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 }
4399#endif
4400
4401#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05304402 if (QDF_TIMER_STATE_RUNNING ==
4403 qdf_mc_timer_get_current_state(&hdd_ctx->skip_acs_scan_timer)) {
4404 qdf_mc_timer_stop(&hdd_ctx->skip_acs_scan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405 }
4406
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304407 if (!QDF_IS_STATUS_SUCCESS
Anurag Chouhan210db072016-02-22 18:42:15 +05304408 (qdf_mc_timer_destroy(&hdd_ctx->skip_acs_scan_timer))) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004409 hdd_err("Cannot deallocate ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 }
4411#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004412
Arun Khandavallifae92942016-08-01 13:31:08 +05304413 mutex_lock(&hdd_ctx->iface_change_lock);
4414 driver_status = hdd_ctx->driver_status;
4415 mutex_unlock(&hdd_ctx->iface_change_lock);
4416
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 /*
4418 * Powersave Offload Case
4419 * Disable Idle Power Save Mode
4420 */
4421 hdd_set_idle_ps_config(hdd_ctx, false);
4422
Arun Khandavallifae92942016-08-01 13:31:08 +05304423 if (driver_status != DRIVER_MODULES_CLOSED) {
4424 hdd_unregister_wext_all_adapters(hdd_ctx);
4425 /*
4426 * Cancel any outstanding scan requests. We are about to close
4427 * all of our adapters, but an adapter structure is what SME
4428 * passes back to our callback function. Hence if there
4429 * are any outstanding scan requests then there is a
4430 * race condition between when the adapter is closed and
4431 * when the callback is invoked. We try to resolve that
4432 * race condition here by canceling any outstanding scans
4433 * before we close the adapters.
4434 * Note that the scans may be cancelled in an asynchronous
4435 * manner, so ideally there needs to be some kind of
4436 * synchronization. Rather than introduce a new
4437 * synchronization here, we will utilize the fact that we are
4438 * about to Request Full Power, and since that is synchronized,
4439 * the expectation is that by the time Request Full Power has
4440 * completed, all scans will be cancelled
4441 */
4442 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4443 hdd_stop_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444 }
4445
Arun Khandavallifae92942016-08-01 13:31:08 +05304446 hdd_wlan_stop_modules(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 /*
4448 * Close the scheduler before calling cds_close to make sure no thread
4449 * is scheduled after the each module close is called i.e after all the
4450 * data structures are freed.
4451 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304452 qdf_status = cds_sched_close(p_cds_context);
4453 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004454 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304455 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004456 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05304458 qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock);
4459 qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock);
4460 qdf_spinlock_destroy(&hdd_ctx->connection_status_lock);
4461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 /*
4463 * Close CDS
4464 * This frees pMac(HAL) context. There should not be any call
4465 * that requires pMac access after this.
4466 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004467
4468 hdd_wlan_green_ap_deinit(hdd_ctx);
4469
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08004470 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004471
4472 hdd_ipa_cleanup(hdd_ctx);
4473
4474 /* Free up RoC request queue and flush workqueue */
4475 cds_flush_work(&hdd_ctx->roc_req_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476
Arun Khandavallifae92942016-08-01 13:31:08 +05304477
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004478
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05304479 wlansap_global_deinit();
Nirav Shahed34b212016-04-25 10:59:16 +05304480 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004481 wiphy_unregister(wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05304482 wlan_hdd_cfg80211_deinit(wiphy);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08004483
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07004484 wlan_hdd_send_status_pkg(NULL, NULL, 0, 0);
4485
Arun Khandavallifae92942016-08-01 13:31:08 +05304486 hdd_exit_netlink_services(hdd_ctx);
4487 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07004488 hdd_context_destroy(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489}
4490
4491void __hdd_wlan_exit(void)
4492{
4493 hdd_context_t *hdd_ctx;
4494
4495 ENTER();
4496
Anurag Chouhan6d760662016-02-20 16:05:43 +05304497 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 if (!hdd_ctx) {
Jeff Johnson5880d792016-08-15 13:32:30 -07004499 hdd_alert("Invalid HDD Context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 EXIT();
4501 return;
4502 }
4503
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004504 /* Check IPA HW Pipe shutdown */
4505 hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
4506
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08004507 memdump_deinit();
4508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 /* Do all the cleanup before deregistering the driver */
4510 hdd_wlan_exit(hdd_ctx);
Mohit Khannaebf8a862016-04-28 17:53:59 -07004511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004512 EXIT();
4513}
4514
4515#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4516void hdd_skip_acs_scan_timer_handler(void *data)
4517{
4518 hdd_context_t *hdd_ctx = (hdd_context_t *) data;
4519
Jeff Johnson760350b2016-08-15 14:01:52 -07004520 hdd_notice("ACS Scan result expired. Reset ACS scan skip");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 hdd_ctx->skip_acs_scan_status = eSAP_DO_NEW_ACS_SCAN;
4522
4523 if (!hdd_ctx->hHal)
4524 return;
4525 sme_scan_flush_result(hdd_ctx->hHal);
4526}
4527#endif
4528
4529#ifdef QCA_HT_2040_COEX
4530/**
4531 * hdd_wlan_set_ht2040_mode() - notify FW with HT20/HT40 mode
4532 * @adapter: pointer to adapter
4533 * @staId: station id
4534 * @macAddrSTA: station MAC address
4535 * @channel_type: channel type
4536 *
4537 * This function notifies FW with HT20/HT40 mode
4538 *
4539 * Return: 0 if successful, error number otherwise
4540 */
4541int hdd_wlan_set_ht2040_mode(hdd_adapter_t *adapter, uint16_t staId,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304542 struct qdf_mac_addr macAddrSTA, int channel_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543{
4544 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304545 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 hdd_context_t *hdd_ctx = NULL;
4547
4548 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4549
4550 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304551 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304553
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 if (!hdd_ctx->hHal)
4555 return -EINVAL;
4556
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304557 qdf_status = sme_notify_ht2040_mode(hdd_ctx->hHal, staId, macAddrSTA,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 adapter->sessionId, channel_type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304559 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004560 hdd_err("Fail to send notification with ht2040 mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004561 return -EINVAL;
4562 }
4563
4564 return 0;
4565}
4566#endif
4567
4568/**
4569 * hdd_wlan_notify_modem_power_state() - notify FW with modem power status
4570 * @state: state
4571 *
4572 * This function notifies FW with modem power status
4573 *
4574 * Return: 0 if successful, error number otherwise
4575 */
4576int hdd_wlan_notify_modem_power_state(int state)
4577{
4578 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304579 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 hdd_context_t *hdd_ctx;
4581
Anurag Chouhan6d760662016-02-20 16:05:43 +05304582 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304584 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004587 if (!hdd_ctx->hHal)
4588 return -EINVAL;
4589
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304590 qdf_status = sme_notify_modem_power_state(hdd_ctx->hHal, state);
4591 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004592 hdd_err("Fail to send notification with modem power state %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593 state);
4594 return -EINVAL;
4595 }
4596 return 0;
4597}
4598
4599/**
4600 *
4601 * hdd_post_cds_enable_config() - HDD post cds start config helper
4602 * @adapter - Pointer to the HDD
4603 *
4604 * Return: None
4605 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304606QDF_STATUS hdd_post_cds_enable_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004607{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304608 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609
4610 /*
4611 * Send ready indication to the HDD. This will kick off the MAC
4612 * into a 'running' state and should kick off an initial scan.
4613 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304614 qdf_ret_status = sme_hdd_ready_ind(hdd_ctx->hHal);
4615 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004616 hdd_err("sme_hdd_ready_ind() failed with status code %08d [x%08x]",
4617 qdf_ret_status, qdf_ret_status);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304618 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004619 }
4620
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304621 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622}
4623
4624/* wake lock APIs for HDD */
4625void hdd_prevent_suspend(uint32_t reason)
4626{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304627 qdf_wake_lock_acquire(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004628}
4629
4630void hdd_allow_suspend(uint32_t reason)
4631{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304632 qdf_wake_lock_release(&wlan_wake_lock, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633}
4634
4635void hdd_prevent_suspend_timeout(uint32_t timeout, uint32_t reason)
4636{
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304637 qdf_wake_lock_timeout_acquire(&wlan_wake_lock, timeout, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638}
4639
4640/**
4641 * hdd_exchange_version_and_caps() - exchange version and capability with target
4642 * @hdd_ctx: Pointer to HDD context
4643 *
4644 * This is the HDD function to exchange version and capability information
4645 * between Host and Target
4646 *
4647 * This function gets reported version of FW.
4648 * It also finds the version of target headers used to compile the host;
4649 * It compares the above two and prints a warning if they are different;
4650 * It gets the SW and HW version string;
4651 * Finally, it exchanges capabilities between host and target i.e. host
4652 * and target exchange a msg indicating the features they support through a
4653 * bitmap
4654 *
4655 * Return: None
4656 */
4657void hdd_exchange_version_and_caps(hdd_context_t *hdd_ctx)
4658{
4659
4660 tSirVersionType versionCompiled;
4661 tSirVersionType versionReported;
4662 tSirVersionString versionString;
4663 uint8_t fwFeatCapsMsgSupported = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304664 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665
4666 memset(&versionCompiled, 0, sizeof(versionCompiled));
4667 memset(&versionReported, 0, sizeof(versionReported));
4668
4669 /* retrieve and display WCNSS version information */
4670 do {
4671
4672 vstatus = sme_get_wcnss_wlan_compiled_version(hdd_ctx->hHal,
4673 &versionCompiled);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304674 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004675 hdd_alert("unable to retrieve WCNSS WLAN compiled version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676 break;
4677 }
4678
4679 vstatus = sme_get_wcnss_wlan_reported_version(hdd_ctx->hHal,
4680 &versionReported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304681 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004682 hdd_alert("unable to retrieve WCNSS WLAN reported version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 break;
4684 }
4685
4686 if ((versionCompiled.major != versionReported.major) ||
4687 (versionCompiled.minor != versionReported.minor) ||
4688 (versionCompiled.version != versionReported.version) ||
4689 (versionCompiled.revision != versionReported.revision)) {
4690 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
4691 "Host expected %u.%u.%u.%u\n",
4692 WLAN_MODULE_NAME,
4693 (int)versionReported.major,
4694 (int)versionReported.minor,
4695 (int)versionReported.version,
4696 (int)versionReported.revision,
4697 (int)versionCompiled.major,
4698 (int)versionCompiled.minor,
4699 (int)versionCompiled.version,
4700 (int)versionCompiled.revision);
4701 } else {
4702 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
4703 WLAN_MODULE_NAME,
4704 (int)versionReported.major,
4705 (int)versionReported.minor,
4706 (int)versionReported.version,
4707 (int)versionReported.revision);
4708 }
4709
4710 vstatus = sme_get_wcnss_software_version(hdd_ctx->hHal,
4711 versionString,
4712 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304713 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004714 hdd_alert("unable to retrieve WCNSS software version string");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715 break;
4716 }
4717
4718 pr_info("%s: WCNSS software version %s\n",
4719 WLAN_MODULE_NAME, versionString);
4720
4721 vstatus = sme_get_wcnss_hardware_version(hdd_ctx->hHal,
4722 versionString,
4723 sizeof(versionString));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304724 if (!QDF_IS_STATUS_SUCCESS(vstatus)) {
Jeff Johnson760350b2016-08-15 14:01:52 -07004725 hdd_alert(FL(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 "unable to retrieve WCNSS hardware version string"
4727 ));
4728 break;
4729 }
4730
4731 pr_info("%s: WCNSS hardware version %s\n",
4732 WLAN_MODULE_NAME, versionString);
4733
4734 /*
4735 * 1.Check if FW version is greater than 0.1.1.0. Only then
4736 * send host-FW capability exchange message
4737 * 2.Host-FW capability exchange message is only present on
4738 * target 1.1 so send the message only if it the target is 1.1
4739 * minor numbers for different target branches:
4740 * 0 -> (1.0)Mainline Build
4741 * 1 -> (1.1)Mainline Build
4742 * 2->(1.04) Stability Build
4743 */
4744 if (((versionReported.major > 0) || (versionReported.minor > 1)
4745 || ((versionReported.minor >= 1)
4746 && (versionReported.version >= 1)))
4747 && ((versionReported.major == 1)
4748 && (versionReported.minor >= 1)))
4749 fwFeatCapsMsgSupported = 1;
4750
4751 if (fwFeatCapsMsgSupported) {
4752 /*
4753 * Indicate if IBSS heartbeat monitoring needs to be
4754 * offloaded
4755 */
4756 if (!hdd_ctx->config->enableIbssHeartBeatOffload) {
4757 sme_disable_feature_capablity
4758 (IBSS_HEARTBEAT_OFFLOAD);
4759 }
4760
4761 sme_feature_caps_exchange(hdd_ctx->hHal);
4762 }
4763
4764 } while (0);
4765
4766}
4767
4768/* Initialize channel list in sme based on the country code */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304769QDF_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770{
4771 return sme_init_chan_list(hdd_ctx->hHal, hdd_ctx->reg.alpha2,
4772 hdd_ctx->reg.cc_src);
4773}
4774
4775/**
4776 * hdd_is_5g_supported() - check if hardware supports 5GHz
4777 * @hdd_ctx: Pointer to the hdd context
4778 *
4779 * HDD function to know if hardware supports 5GHz
4780 *
4781 * Return: true if hardware supports 5GHz
4782 */
4783bool hdd_is_5g_supported(hdd_context_t *hdd_ctx)
4784{
4785 /*
4786 * If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
4787 * then hardware support 5Ghz.
4788 */
4789 return true;
4790}
4791
Amar Singhale4f28ee2015-10-21 14:36:56 -07004792static int hdd_wiphy_init(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793{
4794 struct wiphy *wiphy;
Amar Singhale4f28ee2015-10-21 14:36:56 -07004795 int ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004796
4797 wiphy = hdd_ctx->wiphy;
4798
4799 /*
4800 * The channel information in
4801 * wiphy needs to be initialized before wiphy registration
4802 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004803 ret_val = hdd_regulatory_init(hdd_ctx, wiphy);
4804 if (ret_val) {
4805 hdd_alert("regulatory init failed");
4806 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 }
4808
4809#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4810 wiphy->wowlan = &wowlan_support_reg_init;
4811#else
4812 wiphy->wowlan.flags = WIPHY_WOWLAN_ANY |
4813 WIPHY_WOWLAN_MAGIC_PKT |
4814 WIPHY_WOWLAN_DISCONNECT |
4815 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
4816 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
4817 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
4818 WIPHY_WOWLAN_4WAY_HANDSHAKE |
4819 WIPHY_WOWLAN_RFKILL_RELEASE;
4820
4821 wiphy->wowlan.n_patterns = (WOW_MAX_FILTER_LISTS *
4822 WOW_MAX_FILTERS_PER_LIST);
4823 wiphy->wowlan.pattern_min_len = WOW_MIN_PATTERN_SIZE;
4824 wiphy->wowlan.pattern_max_len = WOW_MAX_PATTERN_SIZE;
4825#endif
4826
4827 /* registration of wiphy dev with cfg80211 */
Amar Singhale4f28ee2015-10-21 14:36:56 -07004828 ret_val = wlan_hdd_cfg80211_register(wiphy);
4829 if (0 > ret_val)
4830 hdd_err("wiphy registration failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831
Amar Singhale4f28ee2015-10-21 14:36:56 -07004832 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833}
4834
Ravi Joshie2331e82015-07-01 18:18:54 -07004835/**
Yuanyuan Liu13738502016-04-06 17:41:37 -07004836 * hdd_pld_request_bus_bandwidth() - Function to control bus bandwidth
Ravi Joshie2331e82015-07-01 18:18:54 -07004837 * @hdd_ctx - handle to hdd context
4838 * @tx_packets - transmit packet count
4839 * @rx_packets - receive packet count
4840 *
4841 * The function controls the bus bandwidth and dynamic control of
4842 * tcp delayed ack configuration
4843 *
4844 * Returns: None
4845 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004846#ifdef MSM_PLATFORM
Yuanyuan Liu13738502016-04-06 17:41:37 -07004847void hdd_pld_request_bus_bandwidth(hdd_context_t *hdd_ctx,
Mohit Khannae71e2262015-11-10 09:37:24 -08004848 const uint64_t tx_packets, const uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004850 uint64_t total = tx_packets + rx_packets;
Mohit Khannae71e2262015-11-10 09:37:24 -08004851 uint64_t temp_rx = 0;
4852 uint64_t temp_tx = 0;
Yuanyuan Liu13738502016-04-06 17:41:37 -07004853 enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
Mohit Khannae71e2262015-11-10 09:37:24 -08004854 enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
4855 enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004856
Mohit Khannae71e2262015-11-10 09:37:24 -08004857
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858 if (total > hdd_ctx->config->busBandwidthHighThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004859 next_vote_level = PLD_BUS_WIDTH_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 else if (total > hdd_ctx->config->busBandwidthMediumThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004861 next_vote_level = PLD_BUS_WIDTH_MEDIUM;
Yue Mad6478e42015-10-20 18:49:24 -07004862 else if (total > hdd_ctx->config->busBandwidthLowThreshold)
Yuanyuan Liu13738502016-04-06 17:41:37 -07004863 next_vote_level = PLD_BUS_WIDTH_LOW;
Yue Mad6478e42015-10-20 18:49:24 -07004864 else
Yuanyuan Liu13738502016-04-06 17:41:37 -07004865 next_vote_level = PLD_BUS_WIDTH_NONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866
Mohit Khannae71e2262015-11-10 09:37:24 -08004867 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_vote_level =
4868 next_vote_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004869
4870 if (hdd_ctx->cur_vote_level != next_vote_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004871 hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
4872 next_vote_level, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 hdd_ctx->cur_vote_level = next_vote_level;
Yuanyuan Liu13738502016-04-06 17:41:37 -07004874 pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
Nirav Shah3bbfa512016-05-12 16:43:49 +05304875 if (next_vote_level == PLD_BUS_WIDTH_LOW) {
Nirav Shahffc6a092016-06-09 16:09:08 +05304876 if (hdd_ctx->hbw_requested) {
4877 pld_remove_pm_qos(hdd_ctx->parent_dev);
4878 hdd_ctx->hbw_requested = false;
4879 }
Nirav Shah3bbfa512016-05-12 16:43:49 +05304880 if (cds_sched_handle_throughput_req(false))
4881 hdd_log(LOGE,
4882 FL("low bandwidth set rx affinity fail"));
4883 } else {
Nirav Shahffc6a092016-06-09 16:09:08 +05304884 if (!hdd_ctx->hbw_requested) {
4885 pld_request_pm_qos(hdd_ctx->parent_dev, 1);
4886 hdd_ctx->hbw_requested = true;
4887 }
4888
Nirav Shah3bbfa512016-05-12 16:43:49 +05304889 if (cds_sched_handle_throughput_req(true))
4890 hdd_log(LOGE,
4891 FL("high bandwidth set rx affinity fail"));
4892 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893 }
Mohit Khannae71e2262015-11-10 09:37:24 -08004894
4895 /* fine-tuning parameters for RX Flows */
4896 temp_rx = (rx_packets + hdd_ctx->prev_rx) / 2;
4897
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004898 hdd_ctx->prev_rx = rx_packets;
4899 if (temp_rx > hdd_ctx->config->tcpDelackThresholdHigh)
Mohit Khannae71e2262015-11-10 09:37:24 -08004900 next_rx_level = WLAN_SVC_TP_HIGH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 else
Mohit Khannae71e2262015-11-10 09:37:24 -08004902 next_rx_level = WLAN_SVC_TP_LOW;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903
Mohit Khannae71e2262015-11-10 09:37:24 -08004904 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_rx_level =
4905 next_rx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906
4907 if (hdd_ctx->cur_rx_level != next_rx_level) {
Ravi Joshie2331e82015-07-01 18:18:54 -07004908 hdd_debug("TCP DELACK trigger level %d, average_rx: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004909 next_rx_level, temp_rx);
4910 hdd_ctx->cur_rx_level = next_rx_level;
Ravi Joshie2331e82015-07-01 18:18:54 -07004911 /* Send throughput indication only if it is enabled.
4912 * Disabling tcp_del_ack will revert the tcp stack behavior
4913 * to default delayed ack. Note that this will disable the
4914 * dynamic delayed ack mechanism across the system
4915 */
4916 if (hdd_ctx->config->enable_tcp_delack)
4917 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 &next_rx_level,
4919 sizeof(next_rx_level));
4920 }
4921
Mohit Khannae71e2262015-11-10 09:37:24 -08004922 /* fine-tuning parameters for TX Flows */
4923 temp_tx = (tx_packets + hdd_ctx->prev_tx) / 2;
4924 hdd_ctx->prev_tx = tx_packets;
4925 if (temp_tx > hdd_ctx->config->tcp_tx_high_tput_thres)
4926 next_tx_level = WLAN_SVC_TP_HIGH;
4927 else
4928 next_tx_level = WLAN_SVC_TP_LOW;
4929
4930 if (hdd_ctx->cur_tx_level != next_tx_level) {
4931 hdd_debug("change TCP TX trigger level %d, average_tx: %llu",
4932 next_tx_level, temp_tx);
4933 hdd_ctx->cur_tx_level = next_tx_level;
4934 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_TX_IND,
4935 &next_tx_level,
4936 sizeof(next_tx_level));
4937 }
4938
4939 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].next_tx_level =
4940 next_tx_level;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941 hdd_ctx->hdd_txrx_hist_idx++;
4942 hdd_ctx->hdd_txrx_hist_idx &= NUM_TX_RX_HISTOGRAM_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004943}
4944
4945#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
4946static void hdd_bus_bw_compute_cbk(void *priv)
4947{
4948 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
4949 hdd_adapter_t *adapter = NULL;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304950 uint64_t tx_packets = 0, rx_packets = 0;
Himanshu Agarwala6cedee2016-06-08 14:50:00 +05304951 uint64_t fwd_tx_packets = 0, fwd_rx_packets = 0;
4952 uint64_t fwd_tx_packets_diff = 0, fwd_rx_packets_diff = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953 uint64_t total_tx = 0, total_rx = 0;
4954 hdd_adapter_list_node_t *adapterNode = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304955 QDF_STATUS status = 0;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304956 A_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004957 bool connected = false;
4958 uint32_t ipa_tx_packets = 0, ipa_rx_packets = 0;
4959
4960 for (status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304961 NULL != adapterNode && QDF_STATUS_SUCCESS == status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004962 status =
4963 hdd_get_next_adapter(hdd_ctx, adapterNode, &adapterNode)) {
4964
4965 if (adapterNode->pAdapter == NULL)
4966 continue;
4967 adapter = adapterNode->pAdapter;
4968
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004969 if ((adapter->device_mode == QDF_STA_MODE ||
4970 adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 WLAN_HDD_GET_STATION_CTX_PTR(adapter)->conn_info.connState
4972 != eConnectionState_Associated) {
4973
4974 continue;
4975 }
4976
Krunal Soni9b04c9b2016-03-10 13:08:05 -08004977 if ((adapter->device_mode == QDF_SAP_MODE ||
4978 adapter->device_mode == QDF_P2P_GO_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004979 WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive == false) {
4980
4981 continue;
4982 }
4983
4984 tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
4985 adapter->prev_tx_packets);
4986 rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
4987 adapter->prev_rx_packets);
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05304988
4989 if (adapter->device_mode == QDF_SAP_MODE ||
4990 adapter->device_mode == QDF_P2P_GO_MODE ||
4991 adapter->device_mode == QDF_IBSS_MODE) {
4992
4993 ret = ol_get_intra_bss_fwd_pkts_count(
4994 adapter->sessionId,
4995 &fwd_tx_packets, &fwd_rx_packets);
4996 if (ret == A_OK) {
4997 fwd_tx_packets_diff += HDD_BW_GET_DIFF(
4998 fwd_tx_packets,
4999 adapter->prev_fwd_tx_packets);
5000 fwd_rx_packets_diff += HDD_BW_GET_DIFF(
5001 fwd_tx_packets,
5002 adapter->prev_fwd_rx_packets);
5003 }
5004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005
5006 total_rx += adapter->stats.rx_packets;
5007 total_tx += adapter->stats.tx_packets;
5008
5009 spin_lock_bh(&hdd_ctx->bus_bw_lock);
5010 adapter->prev_tx_packets = adapter->stats.tx_packets;
5011 adapter->prev_rx_packets = adapter->stats.rx_packets;
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305012 adapter->prev_fwd_tx_packets = fwd_tx_packets;
5013 adapter->prev_fwd_rx_packets = fwd_rx_packets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014 spin_unlock_bh(&hdd_ctx->bus_bw_lock);
5015 connected = true;
5016 }
5017
5018 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_rx = total_rx;
5019 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].total_tx = total_tx;
5020 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_rx =
5021 rx_packets;
5022 hdd_ctx->hdd_txrx_hist[hdd_ctx->hdd_txrx_hist_idx].interval_tx =
5023 tx_packets;
5024
Himanshu Agarwal5ac2f7b2016-05-06 20:08:10 +05305025 /* add intra bss forwarded tx and rx packets */
5026 tx_packets += fwd_tx_packets_diff;
5027 rx_packets += fwd_rx_packets_diff;
5028
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029 hdd_ipa_uc_stat_query(hdd_ctx, &ipa_tx_packets, &ipa_rx_packets);
5030 tx_packets += (uint64_t)ipa_tx_packets;
5031 rx_packets += (uint64_t)ipa_rx_packets;
5032
5033 if (!connected) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005034 hdd_err("bus bandwidth timer running in disconnected state");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005035 return;
5036 }
5037
Yuanyuan Liu13738502016-04-06 17:41:37 -07005038 hdd_pld_request_bus_bandwidth(hdd_ctx, tx_packets, rx_packets);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039
5040 hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
5041 hdd_ipa_uc_stat_request(adapter, 2);
5042
Anurag Chouhan210db072016-02-22 18:42:15 +05305043 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005044 hdd_ctx->config->busBandwidthComputeInterval);
5045}
5046#endif
5047
5048/**
Nirav Shahed34b212016-04-25 10:59:16 +05305049 * wlan_hdd_init_tx_rx_histogram() - init tx/rx histogram stats
5050 * @hdd_ctx: hdd context
5051 *
5052 * Return: 0 for success or error code
5053 */
5054int wlan_hdd_init_tx_rx_histogram(hdd_context_t *hdd_ctx)
5055{
5056 hdd_ctx->hdd_txrx_hist = qdf_mem_malloc(
5057 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
5058 if (hdd_ctx->hdd_txrx_hist == NULL) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005059 hdd_err("Failed malloc for hdd_txrx_hist");
Nirav Shahed34b212016-04-25 10:59:16 +05305060 return -ENOMEM;
5061 }
5062 return 0;
5063}
5064
5065/**
5066 * wlan_hdd_deinit_tx_rx_histogram() - deinit tx/rx histogram stats
5067 * @hdd_ctx: hdd context
5068 *
5069 * Return: none
5070 */
5071void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
5072{
5073 if (hdd_ctx->hdd_txrx_hist) {
5074 qdf_mem_free(hdd_ctx->hdd_txrx_hist);
5075 hdd_ctx->hdd_txrx_hist = NULL;
5076 }
5077}
5078
Nirav Shahda008342016-05-17 18:50:40 +05305079static uint8_t *convert_level_to_string(uint32_t level)
5080{
5081 switch (level) {
5082 /* initialize the wlan sub system */
5083 case WLAN_SVC_TP_NONE:
5084 return "NONE";
5085 case WLAN_SVC_TP_LOW:
5086 return "LOW";
5087 case WLAN_SVC_TP_MEDIUM:
5088 return "MED";
5089 case WLAN_SVC_TP_HIGH:
5090 return "HIGH";
5091 default:
5092 return "INVAL";
5093 }
5094}
5095
Nirav Shahed34b212016-04-25 10:59:16 +05305096
5097/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098 * wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
5099 * @hdd_ctx: hdd context
5100 *
5101 * Return: none
5102 */
5103void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
5104{
5105 int i;
5106
5107#ifdef MSM_PLATFORM
Jeff Johnson760350b2016-08-15 14:01:52 -07005108 hdd_err("BW compute Interval: %dms",
Nirav Shahda008342016-05-17 18:50:40 +05305109 hdd_ctx->config->busBandwidthComputeInterval);
Jeff Johnson760350b2016-08-15 14:01:52 -07005110 hdd_err("BW High TH: %d BW Med TH: %d BW Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005111 hdd_ctx->config->busBandwidthHighThreshold,
5112 hdd_ctx->config->busBandwidthMediumThreshold,
5113 hdd_ctx->config->busBandwidthLowThreshold);
Jeff Johnson760350b2016-08-15 14:01:52 -07005114 hdd_err("Enable TCP DEL ACK: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305115 hdd_ctx->config->enable_tcp_delack);
Jeff Johnson760350b2016-08-15 14:01:52 -07005116 hdd_err("TCP DEL High TH: %d TCP DEL Low TH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117 hdd_ctx->config->tcpDelackThresholdHigh,
5118 hdd_ctx->config->tcpDelackThresholdLow);
Jeff Johnson760350b2016-08-15 14:01:52 -07005119 hdd_err("TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
Nirav Shahda008342016-05-17 18:50:40 +05305120 hdd_ctx->config->tcp_tx_high_tput_thres);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121#endif
5122
Jeff Johnson760350b2016-08-15 14:01:52 -07005123 hdd_err("Total entries: %d Current index: %d",
Nirav Shahda008342016-05-17 18:50:40 +05305124 NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
5125
Jeff Johnson760350b2016-08-15 14:01:52 -07005126 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 -08005127
5128 for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005129 hdd_err("%d: %llu, %llu, %llu, %llu, %s, %s, %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005130 i, hdd_ctx->hdd_txrx_hist[i].total_rx,
5131 hdd_ctx->hdd_txrx_hist[i].interval_rx,
5132 hdd_ctx->hdd_txrx_hist[i].total_tx,
5133 hdd_ctx->hdd_txrx_hist[i].interval_tx,
Nirav Shahda008342016-05-17 18:50:40 +05305134 convert_level_to_string(
5135 hdd_ctx->hdd_txrx_hist[i].next_vote_level),
5136 convert_level_to_string(
5137 hdd_ctx->hdd_txrx_hist[i].next_rx_level),
5138 convert_level_to_string(
5139 hdd_ctx->hdd_txrx_hist[i].next_tx_level));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005140 }
5141 return;
5142}
5143
5144/**
5145 * wlan_hdd_clear_tx_rx_histogram() - clear tx rx histogram
5146 * @hdd_ctx: hdd context
5147 *
5148 * Return: none
5149 */
5150void wlan_hdd_clear_tx_rx_histogram(hdd_context_t *hdd_ctx)
5151{
5152 hdd_ctx->hdd_txrx_hist_idx = 0;
Nirav Shahed34b212016-04-25 10:59:16 +05305153 qdf_mem_zero(hdd_ctx->hdd_txrx_hist,
5154 (sizeof(struct hdd_tx_rx_histogram) * NUM_TX_RX_HISTOGRAM));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005155}
5156
5157/**
5158 * wlan_hdd_display_netif_queue_history() - display netif queue operation history
5159 * @pHddCtx: hdd context
5160 *
5161 * Return: none
5162 */
5163void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
5164{
5165
5166 hdd_adapter_t *adapter = NULL;
5167 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305168 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005169 int i;
Nirav Shahda008342016-05-17 18:50:40 +05305170 qdf_time_t total, pause, unpause, curr_time, delta;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005171
5172 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305173 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174 adapter = adapter_node->pAdapter;
5175
Jeff Johnson760350b2016-08-15 14:01:52 -07005176 hdd_err("\nNetif queue operation statistics:");
5177 hdd_err("Session_id %d device mode %d",
Nirav Shah617cff92016-04-25 10:24:24 +05305178 adapter->sessionId, adapter->device_mode);
Jeff Johnson760350b2016-08-15 14:01:52 -07005179 hdd_err("Current pause_map value %x", adapter->pause_map);
Nirav Shah617cff92016-04-25 10:24:24 +05305180 curr_time = qdf_system_ticks();
5181 total = curr_time - adapter->start_time;
Nirav Shahda008342016-05-17 18:50:40 +05305182 delta = curr_time - adapter->last_time;
Nirav Shah617cff92016-04-25 10:24:24 +05305183 if (adapter->pause_map) {
Nirav Shahda008342016-05-17 18:50:40 +05305184 pause = adapter->total_pause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305185 unpause = adapter->total_unpause_time;
5186 } else {
Nirav Shahda008342016-05-17 18:50:40 +05305187 unpause = adapter->total_unpause_time + delta;
Nirav Shah617cff92016-04-25 10:24:24 +05305188 pause = adapter->total_pause_time;
5189 }
Jeff Johnson760350b2016-08-15 14:01:52 -07005190 hdd_err("Total: %ums Pause: %ums Unpause: %ums",
Nirav Shah617cff92016-04-25 10:24:24 +05305191 qdf_system_ticks_to_msecs(total),
5192 qdf_system_ticks_to_msecs(pause),
5193 qdf_system_ticks_to_msecs(unpause));
Jeff Johnson760350b2016-08-15 14:01:52 -07005194 hdd_err("reason_type: pause_cnt: unpause_cnt: pause_time");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195
Nirav Shahda008342016-05-17 18:50:40 +05305196 for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
5197 qdf_time_t pause_delta = 0;
5198
5199 if (adapter->pause_map & (1 << i))
5200 pause_delta = delta;
5201
Jeff Johnson760350b2016-08-15 14:01:52 -07005202 hdd_err("%s: %d: %d: %ums",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 hdd_reason_type_to_string(i),
5204 adapter->queue_oper_stats[i].pause_count,
Nirav Shahda008342016-05-17 18:50:40 +05305205 adapter->queue_oper_stats[i].unpause_count,
5206 qdf_system_ticks_to_msecs(
5207 adapter->queue_oper_stats[i].total_pause_time +
5208 pause_delta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005209 }
5210
Jeff Johnson760350b2016-08-15 14:01:52 -07005211 hdd_err("\nNetif queue operation history:");
5212 hdd_err("Total entries: %d current index %d",
Nirav Shahda008342016-05-17 18:50:40 +05305213 WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
5214
Jeff Johnson760350b2016-08-15 14:01:52 -07005215 hdd_err("index: time: action_type: reason_type: pause_map");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216
5217 for (i = 0; i < WLAN_HDD_MAX_HISTORY_ENTRY; i++) {
Jeff Johnson760350b2016-08-15 14:01:52 -07005218 hdd_err("%d: %u: %s: %s: %x",
Anurag Chouhan50220ce2016-02-18 20:11:33 +05305219 i, qdf_system_ticks_to_msecs(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 adapter->queue_oper_history[i].time),
5221 hdd_action_type_to_string(
5222 adapter->queue_oper_history[i].netif_action),
5223 hdd_reason_type_to_string(
5224 adapter->queue_oper_history[i].netif_reason),
5225 adapter->queue_oper_history[i].pause_map);
5226 }
5227
5228 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5229 adapter_node = next;
5230 }
5231
5232
5233}
5234
5235/**
5236 * wlan_hdd_clear_netif_queue_history() - clear netif queue operation history
5237 * @hdd_ctx: hdd context
5238 *
5239 * Return: none
5240 */
5241void wlan_hdd_clear_netif_queue_history(hdd_context_t *hdd_ctx)
5242{
5243 hdd_adapter_t *adapter = NULL;
5244 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305245 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246
5247 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305248 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005249 adapter = adapter_node->pAdapter;
5250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305251 qdf_mem_zero(adapter->queue_oper_stats,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 sizeof(adapter->queue_oper_stats));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305253 qdf_mem_zero(adapter->queue_oper_history,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005254 sizeof(adapter->queue_oper_history));
Nirav Shah617cff92016-04-25 10:24:24 +05305255 adapter->history_index = 0;
5256 adapter->start_time = adapter->last_time = qdf_system_ticks();
5257 adapter->total_pause_time = 0;
5258 adapter->total_unpause_time = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next);
5260 adapter_node = next;
5261 }
5262}
5263
5264/**
5265 * hdd_11d_scan_done() - callback for 11d scan completion of flushing results
5266 * @halHandle: Hal handle
5267 * @pContext: Pointer to the context
5268 * @sessionId: Session ID
5269 * @scanId: Scan ID
5270 * @status: Status
5271 *
5272 * This is the callback to be executed when 11d scan is completed to flush out
5273 * the scan results
5274 *
5275 * 11d scan is done during driver load and is a passive scan on all
5276 * channels supported by the device, 11d scans may find some APs on
5277 * frequencies which are forbidden to be used in the regulatory domain
5278 * the device is operating in. If these APs are notified to the supplicant
5279 * it may try to connect to these APs, thus flush out all the scan results
5280 * which are present in SME after 11d scan is done.
5281 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305282 * Return: QDF_STATUS_SUCCESS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005283 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305284static QDF_STATUS hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 uint8_t sessionId, uint32_t scanId,
5286 eCsrScanStatus status)
5287{
5288 ENTER();
5289
5290 sme_scan_flush_result(halHandle);
5291
5292 EXIT();
5293
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305294 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295}
5296
5297#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5298/**
5299 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
5300 * @hdd_ctx: hdd global context
5301 *
5302 * Return: none
5303 */
5304static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5305{
5306 uint8_t i;
5307
5308 mutex_init(&hdd_ctx->op_ctx.op_lock);
5309 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5310 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5311 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
5312 }
5313}
5314#else
5315static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
5316{
5317}
5318#endif
5319
5320#ifdef WLAN_FEATURE_FASTPATH
5321/**
5322 * hdd_enable_fastpath() - Enable fastpath if enabled in config INI
5323 * @hdd_cfg: hdd config
5324 * @context: lower layer context
5325 *
5326 * Return: none
5327 */
Arun Khandavallifae92942016-08-01 13:31:08 +05305328void hdd_enable_fastpath(struct hdd_config *hdd_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 void *context)
5330{
5331 if (hdd_cfg->fastpath_enable)
5332 hif_enable_fastpath(context);
5333}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334#endif
5335
Yuanyuan Liu13738502016-04-06 17:41:37 -07005336#if defined(FEATURE_WLAN_CH_AVOID)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005337/**
5338 * hdd_set_thermal_level_cb() - set thermal level callback function
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005339 * @context: hdd context pointer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 * @level: thermal level
5341 *
5342 * Change IPA data path to SW path when the thermal throttle level greater
5343 * than 0, and restore the original data path when throttle level is 0
5344 *
5345 * Return: none
5346 */
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005347static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348{
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005349 hdd_context_t *hdd_ctx = context;
5350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 /* Change IPA to SW path when throttle level greater than 0 */
5352 if (level > THROTTLE_LEVEL_0)
5353 hdd_ipa_send_mcc_scc_msg(hdd_ctx, true);
5354 else
5355 /* restore original concurrency mode */
5356 hdd_ipa_send_mcc_scc_msg(hdd_ctx, hdd_ctx->mcc_mode);
5357}
5358
5359/**
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305360 * hdd_get_safe_channel_from_pcl_and_acs_range() - Get safe channel for SAP
5361 * restart
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305362 * @adapter: AP adapter, which should be checked for NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305364 * Get a safe channel to restart SAP. PCL already takes into account the
5365 * unsafe channels. So, the PCL is validated with the ACS range to provide
5366 * a safe channel for the SAP to restart.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 *
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305368 * Return: Channel number to restart SAP in case of success. In case of any
5369 * failure, the channel number returned is zero.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005370 */
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305371static uint8_t hdd_get_safe_channel_from_pcl_and_acs_range(
5372 hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373{
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305374 struct sir_pcl_list pcl;
5375 QDF_STATUS status;
5376 uint32_t i, j;
5377 tHalHandle *hal_handle;
5378 hdd_context_t *hdd_ctx;
5379 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305381 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5382 if (!hdd_ctx) {
5383 hdd_err("invalid HDD context");
5384 return INVALID_CHANNEL_ID;
5385 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386
Manishekar Chandrasekaran79746ac2016-06-24 04:45:33 +05305387 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5388 if (!hal_handle) {
5389 hdd_err("invalid HAL handle");
5390 return INVALID_CHANNEL_ID;
5391 }
5392
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305393 status = cds_get_pcl_for_existing_conn(CDS_SAP_MODE,
5394 pcl.pcl_list, &pcl.pcl_len,
5395 pcl.weight_list, QDF_ARRAY_SIZE(pcl.weight_list));
5396 if (QDF_IS_STATUS_ERROR(status)) {
5397 hdd_err("Get PCL failed");
5398 return INVALID_CHANNEL_ID;
5399 }
5400
5401 if (!pcl.pcl_len) {
5402 hdd_alert("pcl length is zero. this is not expected");
5403 return INVALID_CHANNEL_ID;
5404 }
5405
5406 hdd_info("start:%d end:%d",
5407 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch,
5408 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch);
5409
5410 /* PCL already takes unsafe channel into account */
5411 for (i = 0; i < pcl.pcl_len; i++) {
5412 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5413 if ((pcl.pcl_list[i] >=
5414 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5415 (pcl.pcl_list[i] <=
5416 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5417 hdd_info("found PCL safe chan:%d", pcl.pcl_list[i]);
5418 return pcl.pcl_list[i];
5419 }
5420 }
5421
5422 hdd_info("no safe channel from PCL found in ACS range");
5423
5424 /* Try for safe channel from all valid channel */
5425 pcl.pcl_len = MAX_NUM_CHAN;
5426 status = sme_get_cfg_valid_channels(hal_handle, pcl.pcl_list,
5427 &pcl.pcl_len);
5428 if (QDF_IS_STATUS_ERROR(status)) {
5429 hdd_err("error in getting valid channel list");
5430 return INVALID_CHANNEL_ID;
5431 }
5432
5433 for (i = 0; i < pcl.pcl_len; i++) {
5434 hdd_info("chan[%d]:%d", i, pcl.pcl_list[i]);
5435 found = false;
5436 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
5437 if (cds_chan_to_freq(pcl.pcl_list[i]) ==
5438 hdd_ctx->unsafe_channel_list[j]) {
5439 hdd_info("unsafe chan:%d", pcl.pcl_list[i]);
5440 found = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441 break;
5442 }
5443 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305444
5445 if (found)
5446 continue;
5447
5448 if ((pcl.pcl_list[i] >=
5449 adapter->sessionCtx.ap.sapConfig.acs_cfg.start_ch) &&
5450 (pcl.pcl_list[i] <=
5451 adapter->sessionCtx.ap.sapConfig.acs_cfg.end_ch)) {
5452 hdd_info("found safe chan:%d", pcl.pcl_list[i]);
5453 return pcl.pcl_list[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 }
5455 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305456
5457 return INVALID_CHANNEL_ID;
5458}
5459
5460/**
5461 * hdd_restart_sap() - Restarts SAP on the given channel
5462 * @adapter: AP adapter
5463 * @channel: Channel
5464 *
5465 * Restarts the SAP interface by invoking the function which executes the
5466 * callback to perform channel switch using (E)CSA.
5467 *
5468 * Return: None
5469 */
5470void hdd_restart_sap(hdd_adapter_t *adapter, uint8_t channel)
5471{
5472 hdd_ap_ctx_t *hdd_ap_ctx;
5473 tHalHandle *hal_handle;
5474
5475 if (!adapter) {
5476 hdd_err("invalid adapter");
5477 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005478 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305479
5480 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
5481
5482 hal_handle = WLAN_HDD_GET_HAL_CTX(adapter);
5483 if (!hal_handle) {
5484 hdd_err("invalid HAL handle");
5485 return;
5486 }
5487
5488 hdd_ap_ctx->sapConfig.channel = channel;
5489 hdd_ap_ctx->sapConfig.ch_params.ch_width =
5490 hdd_ap_ctx->sapConfig.ch_width_orig;
5491
5492 hdd_info("chan:%d width:%d",
5493 channel, hdd_ap_ctx->sapConfig.ch_width_orig);
5494
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005495 cds_set_channel_params(hdd_ap_ctx->sapConfig.channel,
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305496 hdd_ap_ctx->sapConfig.sec_ch,
5497 &hdd_ap_ctx->sapConfig.ch_params);
5498
5499 cds_change_sap_channel_with_csa(adapter, hdd_ap_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005500}
5501
5502/**
5503 * hdd_ch_avoid_cb() - Avoid notified channels from FW handler
5504 * @adapter: HDD adapter pointer
5505 * @indParam: Channel avoid notification parameter
5506 *
5507 * Avoid channel notification from FW handler.
5508 * FW will send un-safe channel list to avoid over wrapping.
5509 * hostapd should not use notified channel
5510 *
5511 * Return: None
5512 */
5513static void hdd_ch_avoid_cb(void *hdd_context, void *indi_param)
5514{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515 hdd_context_t *hdd_ctxt;
5516 tSirChAvoidIndType *ch_avoid_indi;
5517 uint8_t range_loop;
Amar Singhalb8d4f152016-02-10 10:21:43 -08005518 enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL,
5519 end_channel_idx = INVALID_CHANNEL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 uint16_t start_channel;
5521 uint16_t end_channel;
5522 v_CONTEXT_t cds_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 tHddAvoidFreqList hdd_avoid_freq_list;
5524 uint32_t i;
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305525 QDF_STATUS status;
5526 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
5527 hdd_adapter_t *adapter_temp;
5528 uint8_t restart_chan;
5529 bool found = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530
5531 /* Basic sanity */
5532 if (!hdd_context || !indi_param) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005533 hdd_err("Invalid arguments");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005534 return;
5535 }
5536
5537 hdd_ctxt = (hdd_context_t *) hdd_context;
5538 ch_avoid_indi = (tSirChAvoidIndType *) indi_param;
5539 cds_context = hdd_ctxt->pcds_context;
5540
5541 /* Make unsafe channel list */
Jeff Johnson34c88b72016-08-15 14:27:11 -07005542 hdd_notice("band count %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005543 ch_avoid_indi->avoid_range_count);
5544
5545 /* generate vendor specific event */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305546 qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005547 for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) {
5548 hdd_avoid_freq_list.avoidFreqRange[i].startFreq =
5549 ch_avoid_indi->avoid_freq_range[i].start_freq;
5550 hdd_avoid_freq_list.avoidFreqRange[i].endFreq =
5551 ch_avoid_indi->avoid_freq_range[i].end_freq;
5552 }
5553 hdd_avoid_freq_list.avoidFreqRangeCount =
5554 ch_avoid_indi->avoid_range_count;
5555
5556 wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list);
5557
5558 /* clear existing unsafe channel cache */
5559 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305560 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561 sizeof(hdd_ctxt->unsafe_channel_list));
5562
5563 for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count;
5564 range_loop++) {
Amar Singhalb8d4f152016-02-10 10:21:43 -08005565 if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005566 hdd_warn("LTE Coex unsafe channel list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005567 break;
5568 }
5569
5570 start_channel = ieee80211_frequency_to_channel(
5571 ch_avoid_indi->avoid_freq_range[range_loop].start_freq);
5572 end_channel = ieee80211_frequency_to_channel(
5573 ch_avoid_indi->avoid_freq_range[range_loop].end_freq);
Jeff Johnson34c88b72016-08-15 14:27:11 -07005574 hdd_notice("start %d : %d, end %d : %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 ch_avoid_indi->avoid_freq_range[range_loop].start_freq,
5576 start_channel,
5577 ch_avoid_indi->avoid_freq_range[range_loop].end_freq,
5578 end_channel);
5579
5580 /* do not process frequency bands that are not mapped to
5581 * predefined channels
5582 */
5583 if (start_channel == 0 || end_channel == 0)
5584 continue;
5585
Amar Singhalb8d4f152016-02-10 10:21:43 -08005586 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5587 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005588 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005589 ch_avoid_indi->avoid_freq_range[
5590 range_loop].start_freq) {
5591 start_channel_idx = channel_loop;
5592 break;
5593 }
5594 }
Amar Singhalb8d4f152016-02-10 10:21:43 -08005595 for (channel_loop = CHAN_ENUM_1; channel_loop <=
5596 CHAN_ENUM_184; channel_loop++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005597 if (CDS_CHANNEL_FREQ(channel_loop) >=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 ch_avoid_indi->avoid_freq_range[
5599 range_loop].end_freq) {
5600 end_channel_idx = channel_loop;
Amar Singhal7a1726a2015-10-14 16:28:11 -07005601 if (CDS_CHANNEL_FREQ(channel_loop) >
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 ch_avoid_indi->avoid_freq_range[
5603 range_loop].end_freq)
5604 end_channel_idx--;
5605 break;
5606 }
5607 }
5608
Amar Singhalb8d4f152016-02-10 10:21:43 -08005609 if (start_channel_idx == INVALID_CHANNEL ||
5610 end_channel_idx == INVALID_CHANNEL)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005611 continue;
5612
5613 for (channel_loop = start_channel_idx; channel_loop <=
5614 end_channel_idx; channel_loop++) {
5615 hdd_ctxt->unsafe_channel_list[
Amar Singhal7a1726a2015-10-14 16:28:11 -07005616 hdd_ctxt->unsafe_channel_count++] =
5617 CDS_CHANNEL_FREQ(channel_loop);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005618 if (hdd_ctxt->unsafe_channel_count >=
Amar Singhalb8d4f152016-02-10 10:21:43 -08005619 NUM_CHANNELS) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005620 hdd_warn("LTECoex unsafe ch list full");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005621 break;
5622 }
5623 }
5624 }
5625
Jeff Johnson34c88b72016-08-15 14:27:11 -07005626 hdd_notice("number of unsafe channels is %d ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005627 hdd_ctxt->unsafe_channel_count);
5628
Yuanyuan Liu13738502016-04-06 17:41:37 -07005629 if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev,
5630 hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005631 hdd_ctxt->unsafe_channel_count)) {
5632 hdd_err("Failed to set unsafe channel");
5633
5634 /* clear existing unsafe channel cache */
5635 hdd_ctxt->unsafe_channel_count = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305636 qdf_mem_zero(hdd_ctxt->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005637 sizeof(hdd_ctxt->unsafe_channel_list));
5638
5639 return;
5640 }
5641
5642 for (channel_loop = 0;
5643 channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005644 hdd_notice("channel %d is not safe ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005645 hdd_ctxt->unsafe_channel_list[channel_loop]);
5646 }
5647
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305648 if (!hdd_ctxt->unsafe_channel_count) {
5649 hdd_info("no unsafe channels - not restarting SAP");
5650 return;
5651 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305653 /* No channel change is done for fixed channel SAP.
5654 * Loop through all ACS SAP interfaces and change the channels for
5655 * the ones operating on unsafe channels.
5656 */
5657 status = hdd_get_front_adapter(hdd_ctxt, &adapter_node);
5658 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
5659 adapter_temp = adapter_node->pAdapter;
5660
Manishekar Chandrasekarandb9b8672016-06-10 23:31:19 +05305661 if (!adapter_temp) {
5662 hdd_err("adapter is NULL, moving to next one");
5663 goto next_adapater;
5664 }
5665
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305666 if (!((adapter_temp->device_mode == QDF_SAP_MODE) &&
5667 (adapter_temp->sessionCtx.ap.sapConfig.acs_cfg.acs_mode))) {
5668 hdd_info("skip device mode:%d acs:%d",
5669 adapter_temp->device_mode,
5670 adapter_temp->sessionCtx.ap.sapConfig.
5671 acs_cfg.acs_mode);
5672 goto next_adapater;
5673 }
5674
5675 found = false;
5676 for (i = 0; i < hdd_ctxt->unsafe_channel_count; i++) {
5677 if (cds_chan_to_freq(
5678 adapter_temp->sessionCtx.ap.operatingChannel) ==
5679 hdd_ctxt->unsafe_channel_list[i]) {
5680 found = true;
5681 hdd_info("operating ch:%d is unsafe",
5682 adapter_temp->sessionCtx.ap.operatingChannel);
5683 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 }
5685 }
Manishekar Chandrasekaranc67b2bb2016-05-25 18:44:01 +05305686
5687 if (!found) {
5688 hdd_info("ch:%d is safe. no need to change channel",
5689 adapter_temp->sessionCtx.ap.operatingChannel);
5690 goto next_adapater;
5691 }
5692
5693 restart_chan =
5694 hdd_get_safe_channel_from_pcl_and_acs_range(
5695 adapter_temp);
5696 if (!restart_chan) {
5697 hdd_alert("fail to restart SAP");
5698 } else {
5699 hdd_info("sending coex indication");
5700 wlan_hdd_send_svc_nlink_msg
5701 (WLAN_SVC_LTE_COEX_IND, NULL, 0);
5702 hdd_restart_sap(adapter_temp, restart_chan);
5703 }
5704
5705next_adapater:
5706 status = hdd_get_next_adapter(hdd_ctxt, adapter_node, &next);
5707 adapter_node = next;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005708 }
5709 return;
5710}
5711
5712/**
5713 * hdd_init_channel_avoidance() - Initialize channel avoidance
5714 * @hdd_ctx: HDD global context
5715 *
5716 * Initialize the channel avoidance logic by retrieving the unsafe
Yuanyuan Liu13738502016-04-06 17:41:37 -07005717 * channel list from the platform driver and plumbing the data
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005718 * down to the lower layers. Then subscribe to subsequent channel
5719 * avoidance events.
5720 *
5721 * Return: None
5722 */
5723static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5724{
5725 uint16_t unsafe_channel_count;
5726 int index;
5727
Yuanyuan Liu13738502016-04-06 17:41:37 -07005728 pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
5729 hdd_ctx->unsafe_channel_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005730 &(hdd_ctx->unsafe_channel_count),
Amar Singhalb8d4f152016-02-10 10:21:43 -08005731 sizeof(uint16_t) * NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005732
Jeff Johnson34c88b72016-08-15 14:27:11 -07005733 hdd_notice("num of unsafe channels is %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005734 hdd_ctx->unsafe_channel_count);
5735
Anurag Chouhan6d760662016-02-20 16:05:43 +05305736 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
Amar Singhalb8d4f152016-02-10 10:21:43 -08005737 (uint16_t)NUM_CHANNELS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005738
5739 for (index = 0; index < unsafe_channel_count; index++) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07005740 hdd_notice("channel %d is not safe",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005741 hdd_ctx->unsafe_channel_list[index]);
5742
5743 }
5744
5745 /* Plug in avoid channel notification callback */
5746 sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb);
5747}
5748#else
5749static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx)
5750{
5751}
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08005752static void hdd_set_thermal_level_cb(void *context, u_int8_t level)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753{
5754}
Yuanyuan Liu13738502016-04-06 17:41:37 -07005755#endif /* defined(FEATURE_WLAN_CH_AVOID) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005756
5757/**
Rajeev Kumard004abc2016-02-17 12:09:56 -08005758 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
5759 * user space
5760 * @frame_ind: Management frame data to be informed.
5761 *
5762 * This function is used to indicate management frame to
5763 * user space
5764 *
5765 * Return: None
5766 *
5767 */
5768void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
5769{
5770 hdd_context_t *hdd_ctx = NULL;
5771 hdd_adapter_t *adapter = NULL;
5772 void *cds_context = NULL;
5773 int i;
5774
5775 /* Get the global VOSS context.*/
5776 cds_context = cds_get_global_context();
5777 if (!cds_context) {
5778 hdd_err("Global CDS context is Null");
5779 return;
5780 }
5781 /* Get the HDD context.*/
5782 hdd_ctx = (hdd_context_t *)cds_get_context(QDF_MODULE_ID_HDD);
5783
5784 if (0 != wlan_hdd_validate_context(hdd_ctx))
5785 return;
5786
5787 if (SME_SESSION_ID_ANY == frame_ind->sessionId) {
5788 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
5789 adapter =
5790 hdd_get_adapter_by_sme_session_id(hdd_ctx, i);
5791 if (adapter)
5792 break;
5793 }
5794 } else {
5795 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
5796 frame_ind->sessionId);
5797 }
5798
5799 if ((NULL != adapter) &&
5800 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
5801 __hdd_indicate_mgmt_frame(adapter,
5802 frame_ind->frame_len,
5803 frame_ind->frameBuf,
5804 frame_ind->frameType,
5805 frame_ind->rxChan,
5806 frame_ind->rxRssi);
5807 return;
5808}
5809
5810/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005811 * wlan_hdd_disable_all_dual_mac_features() - Disable dual mac features
5812 * @hdd_ctx: HDD context
5813 *
5814 * Disables all the dual mac features like DBS, Agile DFS etc.
5815 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305816 * Return: QDF_STATUS_SUCCESS on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305818static QDF_STATUS wlan_hdd_disable_all_dual_mac_features(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819{
5820 struct sir_dual_mac_config cfg;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305821 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822
5823 if (!hdd_ctx) {
5824 hdd_err("HDD context is NULL");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305825 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005826 }
5827
Arun Khandavallid4349a92016-07-25 11:10:43 +05305828 if (hdd_ctx->config->dual_mac_feature_disable)
5829 return QDF_STATUS_SUCCESS;
5830
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005831 cfg.scan_config = 0;
5832 cfg.fw_mode_config = 0;
Arun Khandavallid4349a92016-07-25 11:10:43 +05305833 cfg.set_dual_mac_cb = cds_soc_set_dual_mac_cfg_cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005834
5835 hdd_debug("Disabling all dual mac features...");
5836
5837 status = sme_soc_set_dual_mac_config(hdd_ctx->hHal, cfg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305838 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005839 hdd_err("sme_soc_set_dual_mac_config failed %d", status);
5840 return status;
5841 }
5842
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305843 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844}
5845
5846/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005847 * hdd_override_ini_config - Override INI config
5848 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005850 * Override INI config based on module parameter.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005851 *
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005852 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005854static void hdd_override_ini_config(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005855{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005857 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) {
5858 hdd_ctx->config->enableDFSChnlScan = enable_dfs_chan_scan;
5859 hdd_notice("Module enable_dfs_chan_scan set to %d",
5860 enable_dfs_chan_scan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005862 if (0 == enable_11d || 1 == enable_11d) {
5863 hdd_ctx->config->Is11dSupportEnabled = enable_11d;
5864 hdd_notice("Module enable_11d set to %d", enable_11d);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865 }
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005866}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005868/**
5869 * hdd_set_trace_level_for_each - Set trace level for each INI config
5870 * @hdd_ctx - HDD context
5871 *
5872 * Set trace level for each module based on INI config.
5873 *
5874 * Return: None
5875 */
5876static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx)
5877{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305878 hdd_qdf_trace_enable(QDF_MODULE_ID_WMI,
5879 hdd_ctx->config->qdf_trace_enable_wdi);
5880 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD,
5881 hdd_ctx->config->qdf_trace_enable_hdd);
5882 hdd_qdf_trace_enable(QDF_MODULE_ID_SME,
5883 hdd_ctx->config->qdf_trace_enable_sme);
5884 hdd_qdf_trace_enable(QDF_MODULE_ID_PE,
5885 hdd_ctx->config->qdf_trace_enable_pe);
5886 hdd_qdf_trace_enable(QDF_MODULE_ID_WMA,
5887 hdd_ctx->config->qdf_trace_enable_wma);
5888 hdd_qdf_trace_enable(QDF_MODULE_ID_SYS,
5889 hdd_ctx->config->qdf_trace_enable_sys);
5890 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF,
5891 hdd_ctx->config->qdf_trace_enable_qdf);
5892 hdd_qdf_trace_enable(QDF_MODULE_ID_SAP,
5893 hdd_ctx->config->qdf_trace_enable_sap);
5894 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SOFTAP,
5895 hdd_ctx->config->qdf_trace_enable_hdd_sap);
5896 hdd_qdf_trace_enable(QDF_MODULE_ID_BMI,
5897 hdd_ctx->config->qdf_trace_enable_bmi);
5898 hdd_qdf_trace_enable(QDF_MODULE_ID_CFG,
5899 hdd_ctx->config->qdf_trace_enable_cfg);
5900 hdd_qdf_trace_enable(QDF_MODULE_ID_EPPING,
5901 hdd_ctx->config->qdf_trace_enable_epping);
5902 hdd_qdf_trace_enable(QDF_MODULE_ID_QDF_DEVICE,
5903 hdd_ctx->config->qdf_trace_enable_qdf_devices);
5904 hdd_qdf_trace_enable(QDF_MODULE_ID_TXRX,
Bhargav Shah480a90f2015-06-24 15:10:14 +05305905 hdd_ctx->config->cfd_trace_enable_txrx);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305906 hdd_qdf_trace_enable(QDF_MODULE_ID_HTC,
5907 hdd_ctx->config->qdf_trace_enable_htc);
5908 hdd_qdf_trace_enable(QDF_MODULE_ID_HIF,
5909 hdd_ctx->config->qdf_trace_enable_hif);
5910 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_SAP_DATA,
5911 hdd_ctx->config->qdf_trace_enable_hdd_sap_data);
5912 hdd_qdf_trace_enable(QDF_MODULE_ID_HDD_DATA,
5913 hdd_ctx->config->qdf_trace_enable_hdd_data);
Bhargav Shah480a90f2015-06-24 15:10:14 +05305914
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 hdd_cfg_print(hdd_ctx);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005916}
5917
5918/**
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005919 * hdd_context_init() - Initialize HDD context
5920 * @hdd_ctx: HDD context.
5921 *
5922 * Initialize HDD context along with all the feature specific contexts.
5923 *
5924 * return: 0 on success and errno on failure.
5925 */
5926static int hdd_context_init(hdd_context_t *hdd_ctx)
5927{
5928 int ret;
5929
5930 hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN;
5931 hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX;
5932
5933 hdd_init_ll_stats_ctx();
5934
5935 init_completion(&hdd_ctx->mc_sus_event_var);
5936 init_completion(&hdd_ctx->ready_to_suspend);
5937
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305938 hdd_init_bpf_completion();
5939
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005940 qdf_spinlock_create(&hdd_ctx->connection_status_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305941 qdf_spinlock_create(&hdd_ctx->sta_update_info_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005942 qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock);
Manishekar Chandrasekaran7f63d052016-05-07 09:54:00 +05305943
Prashanth Bhatta527fd752016-04-28 12:35:23 -07005944 qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS);
5945
5946 init_completion(&hdd_ctx->set_antenna_mode_cmpl);
5947
5948 ret = hdd_scan_context_init(hdd_ctx);
5949 if (ret)
5950 goto list_destroy;
5951
5952 hdd_tdls_context_init(hdd_ctx);
5953
5954 hdd_rx_wake_lock_create(hdd_ctx);
5955
5956 ret = hdd_sap_context_init(hdd_ctx);
5957 if (ret)
5958 goto scan_destroy;
5959
5960 ret = hdd_roc_context_init(hdd_ctx);
5961 if (ret)
5962 goto sap_destroy;
5963
5964 wlan_hdd_cfg80211_extscan_init(hdd_ctx);
5965
5966 hdd_init_offloaded_packets_ctx(hdd_ctx);
5967
5968 ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy,
5969 hdd_ctx->config);
5970 if (ret)
5971 goto roc_destroy;
5972
5973 return 0;
5974
5975roc_destroy:
5976 hdd_roc_context_destroy(hdd_ctx);
5977
5978sap_destroy:
5979 hdd_sap_context_destroy(hdd_ctx);
5980
5981scan_destroy:
5982 hdd_scan_context_destroy(hdd_ctx);
5983 hdd_rx_wake_lock_destroy(hdd_ctx);
5984 hdd_tdls_context_destroy(hdd_ctx);
5985
5986list_destroy:
5987 qdf_list_destroy(&hdd_ctx->hddAdapters);
5988 return ret;
5989}
5990
5991/**
5992 * hdd_context_create() - Allocate and inialize HDD context.
Arun Khandavallifae92942016-08-01 13:31:08 +05305993 * @dev: Device Pointer to the underlying device
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005994 *
5995 * Allocate and initialize HDD context. HDD context is allocated as part of
5996 * wiphy allocation and then context is initialized.
5997 *
5998 * Return: HDD context on success and ERR_PTR on failure
5999 */
Arun Khandavallifae92942016-08-01 13:31:08 +05306000hdd_context_t *hdd_context_create(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006001{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306002 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006003 int ret = 0;
6004 hdd_context_t *hdd_ctx;
6005 v_CONTEXT_t p_cds_context;
6006
6007 ENTER();
6008
6009 p_cds_context = cds_get_global_context();
6010 if (p_cds_context == NULL) {
6011 hdd_alert("Failed to get CDS global context");
6012 ret = -EINVAL;
6013 goto err_out;
6014 }
6015
6016 hdd_ctx = hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t));
6017
6018 if (hdd_ctx == NULL) {
6019 ret = -ENOMEM;
6020 goto err_out;
6021 }
6022
6023 hdd_ctx->pcds_context = p_cds_context;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006024 hdd_ctx->parent_dev = dev;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006025
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306026 hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config));
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006027 if (hdd_ctx->config == NULL) {
6028 hdd_alert("Failed to alloc memory for HDD config!");
6029 ret = -ENOMEM;
6030 goto err_free_hdd_context;
6031 }
6032
6033 /* Read and parse the qcom_cfg.ini file */
6034 status = hdd_parse_config_ini(hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306035 if (QDF_STATUS_SUCCESS != status) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306036 hdd_err("Error (status: %d) parsing INI file: %s", status,
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006037 WLAN_INI_FILE);
6038 ret = -EINVAL;
6039 goto err_free_config;
6040 }
6041
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006042 hdd_ctx->configuredMcastBcastFilter =
6043 hdd_ctx->config->mcastBcastFilterSetting;
6044
6045 hdd_notice("Setting configuredMcastBcastFilter: %d",
6046 hdd_ctx->config->mcastBcastFilterSetting);
6047
Abhishek Singh5ea86532016-04-27 14:10:53 +05306048 cds_set_fatal_event(hdd_ctx->config->enable_fatal_event);
6049
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006050 hdd_override_ini_config(hdd_ctx);
6051
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006052 ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006053
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006054 ret = hdd_context_init(hdd_ctx);
6055
6056 if (ret)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006057 goto err_free_config;
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006058
Prashanth Bhatta527fd752016-04-28 12:35:23 -07006059
Yuanyuan Liu13738502016-04-06 17:41:37 -07006060 pld_set_fw_debug_mode(hdd_ctx->parent_dev,
6061 hdd_ctx->config->enable_fw_log);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006062
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006063
6064 /* Uses to enabled logging after SSR */
Komal Seelamc11bb222016-01-27 18:57:10 +05306065 hdd_ctx->fw_log_settings.enable = hdd_ctx->config->enable_fw_log;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006066
Anurag Chouhan6d760662016-02-20 16:05:43 +05306067 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006068 goto skip_multicast_logging;
6069
6070 cds_set_multicast_logging(hdd_ctx->config->multicast_host_fw_msgs);
6071
Nirav Shahed34b212016-04-25 10:59:16 +05306072 status = wlan_hdd_init_tx_rx_histogram(hdd_ctx);
6073 if (status)
6074 goto err_free_config;
6075
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006076 ret = hdd_logging_sock_activate_svc(hdd_ctx);
6077 if (ret)
Nirav Shahed34b212016-04-25 10:59:16 +05306078 goto err_free_histogram;
6079
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006080
6081 /*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306082 * Update QDF trace levels based upon the code. The multicast
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006083 * levels of the code need not be set when the logger thread
6084 * is not enabled.
6085 */
6086 if (cds_is_multicast_logging())
6087 wlan_logging_set_log_level();
6088
6089skip_multicast_logging:
6090 hdd_set_trace_level_for_each(hdd_ctx);
6091
6092 return hdd_ctx;
6093
Nirav Shahed34b212016-04-25 10:59:16 +05306094err_free_histogram:
6095 wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
6096
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006097err_free_config:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306098 qdf_mem_free(hdd_ctx->config);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006099
6100err_free_hdd_context:
6101 wiphy_free(hdd_ctx->wiphy);
6102
6103err_out:
6104 return ERR_PTR(ret);
6105}
6106
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006107#ifdef WLAN_OPEN_P2P_INTERFACE
6108/**
6109 * hdd_open_p2p_interface - Open P2P interface
6110 * @hdd_ctx: HDD context
6111 * @rtnl_held: True if RTNL lock held
6112 *
6113 * Open P2P interface during probe. This function called to open the P2P
6114 * interface at probe along with STA interface.
6115 *
6116 * Return: 0 on success and errno on failure
6117 */
6118static int hdd_open_p2p_interface(hdd_context_t *hdd_ctx, bool rtnl_held)
6119{
6120 hdd_adapter_t *adapter;
6121 uint8_t *p2p_dev_addr;
6122
6123 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
6124 !(hdd_ctx->config->intfMacAddr[0].bytes[0] & 0x02)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306125 qdf_mem_copy(hdd_ctx->p2pDeviceAddress.bytes,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006126 hdd_ctx->config->intfMacAddr[0].bytes,
6127 sizeof(tSirMacAddr));
6128
6129 /*
6130 * Generate the P2P Device Address. This consists of
6131 * the device's primary MAC address with the locally
6132 * administered bit set.
6133 */
6134 hdd_ctx->p2pDeviceAddress.bytes[0] |= 0x02;
6135 } else {
6136 p2p_dev_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6137 if (p2p_dev_addr == NULL) {
6138 hdd_alert("Failed to allocate mac_address for p2p_device");
6139 return -ENOSPC;
6140 }
6141
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306142 qdf_mem_copy(&hdd_ctx->p2pDeviceAddress.bytes[0], p2p_dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306143 QDF_MAC_ADDR_SIZE);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006144 }
6145
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006146 adapter = hdd_open_adapter(hdd_ctx, QDF_P2P_DEVICE_MODE, "p2p%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006147 &hdd_ctx->p2pDeviceAddress.bytes[0],
Ryan Hsu07495ea2016-01-21 15:25:39 -08006148 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006149
6150 if (NULL == adapter) {
6151 hdd_alert("Failed to do hdd_open_adapter for P2P Device Interface");
6152 return -ENOSPC;
6153 }
6154
6155 return 0;
6156}
6157#else
Manishekar Chandrasekaranc81ba242016-07-18 17:44:44 +05306158static inline int hdd_open_p2p_interface(hdd_context_t *hdd_ctx,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006159 bool rtnl_held)
6160{
6161 return 0;
6162}
6163#endif
6164
6165/**
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306166 * hdd_start_station_adapter()- Start the Station Adapter
6167 * @adapter: HDD adapter
6168 *
6169 * This function initializes the adapter for the station mode.
6170 *
6171 * Return: 0 on success or errno on failure.
6172 */
6173int hdd_start_station_adapter(hdd_adapter_t *adapter)
6174{
6175 QDF_STATUS status;
6176
6177 ENTER_DEV(adapter->dev);
6178
6179 status = hdd_init_station_mode(adapter);
6180
6181 if (QDF_STATUS_SUCCESS != status) {
6182 hdd_err("Error Initializing station mode: %d", status);
6183 return qdf_status_to_os_return(status);
6184 }
6185
Arun Khandavallifae92942016-08-01 13:31:08 +05306186 hdd_register_tx_flow_control(adapter,
6187 hdd_tx_resume_timer_expired_handler,
6188 hdd_tx_resume_cb);
6189
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306190 EXIT();
6191 return 0;
6192}
6193
6194/**
6195 * hdd_start_ap_adapter()- Start AP Adapter
6196 * @adapter: HDD adapter
6197 *
6198 * This function initializes the adapter for the AP mode.
6199 *
6200 * Return: 0 on success errno on failure.
6201 */
6202int hdd_start_ap_adapter(hdd_adapter_t *adapter)
6203{
6204 QDF_STATUS status;
6205
6206 ENTER();
6207
6208 status = hdd_init_ap_mode(adapter);
6209
6210 if (QDF_STATUS_SUCCESS != status) {
6211 hdd_err("Error Initializing the AP mode: %d", status);
6212 return qdf_status_to_os_return(status);
6213 }
6214
Arun Khandavallifae92942016-08-01 13:31:08 +05306215 hdd_register_tx_flow_control(adapter,
6216 hdd_softap_tx_resume_timer_expired_handler,
6217 hdd_softap_tx_resume_cb);
6218
Arun Khandavalli7e857c32016-06-26 12:07:16 +05306219 EXIT();
6220 return 0;
6221}
6222
6223/**
6224 * hdd_start_ftm_adapter()- Start FTM adapter
6225 * @adapter: HDD adapter
6226 *
6227 * This function initializes the adapter for the FTM mode.
6228 *
6229 * Return: 0 on success or errno on failure.
6230 */
6231int hdd_start_ftm_adapter(hdd_adapter_t *adapter)
6232{
6233 QDF_STATUS qdf_status;
6234
6235 ENTER_DEV(adapter->dev);
6236
6237 qdf_status = hdd_init_tx_rx(adapter);
6238
6239 if (QDF_STATUS_SUCCESS != qdf_status) {
6240 hdd_err("Failed to start FTM adapter: %d", qdf_status);
6241 return qdf_status_to_os_return(qdf_status);
6242 }
6243
6244 return 0;
6245 EXIT();
6246}
6247
6248/**
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006249 * hdd_open_interfaces - Open all required interfaces
6250 * hdd_ctx: HDD context
6251 * rtnl_held: True if RTNL lock is held
6252 *
6253 * Open all the interfaces like STA, P2P and OCB based on the configuration.
6254 *
6255 * Return: Primary adapter on success and PTR_ERR on failure
6256 */
6257static hdd_adapter_t *hdd_open_interfaces(hdd_context_t *hdd_ctx,
6258 bool rtnl_held)
6259{
6260 hdd_adapter_t *adapter = NULL;
6261 hdd_adapter_t *adapter_11p = NULL;
6262 int ret;
6263
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006264 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
Arun Khandavallifae92942016-08-01 13:31:08 +05306265 /* Create only 802.11p interface */
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006266 adapter = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE, "wlanocb%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006267 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006268 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006269
6270 if (adapter == NULL)
6271 return ERR_PTR(-ENOSPC);
6272
6273 return adapter;
6274 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006275 adapter = hdd_open_adapter(hdd_ctx, QDF_STA_MODE, "wlan%d",
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006276 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006277 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006278
6279 if (adapter == NULL)
6280 return ERR_PTR(-ENOSPC);
6281
6282 ret = hdd_open_p2p_interface(hdd_ctx, rtnl_held);
6283 if (ret)
6284 goto err_close_adapter;
6285
6286 /* Open 802.11p Interface */
6287 if (hdd_ctx->config->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08006288 adapter_11p = hdd_open_adapter(hdd_ctx, QDF_OCB_MODE,
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006289 "wlanocb%d",
6290 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -08006291 NET_NAME_UNKNOWN, rtnl_held);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006292 if (adapter_11p == NULL) {
6293 hdd_err("Failed to open 802.11p interface");
6294 goto err_close_adapter;
6295 }
6296 }
6297
6298 return adapter;
6299
6300err_close_adapter:
6301 hdd_close_all_adapters(hdd_ctx, rtnl_held);
6302 return ERR_PTR(ret);
6303}
6304
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006305/**
6306 * hdd_update_country_code - Update country code
6307 * @hdd_ctx: HDD context
6308 * @adapter: Primary adapter context
6309 *
6310 * Update country code based on module parameter country_code at SME and wait
6311 * for the settings to take effect.
6312 *
6313 * Return: 0 on success and errno on failure
6314 */
6315static int hdd_update_country_code(hdd_context_t *hdd_ctx,
6316 hdd_adapter_t *adapter)
6317{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306318 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006319 int ret = 0;
6320 unsigned long rc;
6321
6322 if (country_code == NULL)
6323 return 0;
6324
6325 INIT_COMPLETION(adapter->change_country_code);
6326
6327 status = sme_change_country_code(hdd_ctx->hHal,
6328 wlan_hdd_change_country_code_callback,
6329 country_code, adapter,
6330 hdd_ctx->pcds_context, eSIR_TRUE,
6331 eSIR_TRUE);
6332
6333
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306334 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006335 hdd_err("SME Change Country code from module param fail ret=%d",
6336 ret);
6337 return -EINVAL;
6338 }
6339
6340 rc = wait_for_completion_timeout(&adapter->change_country_code,
6341 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
6342 if (!rc) {
6343 hdd_err("SME while setting country code timed out");
6344 ret = -ETIMEDOUT;
6345 }
6346
6347 return ret;
6348}
6349
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306350#ifdef QCA_LL_TX_FLOW_CONTROL_V2
6351/**
6352 * hdd_txrx_populate_cds_config() - Populate txrx cds configuration
6353 * @cds_cfg: CDS Configuration
6354 * @hdd_ctx: Pointer to hdd context
6355 *
6356 * Return: none
6357 */
6358static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6359 *cds_cfg,
6360 hdd_context_t *hdd_ctx)
6361{
6362 cds_cfg->tx_flow_stop_queue_th =
6363 hdd_ctx->config->TxFlowStopQueueThreshold;
6364 cds_cfg->tx_flow_start_queue_offset =
6365 hdd_ctx->config->TxFlowStartQueueOffset;
6366}
6367#else
6368static inline void hdd_txrx_populate_cds_config(struct cds_config_info
6369 *cds_cfg,
6370 hdd_context_t *hdd_ctx)
6371{
6372}
6373#endif
6374
6375#ifdef FEATURE_WLAN_RA_FILTERING
6376/**
6377 * hdd_ra_populate_cds_config() - Populate RA filtering cds configuration
6378 * @cds_cfg: CDS Configuration
6379 * @hdd_ctx: Pointer to hdd context
6380 *
6381 * Return: none
6382 */
6383inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6384 hdd_context_t *hdd_ctx)
6385{
6386 cds_cfg->ra_ratelimit_interval =
6387 hdd_ctx->config->RArateLimitInterval;
6388 cds_cfg->is_ra_ratelimit_enabled =
6389 hdd_ctx->config->IsRArateLimitEnabled;
6390}
6391#else
6392inline void hdd_ra_populate_cds_config(struct cds_config_info *cds_cfg,
6393 hdd_context_t *hdd_ctx)
6394{
6395}
6396#endif
6397
6398/**
6399 * hdd_update_cds_config() - API to update cds configuration parameters
6400 * @hdd_ctx: HDD Context
6401 *
6402 * Return: 0 for Success, errno on failure
6403 */
6404int hdd_update_cds_config(hdd_context_t *hdd_ctx)
6405{
6406 struct cds_config_info *cds_cfg;
6407
6408 cds_cfg = (struct cds_config_info *)qdf_mem_malloc(sizeof(*cds_cfg));
6409 if (!cds_cfg) {
6410 hdd_err("failed to allocate cds config");
6411 return -ENOMEM;
6412 }
6413
6414 qdf_mem_zero(cds_cfg, sizeof(*cds_cfg));
6415
6416 /* UMA is supported in hardware for performing the
6417 * frame translation 802.11 <-> 802.3
6418 */
6419 cds_cfg->frame_xln_reqd = 1;
6420 cds_cfg->driver_type = DRIVER_TYPE_PRODUCTION;
6421 cds_cfg->powersave_offload_enabled =
6422 hdd_ctx->config->enablePowersaveOffload;
6423 cds_cfg->sta_dynamic_dtim = hdd_ctx->config->enableDynamicDTIM;
6424 cds_cfg->sta_mod_dtim = hdd_ctx->config->enableModulatedDTIM;
6425 cds_cfg->sta_maxlimod_dtim = hdd_ctx->config->fMaxLIModulatedDTIM;
6426 cds_cfg->wow_enable = hdd_ctx->config->wowEnable;
6427 cds_cfg->max_wow_filters = hdd_ctx->config->maxWoWFilters;
6428
6429 /* Here ol_ini_info is used to store ini status of arp offload
6430 * ns offload and others. Currently 1st bit is used for arp
6431 * off load and 2nd bit for ns offload currently, rest bits are unused
6432 */
6433 if (hdd_ctx->config->fhostArpOffload)
6434 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x1;
6435 if (hdd_ctx->config->fhostNSOffload)
6436 cds_cfg->ol_ini_info = cds_cfg->ol_ini_info | 0x2;
6437
6438 /*
6439 * Copy the DFS Phyerr Filtering Offload status.
6440 * This parameter reflects the value of the
6441 * dfs_phyerr_filter_offload flag as set in the ini.
6442 */
6443 cds_cfg->dfs_phyerr_filter_offload =
6444 hdd_ctx->config->fDfsPhyerrFilterOffload;
6445 if (hdd_ctx->config->ssdp)
6446 cds_cfg->ssdp = hdd_ctx->config->ssdp;
6447
6448 cds_cfg->enable_mc_list = hdd_ctx->config->fEnableMCAddrList;
6449 cds_cfg->ap_maxoffload_peers = hdd_ctx->config->apMaxOffloadPeers;
6450
6451 cds_cfg->ap_maxoffload_reorderbuffs =
6452 hdd_ctx->config->apMaxOffloadReorderBuffs;
6453
6454 cds_cfg->ap_disable_intrabss_fwd =
6455 hdd_ctx->config->apDisableIntraBssFwd;
6456
6457 cds_cfg->dfs_pri_multiplier =
6458 hdd_ctx->config->dfsRadarPriMultiplier;
6459 cds_cfg->reorder_offload =
6460 hdd_ctx->config->reorderOffloadSupport;
6461
6462 /* IPA micro controller data path offload resource config item */
6463 cds_cfg->uc_offload_enabled = hdd_ipa_uc_is_enabled(hdd_ctx);
6464 cds_cfg->uc_txbuf_count = hdd_ctx->config->IpaUcTxBufCount;
6465 cds_cfg->uc_txbuf_size = hdd_ctx->config->IpaUcTxBufSize;
6466 cds_cfg->uc_rxind_ringcount =
6467 hdd_ctx->config->IpaUcRxIndRingCount;
6468 cds_cfg->uc_tx_partition_base =
6469 hdd_ctx->config->IpaUcTxPartitionBase;
6470 cds_cfg->max_scan = hdd_ctx->config->max_scan_count;
6471
6472 cds_cfg->ip_tcp_udp_checksum_offload =
6473 hdd_ctx->config->enable_ip_tcp_udp_checksum_offload;
Nirav Shahbd36b062016-07-18 11:12:59 +05306474 cds_cfg->enable_rxthread = hdd_ctx->enableRxThread;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306475 cds_cfg->ce_classify_enabled =
6476 hdd_ctx->config->ce_classify_enabled;
6477 cds_cfg->tx_chain_mask_cck = hdd_ctx->config->tx_chain_mask_cck;
6478 cds_cfg->self_gen_frm_pwr = hdd_ctx->config->self_gen_frm_pwr;
6479 cds_cfg->max_station = hdd_ctx->config->maxNumberOfPeers;
Naveen Rawat64e477e2016-05-20 10:34:56 -07006480 cds_cfg->sub_20_channel_width = WLAN_SUB_20_CH_WIDTH_NONE;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05306481
6482 hdd_ra_populate_cds_config(cds_cfg, hdd_ctx);
6483 hdd_txrx_populate_cds_config(cds_cfg, hdd_ctx);
6484 hdd_nan_populate_cds_config(cds_cfg, hdd_ctx);
6485
6486 cds_init_ini_config(cds_cfg);
6487 return 0;
6488}
6489
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006490/**
6491 * hdd_init_thermal_info - Initialize thermal level
6492 * @hdd_ctx: HDD context
6493 *
6494 * Initialize thermal level at SME layer and set the thermal level callback
6495 * which would be called when a configured thermal threshold is hit.
6496 *
6497 * Return: 0 on success and errno on failure
6498 */
6499static int hdd_init_thermal_info(hdd_context_t *hdd_ctx)
6500{
6501 tSmeThermalParams thermal_param;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306502 QDF_STATUS status;
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006503
6504 thermal_param.smeThermalMgmtEnabled =
6505 hdd_ctx->config->thermalMitigationEnable;
6506 thermal_param.smeThrottlePeriod = hdd_ctx->config->throttlePeriod;
6507
Poddar, Siddarth83905022016-04-16 17:56:08 -07006508 thermal_param.sme_throttle_duty_cycle_tbl[0] =
6509 hdd_ctx->config->throttle_dutycycle_level0;
6510 thermal_param.sme_throttle_duty_cycle_tbl[1] =
6511 hdd_ctx->config->throttle_dutycycle_level1;
6512 thermal_param.sme_throttle_duty_cycle_tbl[2] =
6513 hdd_ctx->config->throttle_dutycycle_level2;
6514 thermal_param.sme_throttle_duty_cycle_tbl[3] =
6515 hdd_ctx->config->throttle_dutycycle_level3;
6516
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006517 thermal_param.smeThermalLevels[0].smeMinTempThreshold =
6518 hdd_ctx->config->thermalTempMinLevel0;
6519 thermal_param.smeThermalLevels[0].smeMaxTempThreshold =
6520 hdd_ctx->config->thermalTempMaxLevel0;
6521 thermal_param.smeThermalLevels[1].smeMinTempThreshold =
6522 hdd_ctx->config->thermalTempMinLevel1;
6523 thermal_param.smeThermalLevels[1].smeMaxTempThreshold =
6524 hdd_ctx->config->thermalTempMaxLevel1;
6525 thermal_param.smeThermalLevels[2].smeMinTempThreshold =
6526 hdd_ctx->config->thermalTempMinLevel2;
6527 thermal_param.smeThermalLevels[2].smeMaxTempThreshold =
6528 hdd_ctx->config->thermalTempMaxLevel2;
6529 thermal_param.smeThermalLevels[3].smeMinTempThreshold =
6530 hdd_ctx->config->thermalTempMinLevel3;
6531 thermal_param.smeThermalLevels[3].smeMaxTempThreshold =
6532 hdd_ctx->config->thermalTempMaxLevel3;
6533
6534 status = sme_init_thermal_info(hdd_ctx->hHal, thermal_param);
6535
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306536 if (!QDF_IS_STATUS_SUCCESS(status))
Anurag Chouhanc5548422016-02-24 18:33:27 +05306537 return qdf_status_to_os_return(status);
Prashanth Bhatta5f7c9b82016-01-09 13:15:21 -08006538
6539 sme_add_set_thermal_level_callback(hdd_ctx->hHal,
6540 hdd_set_thermal_level_cb);
6541
6542 return 0;
6543
6544}
6545
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08006546#if defined(CONFIG_HDD_INIT_WITH_RTNL_LOCK)
6547/**
6548 * hdd_hold_rtnl_lock - Hold RTNL lock
6549 *
6550 * Hold RTNL lock
6551 *
6552 * Return: True if held and false otherwise
6553 */
6554static inline bool hdd_hold_rtnl_lock(void)
6555{
6556 rtnl_lock();
6557 return true;
6558}
6559
6560/**
6561 * hdd_release_rtnl_lock - Release RTNL lock
6562 *
6563 * Release RTNL lock
6564 *
6565 * Return: None
6566 */
6567static inline void hdd_release_rtnl_lock(void)
6568{
6569 rtnl_unlock();
6570}
6571#else
6572static inline bool hdd_hold_rtnl_lock(void) { return false; }
6573static inline void hdd_release_rtnl_lock(void) { }
6574#endif
6575
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006576#if !defined(REMOVE_PKT_LOG)
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006577
6578/**
6579 * hdd_process_pktlog_command() - process pktlog command
6580 * @hdd_ctx: hdd context
6581 * @set_value: value set by user
6582 *
6583 * Return: 0 for success or error.
6584 */
6585int hdd_process_pktlog_command(hdd_context_t *hdd_ctx, uint32_t set_value)
6586{
6587 int ret;
6588 bool enable;
6589 uint8_t user_triggered = 0;
6590
6591 ret = wlan_hdd_validate_context(hdd_ctx);
6592 if (0 != ret)
6593 return ret;
6594
6595 hdd_info("set pktlog %d", set_value);
6596
6597 if (set_value > 2) {
6598 hdd_err("invalid pktlog value %d", set_value);
6599 return -EINVAL;
6600 }
6601
6602 /*
6603 * set_value = 0 then disable packetlog
6604 * set_value = 1 enable packetlog forcefully
6605 * set_vlaue = 2 then disable packetlog if disabled through ini or
6606 * enable packetlog with AUTO type.
6607 */
6608 enable = ((set_value > 0) && cds_is_packet_log_enabled()) ?
6609 true : false;
6610
6611 if (1 == set_value) {
6612 enable = true;
6613 user_triggered = 1;
6614 }
6615
6616 return hdd_pktlog_enable_disable(hdd_ctx, enable, user_triggered);
6617}
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006618/**
6619 * hdd_pktlog_enable_disable() - Enable/Disable packet logging
6620 * @hdd_ctx: HDD context
6621 * @enable: Flag to enable/disable
6622 *
6623 * Return: 0 on success; error number otherwise
6624 */
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006625int hdd_pktlog_enable_disable(hdd_context_t *hdd_ctx, bool enable,
6626 uint8_t user_triggered)
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006627{
6628 struct sir_wifi_start_log start_log;
6629 QDF_STATUS status;
6630
6631 start_log.ring_id = RING_ID_PER_PACKET_STATS;
6632 start_log.verbose_level =
6633 enable ? WLAN_LOG_LEVEL_ACTIVE : WLAN_LOG_LEVEL_OFF;
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08006634 start_log.ini_triggered = cds_is_packet_log_enabled();
6635 start_log.user_triggered = user_triggered;
6636
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08006637 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
6638 if (!QDF_IS_STATUS_SUCCESS(status)) {
6639 hdd_err("sme_wifi_start_logger failed(err=%d)", status);
6640 EXIT();
6641 return -EINVAL;
6642 }
6643
6644 return 0;
6645}
6646#endif /* REMOVE_PKT_LOG */
6647
6648
Chandrasekaran Manishekarcde33d72016-04-14 19:03:39 +05306649#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
6650/**
6651 * hdd_register_for_sap_restart_with_channel_switch() - Register for SAP channel
6652 * switch without restart
6653 *
6654 * Registers callback function to change the operating channel of SAP by using
6655 * channel switch announcements instead of restarting SAP.
6656 *
6657 * Return: QDF_STATUS
6658 */
6659QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void)
6660{
6661 QDF_STATUS status;
6662
6663 status = cds_register_sap_restart_channel_switch_cb(
6664 (void *)hdd_sap_restart_with_channel_switch);
6665 if (!QDF_IS_STATUS_SUCCESS(status))
6666 hdd_err("restart cb registration failed");
6667
6668 return status;
6669}
6670#endif
6671
Komal Seelam92fff912016-03-24 11:51:41 +05306672#ifdef CONFIG_CNSS
6673/**
6674 * hdd_get_cnss_wlan_mac_buff() - API to query platform driver for MAC address
6675 * @dev: Device Pointer
6676 * @num: Number of Valid Mac address
6677 *
6678 * Return: Pointer to MAC address buffer
6679 */
6680static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6681{
6682 return cnss_common_get_wlan_mac_address(dev, num);
6683}
6684#else
6685static uint8_t *hdd_get_cnss_wlan_mac_buff(struct device *dev, uint32_t *num)
6686{
6687 *num = 0;
6688 return NULL;
6689}
6690#endif
6691
6692/**
6693 * hdd_populate_random_mac_addr() - API to populate random mac addresses
6694 * @hdd_ctx: HDD Context
6695 * @num: Number of random mac addresses needed
6696 *
6697 * Generate random addresses using bit manipulation on the base mac address
6698 *
6699 * Return: None
6700 */
6701static void hdd_populate_random_mac_addr(hdd_context_t *hdd_ctx, uint32_t num)
6702{
6703 uint32_t start_idx = QDF_MAX_CONCURRENCY_PERSONA - num;
6704 uint32_t iter;
6705 struct hdd_config *ini = hdd_ctx->config;
6706 uint8_t *buf = NULL;
6707 uint8_t macaddr_b3, tmp_br3;
6708 uint8_t *src = ini->intfMacAddr[0].bytes;
6709
6710 for (iter = start_idx; iter < QDF_MAX_CONCURRENCY_PERSONA; ++iter) {
6711 buf = ini->intfMacAddr[iter].bytes;
6712 qdf_mem_copy(buf, src, QDF_MAC_ADDR_SIZE);
6713 macaddr_b3 = buf[3];
6714 tmp_br3 = ((macaddr_b3 >> 4 & INTF_MACADDR_MASK) + iter) &
6715 INTF_MACADDR_MASK;
6716 macaddr_b3 += tmp_br3;
6717 macaddr_b3 ^= (1 << INTF_MACADDR_MASK);
6718 buf[0] |= 0x02;
6719 buf[3] = macaddr_b3;
Jeff Johnson34c88b72016-08-15 14:27:11 -07006720 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05306721 }
6722}
6723
6724/**
6725 * hdd_cnss_wlan_mac() - API to get mac addresses from cnss platform driver
6726 * @hdd_ctx: HDD Context
6727 *
6728 * API to get mac addresses from platform driver and update the driver
6729 * structures and configure FW with the base mac address.
6730 * Return: int
6731 */
6732static int hdd_cnss_wlan_mac(hdd_context_t *hdd_ctx)
6733{
6734 uint32_t no_of_mac_addr, iter;
6735 uint32_t max_mac_addr = QDF_MAX_CONCURRENCY_PERSONA;
6736 uint32_t mac_addr_size = QDF_MAC_ADDR_SIZE;
6737 uint8_t *addr, *buf;
6738 struct device *dev = hdd_ctx->parent_dev;
6739 struct hdd_config *ini = hdd_ctx->config;
6740 tSirMacAddr mac_addr;
6741 QDF_STATUS status;
6742
6743 addr = hdd_get_cnss_wlan_mac_buff(dev, &no_of_mac_addr);
6744
6745 if (no_of_mac_addr == 0 || !addr) {
6746 hdd_warn("Platform Driver Doesn't have wlan mac addresses");
6747 return -EINVAL;
6748 }
6749
6750 if (no_of_mac_addr > max_mac_addr)
6751 no_of_mac_addr = max_mac_addr;
6752
6753 qdf_mem_copy(&mac_addr, addr, mac_addr_size);
6754
6755 for (iter = 0; iter < no_of_mac_addr; ++iter, addr += mac_addr_size) {
6756 buf = ini->intfMacAddr[iter].bytes;
6757 qdf_mem_copy(buf, addr, QDF_MAC_ADDR_SIZE);
Jeff Johnson34c88b72016-08-15 14:27:11 -07006758 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(buf));
Komal Seelam92fff912016-03-24 11:51:41 +05306759 }
6760
6761 status = sme_set_custom_mac_addr(mac_addr);
6762
6763 if (!QDF_IS_STATUS_SUCCESS(status))
6764 return -EAGAIN;
6765 if (no_of_mac_addr < max_mac_addr)
6766 hdd_populate_random_mac_addr(hdd_ctx, max_mac_addr -
6767 no_of_mac_addr);
6768 return 0;
6769}
6770
6771/**
6772 * hdd_initialize_mac_address() - API to get wlan mac addresses
6773 * @hdd_ctx: HDD Context
6774 *
6775 * Get MAC addresses from platform driver or wlan_mac.bin. If platform driver
6776 * is provisioned with mac addresses, driver uses it, else it will use
6777 * wlan_mac.bin to update HW MAC addresses.
6778 *
6779 * Return: None
6780 */
6781static void hdd_initialize_mac_address(hdd_context_t *hdd_ctx)
6782{
6783 QDF_STATUS status;
6784 int ret;
6785
6786 ret = hdd_cnss_wlan_mac(hdd_ctx);
6787 if (ret == 0)
6788 return;
6789
6790 hdd_warn("Can't update mac config via platform driver ret:%d", ret);
6791
6792 status = hdd_update_mac_config(hdd_ctx);
6793
6794 if (!QDF_IS_STATUS_SUCCESS(status))
6795 hdd_warn("can't update mac config, using MAC from ini file");
6796}
6797
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006798/**
Jeff Johnson89c66ff2016-04-22 15:21:37 -07006799 * hdd_tsf_init() - Initialize the TSF synchronization interface
6800 * @hdd_ctx: HDD global context
6801 *
6802 * When TSF synchronization via GPIO is supported by the driver and
6803 * has been enabled in the configuration file, this function plumbs
6804 * the GPIO value down to firmware via SME.
6805 *
6806 * Return: None
6807 */
6808#ifdef WLAN_FEATURE_TSF
6809static void hdd_tsf_init(hdd_context_t *hdd_ctx)
6810{
6811 QDF_STATUS status;
6812
6813 if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
6814 return;
6815
6816 status = sme_set_tsf_gpio(hdd_ctx->hHal,
6817 hdd_ctx->config->tsf_gpio_pin);
6818 if (!QDF_IS_STATUS_SUCCESS(status))
6819 hdd_err("Set tsf GPIO failed, status: %d", status);
6820}
6821#else
6822static void hdd_tsf_init(hdd_context_t *hdd_ctx)
6823{
6824}
6825#endif
6826
6827/**
Prashanth Bhatta07998752016-04-28 12:35:33 -07006828 * hdd_pre_enable_configure() - Configurations prior to cds_enable
6829 * @hdd_ctx: HDD context
6830 *
6831 * Pre configurations to be done at lower layer before calling cds enable.
6832 *
6833 * Return: 0 on success and errno on failure.
6834 */
6835static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx)
6836{
6837 int ret;
6838 QDF_STATUS status;
6839 tSirRetStatus hal_status;
6840
6841 ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb);
6842
6843 /*
6844 * Set 802.11p config
6845 * TODO-OCB: This has been temporarily added here to ensure this
6846 * parameter is set in CSR when we init the channel list. This should
6847 * be removed once the 5.9 GHz channels are added to the regulatory
6848 * domain.
6849 */
6850 hdd_set_dot11p_config(hdd_ctx);
6851
6852 /*
6853 * Note that the cds_pre_enable() sequence triggers the cfg download.
6854 * The cfg download must occur before we update the SME config
6855 * since the SME config operation must access the cfg database
6856 */
6857 status = hdd_set_sme_config(hdd_ctx);
6858
6859 if (QDF_STATUS_SUCCESS != status) {
6860 hdd_alert("Failed hdd_set_sme_config: %d", status);
6861 ret = qdf_status_to_os_return(status);
6862 goto out;
6863 }
6864
6865 ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS,
6866 hdd_ctx->config->tx_chain_mask_1ss,
6867 PDEV_CMD);
6868 if (0 != ret) {
6869 hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret);
6870 goto out;
6871 }
6872
6873 hdd_program_country_code(hdd_ctx);
6874
6875 status = hdd_set_sme_chan_list(hdd_ctx);
6876 if (status != QDF_STATUS_SUCCESS) {
6877 hdd_alert("Failed to init channel list: %d", status);
6878 ret = qdf_status_to_os_return(status);
6879 goto out;
6880 }
6881
6882 /* Apply the cfg.ini to cfg.dat */
6883 if (!hdd_update_config_dat(hdd_ctx)) {
6884 hdd_alert("config update failed");
6885 ret = -EINVAL;
6886 goto out;
6887 }
6888
Komal Seelam92fff912016-03-24 11:51:41 +05306889 hdd_initialize_mac_address(hdd_ctx);
Prashanth Bhatta07998752016-04-28 12:35:33 -07006890
6891 /*
6892 * Set the MAC Address Currently this is used by HAL to add self sta.
6893 * Remove this once self sta is added as part of session open.
6894 */
6895 hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID,
6896 hdd_ctx->config->intfMacAddr[0].bytes,
6897 sizeof(hdd_ctx->config->intfMacAddr[0]));
6898
6899 if (!IS_SIR_STATUS_SUCCESS(hal_status)) {
6900 hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]",
6901 hal_status, hal_status);
6902 ret = -EINVAL;
6903 goto out;
6904 }
6905
6906 hdd_init_channel_avoidance(hdd_ctx);
6907
6908out:
6909 return ret;
6910}
6911
6912/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006913 * wlan_hdd_p2p_lo_event_callback - P2P listen offload stop event handler
6914 * @context_ptr - hdd context pointer
6915 * @event_ptr - event structure pointer
6916 *
6917 * This is the p2p listen offload stop event handler, it sends vendor
6918 * event back to supplicant to notify the stop reason.
6919 *
6920 * Return: None
6921 */
6922static void wlan_hdd_p2p_lo_event_callback(void *context_ptr,
6923 void *event_ptr)
6924{
6925 hdd_context_t *hdd_ctx = (hdd_context_t *)context_ptr;
6926 struct sir_p2p_lo_event *evt = event_ptr;
6927 struct sk_buff *vendor_event;
6928
6929 ENTER();
6930
6931 if (hdd_ctx == NULL) {
6932 hdd_err("Invalid HDD context pointer");
6933 return;
6934 }
6935
6936 vendor_event =
6937 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
6938 NULL, sizeof(uint32_t) + NLMSG_HDRLEN,
6939 QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
6940 GFP_KERNEL);
6941
6942 if (!vendor_event) {
6943 hdd_err("cfg80211_vendor_event_alloc failed");
6944 return;
6945 }
6946
6947 if (nla_put_u32(vendor_event,
6948 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
6949 evt->reason_code)) {
6950 hdd_err("nla put failed");
6951 kfree_skb(vendor_event);
6952 return;
6953 }
6954
6955 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
6956}
6957
6958/**
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05306959 * hdd_adaptive_dwelltime_init() - initialization for adaptive dwell time config
6960 * @hdd_ctx: HDD context
6961 *
6962 * This function sends the adaptive dwell time config configuration to the
6963 * firmware via WMA
6964 *
6965 * Return: 0 - success, < 0 - failure
6966 */
6967static int hdd_adaptive_dwelltime_init(hdd_context_t *hdd_ctx)
6968{
6969 QDF_STATUS status;
6970 struct adaptive_dwelltime_params dwelltime_params;
6971
6972 dwelltime_params.is_enabled =
6973 hdd_ctx->config->adaptive_dwell_mode_enabled;
6974 dwelltime_params.dwelltime_mode =
6975 hdd_ctx->config->global_adapt_dwelltime_mode;
6976 dwelltime_params.lpf_weight =
6977 hdd_ctx->config->adapt_dwell_lpf_weight;
6978 dwelltime_params.passive_mon_intval =
6979 hdd_ctx->config->adapt_dwell_passive_mon_intval;
6980 dwelltime_params.wifi_act_threshold =
6981 hdd_ctx->config->adapt_dwell_wifi_act_threshold;
6982
6983 status = sme_set_adaptive_dwelltime_config(hdd_ctx->hHal,
6984 &dwelltime_params);
6985
6986 hdd_debug("Sending Adaptive Dwelltime Configuration to fw");
6987 if (!QDF_IS_STATUS_SUCCESS(status)) {
6988 hdd_err("Failed to send Adaptive Dwelltime configuration!");
6989 return -EAGAIN;
6990 }
6991 return 0;
6992}
6993
Arun Khandavallid4349a92016-07-25 11:10:43 +05306994#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
6995/**
6996 * hdd_set_auto_shutdown_cb() - Set auto shutdown callback
6997 * @hdd_ctx: HDD context
6998 *
6999 * Set auto shutdown callback to get indications from firmware to indicate
7000 * userspace to shutdown WLAN after a configured amount of inactivity.
7001 *
7002 * Return: 0 on success and errno on failure.
7003 */
7004static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7005{
7006 QDF_STATUS status;
7007
7008 if (!hdd_ctx->config->WlanAutoShutdown)
7009 return 0;
7010
7011 status = sme_set_auto_shutdown_cb(hdd_ctx->hHal,
7012 wlan_hdd_auto_shutdown_cb);
7013 if (status != QDF_STATUS_SUCCESS)
7014 hdd_err("Auto shutdown feature could not be enabled: %d",
7015 status);
7016
7017 return qdf_status_to_os_return(status);
7018}
7019#else
7020static int hdd_set_auto_shutdown_cb(hdd_context_t *hdd_ctx)
7021{
7022 return 0;
7023}
7024#endif
7025
7026/**
7027 * hdd_features_init() - Init features
7028 * @hdd_ctx: HDD context
7029 * @adapter: Primary adapter context
7030 *
7031 * Initialize features and their feature context after WLAN firmware is up.
7032 *
7033 * Return: 0 on success and errno on failure.
7034 */
7035static int hdd_features_init(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7036{
7037 tSirTxPowerLimit hddtxlimit;
7038 QDF_STATUS status;
7039 int ret;
7040
7041 ENTER();
7042
7043 ret = hdd_update_country_code(hdd_ctx, adapter);
7044 if (ret) {
7045 hdd_err("Failed to update country code: %d", ret);
7046 goto out;
7047 }
7048
7049 /* FW capabilities received, Set the Dot11 mode */
7050 sme_setdef_dot11mode(hdd_ctx->hHal);
7051
Arun Khandavallid4349a92016-07-25 11:10:43 +05307052
7053 if (hdd_ctx->config->fIsImpsEnabled)
7054 hdd_set_idle_ps_config(hdd_ctx, true);
7055 else
7056 hdd_set_idle_ps_config(hdd_ctx, false);
7057
7058 if (hdd_lro_init(hdd_ctx))
7059 hdd_err("Unable to initialize LRO in fw");
7060
7061 if (hdd_adaptive_dwelltime_init(hdd_ctx))
7062 hdd_err("Unable to send adaptive dwelltime setting to FW");
7063
7064 ret = hdd_init_thermal_info(hdd_ctx);
7065 if (ret) {
7066 hdd_err("Error while initializing thermal information");
7067 goto deregister_frames;
7068 }
7069
7070 hddtxlimit.txPower2g = hdd_ctx->config->TxPower2g;
7071 hddtxlimit.txPower5g = hdd_ctx->config->TxPower5g;
7072 status = sme_txpower_limit(hdd_ctx->hHal, &hddtxlimit);
7073 if (!QDF_IS_STATUS_SUCCESS(status))
7074 hdd_err("Error setting txlimit in sme: %d", status);
7075
7076 hdd_tsf_init(hdd_ctx);
7077
7078 if (hdd_ctx->config->dual_mac_feature_disable) {
7079 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7080 if (status != QDF_STATUS_SUCCESS) {
7081 hdd_err("Failed to disable dual mac features");
7082 goto deregister_frames;
7083 }
7084 }
7085
7086 ret = hdd_register_cb(hdd_ctx);
7087 if (ret) {
7088 hdd_err("Failed to register HDD callbacks!");
7089 goto deregister_frames;
7090 }
7091
7092 if (hdd_ctx->config->dual_mac_feature_disable) {
7093 status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
7094 if (status != QDF_STATUS_SUCCESS) {
7095 hdd_err("Failed to disable dual mac features");
7096 goto deregister_cb;
7097 }
7098 }
7099
7100 /* register P2P Listen Offload event callback */
7101 if (wma_is_p2p_lo_capable())
7102 sme_register_p2p_lo_event(hdd_ctx->hHal, hdd_ctx,
7103 wlan_hdd_p2p_lo_event_callback);
7104
7105 ret = hdd_set_auto_shutdown_cb(hdd_ctx);
7106
7107 if (ret)
7108 goto deregister_cb;
7109
7110 EXIT();
7111 return 0;
7112
7113deregister_cb:
7114 hdd_deregister_cb(hdd_ctx);
7115deregister_frames:
7116 wlan_hdd_cfg80211_deregister_frames(adapter);
7117out:
7118 return -EINVAL;
7119
7120}
7121
7122
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05307123/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307124 * hdd_configure_cds() - Configure cds modules
7125 * @hdd_ctx: HDD context
7126 * @adapter: Primary adapter context
7127 *
7128 * Enable Cds modules after WLAN firmware is up.
7129 *
7130 * Return: 0 on success and errno on failure.
7131 */
7132int hdd_configure_cds(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter)
7133{
7134 int ret;
7135 QDF_STATUS status;
7136 /* structure of function pointers to be used by CDS */
7137 struct cds_sme_cbacks sme_cbacks;
7138
7139 ret = hdd_pre_enable_configure(hdd_ctx);
7140 if (ret) {
7141 hdd_err("Failed to pre-configure cds");
7142 goto out;
7143 }
7144
7145 /*
7146 * Start CDS which starts up the SME/MAC/HAL modules and everything
7147 * else
7148 */
7149 status = cds_enable(hdd_ctx->pcds_context);
7150
7151 if (!QDF_IS_STATUS_SUCCESS(status)) {
7152 hdd_alert("cds_enable failed");
7153 goto out;
7154 }
7155
7156 status = hdd_post_cds_enable_config(hdd_ctx);
7157 if (!QDF_IS_STATUS_SUCCESS(status)) {
7158 hdd_alert("hdd_post_cds_enable_config failed");
7159 goto out;
7160 }
7161
7162 ret = hdd_features_init(hdd_ctx, adapter);
7163 if (ret)
7164 goto out;
7165
7166 sme_cbacks.sme_get_valid_channels = sme_get_cfg_valid_channels;
7167 sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
7168 status = cds_init_policy_mgr(&sme_cbacks);
7169 if (!QDF_IS_STATUS_SUCCESS(status)) {
7170 hdd_err("Policy manager initialization failed");
7171 goto out;
7172 }
7173
7174 return 0;
7175out:
7176 return -EINVAL;
7177}
7178
7179/**
7180 * hdd_deconfigure_cds() -De-Configure cds
7181 * @hdd_ctx: HDD context
7182 *
7183 * Deconfigure Cds modules before WLAN firmware is down.
7184 *
7185 * Return: 0 on success and errno on failure.
7186 */
7187int hdd_deconfigure_cds(hdd_context_t *hdd_ctx)
7188{
7189 QDF_STATUS qdf_status;
7190
7191 ENTER();
7192 /* De-register the SME callbacks */
7193 hdd_deregister_cb(hdd_ctx);
7194
7195 /* De-init Policy Manager */
7196 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7197 hdd_err("Failed to deinit policy manager");
7198 /* Proceed and complete the clean up */
7199 return -EINVAL;
7200 }
7201
7202 qdf_status = cds_disable(hdd_ctx->pcds_context);
7203 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7204 hdd_err("Failed to Disable the CDS Modules! :%d",
7205 qdf_status);
7206 return -EINVAL;
7207 }
7208
7209 EXIT();
7210 return 0;
7211}
7212
7213
7214/**
7215 * hdd_wlan_stop_modules - Single driver state machine for stoping modules
7216 * @hdd_ctx: HDD context
7217 * @shutdown: flag to indicate from SSR or normal path
7218 *
7219 * This function maintains the driver state machine it will be invoked from
7220 * exit, shutdown and con_mode change handler. Depending on the driver state
7221 * shall perform the stopping/closing of the modules.
7222 *
7223 * Return: 0 for success; non-zero for failure
7224 */
7225int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx, bool shutdown)
7226{
7227 void *hif_ctx;
7228 qdf_device_t qdf_ctx;
7229 QDF_STATUS qdf_status;
7230 int ret;
7231 p_cds_sched_context cds_sched_context = NULL;
7232
7233 ENTER();
7234
7235 qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7236 if (!qdf_ctx) {
7237 hdd_err("QDF device context NULL");
7238 return -EINVAL;
7239 }
7240
7241 cds_sched_context = get_cds_sched_ctxt();
7242 if (!cds_sched_context) {
7243 hdd_err("cds scheduler context NULL");
7244 return -EINVAL;
7245 }
7246
7247 hdd_info("Present Driver Status: %d", hdd_ctx->driver_status);
7248
7249 switch (hdd_ctx->driver_status) {
7250 case DRIVER_MODULES_UNINITIALIZED:
7251 hdd_info("Modules not initialized just return");
7252 return 0;
7253 case DRIVER_MODULES_CLOSED:
7254 hdd_info("Modules already closed");
7255 return 0;
7256 case DRIVER_MODULES_ENABLED:
7257 if (hdd_deconfigure_cds(hdd_ctx)) {
7258 hdd_alert("Failed to de-configure CDS");
7259 QDF_ASSERT(0);
7260 return -EINVAL;
7261 }
7262 hdd_info("successfully Disabled the CDS modules!");
7263 hdd_ctx->driver_status = DRIVER_MODULES_OPENED;
7264 break;
7265 case DRIVER_MODULES_OPENED:
7266 hdd_info("Closing CDS modules!");
7267 break;
7268 default:
7269 hdd_err("Trying to stop wlan in a wrong state: %d",
7270 hdd_ctx->driver_status);
7271 QDF_ASSERT(0);
7272 return -EINVAL;
7273 }
7274
7275 qdf_status = cds_close(hdd_ctx->pcds_context);
7276 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
7277 hdd_warn("Failed to stop CDS:%d", qdf_status);
7278 QDF_ASSERT(0);
7279 }
7280 /* Clean up message queues of TX, RX and MC thread */
7281 cds_sched_flush_mc_mqs(cds_sched_context);
7282
7283 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
7284 if (!hif_ctx) {
7285 hdd_err("Hif context is Null");
7286 return -EINVAL;
7287 }
7288
7289 hdd_hif_close(hif_ctx);
7290
7291 ol_cds_free();
7292
7293 if (!shutdown) {
7294 ret = pld_power_off(qdf_ctx->dev);
7295 if (ret)
7296 hdd_err("CNSS power down failed put device into Low power mode:%d",
7297 ret);
7298 }
7299 hdd_ctx->driver_status = DRIVER_MODULES_CLOSED;
7300
7301 EXIT();
7302
7303 return 0;
7304
7305}
7306
7307/**
7308 * hdd_iface_change_callback() - Function invoked when stop modules expires
7309 * @priv: pointer to hdd context
7310 *
7311 * This function is invoked when the timer waiting for the interface change
7312 * expires, it shall cut-down the power to wlan and stop all the modules.
7313 *
7314 * Return: void
7315 */
7316static void hdd_iface_change_callback(void *priv)
7317{
7318 hdd_context_t *hdd_ctx = (hdd_context_t *) priv;
7319 int ret;
7320 int status = wlan_hdd_validate_context(hdd_ctx);
7321
7322 if (status)
7323 return;
7324
7325 ENTER();
7326 hdd_info("Interface change timer expired close the modules!");
7327 mutex_lock(&hdd_ctx->iface_change_lock);
7328 ret = hdd_wlan_stop_modules(hdd_ctx, false);
7329 if (ret)
7330 hdd_alert("Failed to stop modules");
7331 mutex_unlock(&hdd_ctx->iface_change_lock);
7332 EXIT();
7333}
7334
7335/**
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007336 * hdd_wlan_startup() - HDD init function
7337 * @dev: Pointer to the underlying device
7338 *
7339 * This is the driver startup code executed once a WLAN device has been detected
7340 *
7341 * Return: 0 for success, < 0 for failure
7342 */
Arun Khandavallifae92942016-08-01 13:31:08 +05307343int hdd_wlan_startup(struct device *dev)
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007344{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307345 QDF_STATUS status;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007346 hdd_adapter_t *adapter = NULL;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007347 hdd_context_t *hdd_ctx = NULL;
7348 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05307349 void *hif_sc;
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007350 bool rtnl_held;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007351
7352 ENTER();
7353
Arun Khandavallifae92942016-08-01 13:31:08 +05307354 hdd_ctx = hdd_context_create(dev);
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007355
7356 if (IS_ERR(hdd_ctx))
7357 return PTR_ERR(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007358
Arun Khandavallifae92942016-08-01 13:31:08 +05307359 qdf_mc_timer_init(&hdd_ctx->iface_change_timer, QDF_TIMER_TYPE_SW,
7360 hdd_iface_change_callback, (void *)hdd_ctx);
7361
7362 mutex_init(&hdd_ctx->iface_change_lock);
7363
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007364 ret = hdd_init_netlink_services(hdd_ctx);
7365 if (ret)
7366 goto err_hdd_free_context;
7367
Arun Khandavallifae92942016-08-01 13:31:08 +05307368 hdd_wlan_green_ap_init(hdd_ctx);
7369
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307370 ret = hdd_update_config(hdd_ctx);
7371 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +05307372 goto err_exit_nl_srv;
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307373
Arun Khandavallifae92942016-08-01 13:31:08 +05307374 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
7375 if (ret) {
7376 hdd_alert("Failed to start modules: %d", ret);
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007377 goto err_exit_nl_srv;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007378 }
7379
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007380 wlan_hdd_update_wiphy(hdd_ctx->wiphy, hdd_ctx->config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007381
Anurag Chouhan6d760662016-02-20 16:05:43 +05307382 hdd_ctx->hHal = cds_get_context(QDF_MODULE_ID_SME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007383
7384 if (NULL == hdd_ctx->hHal) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007385 hdd_alert("HAL context is null");
Arun Khandavallifae92942016-08-01 13:31:08 +05307386 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007387 }
7388
Prashanth Bhatta07998752016-04-28 12:35:33 -07007389 ret = hdd_wiphy_init(hdd_ctx);
7390 if (ret) {
7391 hdd_alert("Failed to initialize wiphy: %d", ret);
Arun Khandavallifae92942016-08-01 13:31:08 +05307392 goto err_stop_modules;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007393 }
7394
Nirav Shahcc1f1ae2016-04-26 11:41:29 +05307395 if (hdd_ctx->config->enable_dp_trace)
7396 qdf_dp_trace_init();
7397
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307398 if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007399 goto err_wiphy_unregister;
7400
Prashanth Bhatta75fa9a12016-01-11 18:30:08 -08007401
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007402 rtnl_held = hdd_hold_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007403
Arun Khandavallifae92942016-08-01 13:31:08 +05307404
7405 adapter = hdd_open_interfaces(hdd_ctx, rtnl_held);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007406
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007407 if (IS_ERR(adapter)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007408 hdd_alert("Failed to open interface, adapter is NULL");
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007409 ret = PTR_ERR(adapter);
Arun Khandavallifae92942016-08-01 13:31:08 +05307410 goto err_ipa_cleanup;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007411 }
7412
Arun Khandavallifae92942016-08-01 13:31:08 +05307413 hif_sc = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007414 /*
7415 * target hw version/revision would only be retrieved after firmware
7416 * donwload
7417 */
7418 hif_get_hw_info(hif_sc, &hdd_ctx->target_hw_version,
7419 &hdd_ctx->target_hw_revision,
7420 &hdd_ctx->target_hw_name);
7421
7422 /* Get the wlan hw/fw version */
Arun Khandavallia96c2c02016-05-17 19:15:34 +05307423 hdd_wlan_get_version(hdd_ctx, NULL, NULL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007424
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007425 hdd_release_rtnl_lock();
7426 rtnl_held = false;
7427
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007428#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
Anurag Chouhan210db072016-02-22 18:42:15 +05307429 status = qdf_mc_timer_init(&hdd_ctx->skip_acs_scan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307430 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007431 hdd_skip_acs_scan_timer_handler,
7432 (void *)hdd_ctx);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307433 if (!QDF_IS_STATUS_SUCCESS(status))
Jeff Johnson34c88b72016-08-15 14:27:11 -07007434 hdd_err("Failed to init ACS Skip timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007435#endif
7436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007437#ifdef MSM_PLATFORM
7438 spin_lock_init(&hdd_ctx->bus_bw_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +05307439 qdf_mc_timer_init(&hdd_ctx->bus_bw_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307440 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007441 hdd_bus_bw_compute_cbk, (void *)hdd_ctx);
7442#endif
7443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007444 wlan_hdd_send_all_scan_intf_info(hdd_ctx);
7445 wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
7446 hdd_ctx->target_hw_version,
7447 hdd_ctx->target_hw_name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007448
Nirav Shahbd36b062016-07-18 11:12:59 +05307449 if (hdd_ctx->rps)
7450 hdd_set_rps_cpu_mask(hdd_ctx);
Peng Xu8fdaa492016-06-22 10:20:47 -07007451
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007452
7453 if (cds_is_packet_log_enabled())
Srinivas Girigowdac34f11d2016-02-25 16:02:42 -08007454 hdd_pktlog_enable_disable(hdd_ctx, true, 0);
Srinivas Girigowdad9e6f7b2016-02-01 19:37:52 -08007455
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007456 ret = hdd_register_notifiers(hdd_ctx);
7457 if (ret)
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05307458 goto err_debugfs_exit;
7459
7460 status = wlansap_global_init();
7461 if (QDF_IS_STATUS_ERROR(status))
7462 goto err_debugfs_exit;
Prashanth Bhatta9b03ab32016-04-28 12:35:13 -07007463
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08007464 memdump_init();
7465
Arun Khandavallifae92942016-08-01 13:31:08 +05307466 if (hdd_ctx->config->fIsImpsEnabled)
7467 hdd_set_idle_ps_config(hdd_ctx, true);
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307468
Arun Khandavallifae92942016-08-01 13:31:08 +05307469 qdf_mc_timer_start(&hdd_ctx->iface_change_timer,
7470 hdd_ctx->config->iface_change_wait_time * 5000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007471 goto success;
7472
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007473err_debugfs_exit:
7474 hdd_debugfs_exit(adapter);
Prashanth Bhatta98f04d22016-01-08 16:46:21 -08007475 hdd_close_all_adapters(hdd_ctx, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007476
Arun Khandavallid4349a92016-07-25 11:10:43 +05307477 if (rtnl_held)
7478 hdd_release_rtnl_lock();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007479
Yun Park6a46ad82016-01-04 16:48:19 -08007480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007481err_wiphy_unregister:
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007482 wiphy_unregister(hdd_ctx->wiphy);
Abhishek Singhf512bf32016-05-04 16:47:46 +05307483 wlan_hdd_cfg80211_deinit(hdd_ctx->wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007484
Arun Khandavallifae92942016-08-01 13:31:08 +05307485err_ipa_cleanup:
7486 hdd_ipa_cleanup(hdd_ctx);
7487
7488err_stop_modules:
7489 hdd_wlan_stop_modules(hdd_ctx, false);
7490
7491
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007492 status = cds_sched_close(hdd_ctx->pcds_context);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307493 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007494 hdd_alert("Failed to close CDS Scheduler");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307495 QDF_ASSERT(QDF_IS_STATUS_SUCCESS(status));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007496 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007497
Ryan Hsucfef0ae2016-04-28 10:20:46 -07007498err_exit_nl_srv:
7499 hdd_exit_netlink_services(hdd_ctx);
7500
7501 if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) {
7502 hdd_err("Failed to deinit policy manager");
7503 /* Proceed and complete the clean up */
7504 }
Arun Khandavallic811dcc2016-06-26 07:37:21 +05307505 cds_deinit_ini_config();
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007506err_hdd_free_context:
Arun Khandavallifae92942016-08-01 13:31:08 +05307507 qdf_mc_timer_destroy(&hdd_ctx->iface_change_timer);
7508 mutex_destroy(&hdd_ctx->iface_change_lock);
Prashanth Bhatta527fd752016-04-28 12:35:23 -07007509 hdd_context_destroy(hdd_ctx);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307510 QDF_BUG(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007512 return -EIO;
7513
7514success:
7515 EXIT();
7516 return 0;
7517}
7518
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007519/**
Arun Khandavallifae92942016-08-01 13:31:08 +05307520 * hdd_wlan_update_target_info() - update target type info
7521 * @hdd_ctx: HDD context
7522 * @context: hif context
7523 *
7524 * Update target info received from firmware in hdd context
7525 * Return:None
7526 */
7527
7528void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context)
7529{
7530 struct hif_target_info *tgt_info = hif_get_target_info_handle(context);
7531
7532 if (!tgt_info) {
7533 hdd_err("Target info is Null");
7534 return;
7535 }
7536
7537 hdd_ctx->target_type = tgt_info->target_type;
7538}
7539
7540/**
7541 * hdd_register_cb - Register HDD callbacks.
Arun Khandavalli4b55da72016-07-19 19:55:01 +05307542 * @hdd_ctx: HDD context
7543 *
7544 * Register the HDD callbacks to CDS/SME.
7545 *
7546 * Return: 0 for success or Error code for failure
7547 */
7548int hdd_register_cb(hdd_context_t *hdd_ctx)
7549{
7550 QDF_STATUS status;
7551 int ret = 0;
7552
7553 ENTER();
7554
7555 sme_register11d_scan_done_callback(hdd_ctx->hHal, hdd_11d_scan_done);
7556
7557 sme_register_oem_data_rsp_callback(hdd_ctx->hHal,
7558 hdd_send_oem_data_rsp_msg);
7559
7560 status = sme_fw_mem_dump_register_cb(hdd_ctx->hHal,
7561 wlan_hdd_cfg80211_fw_mem_dump_cb);
7562 if (!QDF_IS_STATUS_SUCCESS(status)) {
7563 hdd_err("Failed to register memdump callback");
7564 ret = -EINVAL;
7565 return ret;
7566 }
7567
7568 sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
7569 sme_nan_register_callback(hdd_ctx->hHal,
7570 wlan_hdd_cfg80211_nan_callback);
7571 sme_stats_ext_register_callback(hdd_ctx->hHal,
7572 wlan_hdd_cfg80211_stats_ext_callback);
7573
7574 sme_ext_scan_register_callback(hdd_ctx->hHal,
7575 wlan_hdd_cfg80211_extscan_callback);
7576
7577 status = cds_register_sap_restart_channel_switch_cb(
7578 (void *)hdd_sap_restart_with_channel_switch);
7579 if (!QDF_IS_STATUS_SUCCESS(status)) {
7580 hdd_err("restart cb registration failed");
7581 ret = -EINVAL;
7582 return ret;
7583 }
7584
7585 sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal,
7586 hdd_rssi_threshold_breached);
7587
7588 status = sme_bpf_offload_register_callback(hdd_ctx->hHal,
7589 hdd_get_bpf_offload_cb);
7590 if (!QDF_IS_STATUS_SUCCESS(status)) {
7591 hdd_err("set bpf offload callback failed");
7592 ret = -EINVAL;
7593 return ret;
7594 }
7595
7596 sme_set_link_layer_stats_ind_cb(hdd_ctx->hHal,
7597 wlan_hdd_cfg80211_link_layer_stats_callback);
7598
7599 wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx);
7600
7601 EXIT();
7602
7603 return ret;
7604}
7605
7606/**
7607 * hdd_deregister_cb() - De-Register HDD callbacks.
7608 * @hdd_ctx: HDD context
7609 *
7610 * De-Register the HDD callbacks to CDS/SME.
7611 *
7612 * Return: void
7613 */
7614void hdd_deregister_cb(hdd_context_t *hdd_ctx)
7615{
7616 QDF_STATUS status;
7617
7618 ENTER();
7619
7620 status = sme_deregister_for_dcc_stats_event(hdd_ctx->hHal);
7621 if (!QDF_IS_STATUS_SUCCESS(status))
7622 hdd_err("De-register of dcc stats callback failed: %d",
7623 status);
7624
7625 sme_reset_link_layer_stats_ind_cb(hdd_ctx->hHal);
7626 status = sme_bpf_offload_deregister_callback(hdd_ctx->hHal);
7627 if (!QDF_IS_STATUS_SUCCESS(status))
7628 hdd_err("De-register bpf offload callback failed: %d",
7629 status);
7630 sme_reset_rssi_threshold_breached_cb(hdd_ctx->hHal);
7631
7632 status = cds_deregister_sap_restart_channel_switch_cb();
7633 if (!QDF_IS_STATUS_SUCCESS(status))
7634 hdd_err("De-register restart cb registration failed: %d",
7635 status);
7636
7637 sme_stats_ext_register_callback(hdd_ctx->hHal,
7638 wlan_hdd_cfg80211_stats_ext_callback);
7639
7640 sme_nan_deregister_callback(hdd_ctx->hHal);
7641 status = sme_reset_tsfcb(hdd_ctx->hHal);
7642 if (!QDF_IS_STATUS_SUCCESS(status))
7643 hdd_err("Failed to de-register tsfcb the callback:%d",
7644 status);
7645 status = sme_fw_mem_dump_unregister_cb(hdd_ctx->hHal);
7646 if (!QDF_IS_STATUS_SUCCESS(status))
7647 hdd_err("Failed to de-register the fw mem dump callback: %d",
7648 status);
7649
7650 sme_deregister_oem_data_rsp_callback(hdd_ctx->hHal);
7651 sme_deregister11d_scan_done_callback(hdd_ctx->hHal);
7652
7653 EXIT();
7654}
7655
7656/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007657 * hdd_softap_sta_deauth() - handle deauth req from HDD
7658 * @adapter: Pointer to the HDD
7659 * @enable: bool value
7660 *
7661 * This to take counter measure to handle deauth req from HDD
7662 *
7663 * Return: None
7664 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307665QDF_STATUS hdd_softap_sta_deauth(hdd_adapter_t *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007666 struct tagCsrDelStaParams *pDelStaParams)
7667{
7668#ifndef WLAN_FEATURE_MBSSID
7669 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7670#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307671 QDF_STATUS qdf_status = QDF_STATUS_E_FAULT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007672
7673 ENTER();
7674
Jeff Johnson34c88b72016-08-15 14:27:11 -07007675 hdd_notice("hdd_softap_sta_deauth:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007676 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7677
7678 /* Ignore request to deauth bcmc station */
7679 if (pDelStaParams->peerMacAddr.bytes[0] & 0x1)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307680 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007681
7682#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307683 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007684 wlansap_deauth_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7685 pDelStaParams);
7686#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307687 qdf_status = wlansap_deauth_sta(p_cds_context, pDelStaParams);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007688#endif
7689
7690 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307691 return qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007692}
7693
7694/**
7695 * hdd_softap_sta_disassoc() - take counter measure to handle deauth req from HDD
7696 * @adapter: Pointer to the HDD
7697 *
7698 * This to take counter measure to handle deauth req from HDD
7699 *
7700 * Return: None
7701 */
7702void hdd_softap_sta_disassoc(hdd_adapter_t *adapter,
7703 uint8_t *pDestMacAddress)
7704{
7705#ifndef WLAN_FEATURE_MBSSID
7706 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7707#endif
7708
7709 ENTER();
7710
Jeff Johnson34c88b72016-08-15 14:27:11 -07007711 hdd_err("hdd_softap_sta_disassoc:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007712 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7713
7714 /* Ignore request to disassoc bcmc station */
7715 if (pDestMacAddress[0] & 0x1)
7716 return;
7717
7718#ifdef WLAN_FEATURE_MBSSID
7719 wlansap_disassoc_sta(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7720 pDestMacAddress);
7721#else
7722 wlansap_disassoc_sta(p_cds_context, pDestMacAddress);
7723#endif
7724}
7725
7726void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *adapter,
7727 bool enable)
7728{
7729#ifndef WLAN_FEATURE_MBSSID
7730 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(adapter))->pcds_context;
7731#endif
7732
7733 ENTER();
7734
Jeff Johnson34c88b72016-08-15 14:27:11 -07007735 hdd_err("hdd_softap_tkip_mic_fail_counter_measure:(%p, false)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007736 (WLAN_HDD_GET_CTX(adapter))->pcds_context);
7737
7738#ifdef WLAN_FEATURE_MBSSID
7739 wlansap_set_counter_measure(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
7740 (bool) enable);
7741#else
7742 wlansap_set_counter_measure(p_cds_context, (bool) enable);
7743#endif
7744}
7745
7746/**
7747 * hdd_issta_p2p_clientconnected() - check if sta or p2p client is connected
7748 * @hdd_ctx: HDD Context
7749 *
7750 * API to find if there is any STA or P2P-Client is connected
7751 *
7752 * Return: true if connected; false otherwise
7753 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307754QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007755{
7756 return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
7757}
7758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007759/**
7760 * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
7761 * @adapter: HDD adapter pointer
7762 *
7763 * This function loop through each adapter and disable roaming on each STA
7764 * device mode except the input adapter.
7765 *
7766 * Note: On the input adapter roaming is not enabled yet hence no need to
7767 * disable.
7768 *
7769 * Return: None
7770 */
7771void wlan_hdd_disable_roaming(hdd_adapter_t *adapter)
7772{
7773 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7774 hdd_adapter_t *adapterIdx = NULL;
7775 hdd_adapter_list_node_t *adapterNode = NULL;
7776 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307777 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007778
7779 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
7780 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007781 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007782 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007783 hdd_notice("Connect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007784 adapter->sessionId);
7785 /*
7786 * Loop through adapter and disable roaming for each STA device
7787 * mode except the input adapter.
7788 */
7789 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
7790
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307791 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007792 adapterIdx = adapterNode->pAdapter;
7793
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007794 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007795 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007796 hdd_notice("Disable Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007797 adapterIdx->sessionId);
7798 sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
7799 (adapterIdx),
7800 adapterIdx->sessionId, 0);
7801 }
7802
7803 status = hdd_get_next_adapter(hdd_ctx,
7804 adapterNode,
7805 &pNext);
7806 adapterNode = pNext;
7807 }
7808 }
7809}
7810
7811/**
7812 * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
7813 * @adapter: HDD adapter pointer
7814 *
7815 * This function loop through each adapter and enable roaming on each STA
7816 * device mode except the input adapter.
7817 * Note: On the input adapter no need to enable roaming because link got
7818 * disconnected on this.
7819 *
7820 * Return: None
7821 */
7822void wlan_hdd_enable_roaming(hdd_adapter_t *adapter)
7823{
7824 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7825 hdd_adapter_t *adapterIdx = NULL;
7826 hdd_adapter_list_node_t *adapterNode = NULL;
7827 hdd_adapter_list_node_t *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307828 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007829
7830 if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
7831 hdd_ctx->config->isRoamOffloadScanEnabled &&
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007832 QDF_STA_MODE == adapter->device_mode &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007833 cds_is_sta_active_connection_exists()) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007834 hdd_notice("Disconnect received on STA sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007835 adapter->sessionId);
7836 /*
7837 * Loop through adapter and enable roaming for each STA device
7838 * mode except the input adapter.
7839 */
7840 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
7841
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307842 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007843 adapterIdx = adapterNode->pAdapter;
7844
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007845 if (QDF_STA_MODE == adapterIdx->device_mode
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007846 && adapter->sessionId != adapterIdx->sessionId) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007847 hdd_notice("Enabling Roaming on sessionId(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007848 adapterIdx->sessionId);
7849 sme_start_roaming(WLAN_HDD_GET_HAL_CTX
7850 (adapterIdx),
7851 adapterIdx->sessionId,
7852 REASON_CONNECT);
7853 }
7854
7855 status = hdd_get_next_adapter(hdd_ctx,
7856 adapterNode,
7857 &pNext);
7858 adapterNode = pNext;
7859 }
7860 }
7861}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007862
7863void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
7864{
7865 struct sk_buff *skb;
7866 struct nlmsghdr *nlh;
7867 tAniMsgHdr *ani_hdr;
7868 void *nl_data = NULL;
7869 int flags = GFP_KERNEL;
7870
7871 if (in_interrupt() || irqs_disabled() || in_atomic())
7872 flags = GFP_ATOMIC;
7873
7874 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
7875
7876 if (skb == NULL) {
Jeff Johnson34c88b72016-08-15 14:27:11 -07007877 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007878 return;
7879 }
7880
7881 nlh = (struct nlmsghdr *)skb->data;
7882 nlh->nlmsg_pid = 0; /* from kernel */
7883 nlh->nlmsg_flags = 0;
7884 nlh->nlmsg_seq = 0;
7885 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
7886
7887 ani_hdr = NLMSG_DATA(nlh);
7888 ani_hdr->type = type;
7889
7890 switch (type) {
7891 case WLAN_SVC_FW_CRASHED_IND:
7892 case WLAN_SVC_LTE_COEX_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007893 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND:
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07007894 case WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007895 ani_hdr->length = 0;
7896 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
7897 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
7898 break;
7899 case WLAN_SVC_WLAN_STATUS_IND:
7900 case WLAN_SVC_WLAN_VERSION_IND:
7901 case WLAN_SVC_DFS_CAC_START_IND:
7902 case WLAN_SVC_DFS_CAC_END_IND:
7903 case WLAN_SVC_DFS_RADAR_DETECT_IND:
7904 case WLAN_SVC_DFS_ALL_CHANNEL_UNAVAIL_IND:
7905 case WLAN_SVC_WLAN_TP_IND:
Mohit Khannae71e2262015-11-10 09:37:24 -08007906 case WLAN_SVC_WLAN_TP_TX_IND:
Nirav Shahbd36b062016-07-18 11:12:59 +05307907 case WLAN_SVC_RPS_ENABLE_IND:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007908 ani_hdr->length = len;
7909 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
7910 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
7911 memcpy(nl_data, data, len);
7912 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
7913 break;
7914
7915 default:
Jeff Johnson34c88b72016-08-15 14:27:11 -07007916 hdd_err("WLAN SVC: Attempt to send unknown nlink message %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007917 type);
7918 kfree_skb(skb);
7919 return;
7920 }
7921
7922 nl_srv_bcast(skb);
7923
7924 return;
7925}
7926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007927#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
7928void wlan_hdd_auto_shutdown_cb(void)
7929{
Jeff Johnson28f8a772016-08-15 15:30:36 -07007930 hdd_err("Wlan Idle. Sending Shutdown event..");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007931 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_AUTO_SHUTDOWN_IND, NULL, 0);
7932}
7933
7934void wlan_hdd_auto_shutdown_enable(hdd_context_t *hdd_ctx, bool enable)
7935{
7936 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307937 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007938 hdd_adapter_t *adapter;
7939 bool ap_connected = false, sta_connected = false;
7940 tHalHandle hal_handle;
7941
7942 hal_handle = hdd_ctx->hHal;
7943 if (hal_handle == NULL)
7944 return;
7945
7946 if (hdd_ctx->config->WlanAutoShutdown == 0)
7947 return;
7948
7949 if (enable == false) {
7950 if (sme_set_auto_shutdown_timer(hal_handle, 0) !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307951 QDF_STATUS_SUCCESS) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07007952 hdd_err("Failed to stop wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007953 }
Manikandan Mohan5b1980a2016-05-06 12:41:18 -07007954 wlan_hdd_send_svc_nlink_msg(
7955 WLAN_SVC_WLAN_AUTO_SHUTDOWN_CANCEL_IND, NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007956 return;
7957 }
7958
7959 /* To enable shutdown timer check conncurrency */
7960 if (cds_concurrent_open_sessions_running()) {
7961 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
7962
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307963 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007964 adapter = adapterNode->pAdapter;
7965 if (adapter
7966 && adapter->device_mode ==
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007967 QDF_STA_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007968 if (WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
7969 conn_info.connState ==
7970 eConnectionState_Associated) {
7971 sta_connected = true;
7972 break;
7973 }
7974 }
7975 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08007976 && adapter->device_mode == QDF_SAP_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007977 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->
7978 bApActive == true) {
7979 ap_connected = true;
7980 break;
7981 }
7982 }
7983 status = hdd_get_next_adapter(hdd_ctx,
7984 adapterNode,
7985 &pNext);
7986 adapterNode = pNext;
7987 }
7988 }
7989
7990 if (ap_connected == true || sta_connected == true) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07007991 hdd_notice("CC Session active. Shutdown timer not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007992 return;
7993 } else {
7994 if (sme_set_auto_shutdown_timer(hal_handle,
7995 hdd_ctx->config->
7996 WlanAutoShutdown)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307997 != QDF_STATUS_SUCCESS)
Jeff Johnson28f8a772016-08-15 15:30:36 -07007998 hdd_err("Failed to start wlan auto shutdown timer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007999 else
Jeff Johnson28f8a772016-08-15 15:30:36 -07008000 hdd_notice("Auto Shutdown timer for %d seconds enabled",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008001 hdd_ctx->config->WlanAutoShutdown);
8002
8003 }
8004}
8005#endif
8006
8007hdd_adapter_t *hdd_get_con_sap_adapter(hdd_adapter_t *this_sap_adapter,
8008 bool check_start_bss)
8009{
8010 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(this_sap_adapter);
8011 hdd_adapter_t *adapter, *con_sap_adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308012 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008013 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
8014
8015 con_sap_adapter = NULL;
8016
8017 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308018 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008019 adapter = adapterNode->pAdapter;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008020 if (adapter && ((adapter->device_mode == QDF_SAP_MODE) ||
8021 (adapter->device_mode == QDF_P2P_GO_MODE)) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008022 adapter != this_sap_adapter) {
8023 if (check_start_bss) {
8024 if (test_bit(SOFTAP_BSS_STARTED,
8025 &adapter->event_flags)) {
8026 con_sap_adapter = adapter;
8027 break;
8028 }
8029 } else {
8030 con_sap_adapter = adapter;
8031 break;
8032 }
8033 }
8034 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
8035 adapterNode = pNext;
8036 }
8037
8038 return con_sap_adapter;
8039}
8040
8041#ifdef MSM_PLATFORM
8042void hdd_start_bus_bw_compute_timer(hdd_adapter_t *adapter)
8043{
8044 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8045
Anurag Chouhan210db072016-02-22 18:42:15 +05308046 if (QDF_TIMER_STATE_RUNNING ==
8047 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008048 return;
8049
Anurag Chouhan210db072016-02-22 18:42:15 +05308050 qdf_mc_timer_start(&hdd_ctx->bus_bw_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008051 hdd_ctx->config->busBandwidthComputeInterval);
8052}
8053
8054void hdd_stop_bus_bw_compute_timer(hdd_adapter_t *adapter)
8055{
8056 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308057 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008058 bool can_stop = true;
8059 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8060
Anurag Chouhan210db072016-02-22 18:42:15 +05308061 if (QDF_TIMER_STATE_RUNNING !=
8062 qdf_mc_timer_get_current_state(&hdd_ctx->bus_bw_timer)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008063 /* trying to stop timer, when not running is not good */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008064 hdd_err("bus band width compute timer is not running");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008065 return;
8066 }
8067
8068 if (cds_concurrent_open_sessions_running()) {
8069 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
8070
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308071 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008072 adapter = adapterNode->pAdapter;
8073 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008074 && (adapter->device_mode == QDF_STA_MODE
8075 || adapter->device_mode == QDF_P2P_CLIENT_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008076 && WLAN_HDD_GET_STATION_CTX_PTR(adapter)->
8077 conn_info.connState ==
8078 eConnectionState_Associated) {
8079 can_stop = false;
8080 break;
8081 }
8082 if (adapter
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008083 && (adapter->device_mode == QDF_SAP_MODE
8084 || adapter->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008085 && WLAN_HDD_GET_AP_CTX_PTR(adapter)->bApActive ==
8086 true) {
8087 can_stop = false;
8088 break;
8089 }
8090 status = hdd_get_next_adapter(hdd_ctx,
8091 adapterNode,
8092 &pNext);
8093 adapterNode = pNext;
8094 }
8095 }
8096
8097 if (can_stop == true)
Anurag Chouhan210db072016-02-22 18:42:15 +05308098 qdf_mc_timer_stop(&hdd_ctx->bus_bw_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008099}
8100#endif
8101
8102/**
8103 * wlan_hdd_check_custom_con_channel_rules() - This function checks the sap's
8104 * and sta's operating channel.
8105 * @sta_adapter: Describe the first argument to foobar.
8106 * @ap_adapter: Describe the second argument to foobar.
8107 * @roam_profile: Roam profile of AP to which STA wants to connect.
8108 * @concurrent_chnl_same: If both SAP and STA channels are same then
8109 * set this flag to true else false.
8110 *
8111 * This function checks the sap's operating channel and sta's operating channel.
8112 * if both are same then it will return false else it will restart the sap in
8113 * sta's channel and return true.
8114 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308115 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008116 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308117QDF_STATUS wlan_hdd_check_custom_con_channel_rules(hdd_adapter_t *sta_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008118 hdd_adapter_t *ap_adapter,
8119 tCsrRoamProfile *roam_profile,
8120 tScanResultHandle *scan_cache,
8121 bool *concurrent_chnl_same)
8122{
8123 hdd_ap_ctx_t *hdd_ap_ctx;
8124 uint8_t channel_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308125 QDF_STATUS status;
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008126 enum tQDF_ADAPTER_MODE device_mode = ap_adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008127 *concurrent_chnl_same = true;
8128
8129 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8130 status =
8131 sme_get_ap_channel_from_scan_cache(WLAN_HDD_GET_HAL_CTX(sta_adapter),
8132 roam_profile,
8133 scan_cache,
8134 &channel_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308135 if ((QDF_STATUS_SUCCESS == status)) {
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008136 if ((QDF_SAP_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008137 (channel_id < SIR_11A_CHANNEL_BEGIN)) {
8138 if (hdd_ap_ctx->operatingChannel != channel_id) {
8139 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008140 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008141 }
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008142 } else if ((QDF_P2P_GO_MODE == device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008143 (channel_id >= SIR_11A_CHANNEL_BEGIN)) {
8144 if (hdd_ap_ctx->operatingChannel != channel_id) {
8145 *concurrent_chnl_same = false;
Jeff Johnson28f8a772016-08-15 15:30:36 -07008146 hdd_info("channels are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008147 }
8148 }
8149 } else {
8150 /*
8151 * Lets handle worst case scenario here, Scan cache lookup is
8152 * failed so we have to stop the SAP to avoid any channel
8153 * discrepancy between SAP's channel and STA's channel.
8154 * Return the status as failure so caller function could know
8155 * that scan look up is failed.
8156 */
Jeff Johnson28f8a772016-08-15 15:30:36 -07008157 hdd_err("Finding AP from scan cache failed");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308158 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008159 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308160 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008161}
8162
8163#ifdef WLAN_FEATURE_MBSSID
8164/**
8165 * wlan_hdd_stop_sap() - This function stops bss of SAP.
8166 * @ap_adapter: SAP adapter
8167 *
8168 * This function will process the stopping of sap adapter.
8169 *
8170 * Return: None
8171 */
8172void wlan_hdd_stop_sap(hdd_adapter_t *ap_adapter)
8173{
8174 hdd_ap_ctx_t *hdd_ap_ctx;
8175 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308176 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008177 hdd_context_t *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008178
8179 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008180 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008181 return;
8182 }
8183
8184 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8185 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308186 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008187 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308188
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008189 mutex_lock(&hdd_ctx->sap_lock);
8190 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -08008191 wlan_hdd_del_station(ap_adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008192 hdd_cleanup_actionframe(hdd_ctx, ap_adapter);
8193 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008194 hdd_info("Now doing SAP STOPBSS");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308195 qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308196 if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008197 sapContext)) {
Anurag Chouhance0dc992016-02-16 18:18:03 +05308198 qdf_status = qdf_wait_single_event(&hostapd_state->
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308199 qdf_stop_bss_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008200 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308201 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008202 mutex_unlock(&hdd_ctx->sap_lock);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008203 hdd_err("SAP Stop Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008204 return;
8205 }
8206 }
8207 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008208 cds_decr_session_set_pcl(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008209 ap_adapter->sessionId);
Jeff Johnson28f8a772016-08-15 15:30:36 -07008210 hdd_info("SAP Stop Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008211 } else {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008212 hdd_err("Can't stop ap because its not started");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008213 }
8214 mutex_unlock(&hdd_ctx->sap_lock);
8215 return;
8216}
8217
8218/**
8219 * wlan_hdd_start_sap() - this function starts bss of SAP.
8220 * @ap_adapter: SAP adapter
8221 *
8222 * This function will process the starting of sap adapter.
8223 *
8224 * Return: None
8225 */
8226void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
8227{
8228 hdd_ap_ctx_t *hdd_ap_ctx;
8229 hdd_hostapd_state_t *hostapd_state;
Anurag Chouhance0dc992016-02-16 18:18:03 +05308230 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008231 hdd_context_t *hdd_ctx;
8232 tsap_Config_t *sap_config;
8233
8234 if (NULL == ap_adapter) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008235 hdd_err("ap_adapter is NULL here");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008236 return;
8237 }
8238
Krunal Soni9b04c9b2016-03-10 13:08:05 -08008239 if (QDF_SAP_MODE != ap_adapter->device_mode) {
Peng Xuf5d60c82015-10-02 17:17:03 -07008240 hdd_err("SoftAp role has not been enabled");
8241 return;
8242 }
8243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008244 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
8245 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8246 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8247 sap_config = &ap_adapter->sessionCtx.ap.sapConfig;
8248
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308249 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008250 return;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308251
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008252 mutex_lock(&hdd_ctx->sap_lock);
8253 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
8254 goto end;
8255
8256 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008257 hdd_err("SAP Not able to set AP IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008258 wlansap_reset_sap_config_add_ie(sap_config, eUPDATE_IE_ALL);
8259 goto end;
8260 }
8261
8262 if (wlansap_start_bss(hdd_ap_ctx->sapContext, hdd_hostapd_sap_event_cb,
8263 &hdd_ap_ctx->sapConfig,
8264 ap_adapter->dev)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308265 != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008266 goto end;
8267
Jeff Johnson28f8a772016-08-15 15:30:36 -07008268 hdd_info("Waiting for SAP to start");
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308269 qdf_status = qdf_wait_single_event(&hostapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008270 BSS_WAIT_TIMEOUT);
Anurag Chouhance0dc992016-02-16 18:18:03 +05308271 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson28f8a772016-08-15 15:30:36 -07008272 hdd_err("SAP Start failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008273 goto end;
8274 }
Jeff Johnson28f8a772016-08-15 15:30:36 -07008275 hdd_info("SAP Start Success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008276 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008277 cds_incr_active_session(ap_adapter->device_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008278 ap_adapter->sessionId);
8279 hostapd_state->bCommit = true;
8280
8281end:
8282 mutex_unlock(&hdd_ctx->sap_lock);
8283 return;
8284}
8285#endif
8286
8287/**
Archana Ramachandrana20ef812015-11-13 16:12:13 -08008288 * wlan_hdd_soc_set_antenna_mode_cb() - Callback for set dual
8289 * mac scan config
8290 * @status: Status of set antenna mode
8291 *
8292 * Callback on setting the dual mac configuration
8293 *
8294 * Return: None
8295 */
8296void wlan_hdd_soc_set_antenna_mode_cb(
8297 enum set_antenna_mode_status status)
8298{
8299 hdd_context_t *hdd_ctx;
8300
8301 hdd_info("Status: %d", status);
8302
8303 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8304 if (0 != wlan_hdd_validate_context(hdd_ctx))
8305 return;
8306
8307 /* Signal the completion of set dual mac config */
8308 complete(&hdd_ctx->set_antenna_mode_cmpl);
8309}
8310
8311/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008312 * hdd_get_fw_version() - Get FW version
8313 * @hdd_ctx: pointer to HDD context.
8314 * @major_spid: FW version - major spid.
8315 * @minor_spid: FW version - minor spid
8316 * @ssid: FW version - ssid
8317 * @crmid: FW version - crmid
8318 *
8319 * This function is called to get the firmware build version stored
8320 * as part of the HDD context
8321 *
8322 * Return: None
8323 */
8324void hdd_get_fw_version(hdd_context_t *hdd_ctx,
8325 uint32_t *major_spid, uint32_t *minor_spid,
8326 uint32_t *siid, uint32_t *crmid)
8327{
8328 *major_spid = (hdd_ctx->target_fw_version & 0xf0000000) >> 28;
8329 *minor_spid = (hdd_ctx->target_fw_version & 0xf000000) >> 24;
8330 *siid = (hdd_ctx->target_fw_version & 0xf00000) >> 20;
8331 *crmid = hdd_ctx->target_fw_version & 0x7fff;
8332}
8333
8334#ifdef QCA_CONFIG_SMP
8335/**
8336 * wlan_hdd_get_cpu() - get cpu_index
8337 *
8338 * Return: cpu_index
8339 */
8340int wlan_hdd_get_cpu(void)
8341{
8342 int cpu_index = get_cpu();
8343 put_cpu();
8344 return cpu_index;
8345}
8346#endif
8347
8348/**
8349 * hdd_get_fwpath() - get framework path
8350 *
8351 * This function is used to get the string written by
8352 * userspace to start the wlan driver
8353 *
8354 * Return: string
8355 */
8356const char *hdd_get_fwpath(void)
8357{
8358 return fwpath.string;
8359}
8360
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008361/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008362 * hdd_init() - Initialize Driver
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008363 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008364 * This function initilizes CDS global context with the help of cds_init. This
8365 * has to be the first function called after probe to get a valid global
8366 * context.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008367 *
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008368 * Return: 0 for success, errno on failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008369 */
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008370int hdd_init(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008371{
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008372 v_CONTEXT_t p_cds_context = NULL;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008373 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008374
8375#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8376 wlan_logging_sock_init_svc();
8377#endif
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008378 p_cds_context = cds_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008379
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008380 if (p_cds_context == NULL) {
8381 hdd_alert("Failed to allocate CDS context");
8382 ret = -ENOMEM;
8383 goto err_out;
8384 }
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008385
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008386 hdd_trace_init();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008387
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008388err_out:
8389 return ret;
8390}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008391
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008392/**
8393 * hdd_deinit() - Deinitialize Driver
8394 *
8395 * This function frees CDS global context with the help of cds_deinit. This
8396 * has to be the last function call in remove callback to free the global
8397 * context.
8398 */
8399void hdd_deinit(void)
8400{
8401 cds_deinit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008402
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008403#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8404 wlan_logging_sock_deinit_svc();
8405#endif
8406}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008407
8408#ifdef QCA_WIFI_3_0_ADRASTEA
8409#define HDD_WLAN_START_WAIT_TIME (3600 * 1000)
8410#else
8411#define HDD_WLAN_START_WAIT_TIME (CDS_WMA_TIMEOUT + 5000)
8412#endif
8413
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008414/**
8415 * __hdd_module_init - Module init helper
8416 *
8417 * Module init helper function used by both module and static driver.
8418 *
8419 * Return: 0 for success, errno on failure
8420 */
8421static int __hdd_module_init(void)
8422{
8423 int ret = 0;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008424
Arun Khandavallifae92942016-08-01 13:31:08 +05308425 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008426 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008427
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008428 pld_init();
8429
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308430 qdf_wake_lock_create(&wlan_wake_lock, "wlan");
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008431
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008432 hdd_set_conparam((uint32_t) con_mode);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008433
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008434 ret = wlan_hdd_register_driver();
8435 if (ret) {
Mohit Khannafa99aea2016-05-12 21:43:13 -07008436 pr_err("%s: driver load failure, err %d\n", WLAN_MODULE_NAME,
8437 ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008438 goto out;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008439 }
8440
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308441 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008442
8443 return 0;
8444out:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308445 qdf_wake_lock_destroy(&wlan_wake_lock);
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008446 pld_deinit();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008447 return ret;
8448}
8449
8450/**
8451 * __hdd_module_exit - Module exit helper
8452 *
8453 * Module exit helper function used by both module and static driver.
8454 */
8455static void __hdd_module_exit(void)
8456{
8457 pr_info("%s: Unloading driver v%s\n", WLAN_MODULE_NAME,
8458 QWLAN_VERSIONSTR);
8459
8460 wlan_hdd_unregister_driver();
8461
Anurag Chouhana37b5b72016-02-21 14:53:42 +05308462 qdf_wake_lock_destroy(&wlan_wake_lock);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008463
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07008464 pld_deinit();
8465
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008466 return;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008467}
8468
Arun Khandavallifae92942016-08-01 13:31:08 +05308469#ifndef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008470/**
Arun Khandavallifae92942016-08-01 13:31:08 +05308471 * wlan_boot_cb() - Wlan boot callback
8472 * @kobj: object whose directory we're creating the link in.
8473 * @attr: attribute the user is interacting with
8474 * @buff: the buffer containing the user data
8475 * @count: number of bytes in the buffer
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008476 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308477 * This callback is invoked when the fs is ready to start the
8478 * wlan driver initialization.
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008479 *
Arun Khandavallifae92942016-08-01 13:31:08 +05308480 * Return: 'count' on success or a negative error code in case of failure
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008481 */
Arun Khandavallifae92942016-08-01 13:31:08 +05308482static ssize_t wlan_boot_cb(struct kobject *kobj,
8483 struct kobj_attribute *attr,
8484 const char *buf,
8485 size_t count)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008486{
Arun Khandavallifae92942016-08-01 13:31:08 +05308487
8488 int ret = 0;
8489
8490 if (wlan_loader->loaded_state) {
8491 pr_info("Wlan driver already initialized");
8492 return 0;
8493 }
8494
8495
8496 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8497 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8498
8499 if (__hdd_module_init()) {
8500 pr_err("%s: Failed to register handler\n", __func__);
8501 ret = -EINVAL;
8502 } else
8503 wlan_loader->loaded_state = MODULE_INITIALIZED;
8504
8505 return count;
8506
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008507}
Arun Khandavallifae92942016-08-01 13:31:08 +05308508
8509/**
8510 * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is
8511 * ready
8512 *
8513 * This is creates the syfs entry boot_wlan. Which shall be invoked
8514 * when the filesystem is ready.
8515 *
8516 * Return: None
8517 */
8518static int wlan_init_sysfs(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008519{
Arun Khandavallifae92942016-08-01 13:31:08 +05308520 int ret = -EINVAL;
8521
8522 wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL);
8523 if (!wlan_loader) {
8524 pr_err("%s: memory alloc failed\n", __func__);
8525 ret = -ENOMEM;
8526 return ret;
8527 }
8528
8529 wlan_loader->boot_wlan_obj = NULL;
8530 wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)),
8531 GFP_KERNEL);
8532 if (!wlan_loader->attr_group) {
8533 pr_err("%s: malloc attr_group failed\n", __func__);
8534 ret = -ENOMEM;
8535 goto error_return;
8536 }
8537
8538 wlan_loader->loaded_state = 0;
8539 wlan_loader->attr_group->attrs = attrs;
8540
8541 wlan_loader->boot_wlan_obj = kobject_create_and_add("boot_wlan",
8542 kernel_kobj);
8543 if (!wlan_loader->boot_wlan_obj) {
8544 pr_err("%s: sysfs create and add failed\n", __func__);
8545 ret = -ENOMEM;
8546 goto error_return;
8547 }
8548
8549 ret = sysfs_create_group(wlan_loader->boot_wlan_obj,
8550 wlan_loader->attr_group);
8551 if (ret) {
8552 pr_err("%s: sysfs create group failed %d\n", __func__, ret);
8553 goto error_return;
8554 }
8555
8556 return 0;
8557
8558error_return:
8559
8560 if (wlan_loader->boot_wlan_obj) {
8561 kobject_del(wlan_loader->boot_wlan_obj);
8562 wlan_loader->boot_wlan_obj = NULL;
8563 }
8564
8565 return ret;
8566}
8567
8568/**
8569 * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan
8570 *
8571 * Return: 0 on success or errno on failure
8572 */
8573static int wlan_deinit_sysfs(void)
8574{
8575
8576 if (!wlan_loader) {
8577 hdd_alert("wlan loader context is Null!");
8578 return -EINVAL;
8579 }
8580
8581 if (wlan_loader->boot_wlan_obj) {
8582 sysfs_remove_group(wlan_loader->boot_wlan_obj,
8583 wlan_loader->attr_group);
8584 kobject_del(wlan_loader->boot_wlan_obj);
8585 wlan_loader->boot_wlan_obj = NULL;
8586 }
8587
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008588 return 0;
8589}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008590
Arun Khandavallifae92942016-08-01 13:31:08 +05308591#endif
8592
8593#ifdef MODULE
8594/**
8595 * __hdd_module_init - Module init helper
8596 *
8597 * Module init helper function used by both module and static driver.
8598 *
8599 * Return: 0 for success, errno on failure
8600 */
8601static int hdd_module_init(void)
8602{
8603 int ret = 0;
8604
8605 pr_err("%s: Loading driver v%s\n", WLAN_MODULE_NAME,
8606 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8607
8608 if (__hdd_module_init()) {
8609 pr_err("%s: Failed to register handler\n", __func__);
8610 ret = -EINVAL;
8611 }
8612
8613 return ret;
8614}
8615#else
8616static int __init hdd_module_init(void)
8617{
8618 int ret = -EINVAL;
8619
8620 ret = wlan_init_sysfs();
8621 if (!ret)
8622 pr_err("Failed to create sysfs entry for loading wlan");
8623
8624 return ret;
8625}
8626#endif
8627
8628
8629#ifdef MODULE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008630/**
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008631 * hdd_module_exit() - Exit function
8632 *
8633 * This is the driver exit point (invoked when module is unloaded using rmmod)
8634 *
8635 * Return: None
8636 */
8637static void __exit hdd_module_exit(void)
8638{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008639 __hdd_module_exit();
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008640}
Arun Khandavallifae92942016-08-01 13:31:08 +05308641#else
8642static void __exit hdd_module_exit(void)
8643{
8644 __hdd_module_exit();
8645 wlan_deinit_sysfs();
8646}
8647#endif
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008648
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008649static int fwpath_changed_handler(const char *kmessage, struct kernel_param *kp)
8650{
8651 return param_set_copystring(kmessage, kp);
8652}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -08008653
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008654
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008655/**
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08008656 * con_mode_handler() - Handles module param con_mode change
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008657 *
8658 * Handler function for module param con_mode when it is changed by userspace
8659 * Dynamically linked - do nothing
8660 * Statically linked - exit and init driver, as in rmmod and insmod
8661 *
8662 * Return -
8663 */
8664static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
8665{
8666 int ret;
Arun Khandavallifae92942016-08-01 13:31:08 +05308667 hdd_context_t *hdd_ctx;
8668 hdd_adapter_t *adapter;
8669 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8670 QDF_STATUS status;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008671
Arun Khandavallifae92942016-08-01 13:31:08 +05308672 hdd_info("con_mode handler: %s", kmessage);
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008673 ret = param_set_int(kmessage, kp);
Arun Khandavallifae92942016-08-01 13:31:08 +05308674
8675 if (!qdf_dev) {
8676 hdd_err("qdf device context is Null return!");
8677 return -EINVAL;
8678 }
8679
8680 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8681 if (!hdd_ctx) {
8682 hdd_err("Hdd context Null return!");
8683 return -EINVAL;
8684 }
8685 mutex_lock(&hdd_ctx->iface_change_lock);
8686 ret = hdd_wlan_stop_modules(hdd_ctx, false);
8687 mutex_unlock(&hdd_ctx->iface_change_lock);
8688 if (ret) {
8689 hdd_err("Stop wlan modules failed");
8690 return -EINVAL;
8691 }
8692
8693 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
8694 if (!adapter) {
8695 hdd_err("Failed to get station adapter");
8696 return -EINVAL;
8697 }
8698
8699 if (con_mode == QDF_GLOBAL_FTM_MODE) {
8700 adapter->device_mode = QDF_FTM_MODE;
8701 hdd_set_conparam(QDF_GLOBAL_FTM_MODE);
8702 } else if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
8703 adapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
8704 adapter->device_mode = QDF_MONITOR_MODE;
8705 hdd_set_conparam(QDF_GLOBAL_MONITOR_MODE);
8706 hdd_set_station_ops(adapter->dev);
8707 } else if (con_mode == QDF_GLOBAL_EPPING_MODE) {
8708 hdd_set_conparam(QDF_GLOBAL_EPPING_MODE);
8709 status = epping_open();
8710 if (status != QDF_STATUS_SUCCESS) {
8711 hdd_err("Failed to open in eeping mode: %d", status);
8712 return -EINVAL;
8713 }
8714 ret = epping_enable(qdf_dev->dev);
8715 if (ret) {
8716 hdd_err("Failed to enable in epping mode : %d", ret);
8717 epping_close();
8718 return -EINVAL;
8719 }
8720 hdd_info("epping mode successfully enabled");
8721 return 0;
8722 } else {
8723 hdd_info("Con mode not supported");
8724 return -EINVAL;
8725 }
8726
8727 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
8728 if (ret) {
8729 hdd_err("Start wlan modules failed: %d", ret);
8730 return -EINVAL;
8731 }
8732
8733 if (hdd_start_adapter(adapter)) {
8734 hdd_err("Failed to start %s adapter", kmessage);
8735 return -EINVAL;
8736 } else {
8737 hdd_info("Mode successfully changed to %s", kmessage);
8738 ret = 0;
8739 }
8740
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008741 return ret;
8742}
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008743
8744/**
8745 * hdd_get_conparam() - driver exit point
8746 *
8747 * This is the driver exit point (invoked when module is unloaded using rmmod)
8748 *
Anurag Chouhan6d760662016-02-20 16:05:43 +05308749 * Return: enum tQDF_GLOBAL_CON_MODE
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008750 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05308751enum tQDF_GLOBAL_CON_MODE hdd_get_conparam(void)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008752{
Anurag Chouhan6d760662016-02-20 16:05:43 +05308753 return (enum tQDF_GLOBAL_CON_MODE) curr_con_mode;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008754}
8755
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08008756void hdd_set_conparam(uint32_t con_param)
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008757{
Prashanth Bhatta05aaf012015-12-10 17:34:24 -08008758 curr_con_mode = con_param;
Prashanth Bhattaedd6ca22015-12-10 17:21:29 -08008759}
8760
Komal Seelamc11bb222016-01-27 18:57:10 +05308761#ifdef WLAN_FEATURE_LPSS
8762static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
8763{
8764 return hdd_ctx->config->enable_lpass_support;
8765}
8766#else
8767static inline bool hdd_is_lpass_supported(hdd_context_t *hdd_ctx)
8768{
8769 return false;
8770}
8771#endif
8772
8773/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308774 * hdd_clean_up_pre_cac_interface() - Clean up the pre cac interface
8775 * @hdd_ctx: HDD context
8776 *
8777 * Cleans up the pre cac interface, if it exists
8778 *
8779 * Return: None
8780 */
8781void hdd_clean_up_pre_cac_interface(hdd_context_t *hdd_ctx)
8782{
8783 uint8_t session_id;
8784 QDF_STATUS status;
8785 struct hdd_adapter_s *precac_adapter;
8786
8787 status = wlan_sap_get_pre_cac_vdev_id(hdd_ctx->hHal, &session_id);
8788 if (QDF_IS_STATUS_ERROR(status)) {
8789 hdd_err("failed to get pre cac vdev id");
8790 return;
8791 }
8792
8793 precac_adapter = hdd_get_adapter_by_vdev(hdd_ctx, session_id);
8794 if (!precac_adapter) {
8795 hdd_err("invalid pre cac adapater");
8796 return;
8797 }
8798
8799 qdf_create_work(0, &hdd_ctx->sap_pre_cac_work,
8800 wlan_hdd_sap_pre_cac_failure,
8801 (void *)precac_adapter);
8802 qdf_sched_work(0, &hdd_ctx->sap_pre_cac_work);
8803
8804}
8805
8806/**
Komal Seelamec702b02016-02-24 18:42:16 +05308807 * hdd_update_ol_config - API to update ol configuration parameters
8808 * @hdd_ctx: HDD context
Komal Seelamc11bb222016-01-27 18:57:10 +05308809 *
Komal Seelamc11bb222016-01-27 18:57:10 +05308810 * Return: void
8811 */
Komal Seelamec702b02016-02-24 18:42:16 +05308812static void hdd_update_ol_config(hdd_context_t *hdd_ctx)
Komal Seelamc11bb222016-01-27 18:57:10 +05308813{
Komal Seelamec702b02016-02-24 18:42:16 +05308814 struct ol_config_info cfg;
Anurag Chouhandf2b2682016-02-29 14:15:27 +05308815 struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI);
Komal Seelamc11bb222016-01-27 18:57:10 +05308816
Komal Seelamec702b02016-02-24 18:42:16 +05308817 if (!ol_ctx)
8818 return;
8819
8820 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
8821 cfg.enable_uart_print = hdd_ctx->config->enablefwprint;
8822 cfg.enable_fw_log = hdd_ctx->config->enable_fw_log;
8823 cfg.enable_ramdump_collection = hdd_ctx->config->is_ramdump_enabled;
8824 cfg.enable_lpass_support = hdd_is_lpass_supported(hdd_ctx);
8825
8826 ol_init_ini_config(ol_ctx, &cfg);
8827}
8828
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07008829#ifdef FEATURE_RUNTIME_PM
8830/**
8831 * hdd_populate_runtime_cfg() - populate runtime configuration
8832 * @hdd_ctx: hdd context
8833 * @cfg: pointer to the configuration memory being populated
8834 *
8835 * Return: void
8836 */
8837static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
8838 struct hif_config_info *cfg)
8839{
8840 cfg->enable_runtime_pm = hdd_ctx->config->runtime_pm;
8841 cfg->runtime_pm_delay = hdd_ctx->config->runtime_pm_delay;
8842}
8843#else
8844static void hdd_populate_runtime_cfg(hdd_context_t *hdd_ctx,
8845 struct hif_config_info *cfg)
8846{
8847}
8848#endif
8849
Komal Seelamec702b02016-02-24 18:42:16 +05308850/**
8851 * hdd_update_hif_config - API to update HIF configuration parameters
8852 * @hdd_ctx: HDD Context
8853 *
8854 * Return: void
8855 */
8856static void hdd_update_hif_config(hdd_context_t *hdd_ctx)
8857{
Anurag Chouhandf2b2682016-02-29 14:15:27 +05308858 struct hif_opaque_softc *scn = cds_get_context(QDF_MODULE_ID_HIF);
Komal Seelamec702b02016-02-24 18:42:16 +05308859 struct hif_config_info cfg;
8860
8861 if (!scn)
8862 return;
8863
8864 cfg.enable_self_recovery = hdd_ctx->config->enableSelfRecovery;
Houston Hoffmanc7c69f02016-03-24 22:45:52 -07008865 hdd_populate_runtime_cfg(hdd_ctx, &cfg);
Komal Seelamec702b02016-02-24 18:42:16 +05308866 hif_init_ini_config(scn, &cfg);
8867}
8868
8869/**
8870 * hdd_update_config() - Initialize driver per module ini parameters
8871 * @hdd_ctx: HDD Context
8872 *
8873 * API is used to initialize all driver per module configuration parameters
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308874 * Return: 0 for success, errno for failure
Komal Seelamec702b02016-02-24 18:42:16 +05308875 */
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308876int hdd_update_config(hdd_context_t *hdd_ctx)
Komal Seelamec702b02016-02-24 18:42:16 +05308877{
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308878 int ret;
8879
Komal Seelamec702b02016-02-24 18:42:16 +05308880 hdd_update_ol_config(hdd_ctx);
8881 hdd_update_hif_config(hdd_ctx);
Arun Khandavallic811dcc2016-06-26 07:37:21 +05308882 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam())
8883 ret = hdd_update_cds_config_ftm(hdd_ctx);
8884 else
8885 ret = hdd_update_cds_config(hdd_ctx);
8886
8887 return ret;
Komal Seelamc11bb222016-01-27 18:57:10 +05308888}
8889
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008890/* Register the module init/exit functions */
8891module_init(hdd_module_init);
8892module_exit(hdd_module_exit);
8893
8894MODULE_LICENSE("Dual BSD/GPL");
8895MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8896MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8897
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008898module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8899 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008900
8901module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
8902 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
8903
8904module_param(enable_dfs_chan_scan, int, S_IRUSR | S_IRGRP | S_IROTH);
8905
8906module_param(enable_11d, int, S_IRUSR | S_IRGRP | S_IROTH);
8907
8908module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH);