blob: 7d36c8843c152d6aadea3f435d95819b711a5095 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jingxiang Geb5fb05b2019-01-09 17:34:35 +08002 * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019/**
20 * DOC: wlan_hdd_power.c
21 *
22 * WLAN power management functions
23 *
24 */
25
26/* Include files */
27
28#include <linux/pm.h>
29#include <linux/wait.h>
30#include <linux/cpu.h>
Dustin Brown1d31b082018-11-22 14:41:20 +053031#include "osif_sync.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080032#include <wlan_hdd_includes.h>
33#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
34#include <linux/wakelock.h>
35#endif
Anurag Chouhan6d760662016-02-20 16:05:43 +053036#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080037#include "sme_api.h"
38#include <cds_api.h>
39#include <cds_sched.h>
40#include <mac_init_api.h>
41#include <wlan_qct_sys.h>
42#include <wlan_hdd_main.h>
43#include <wlan_hdd_assoc.h>
44#include <wlan_nlink_srv.h>
45#include <wlan_hdd_misc.h>
46#include <wlan_hdd_power.h>
Jeff Johnsonc8d0c252016-10-05 16:19:50 -070047#include <wlan_hdd_host_offload.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include <dbglog_host.h>
49#include <wlan_hdd_trace.h>
Masti, Narayanraddi3e26de62016-08-19 14:33:22 +053050#include <wlan_hdd_p2p.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051
52#include <linux/semaphore.h>
53#include <wlan_hdd_hostapd.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080054
55#include <linux/inetdevice.h>
56#include <wlan_hdd_cfg.h>
Sandeep Puligillae390be52016-02-08 17:07:05 -080057#include <wlan_hdd_scan.h>
Jeff Johnson5fe539b2018-03-23 13:53:30 -070058#include <wlan_hdd_stats.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080059#include <wlan_hdd_cfg80211.h>
60#include <net/addrconf.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070061#include <wlan_hdd_lpass.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062
63#include <wma_types.h>
Poddar, Siddartha78cac32016-12-29 20:08:34 +053064#include <ol_txrx_osif_api.h>
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +053065#include <ol_defines.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080066#include "hif.h"
Dustin Brown0f8dc3d2017-06-01 14:37:26 -070067#include "hif_unit_test_suspend.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080068#include "sme_power_save_api.h"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080069#include "wlan_policy_mgr_api.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080070#include "cdp_txrx_flow_ctrl_v2.h"
Yuanyuan Liu13738502016-04-06 17:41:37 -070071#include "pld_common.h"
Rajeev Kumar9bb2e852016-09-24 12:29:25 -070072#include "wlan_hdd_driver_ops.h"
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +053073#include <wlan_logging_sock_svc.h>
Krunal Sonid32c6bc2016-10-18 18:00:21 -070074#include "scheduler_api.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053075#include "cds_utils.h"
Hanumanth Reddy Pothula3def8942017-10-05 16:19:36 +053076#include "wlan_hdd_packet_filter_api.h"
Arunk Khandavallif0c0d762017-12-07 10:18:50 +053077#include "wlan_cfg80211_scan.h"
Mohit Khanna70322002018-05-15 19:21:32 -070078#include <dp_txrx.h>
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +053079#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -080080#include <wlan_cfg80211_mc_cp_stats.h>
Wu Gao4a1ec8c2018-07-23 19:18:40 +080081#include "wlan_p2p_ucfg_api.h"
Wu Gao93816212018-08-31 16:49:54 +080082#include "wlan_mlme_ucfg_api.h"
Sourav Mohapatra2a67b0e2019-10-15 17:59:59 +053083#include "wlan_osif_request_manager.h"
Wu Gao93816212018-08-31 16:49:54 +080084
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080085/* Preprocessor definitions and constants */
Yue Ma5fe30dd2017-05-02 15:47:40 -070086#ifdef QCA_WIFI_NAPIER_EMULATION
87#define HDD_SSR_BRING_UP_TIME 3000000
88#else
Yue Ma4ea4f052015-10-27 12:25:27 -070089#define HDD_SSR_BRING_UP_TIME 30000
Yue Ma5fe30dd2017-05-02 15:47:40 -070090#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091
92/* Type declarations */
93
Abhishek Singhbaea27d2016-04-27 13:29:30 +053094#ifdef FEATURE_WLAN_DIAG_SUPPORT
Abhishek Singhbaea27d2016-04-27 13:29:30 +053095void hdd_wlan_suspend_resume_event(uint8_t state)
96{
97 WLAN_HOST_DIAG_EVENT_DEF(suspend_state, struct host_event_suspend);
98 qdf_mem_zero(&suspend_state, sizeof(suspend_state));
99
100 suspend_state.state = state;
101 WLAN_HOST_DIAG_EVENT_REPORT(&suspend_state, EVENT_WLAN_SUSPEND_RESUME);
102}
Abhishek Singh4aad0f72016-04-27 13:43:29 +0530103
104/**
105 * hdd_wlan_offload_event()- send offloads event
106 * @type: offload type
107 * @state: enabled or disabled
108 *
109 * This Function send offloads enable/disable diag event
110 *
111 * Return: void.
112 */
113
114void hdd_wlan_offload_event(uint8_t type, uint8_t state)
115{
116 WLAN_HOST_DIAG_EVENT_DEF(host_offload, struct host_event_offload_req);
117 qdf_mem_zero(&host_offload, sizeof(host_offload));
118
119 host_offload.offload_type = type;
120 host_offload.state = state;
121
122 WLAN_HOST_DIAG_EVENT_REPORT(&host_offload, EVENT_WLAN_OFFLOAD_REQ);
123}
Abhishek Singhbaea27d2016-04-27 13:29:30 +0530124#endif
125
Lin Baif5e8cc22018-11-05 10:57:38 +0800126#ifdef QCA_CONFIG_SMP
127
128/* timeout in msec to wait for RX_THREAD to suspend */
129#define HDD_RXTHREAD_SUSPEND_TIMEOUT 200
130
131void wlan_hdd_rx_thread_resume(struct hdd_context *hdd_ctx)
132{
133 if (hdd_ctx->is_ol_rx_thread_suspended) {
134 cds_resume_rx_thread();
135 hdd_ctx->is_ol_rx_thread_suspended = false;
136 }
137}
138
139int wlan_hdd_rx_thread_suspend(struct hdd_context *hdd_ctx)
140{
141 p_cds_sched_context cds_sched_context = get_cds_sched_ctxt();
142 int rc;
143
144 if (!cds_sched_context)
145 return 0;
146
147 /* Suspend tlshim rx thread */
148 set_bit(RX_SUSPEND_EVENT, &cds_sched_context->ol_rx_event_flag);
149 wake_up_interruptible(&cds_sched_context->ol_rx_wait_queue);
150 rc = wait_for_completion_timeout(&cds_sched_context->
151 ol_suspend_rx_event,
152 msecs_to_jiffies
153 (HDD_RXTHREAD_SUSPEND_TIMEOUT)
154 );
155 if (!rc) {
156 clear_bit(RX_SUSPEND_EVENT,
157 &cds_sched_context->ol_rx_event_flag);
158 hdd_err("Failed to stop tl_shim rx thread");
159 return -EINVAL;
160 }
161 hdd_ctx->is_ol_rx_thread_suspended = true;
162
163 return 0;
164}
165#endif /* QCA_CONFIG_SMP */
166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167/**
Mukul Sharma3d36c392017-01-18 18:39:12 +0530168 * hdd_enable_gtk_offload() - enable GTK offload
169 * @adapter: pointer to the adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 *
Mukul Sharma3d36c392017-01-18 18:39:12 +0530171 * Central function to enable GTK offload.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172 *
173 * Return: nothing
174 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700175static void hdd_enable_gtk_offload(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800176{
Mukul Sharma3d36c392017-01-18 18:39:12 +0530177 QDF_STATUS status;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -0700178
Wu Gaod7dd6e42018-10-16 17:22:56 +0800179 status = ucfg_pmo_enable_gtk_offload_in_fwr(adapter->vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +0530180 if (status != QDF_STATUS_SUCCESS)
181 hdd_info("Failed to enable gtk offload");
182}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800183
Mukul Sharma3d36c392017-01-18 18:39:12 +0530184/**
185 * hdd_disable_gtk_offload() - disable GTK offload
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700186 * @adapter: pointer to the adapter
Mukul Sharma3d36c392017-01-18 18:39:12 +0530187 *
188 * Central function to disable GTK offload.
189 *
190 * Return: nothing
191 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700192static void hdd_disable_gtk_offload(struct hdd_adapter *adapter)
Mukul Sharma3d36c392017-01-18 18:39:12 +0530193{
194 struct pmo_gtk_rsp_req gtk_rsp_request;
195 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196
Mukul Sharma3d36c392017-01-18 18:39:12 +0530197 /* ensure to get gtk rsp first before disable it*/
Dustin Brown89fa06e2018-09-07 10:47:27 -0700198 gtk_rsp_request.callback = wlan_hdd_cfg80211_update_replay_counter_cb;
199
Mukul Sharma3d36c392017-01-18 18:39:12 +0530200 /* Passing as void* as PMO does not know legacy HDD adapter type */
Dustin Brown89fa06e2018-09-07 10:47:27 -0700201 gtk_rsp_request.callback_context = (void *)adapter;
202
Wu Gaod7dd6e42018-10-16 17:22:56 +0800203 status = ucfg_pmo_get_gtk_rsp(adapter->vdev, &gtk_rsp_request);
Mukul Sharma3d36c392017-01-18 18:39:12 +0530204 if (status != QDF_STATUS_SUCCESS) {
205 hdd_err("Failed to send get gtk rsp status:%d", status);
206 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 }
Dustin Brown89fa06e2018-09-07 10:47:27 -0700208
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800209 hdd_debug("send get_gtk_rsp successful");
Wu Gaod7dd6e42018-10-16 17:22:56 +0800210 status = ucfg_pmo_disable_gtk_offload_in_fwr(adapter->vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +0530211 if (status != QDF_STATUS_SUCCESS)
212 hdd_info("Failed to disable gtk offload");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214
Qiwei Cai1083f5b2018-07-02 19:10:11 +0800215#ifdef WLAN_NS_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216/**
217 * __wlan_hdd_ipv6_changed() - IPv6 notifier callback function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800218 * @net_dev: net_device whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 *
220 * This is a callback function that is registered with the kernel via
221 * register_inet6addr_notifier() which allows the driver to be
222 * notified when there is an IPv6 address change.
223 *
Dustin Brown39b33ba2019-02-27 10:54:56 -0800224 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800226static void __wlan_hdd_ipv6_changed(struct net_device *net_dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800228 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700229 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700230 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231
Dustin Brown39b33ba2019-02-27 10:54:56 -0800232 hdd_enter_dev(net_dev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530233
Dustin Brownf13b8c32017-05-19 17:23:08 -0700234 errno = hdd_validate_adapter(adapter);
Dustin Brown39b33ba2019-02-27 10:54:56 -0800235 if (errno || adapter->dev != net_dev)
236 goto exit;
237
238 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
239 errno = wlan_hdd_validate_context(hdd_ctx);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700240 if (errno)
241 goto exit;
242
Dustin Brown39b33ba2019-02-27 10:54:56 -0800243 if (adapter->device_mode == QDF_STA_MODE ||
244 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
245 adapter->device_mode == QDF_NDI_MODE) {
Dustin Brownf13b8c32017-05-19 17:23:08 -0700246 hdd_debug("invoking sme_dhcp_done_ind");
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800247 sme_dhcp_done_ind(hdd_ctx->mac_handle, adapter->vdev_id);
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700248 schedule_work(&adapter->ipv6_notifier_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800249 }
250
Dustin Brownf13b8c32017-05-19 17:23:08 -0700251exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700252 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253}
254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800255int wlan_hdd_ipv6_changed(struct notifier_block *nb,
Dustin Brown39b33ba2019-02-27 10:54:56 -0800256 unsigned long data, void *context)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800257{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800258 struct inet6_ifaddr *ifa = context;
259 struct net_device *net_dev = ifa->idev->dev;
260 struct osif_vdev_sync *vdev_sync;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800261
Dustin Brown39b33ba2019-02-27 10:54:56 -0800262 if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
263 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800264
Dustin Brown39b33ba2019-02-27 10:54:56 -0800265 __wlan_hdd_ipv6_changed(net_dev);
266
267 osif_vdev_sync_op_stop(vdev_sync);
268
269 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800270}
271
272/**
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530273 * hdd_fill_ipv6_uc_addr() - fill IPv6 unicast addresses
274 * @idev: pointer to net device
275 * @ipv6addr: destination array to fill IPv6 addresses
276 * @ipv6addr_type: IPv6 Address type
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530277 * @scope_array: scope of ipv6 addr
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530278 * @count: number of IPv6 addresses
279 *
280 * This is the IPv6 utility function to populate unicast addresses.
281 *
282 * Return: 0 on success, error number otherwise.
283 */
284static int hdd_fill_ipv6_uc_addr(struct inet6_dev *idev,
Srinivas Girigowdad1e45b82019-04-15 15:08:28 -0700285 uint8_t ipv6_uc_addr[][QDF_IPV6_ADDR_SIZE],
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530286 uint8_t *ipv6addr_type,
287 enum pmo_ns_addr_scope *scope_array,
288 uint32_t *count)
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530289{
290 struct inet6_ifaddr *ifa;
291 struct list_head *p;
292 uint32_t scope;
293
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700294 read_lock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530295 list_for_each(p, &idev->addr_list) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530296 if (*count >= PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) {
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700297 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530298 return -EINVAL;
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700299 }
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530300 ifa = list_entry(p, struct inet6_ifaddr, if_list);
301 if (ifa->flags & IFA_F_DADFAILED)
302 continue;
303 scope = ipv6_addr_src_scope(&ifa->addr);
304 switch (scope) {
305 case IPV6_ADDR_SCOPE_GLOBAL:
306 case IPV6_ADDR_SCOPE_LINKLOCAL:
307 qdf_mem_copy(ipv6_uc_addr[*count], &ifa->addr.s6_addr,
308 sizeof(ifa->addr.s6_addr));
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530309 ipv6addr_type[*count] = PMO_IPV6_ADDR_UC_TYPE;
Wu Gaod7dd6e42018-10-16 17:22:56 +0800310 scope_array[*count] = ucfg_pmo_ns_addr_scope(scope);
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800311 hdd_debug("Index %d scope = %s UC-Address: %pI6",
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530312 *count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
313 "LINK LOCAL" : "GLOBAL", ipv6_uc_addr[*count]);
314 *count += 1;
315 break;
316 default:
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800317 hdd_warn("The Scope %d is not supported", scope);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530318 }
319 }
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700320
321 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530322 return 0;
323}
324
325/**
326 * hdd_fill_ipv6_ac_addr() - fill IPv6 anycast addresses
327 * @idev: pointer to net device
328 * @ipv6addr: destination array to fill IPv6 addresses
329 * @ipv6addr_type: IPv6 Address type
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530330 * @scope_array: scope of ipv6 addr
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530331 * @count: number of IPv6 addresses
332 *
333 * This is the IPv6 utility function to populate anycast addresses.
334 *
335 * Return: 0 on success, error number otherwise.
336 */
337static int hdd_fill_ipv6_ac_addr(struct inet6_dev *idev,
Srinivas Girigowdad1e45b82019-04-15 15:08:28 -0700338 uint8_t ipv6_ac_addr[][QDF_IPV6_ADDR_SIZE],
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530339 uint8_t *ipv6addr_type,
340 enum pmo_ns_addr_scope *scope_array,
341 uint32_t *count)
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530342{
343 struct ifacaddr6 *ifaca;
344 uint32_t scope;
345
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700346 read_lock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530347 for (ifaca = idev->ac_list; ifaca; ifaca = ifaca->aca_next) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530348 if (*count >= PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) {
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700349 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530350 return -EINVAL;
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700351 }
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530352 /* For anycast addr no DAD */
353 scope = ipv6_addr_src_scope(&ifaca->aca_addr);
354 switch (scope) {
355 case IPV6_ADDR_SCOPE_GLOBAL:
356 case IPV6_ADDR_SCOPE_LINKLOCAL:
357 qdf_mem_copy(ipv6_ac_addr[*count], &ifaca->aca_addr,
358 sizeof(ifaca->aca_addr));
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530359 ipv6addr_type[*count] = PMO_IPV6_ADDR_AC_TYPE;
Wu Gaod7dd6e42018-10-16 17:22:56 +0800360 scope_array[*count] = ucfg_pmo_ns_addr_scope(scope);
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800361 hdd_debug("Index %d scope = %s AC-Address: %pI6",
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530362 *count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
363 "LINK LOCAL" : "GLOBAL", ipv6_ac_addr[*count]);
364 *count += 1;
365 break;
366 default:
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800367 hdd_warn("The Scope %d is not supported", scope);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530368 }
369 }
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700370
371 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530372 return 0;
373}
374
Jeff Johnson75b737d2017-08-29 14:24:41 -0700375void hdd_enable_ns_offload(struct hdd_adapter *adapter,
Dustin Brownc1cdb712018-06-11 15:42:17 -0700376 enum pmo_offload_trigger trigger)
Dustin Brown2444ee62016-09-06 17:20:36 -0700377{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700378 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown05d81302018-09-11 16:49:22 -0700379 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
Dustin Brownc1cdb712018-06-11 15:42:17 -0700380 struct inet6_dev *in6_dev;
381 struct pmo_ns_req *ns_req;
382 QDF_STATUS status;
383 int errno;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530384
Dustin Brown491d54b2018-03-14 12:39:11 -0700385 hdd_enter();
Dustin Brownc1cdb712018-06-11 15:42:17 -0700386
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530387 if (!psoc) {
388 hdd_err("psoc is NULL");
389 goto out;
390 }
Dustin Brown2444ee62016-09-06 17:20:36 -0700391
392 in6_dev = __in6_dev_get(adapter->dev);
Jeff Johnsond36fa332019-03-18 13:42:25 -0700393 if (!in6_dev) {
Dustin Brown2444ee62016-09-06 17:20:36 -0700394 hdd_err("IPv6 dev does not exist. Failed to request NSOffload");
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530395 goto out;
Dustin Brown2444ee62016-09-06 17:20:36 -0700396 }
397
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530398 ns_req = qdf_mem_malloc(sizeof(*ns_req));
Min Liu74a1a502018-10-10 19:59:07 +0800399 if (!ns_req)
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530400 goto out;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530401
402 ns_req->psoc = psoc;
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800403 ns_req->vdev_id = adapter->vdev_id;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530404 ns_req->trigger = trigger;
405 ns_req->count = 0;
406
Sourav Mohapatra60c3b2b2019-11-19 10:27:33 +0530407 /* check if offload cache and send is required or not */
408 status = ucfg_pmo_ns_offload_check(psoc, trigger, adapter->vdev_id);
409 if (QDF_IS_STATUS_ERROR(status)) {
410 hdd_info("NS offload is not required");
411 goto free_req;
412 }
413
Dustin Brown2444ee62016-09-06 17:20:36 -0700414 /* Unicast Addresses */
Dustin Brownc1cdb712018-06-11 15:42:17 -0700415 errno = hdd_fill_ipv6_uc_addr(in6_dev, ns_req->ipv6_addr,
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530416 ns_req->ipv6_addr_type, ns_req->scope,
417 &ns_req->count);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700418 if (errno) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530419 hdd_disable_ns_offload(adapter, trigger);
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +0530420 hdd_debug("Max supported addresses: disabling NS offload");
Dustin Brownc1cdb712018-06-11 15:42:17 -0700421 goto free_req;
Dustin Brown2444ee62016-09-06 17:20:36 -0700422 }
423
424 /* Anycast Addresses */
Dustin Brownc1cdb712018-06-11 15:42:17 -0700425 errno = hdd_fill_ipv6_ac_addr(in6_dev, ns_req->ipv6_addr,
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530426 ns_req->ipv6_addr_type, ns_req->scope,
427 &ns_req->count);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700428 if (errno) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530429 hdd_disable_ns_offload(adapter, trigger);
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +0530430 hdd_debug("Max supported addresses: disabling NS offload");
Dustin Brownc1cdb712018-06-11 15:42:17 -0700431 goto free_req;
Dustin Brown2444ee62016-09-06 17:20:36 -0700432 }
433
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530434 /* cache ns request */
Wu Gaod7dd6e42018-10-16 17:22:56 +0800435 status = ucfg_pmo_cache_ns_offload_req(ns_req);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700436 if (QDF_IS_STATUS_ERROR(status)) {
437 hdd_err("Failed to cache ns request; status:%d", status);
438 goto free_req;
Dustin Brown2444ee62016-09-06 17:20:36 -0700439 }
440
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530441 /* enable ns request */
Wu Gaod7dd6e42018-10-16 17:22:56 +0800442 status = ucfg_pmo_enable_ns_offload_in_fwr(adapter->vdev, trigger);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700443 if (QDF_IS_STATUS_ERROR(status)) {
444 hdd_err("Failed to enable ns offload; status:%d", status);
445 goto free_req;
446 }
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530447
Dustin Brownc1cdb712018-06-11 15:42:17 -0700448 hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD, SIR_OFFLOAD_ENABLE);
449
450free_req:
451 qdf_mem_free(ns_req);
452
453out:
454 hdd_exit();
Dustin Brown2444ee62016-09-06 17:20:36 -0700455}
456
Jeff Johnson75b737d2017-08-29 14:24:41 -0700457void hdd_disable_ns_offload(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530458 enum pmo_offload_trigger trigger)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800459{
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530460 QDF_STATUS status;
Sourav Mohapatra60c3b2b2019-11-19 10:27:33 +0530461 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462
Dustin Brown491d54b2018-03-14 12:39:11 -0700463 hdd_enter();
Sourav Mohapatra60c3b2b2019-11-19 10:27:33 +0530464
465 status = ucfg_pmo_ns_offload_check(hdd_ctx->psoc, trigger,
466 adapter->vdev_id);
467 if (status != QDF_STATUS_SUCCESS) {
468 hdd_err("Flushing of NS offload not required");
469 goto out;
470 }
471
Wu Gaod7dd6e42018-10-16 17:22:56 +0800472 status = ucfg_pmo_flush_ns_offload_req(adapter->vdev);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530473 if (status != QDF_STATUS_SUCCESS) {
474 hdd_err("Failed to flush NS Offload");
475 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476 }
477
Wu Gaod7dd6e42018-10-16 17:22:56 +0800478 status = ucfg_pmo_disable_ns_offload_in_fwr(adapter->vdev, trigger);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530479 if (status != QDF_STATUS_SUCCESS)
480 hdd_err("Failed to disable NS Offload");
Dustin Brown2444ee62016-09-06 17:20:36 -0700481 else
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530482 hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD,
483 SIR_OFFLOAD_DISABLE);
484out:
Dustin Browne74003f2018-03-14 12:51:58 -0700485 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530486
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800487}
488
489/**
490 * __hdd_ipv6_notifier_work_queue() - IPv6 notification work function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800491 * @adapter: adapter whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492 *
493 * This function performs the work initially trigged by a callback
494 * from the IPv6 netdev notifier. Since this means there has been a
495 * change in IPv6 state for the interface, the NS offload is
496 * reconfigured.
497 *
498 * Return: None
499 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800500static void __hdd_ipv6_notifier_work_queue(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700502 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700503 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504
Dustin Brown491d54b2018-03-14 12:39:11 -0700505 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506
Dustin Brownf13b8c32017-05-19 17:23:08 -0700507 errno = hdd_validate_adapter(adapter);
508 if (errno)
509 goto exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510
Dustin Brownf13b8c32017-05-19 17:23:08 -0700511 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
512 errno = wlan_hdd_validate_context(hdd_ctx);
513 if (errno)
514 goto exit;
515
516 hdd_enable_ns_offload(adapter, pmo_ipv6_change_notify);
517
518exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700519 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520}
521
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522void hdd_ipv6_notifier_work_queue(struct work_struct *work)
523{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800524 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
525 ipv6_notifier_work);
526 struct osif_vdev_sync *vdev_sync;
527
528 if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
529 return;
530
531 __hdd_ipv6_notifier_work_queue(adapter);
532
533 osif_vdev_sync_op_stop(vdev_sync);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534}
Qiwei Cai1083f5b2018-07-02 19:10:11 +0800535#endif /* WLAN_NS_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800536
Jeff Johnson75b737d2017-08-29 14:24:41 -0700537static void hdd_enable_hw_filter(struct hdd_adapter *adapter)
Dustin Brown1224e212017-05-12 14:02:12 -0700538{
539 QDF_STATUS status;
540
Dustin Brown491d54b2018-03-14 12:39:11 -0700541 hdd_enter();
Dustin Brown1224e212017-05-12 14:02:12 -0700542
Wu Gaod7dd6e42018-10-16 17:22:56 +0800543 status = ucfg_pmo_enable_hw_filter_in_fwr(adapter->vdev);
Dustin Brown1224e212017-05-12 14:02:12 -0700544 if (status != QDF_STATUS_SUCCESS)
545 hdd_info("Failed to enable hardware filter");
546
Dustin Browne74003f2018-03-14 12:51:58 -0700547 hdd_exit();
Dustin Brown1224e212017-05-12 14:02:12 -0700548}
549
Jeff Johnson75b737d2017-08-29 14:24:41 -0700550static void hdd_disable_hw_filter(struct hdd_adapter *adapter)
Dustin Brown1224e212017-05-12 14:02:12 -0700551{
552 QDF_STATUS status;
553
Dustin Brown491d54b2018-03-14 12:39:11 -0700554 hdd_enter();
Dustin Brown1224e212017-05-12 14:02:12 -0700555
Wu Gaod7dd6e42018-10-16 17:22:56 +0800556 status = ucfg_pmo_disable_hw_filter_in_fwr(adapter->vdev);
Dustin Brown1224e212017-05-12 14:02:12 -0700557 if (status != QDF_STATUS_SUCCESS)
558 hdd_info("Failed to disable hardware filter");
559
Dustin Browne74003f2018-03-14 12:51:58 -0700560 hdd_exit();
Dustin Brown1224e212017-05-12 14:02:12 -0700561}
562
Pragaspathi Thilagarajb40c2602019-08-21 14:17:48 +0530563static void hdd_enable_action_frame_patterns(struct hdd_adapter *adapter)
564{
565 QDF_STATUS status;
566
567 hdd_enter();
568
569 status = ucfg_pmo_enable_action_frame_patterns(adapter->vdev,
570 QDF_SYSTEM_SUSPEND);
571 if (QDF_IS_STATUS_ERROR(status))
572 hdd_info("Failed to enable action frame patterns");
573
574 hdd_exit();
575}
576
577static void hdd_disable_action_frame_patterns(struct hdd_adapter *adapter)
578{
579 QDF_STATUS status;
580
581 hdd_enter();
582
583 status = ucfg_pmo_disable_action_frame_patterns(adapter->vdev);
584 if (QDF_IS_STATUS_ERROR(status))
585 hdd_info("Failed to disable action frame patterns");
586
587 hdd_exit();
588}
589
Jeff Johnson75b737d2017-08-29 14:24:41 -0700590void hdd_enable_host_offloads(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530591 enum pmo_offload_trigger trigger)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592{
Dustin Brown491d54b2018-03-14 12:39:11 -0700593 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530594
Dustin Brown89fa06e2018-09-07 10:47:27 -0700595 if (!ucfg_pmo_is_vdev_supports_offload(adapter->vdev)) {
Dustin Brownc1cdb712018-06-11 15:42:17 -0700596 hdd_debug("offload is not supported on vdev opmode %d",
597 adapter->device_mode);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530598 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800599 }
600
Dustin Brown89fa06e2018-09-07 10:47:27 -0700601 if (!ucfg_pmo_is_vdev_connected(adapter->vdev)) {
Dustin Brownc1cdb712018-06-11 15:42:17 -0700602 hdd_debug("offload is not supported on disconnected vdevs");
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530603 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604 }
605
Dustin Brownc1cdb712018-06-11 15:42:17 -0700606 hdd_debug("enable offloads");
Mukul Sharma3d36c392017-01-18 18:39:12 +0530607 hdd_enable_gtk_offload(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530608 hdd_enable_arp_offload(adapter, trigger);
609 hdd_enable_ns_offload(adapter, trigger);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +0530610 hdd_enable_mc_addr_filtering(adapter, trigger);
Dustin Brown1224e212017-05-12 14:02:12 -0700611 hdd_enable_hw_filter(adapter);
Pragaspathi Thilagarajb40c2602019-08-21 14:17:48 +0530612 hdd_enable_action_frame_patterns(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530613out:
Dustin Browne74003f2018-03-14 12:51:58 -0700614 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530615
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616}
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530617
Jeff Johnson75b737d2017-08-29 14:24:41 -0700618void hdd_disable_host_offloads(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530619 enum pmo_offload_trigger trigger)
620{
Dustin Brown491d54b2018-03-14 12:39:11 -0700621 hdd_enter();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530622
Dustin Brown89fa06e2018-09-07 10:47:27 -0700623 if (!ucfg_pmo_is_vdev_supports_offload(adapter->vdev)) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530624 hdd_info("offload is not supported on this vdev opmode: %d",
625 adapter->device_mode);
626 goto out;
627 }
628
Dustin Brown89fa06e2018-09-07 10:47:27 -0700629 if (!ucfg_pmo_is_vdev_connected(adapter->vdev)) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530630 hdd_info("vdev is not connected");
631 goto out;
632 }
633
Dustin Brownc1cdb712018-06-11 15:42:17 -0700634 hdd_debug("disable offloads");
Mukul Sharma3d36c392017-01-18 18:39:12 +0530635 hdd_disable_gtk_offload(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530636 hdd_disable_arp_offload(adapter, trigger);
637 hdd_disable_ns_offload(adapter, trigger);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +0530638 hdd_disable_mc_addr_filtering(adapter, trigger);
Dustin Brown1224e212017-05-12 14:02:12 -0700639 hdd_disable_hw_filter(adapter);
Pragaspathi Thilagarajb40c2602019-08-21 14:17:48 +0530640 hdd_disable_action_frame_patterns(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530641out:
Dustin Browne74003f2018-03-14 12:51:58 -0700642 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530643
644}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800645
646/**
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800647 * hdd_lookup_ifaddr() - Lookup interface address data by name
648 * @adapter: the adapter whose name should be searched for
649 *
650 * return in_ifaddr pointer on success, NULL for failure
651 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700652static struct in_ifaddr *hdd_lookup_ifaddr(struct hdd_adapter *adapter)
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800653{
654 struct in_ifaddr *ifa;
655 struct in_device *in_dev;
656
657 if (!adapter) {
658 hdd_err("adapter is null");
659 return NULL;
660 }
661
662 in_dev = __in_dev_get_rtnl(adapter->dev);
663 if (!in_dev) {
664 hdd_err("Failed to get in_device");
665 return NULL;
666 }
667
668 /* lookup address data by interface name */
669 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
670 if (!strcmp(adapter->dev->name, ifa->ifa_label))
671 return ifa;
672 }
673
674 return NULL;
675}
676
677/**
678 * hdd_populate_ipv4_addr() - Populates the adapter's IPv4 address
679 * @adapter: the adapter whose IPv4 address is desired
680 * @ipv4_addr: the address of the array to copy the IPv4 address into
681 *
682 * return: zero for success; non-zero for failure
683 */
Jeff Johnsond6d1f632017-10-06 20:06:10 -0700684static int hdd_populate_ipv4_addr(struct hdd_adapter *adapter,
685 uint8_t *ipv4_addr)
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800686{
687 struct in_ifaddr *ifa;
688 int i;
689
690 if (!adapter) {
691 hdd_err("adapter is null");
692 return -EINVAL;
693 }
694
695 if (!ipv4_addr) {
696 hdd_err("ipv4_addr is null");
697 return -EINVAL;
698 }
699
700 ifa = hdd_lookup_ifaddr(adapter);
701 if (!ifa || !ifa->ifa_local) {
702 hdd_err("ipv4 address not found");
703 return -EINVAL;
704 }
705
706 /* convert u32 to byte array */
707 for (i = 0; i < 4; i++)
708 ipv4_addr[i] = (ifa->ifa_local >> i * 8) & 0xff;
709
710 return 0;
711}
712
713/**
714 * hdd_set_grat_arp_keepalive() - Enable grat APR keepalive
715 * @adapter: the HDD adapter to configure
716 *
717 * This configures gratuitous APR keepalive based on the adapter's current
718 * connection information, specifically IPv4 address and BSSID
719 *
720 * return: zero for success, non-zero for failure
721 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700722static int hdd_set_grat_arp_keepalive(struct hdd_adapter *adapter)
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800723{
724 QDF_STATUS status;
725 int exit_code;
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700726 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700727 struct hdd_station_ctx *sta_ctx;
Jeff Johnson562ccad2019-02-06 22:10:24 -0800728 struct keep_alive_req req = {
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800729 .packetType = SIR_KEEP_ALIVE_UNSOLICIT_ARP_RSP,
Dustin Brownce5b3d32018-01-17 15:07:38 -0800730 .dest_macaddr = QDF_MAC_ADDR_BCAST_INIT,
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800731 };
732
733 if (!adapter) {
734 hdd_err("adapter is null");
735 return -EINVAL;
736 }
737
738 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
739 if (!hdd_ctx) {
740 hdd_err("hdd_ctx is null");
741 return -EINVAL;
742 }
743
744 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
745 if (!sta_ctx) {
746 hdd_err("sta_ctx is null");
747 return -EINVAL;
748 }
749
750 exit_code = hdd_populate_ipv4_addr(adapter, req.hostIpv4Addr);
751 if (exit_code) {
752 hdd_err("Failed to populate ipv4 address");
753 return exit_code;
754 }
755
Dustin Brown6b4643d2017-02-09 12:19:28 -0800756 /* according to RFC5227, sender/target ip address should be the same */
757 qdf_mem_copy(&req.destIpv4Addr, &req.hostIpv4Addr,
758 sizeof(req.destIpv4Addr));
759
Jeff Johnsone04b6992019-02-27 14:06:55 -0800760 qdf_copy_macaddr(&req.bssid, &sta_ctx->conn_info.bssid);
Dustin Brown05d81302018-09-11 16:49:22 -0700761 ucfg_mlme_get_sta_keep_alive_period(hdd_ctx->psoc, &req.timePeriod);
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800762 req.sessionId = adapter->vdev_id;
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800763
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800764 hdd_debug("Setting gratuitous ARP keepalive; ipv4_addr:%u.%u.%u.%u",
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800765 req.hostIpv4Addr[0], req.hostIpv4Addr[1],
766 req.hostIpv4Addr[2], req.hostIpv4Addr[3]);
767
Jeff Johnson2954ded2018-06-13 16:34:49 -0700768 status = sme_set_keep_alive(hdd_ctx->mac_handle, req.sessionId, &req);
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800769 if (QDF_IS_STATUS_ERROR(status)) {
770 hdd_err("Failed to set keepalive");
771 return qdf_status_to_os_return(status);
772 }
773
774 return 0;
775}
776
777/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 * __hdd_ipv4_notifier_work_queue() - IPv4 notification work function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800779 * @adapter: adapter whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 *
781 * This function performs the work initially trigged by a callback
782 * from the IPv4 netdev notifier. Since this means there has been a
783 * change in IPv4 state for the interface, the ARP offload is
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530784 * reconfigured. Also, Updates the HLP IE info with IP address info
785 * to fw if LFR3 is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786 *
787 * Return: None
788 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800789static void __hdd_ipv4_notifier_work_queue(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700791 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700792 int errno;
Jeff Johnson61b5e982018-03-15 11:33:31 -0700793 struct csr_roam_profile *roam_profile;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530794 struct in_ifaddr *ifa;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +0530795 enum station_keepalive_method val;
796 QDF_STATUS status;
Dustin Brownb6b0f182017-03-08 13:08:27 -0800797
Dustin Brown491d54b2018-03-14 12:39:11 -0700798 hdd_enter();
Dustin Brownb6b0f182017-03-08 13:08:27 -0800799
Dustin Brownf13b8c32017-05-19 17:23:08 -0700800 errno = hdd_validate_adapter(adapter);
801 if (errno)
802 goto exit;
Dustin Brownb6b0f182017-03-08 13:08:27 -0800803
804 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700805 errno = wlan_hdd_validate_context(hdd_ctx);
806 if (errno)
807 goto exit;
808
809 hdd_enable_arp_offload(adapter, pmo_ipv4_change_notify);
810
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +0530811 status = ucfg_mlme_get_sta_keepalive_method(hdd_ctx->psoc, &val);
812 if (QDF_IS_STATUS_ERROR(status))
813 goto exit;
814
815 if (val == MLME_STA_KEEPALIVE_GRAT_ARP)
Dustin Brownb6b0f182017-03-08 13:08:27 -0800816 hdd_set_grat_arp_keepalive(adapter);
817
Vignesh Viswanathan731186f2017-09-18 13:47:37 +0530818 hdd_debug("FILS Roaming support: %d",
819 hdd_ctx->is_fils_roaming_supported);
Jeff Johnsona0c1ca72018-03-18 14:52:03 -0700820 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathan731186f2017-09-18 13:47:37 +0530821
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530822 ifa = hdd_lookup_ifaddr(adapter);
Vignesh Viswanathan731186f2017-09-18 13:47:37 +0530823 if (ifa && hdd_ctx->is_fils_roaming_supported)
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800824 sme_send_hlp_ie_info(hdd_ctx->mac_handle, adapter->vdev_id,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530825 roam_profile, ifa->ifa_local);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700826exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700827 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828}
829
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830void hdd_ipv4_notifier_work_queue(struct work_struct *work)
831{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800832 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
833 ipv4_notifier_work);
834 struct osif_vdev_sync *vdev_sync;
835
836 if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
837 return;
838
839 __hdd_ipv4_notifier_work_queue(adapter);
840
841 osif_vdev_sync_op_stop(vdev_sync);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842}
843
844/**
845 * __wlan_hdd_ipv4_changed() - IPv4 notifier callback function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800846 * @net_dev: the net_device whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847 *
848 * This is a callback function that is registered with the kernel via
849 * register_inetaddr_notifier() which allows the driver to be
850 * notified when there is an IPv4 address change.
851 *
Dustin Brown39b33ba2019-02-27 10:54:56 -0800852 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800854static void __wlan_hdd_ipv4_changed(struct net_device *net_dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800856 struct in_ifaddr *ifa;
857 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700858 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700859 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860
Dustin Brown39b33ba2019-02-27 10:54:56 -0800861 hdd_enter_dev(net_dev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530862
Dustin Brownf13b8c32017-05-19 17:23:08 -0700863 errno = hdd_validate_adapter(adapter);
Dustin Brown39b33ba2019-02-27 10:54:56 -0800864 if (errno || adapter->dev != net_dev)
865 goto exit;
866
867 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
868 errno = wlan_hdd_validate_context(hdd_ctx);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700869 if (errno)
870 goto exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871
Dustin Brown39b33ba2019-02-27 10:54:56 -0800872 if (adapter->device_mode == QDF_STA_MODE ||
873 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
874 adapter->device_mode == QDF_NDI_MODE) {
Padma, Santhosh Kumar8392fb42017-03-17 12:35:27 +0530875 hdd_debug("invoking sme_dhcp_done_ind");
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800876 sme_dhcp_done_ind(hdd_ctx->mac_handle, adapter->vdev_id);
Abhishek Singhca408032016-09-13 15:26:12 +0530877
Wu Gao66454f12018-09-26 19:55:41 +0800878 if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc)) {
879 hdd_debug("Offload not enabled");
Dustin Brownf13b8c32017-05-19 17:23:08 -0700880 goto exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800881 }
882
Dustin Brownf13b8c32017-05-19 17:23:08 -0700883 ifa = hdd_lookup_ifaddr(adapter);
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800884 if (ifa && ifa->ifa_local)
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700885 schedule_work(&adapter->ipv4_notifier_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 }
Dustin Brownf13b8c32017-05-19 17:23:08 -0700887
888exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700889 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890}
891
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800892int wlan_hdd_ipv4_changed(struct notifier_block *nb,
Dustin Brown39b33ba2019-02-27 10:54:56 -0800893 unsigned long data, void *context)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800895 struct in_ifaddr *ifa = context;
896 struct net_device *net_dev = ifa->ifa_dev->dev;
897 struct osif_vdev_sync *vdev_sync;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898
Dustin Brown39b33ba2019-02-27 10:54:56 -0800899 if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
900 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901
Dustin Brown39b33ba2019-02-27 10:54:56 -0800902 __wlan_hdd_ipv4_changed(net_dev);
903
904 osif_vdev_sync_op_stop(vdev_sync);
905
906 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800907}
908
909/**
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530910 * hdd_get_ipv4_local_interface() - get ipv4 local interafce from iface list
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700911 * @adapter: Adapter context for which ARP offload is to be configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 *
913 * Return:
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530914 * ifa - on successful operation,
915 * NULL - on failure of operation
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 */
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530917static struct in_ifaddr *hdd_get_ipv4_local_interface(
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700918 struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919{
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530920 struct in_ifaddr **ifap = NULL;
921 struct in_ifaddr *ifa = NULL;
922 struct in_device *in_dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700924 in_dev = __in_dev_get_rtnl(adapter->dev);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530925 if (in_dev) {
926 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
927 ifap = &ifa->ifa_next) {
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700928 if (!strcmp(adapter->dev->name, ifa->ifa_label)) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530929 /* if match break */
930 return ifa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800932 }
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530933 }
934 ifa = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800935
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530936 return ifa;
937}
938
Jeff Johnson75b737d2017-08-29 14:24:41 -0700939void hdd_enable_arp_offload(struct hdd_adapter *adapter,
Dustin Brownc1cdb712018-06-11 15:42:17 -0700940 enum pmo_offload_trigger trigger)
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530941{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700942 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown05d81302018-09-11 16:49:22 -0700943 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530944 QDF_STATUS status;
Dustin Brownc1cdb712018-06-11 15:42:17 -0700945 struct pmo_arp_req *arp_req;
946 struct in_ifaddr *ifa;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530947
Dustin Brown491d54b2018-03-14 12:39:11 -0700948 hdd_enter();
Dustin Brownc1cdb712018-06-11 15:42:17 -0700949
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530950 arp_req = qdf_mem_malloc(sizeof(*arp_req));
Min Liu74a1a502018-10-10 19:59:07 +0800951 if (!arp_req)
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530952 goto out;
Jeff Johnson68755312017-02-10 11:46:55 -0800953
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530954 arp_req->psoc = psoc;
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800955 arp_req->vdev_id = adapter->vdev_id;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530956 arp_req->trigger = trigger;
Jeff Johnson68755312017-02-10 11:46:55 -0800957
Sourav Mohapatra60c3b2b2019-11-19 10:27:33 +0530958 status = ucfg_pmo_check_arp_offload(psoc, trigger, adapter->vdev_id);
959 if (QDF_IS_STATUS_ERROR(status)) {
960 hdd_info("ARP offload not required");
961 goto free_req;
962 }
963
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530964 ifa = hdd_get_ipv4_local_interface(adapter);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700965 if (!ifa || !ifa->ifa_local) {
Dustin Brown5e89ef82018-03-14 11:50:23 -0700966 hdd_info("IP Address is not assigned");
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530967 status = QDF_STATUS_NOT_INITIALIZED;
Dustin Brownc1cdb712018-06-11 15:42:17 -0700968 goto free_req;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530969 }
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530970
Dustin Brownc1cdb712018-06-11 15:42:17 -0700971 arp_req->ipv4_addr = (uint32_t)ifa->ifa_local;
972
Wu Gaod7dd6e42018-10-16 17:22:56 +0800973 status = ucfg_pmo_cache_arp_offload_req(arp_req);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700974 if (QDF_IS_STATUS_ERROR(status)) {
Dustin Brown0127a732018-07-19 14:06:34 -0700975 hdd_err("failed to cache arp offload req; status:%d", status);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700976 goto free_req;
977 }
978
Wu Gaod7dd6e42018-10-16 17:22:56 +0800979 status = ucfg_pmo_enable_arp_offload_in_fwr(adapter->vdev, trigger);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700980 if (QDF_IS_STATUS_ERROR(status)) {
Dustin Brown0127a732018-07-19 14:06:34 -0700981 hdd_err("failed arp offload config in fw; status:%d", status);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700982 goto free_req;
983 }
984
985 hdd_wlan_offload_event(PMO_IPV4_ARP_REPLY_OFFLOAD, PMO_OFFLOAD_ENABLE);
986
987free_req:
988 qdf_mem_free(arp_req);
989
990out:
991 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530992}
993
Jeff Johnson75b737d2017-08-29 14:24:41 -0700994void hdd_disable_arp_offload(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530995 enum pmo_offload_trigger trigger)
996{
997 QDF_STATUS status;
Sourav Mohapatra60c3b2b2019-11-19 10:27:33 +0530998 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530999
Dustin Brown491d54b2018-03-14 12:39:11 -07001000 hdd_enter();
Sourav Mohapatra60c3b2b2019-11-19 10:27:33 +05301001
1002 status = ucfg_pmo_check_arp_offload(hdd_ctx->psoc, trigger,
1003 adapter->vdev_id);
1004 if (status != QDF_STATUS_SUCCESS) {
1005 hdd_err("Flushing of ARP offload not required");
1006 goto out;
1007 }
1008
Wu Gaod7dd6e42018-10-16 17:22:56 +08001009 status = ucfg_pmo_flush_arp_offload_req(adapter->vdev);
Mukul Sharma3ba26b82017-01-12 21:59:41 +05301010 if (status != QDF_STATUS_SUCCESS) {
1011 hdd_err("Failed to flush arp Offload");
1012 goto out;
Jeff Johnson68755312017-02-10 11:46:55 -08001013 }
1014
Wu Gaod7dd6e42018-10-16 17:22:56 +08001015 status = ucfg_pmo_disable_arp_offload_in_fwr(adapter->vdev,
Jeff Johnsond6d1f632017-10-06 20:06:10 -07001016 trigger);
Mukul Sharma3ba26b82017-01-12 21:59:41 +05301017 if (status == QDF_STATUS_SUCCESS)
1018 hdd_wlan_offload_event(PMO_IPV4_ARP_REPLY_OFFLOAD,
1019 PMO_OFFLOAD_DISABLE);
1020 else
1021 hdd_info("fail to disable arp offload");
1022out:
Dustin Browne74003f2018-03-14 12:51:58 -07001023 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001024}
1025
Jeff Johnson75b737d2017-08-29 14:24:41 -07001026void hdd_enable_mc_addr_filtering(struct hdd_adapter *adapter,
Dustin Brown0127a732018-07-19 14:06:34 -07001027 enum pmo_offload_trigger trigger)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001028{
Jeff Johnson399c6272017-08-30 10:51:00 -07001029 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301030 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031
Dustin Brown491d54b2018-03-14 12:39:11 -07001032 hdd_enter();
Dustin Brown0127a732018-07-19 14:06:34 -07001033
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301034 if (wlan_hdd_validate_context(hdd_ctx))
1035 goto out;
Ravi Joshi24477b72016-07-19 15:45:09 -07001036
Dustin Brown0127a732018-07-19 14:06:34 -07001037 if (!hdd_adapter_is_connected_sta(adapter))
1038 goto out;
1039
Wu Gaod7dd6e42018-10-16 17:22:56 +08001040 status = ucfg_pmo_enable_mc_addr_filtering_in_fwr(hdd_ctx->psoc,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001041 adapter->vdev_id,
Dustin Brown0127a732018-07-19 14:06:34 -07001042 trigger);
Dustin Brownc1cdb712018-06-11 15:42:17 -07001043 if (QDF_IS_STATUS_ERROR(status))
Dustin Brown0127a732018-07-19 14:06:34 -07001044 hdd_err("failed to enable mc list; status:%d", status);
1045
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301046out:
Dustin Browne74003f2018-03-14 12:51:58 -07001047 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048}
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301049
Jeff Johnson75b737d2017-08-29 14:24:41 -07001050void hdd_disable_mc_addr_filtering(struct hdd_adapter *adapter,
Dustin Brown0127a732018-07-19 14:06:34 -07001051 enum pmo_offload_trigger trigger)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301052{
Jeff Johnson399c6272017-08-30 10:51:00 -07001053 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown0127a732018-07-19 14:06:34 -07001054 QDF_STATUS status;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301055
Dustin Brown491d54b2018-03-14 12:39:11 -07001056 hdd_enter();
Dustin Brown0127a732018-07-19 14:06:34 -07001057
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301058 if (wlan_hdd_validate_context(hdd_ctx))
1059 goto out;
1060
Dustin Brown0127a732018-07-19 14:06:34 -07001061 if (!hdd_adapter_is_connected_sta(adapter))
1062 goto out;
1063
Wu Gaod7dd6e42018-10-16 17:22:56 +08001064 status = ucfg_pmo_disable_mc_addr_filtering_in_fwr(hdd_ctx->psoc,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001065 adapter->vdev_id,
Dustin Brown0127a732018-07-19 14:06:34 -07001066 trigger);
1067 if (QDF_IS_STATUS_ERROR(status))
1068 hdd_err("failed to disable mc list; status:%d", status);
Dustin Brown0f874482018-06-13 14:39:22 -07001069
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301070out:
Dustin Browne74003f2018-03-14 12:51:58 -07001071 hdd_exit();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301072}
1073
1074int hdd_cache_mc_addr_list(struct pmo_mc_addr_list_params *mc_list_config)
1075{
1076 QDF_STATUS status;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301077
Dustin Brown491d54b2018-03-14 12:39:11 -07001078 hdd_enter();
Wu Gaod7dd6e42018-10-16 17:22:56 +08001079 status = ucfg_pmo_cache_mc_addr_list(mc_list_config);
Dustin Browne74003f2018-03-14 12:51:58 -07001080 hdd_exit();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301081
Dustin Brown0f874482018-06-13 14:39:22 -07001082 return qdf_status_to_os_return(status);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301083}
1084
Jeff Johnson75b737d2017-08-29 14:24:41 -07001085void hdd_disable_and_flush_mc_addr_list(struct hdd_adapter *adapter,
Dustin Brown0127a732018-07-19 14:06:34 -07001086 enum pmo_offload_trigger trigger)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301087{
Jeff Johnson399c6272017-08-30 10:51:00 -07001088 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown0127a732018-07-19 14:06:34 -07001089 QDF_STATUS status;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301090
Dustin Brown491d54b2018-03-14 12:39:11 -07001091 hdd_enter();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301092
Dustin Brown0127a732018-07-19 14:06:34 -07001093 if (!hdd_adapter_is_connected_sta(adapter))
1094 goto flush_mc_list;
1095
1096 /* disable mc list first because the mc list is cached in PMO */
Wu Gaod7dd6e42018-10-16 17:22:56 +08001097 status = ucfg_pmo_disable_mc_addr_filtering_in_fwr(hdd_ctx->psoc,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001098 adapter->vdev_id,
Dustin Brown0127a732018-07-19 14:06:34 -07001099 trigger);
1100 if (QDF_IS_STATUS_ERROR(status))
1101 hdd_err("failed to disable mc list; status:%d", status);
1102
1103flush_mc_list:
Wu Gaod7dd6e42018-10-16 17:22:56 +08001104 status = ucfg_pmo_flush_mc_addr_list(hdd_ctx->psoc,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001105 adapter->vdev_id);
Dustin Brown0127a732018-07-19 14:06:34 -07001106 if (QDF_IS_STATUS_ERROR(status))
Bala Venkatesha5c1eb82019-08-26 19:19:49 +05301107 hdd_debug("failed to flush mc list; status:%d", status);
Dustin Brown0f874482018-06-13 14:39:22 -07001108
Dustin Browne74003f2018-03-14 12:51:58 -07001109 hdd_exit();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301110}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111
1112/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001113 * hdd_update_conn_state_mask(): record info needed by wma_suspend_req
1114 * @adapter: adapter to get info from
1115 * @conn_state_mask: mask of connection info
1116 *
1117 * currently only need to send connection info.
1118 */
Jeff Johnsond6d1f632017-10-06 20:06:10 -07001119static void hdd_update_conn_state_mask(struct hdd_adapter *adapter,
1120 uint32_t *conn_state_mask)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001121{
1122
Jeff Johnsone7951512019-02-27 10:02:51 -08001123 eConnectionState conn_state;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07001124 struct hdd_station_ctx *sta_ctx;
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301125
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001126 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301127
Jeff Johnsone7951512019-02-27 10:02:51 -08001128 conn_state = sta_ctx->conn_info.conn_state;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001129
Jeff Johnsone7951512019-02-27 10:02:51 -08001130 if (conn_state == eConnectionState_Associated ||
1131 conn_state == eConnectionState_IbssConnected)
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001132 *conn_state_mask |= (1 << adapter->vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001133}
1134
1135/**
1136 * hdd_suspend_wlan() - Driver suspend function
1137 * @callback: Callback function to invoke when driver is ready to suspend
1138 * @callbackContext: Context to pass back to @callback function
1139 *
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301140 * Return: 0 on success else error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 */
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301142static int
1143hdd_suspend_wlan(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001145 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301146 QDF_STATUS status;
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001147 struct hdd_adapter *adapter = NULL;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001148 uint32_t conn_state_mask = 0;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07001149
Jeff Johnsonc3273322016-07-06 15:28:17 -07001150 hdd_info("WLAN being suspended by OS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001152 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1153 if (!hdd_ctx) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001154 hdd_err("HDD context is Null");
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301155 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 }
1157
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +05301158 if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001159 hdd_info("Recovery in Progress. State: 0x%x Ignore suspend!!!",
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001160 cds_get_driver_state());
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301161 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001162 }
1163
Dustin Brown920397d2017-12-13 16:27:50 -08001164 hdd_for_each_adapter(hdd_ctx, adapter) {
Jeff Johnson48363022019-02-24 16:26:51 -08001165 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown920397d2017-12-13 16:27:50 -08001166 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001167
1168 /* stop all TX queues before suspend */
Dustin Brownc1cdb712018-06-11 15:42:17 -07001169 hdd_debug("Disabling queues for dev mode %s",
Dustin Brown458027c2018-10-19 12:26:27 -07001170 qdf_opmode_str(adapter->device_mode));
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001171 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05301172 WLAN_STOP_ALL_NETIF_QUEUE,
1173 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174
Hanumanth Reddy Pothula3def8942017-10-05 16:19:36 +05301175 if (adapter->device_mode == QDF_STA_MODE)
1176 status = hdd_enable_default_pkt_filters(adapter);
1177
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001178 /* Configure supported OffLoads */
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001179 hdd_enable_host_offloads(adapter, pmo_apps_suspend);
1180 hdd_update_conn_state_mask(adapter, &conn_state_mask);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001181 }
1182
Wu Gaod7dd6e42018-10-16 17:22:56 +08001183 status = ucfg_pmo_psoc_user_space_suspend_req(hdd_ctx->psoc,
1184 QDF_SYSTEM_SUSPEND);
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301185 if (status != QDF_STATUS_SUCCESS)
1186 return -EAGAIN;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001187
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001188 hdd_ctx->hdd_wlan_suspended = true;
Abhishek Singhbaea27d2016-04-27 13:29:30 +05301189 hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_SUSPEND);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001190
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301191 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192}
1193
1194/**
1195 * hdd_resume_wlan() - Driver resume function
1196 *
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301197 * Return: 0 on success else error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001198 */
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301199static int hdd_resume_wlan(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001200{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001201 struct hdd_context *hdd_ctx;
Dustin Brownc1cdb712018-06-11 15:42:17 -07001202 struct hdd_adapter *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301203 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204
Dustin Brown2d228232016-09-22 15:06:19 -07001205 hdd_info("WLAN being resumed by OS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001207 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1208 if (!hdd_ctx) {
Dustin Brown2d228232016-09-22 15:06:19 -07001209 hdd_err("HDD context is Null");
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301210 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211 }
1212
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +05301213 if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001214 hdd_info("Recovery in Progress. State: 0x%x Ignore resume!!!",
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001215 cds_get_driver_state());
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301216 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 }
1218
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001219 hdd_ctx->hdd_wlan_suspended = false;
Abhishek Singhbaea27d2016-04-27 13:29:30 +05301220 hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_RESUME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221
1222 /*loop through all adapters. Concurrency */
Dustin Brown920397d2017-12-13 16:27:50 -08001223 hdd_for_each_adapter(hdd_ctx, adapter) {
Jeff Johnson48363022019-02-24 16:26:51 -08001224 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown920397d2017-12-13 16:27:50 -08001225 continue;
Dustin Brown63500612018-08-07 11:36:09 -07001226
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301227 /* Disable supported OffLoads */
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001228 hdd_disable_host_offloads(adapter, pmo_apps_resume);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229
1230 /* wake the tx queues */
Dustin Brownc1cdb712018-06-11 15:42:17 -07001231 hdd_debug("Enabling queues for dev mode %s",
Dustin Brown458027c2018-10-19 12:26:27 -07001232 qdf_opmode_str(adapter->device_mode));
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001233 wlan_hdd_netif_queue_control(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 WLAN_WAKE_ALL_NETIF_QUEUE,
1235 WLAN_CONTROL_PATH);
1236
Hanumanth Reddy Pothula3def8942017-10-05 16:19:36 +05301237 if (adapter->device_mode == QDF_STA_MODE)
1238 status = hdd_disable_default_pkt_filters(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 }
Dustin Brown920397d2017-12-13 16:27:50 -08001240
Dustin Brown07901ec2018-09-07 11:02:41 -07001241 ucfg_ipa_resume(hdd_ctx->pdev);
Wu Gaod7dd6e42018-10-16 17:22:56 +08001242 status = ucfg_pmo_psoc_user_space_resume_req(hdd_ctx->psoc,
Dustin Brownc1cdb712018-06-11 15:42:17 -07001243 QDF_SYSTEM_SUSPEND);
1244 if (QDF_IS_STATUS_ERROR(status))
1245 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301247 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248}
1249
Komal Seelam78ff65a2016-08-18 15:25:24 +05301250void hdd_svc_fw_shutdown_ind(struct device *dev)
1251{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001252 struct hdd_context *hdd_ctx;
Komal Seelam78ff65a2016-08-18 15:25:24 +05301253
1254 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1255
1256 hdd_ctx ? wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
1257 WLAN_SVC_FW_SHUTDOWN_IND,
1258 NULL, 0) : 0;
1259}
1260
1261/**
Arun Khandavallicc544b32017-01-30 19:52:16 +05301262 * hdd_ssr_restart_sap() - restart sap on SSR
1263 * @hdd_ctx: hdd context
1264 *
1265 * Return: nothing
1266 */
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001267static void hdd_ssr_restart_sap(struct hdd_context *hdd_ctx)
Arun Khandavallicc544b32017-01-30 19:52:16 +05301268{
Jeff Johnson75b737d2017-08-29 14:24:41 -07001269 struct hdd_adapter *adapter;
Arun Khandavallicc544b32017-01-30 19:52:16 +05301270
Dustin Brown491d54b2018-03-14 12:39:11 -07001271 hdd_enter();
Arun Khandavallicc544b32017-01-30 19:52:16 +05301272
Dustin Brown920397d2017-12-13 16:27:50 -08001273 hdd_for_each_adapter(hdd_ctx, adapter) {
1274 if (adapter->device_mode == QDF_SAP_MODE) {
Manikandan Mohan0a0ac952017-02-16 15:49:31 -08001275 if (test_bit(SOFTAP_INIT_DONE, &adapter->event_flags)) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001276 hdd_debug("Restart prev SAP session");
Manikandan Mohan0a0ac952017-02-16 15:49:31 -08001277 wlan_hdd_start_sap(adapter, true);
1278 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301279 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301280 }
1281
Dustin Browne74003f2018-03-14 12:51:58 -07001282 hdd_exit();
Arun Khandavallicc544b32017-01-30 19:52:16 +05301283}
1284
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301285QDF_STATUS hdd_wlan_shutdown(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001287 struct hdd_context *hdd_ctx;
Manikandan Mohan8b4e2012017-03-22 11:15:55 -07001288 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001290 hdd_info("WLAN driver shutting down!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001292 /* Get the HDD context. */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001293 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1294 if (!hdd_ctx) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001295 hdd_err("HDD context is Null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301296 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 }
1298
Rajeev Kumarc27efb62018-08-31 14:21:22 -07001299 hdd_bus_bw_compute_timer_stop(hdd_ctx);
Bala Venkatesh23561582019-09-03 17:45:45 +05301300 hdd_set_connection_in_progress(false);
Dustin Brown05d81302018-09-11 16:49:22 -07001301 policy_mgr_clear_concurrent_session_count(hdd_ctx->psoc);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05301302
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001303 hdd_debug("Invoking packetdump deregistration API");
Rakesh Pillai6a36b0a2019-09-06 16:30:05 +05301304 wlan_deregister_txrx_packetdump(OL_TXRX_PDEV_ID);
jitiphilfb410612018-03-26 22:37:56 +05301305
Rajeev Kumar9f461582018-09-27 18:24:47 -07001306 /* resume wlan threads before adapter reset which does vdev destroy */
1307 if (hdd_ctx->is_scheduler_suspended) {
1308 scheduler_resume();
1309 hdd_ctx->is_scheduler_suspended = false;
1310 hdd_ctx->is_wiphy_suspended = false;
1311 }
1312
Lin Baif5e8cc22018-11-05 10:57:38 +08001313 wlan_hdd_rx_thread_resume(hdd_ctx);
Rajeev Kumar9f461582018-09-27 18:24:47 -07001314
Mohit Khanna7a2116a2019-09-17 15:34:18 -07001315 dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
1316
jitiphilfb410612018-03-26 22:37:56 +05301317 /*
1318 * After SSR, FW clear its txrx stats. In host,
1319 * as adapter is intact so those counts are still
1320 * available. Now if agains Set stats command comes,
1321 * then host will increment its counts start from its
1322 * last saved value, i.e., count before SSR, and FW will
1323 * increment its count from 0. This will finally sends a
1324 * mismatch of packet counts b/w host and FW to framework
1325 * that will create ambiquity. Therfore, Resetting the host
1326 * counts here so that after SSR both FW and host start
1327 * increment their counts from 0.
1328 */
1329 hdd_reset_all_adapters_connectivity_stats(hdd_ctx);
Abhishek Singh0d0568a2018-11-22 15:01:51 +05301330 /*
1331 * Purge all active and pending list to avoid vdev destroy timeout and
1332 * thus avoid peer/vdev refcount leak.
1333 */
1334 sme_purge_pdev_all_ser_cmd_list(hdd_ctx->mac_handle);
jitiphilfb410612018-03-26 22:37:56 +05301335
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001336 hdd_reset_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001337
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05301338 ucfg_ipa_uc_ssr_cleanup(hdd_ctx->pdev);
1339
Poddar, Siddarth1ab0a3d2016-09-29 18:58:45 +05301340 /* Flush cached rx frame queue */
Manikandan Mohan8b4e2012017-03-22 11:15:55 -07001341 if (soc)
1342 cdp_flush_cache_rx_queue(soc);
Poddar, Siddarth1ab0a3d2016-09-29 18:58:45 +05301343
Arun Khandavalli4b55da72016-07-19 19:55:01 +05301344 /* De-register the HDD callbacks */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001345 hdd_deregister_cb(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001347 hdd_wlan_stop_modules(hdd_ctx, false);
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05301348
Dustin Brown86d196b2018-08-02 11:51:49 -07001349 hdd_bus_bandwidth_deinit(hdd_ctx);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001350 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07001351
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001352 hdd_info("WLAN driver shutdown complete");
Yue Ma2be12872017-06-02 13:06:58 -07001353
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301354 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355}
1356
Sen, Devendra154b3c42017-02-13 20:44:15 +05301357#ifdef FEATURE_WLAN_DIAG_SUPPORT
1358/**
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301359 * hdd_wlan_ssr_reinit_event()- send ssr reinit state
1360 *
1361 * This Function send send ssr reinit state diag event
1362 *
1363 * Return: void.
1364 */
Sen, Devendra154b3c42017-02-13 20:44:15 +05301365static void hdd_wlan_ssr_reinit_event(void)
1366{
1367 WLAN_HOST_DIAG_EVENT_DEF(ssr_reinit, struct host_event_wlan_ssr_reinit);
1368 qdf_mem_zero(&ssr_reinit, sizeof(ssr_reinit));
1369 ssr_reinit.status = SSR_SUB_SYSTEM_REINIT;
1370 WLAN_HOST_DIAG_EVENT_REPORT(&ssr_reinit,
1371 EVENT_WLAN_SSR_REINIT_SUBSYSTEM);
1372}
1373#else
1374static inline void hdd_wlan_ssr_reinit_event(void)
1375{
1376
1377}
1378#endif
1379
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380/**
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301381 * hdd_send_default_scan_ies - send default scan ies to fw
1382 *
1383 * This function is used to send default scan ies to fw
1384 * in case of wlan re-init
1385 *
1386 * Return: void
1387 */
1388static void hdd_send_default_scan_ies(struct hdd_context *hdd_ctx)
1389{
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301390 struct hdd_adapter *adapter;
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301391
Dustin Brown920397d2017-12-13 16:27:50 -08001392 hdd_for_each_adapter(hdd_ctx, adapter) {
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301393 if (hdd_is_interface_up(adapter) &&
1394 (adapter->device_mode == QDF_STA_MODE ||
Hanumanth Reddy Pothula53dec122017-12-12 17:08:18 +05301395 adapter->device_mode == QDF_P2P_DEVICE_MODE) &&
1396 adapter->scan_info.default_scan_ies) {
Jeff Johnson2954ded2018-06-13 16:34:49 -07001397 sme_set_default_scan_ie(hdd_ctx->mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001398 adapter->vdev_id,
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301399 adapter->scan_info.default_scan_ies,
1400 adapter->scan_info.default_scan_ies_len);
1401 }
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301402 }
1403}
1404
Arunk Khandavalli987c8d52018-06-21 17:40:31 +05301405/**
1406 * hdd_is_interface_down_during_ssr - Check if the interface went down during
1407 * SSR
1408 * @hdd_ctx: HDD context
1409 *
1410 * Check if any of the interface went down while the device is recovering.
1411 * If the interface went down close the session.
1412 */
1413static void hdd_is_interface_down_during_ssr(struct hdd_context *hdd_ctx)
1414{
1415 struct hdd_adapter *adapter = NULL, *pnext = NULL;
1416 QDF_STATUS status;
1417
1418 hdd_enter();
1419
1420 status = hdd_get_front_adapter(hdd_ctx, &adapter);
1421 while (adapter && status == QDF_STATUS_SUCCESS) {
1422 if (test_bit(DOWN_DURING_SSR, &adapter->event_flags)) {
1423 clear_bit(DOWN_DURING_SSR, &adapter->event_flags);
1424 hdd_stop_adapter(hdd_ctx, adapter);
1425 hdd_deinit_adapter(hdd_ctx, adapter, true);
1426 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1427 }
1428 status = hdd_get_next_adapter(hdd_ctx, adapter, &pnext);
1429 adapter = pnext;
1430 }
1431
1432 hdd_exit();
1433}
1434
Sourav Mohapatra9036f652019-04-02 15:02:59 +05301435/**
1436 * hdd_restore_sar_config - Restore the saved SAR config after SSR
1437 * @hdd_ctx: HDD context
1438 *
1439 * Restore the SAR config that was lost during SSR.
1440 *
1441 * Return: None
1442 */
1443static void hdd_restore_sar_config(struct hdd_context *hdd_ctx)
1444{
1445 QDF_STATUS status;
1446
1447 if (!hdd_ctx->sar_cmd_params)
1448 return;
1449
1450 status = sme_set_sar_power_limits(hdd_ctx->mac_handle,
1451 hdd_ctx->sar_cmd_params);
1452 if (QDF_IS_STATUS_ERROR(status))
1453 hdd_err("Unable to configured SAR after SSR");
1454}
1455
Arun Khandavallifae92942016-08-01 13:31:08 +05301456QDF_STATUS hdd_wlan_re_init(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001458 struct hdd_context *hdd_ctx = NULL;
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001459 struct hdd_adapter *adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05301460 int ret;
Mukul Sharmaf7d62e12016-09-03 15:16:22 +05301461 bool bug_on_reinit_failure = CFG_BUG_ON_REINIT_FAILURE_DEFAULT;
Bala Venkatesh2fde2c62018-09-11 20:33:24 +05301462 bool value;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001463
1464 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
1465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 /* Get the HDD context */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001467 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1468 if (!hdd_ctx) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001469 hdd_err("HDD context is Null");
Sourav Mohapatrab1260132018-08-21 14:42:55 +05301470 goto err_ctx_null;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001471 }
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001472 bug_on_reinit_failure = hdd_ctx->config->bug_on_reinit_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001473
Sourav Mohapatra92ea8d62018-02-05 10:03:10 +05301474 adapter = hdd_get_first_valid_adapter(hdd_ctx);
1475 if (!adapter)
1476 hdd_err("Failed to get adapter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477
Nirav Shahd21a2e32018-04-20 16:34:43 +05301478 hdd_dp_trace_init(hdd_ctx->config);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001479 hdd_bus_bandwidth_init(hdd_ctx);
Prashanth Bhattaab004382016-10-11 16:08:11 -07001480
Dustin Browne7e71d32018-05-11 16:00:08 -07001481 ret = hdd_wlan_start_modules(hdd_ctx, true);
Arun Khandavallifae92942016-08-01 13:31:08 +05301482 if (ret) {
1483 hdd_err("Failed to start wlan after error");
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +05301484 goto err_re_init;
Arun Khandavallifae92942016-08-01 13:31:08 +05301485 }
1486
Ryan Hsuaadba072018-04-20 13:01:53 -07001487 hdd_update_hw_sw_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001489 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Wu Gao36717432016-11-21 15:09:48 +08001490 WLAN_SVC_FW_CRASHED_IND, NULL, 0);
1491
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492 /* Restart all adapters */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001493 hdd_start_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494
Paul Zhangcb573e02018-11-06 10:37:16 +08001495 hdd_init_scan_reject_params(hdd_ctx);
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05301496
Selvaraj, Sridhar1c487562017-04-19 14:29:07 +05301497 hdd_set_roaming_in_progress(false);
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001498 complete(&adapter->roaming_comp_var);
Jeff Johnson59b19312017-11-02 21:14:33 -07001499 hdd_ctx->bt_coex_mode_set = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501 /* Allow the phone to go to sleep */
1502 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301503 /* set chip power save failure detected callback */
Jeff Johnson2954ded2018-06-13 16:34:49 -07001504 sme_set_chip_pwr_save_fail_cb(hdd_ctx->mac_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301505 hdd_chip_pwr_save_fail_detected_cb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506
Sourav Mohapatra9036f652019-04-02 15:02:59 +05301507 hdd_restore_sar_config(hdd_ctx);
1508
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301509 hdd_send_default_scan_ies(hdd_ctx);
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001510 hdd_info("WLAN host driver reinitiation completed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511
Dustin Brown05d81302018-09-11 16:49:22 -07001512 ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +05301513 if (value)
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001514 hdd_ssr_restart_sap(hdd_ctx);
Arunk Khandavalli987c8d52018-06-21 17:40:31 +05301515 hdd_is_interface_down_during_ssr(hdd_ctx);
Sen, Devendra154b3c42017-02-13 20:44:15 +05301516 hdd_wlan_ssr_reinit_event();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301517 return QDF_STATUS_SUCCESS;
Sourav Mohapatrab1260132018-08-21 14:42:55 +05301518
1519err_re_init:
1520 hdd_bus_bandwidth_deinit(hdd_ctx);
1521 qdf_dp_trace_deinit();
1522
1523err_ctx_null:
1524 /* Allow the phone to go to sleep */
1525 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
1526 if (bug_on_reinit_failure)
1527 QDF_BUG(0);
1528 return -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001529}
1530
Jeff Johnson75b737d2017-08-29 14:24:41 -07001531int wlan_hdd_set_powersave(struct hdd_adapter *adapter,
Dustin Brownf660fb42016-09-09 12:04:00 -07001532 bool allow_power_save, uint32_t timeout)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533{
Jeff Johnson2954ded2018-06-13 16:34:49 -07001534 mac_handle_t mac_handle;
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001535 struct hdd_context *hdd_ctx;
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301536 QDF_STATUS status = QDF_STATUS_SUCCESS;
Pragaspathi Thilagaraj784c4922018-12-02 22:47:29 +05301537 bool is_bmps_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538
Jeff Johnsond36fa332019-03-18 13:42:25 -07001539 if (!adapter) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001540 hdd_err("Adapter NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 return -ENODEV;
1542 }
1543
1544 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1545 if (!hdd_ctx) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07001546 hdd_err("hdd context is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 return -EINVAL;
1548 }
1549
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001550 hdd_debug("Allow power save: %d", allow_power_save);
Jeff Johnson2954ded2018-06-13 16:34:49 -07001551 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001552
Dustin Brown84411b02017-07-21 16:44:44 -07001553 /*
1554 * This is a workaround for defective AP's that send a disassoc
1555 * immediately after WPS connection completes. Defer powersave by a
1556 * small amount if the affected AP is detected.
1557 */
1558 if (allow_power_save &&
1559 adapter->device_mode == QDF_STA_MODE &&
Jeff Johnsonb9424862017-10-30 08:49:35 -07001560 !adapter->session.station.ap_supports_immediate_power_save) {
Dustin Brown84411b02017-07-21 16:44:44 -07001561 timeout = AUTO_PS_DEFER_TIMEOUT_MS;
1562 hdd_debug("Defer power-save due to AP spec non-conformance");
Krunal Soni364e0872017-05-10 21:24:34 -07001563 }
1564
Dustin Brownf660fb42016-09-09 12:04:00 -07001565 if (allow_power_save) {
1566 if (QDF_STA_MODE == adapter->device_mode ||
1567 QDF_P2P_CLIENT_MODE == adapter->device_mode) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001568 hdd_debug("Disabling Auto Power save timer");
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301569 status = sme_ps_disable_auto_ps_timer(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001570 adapter->vdev_id);
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301571 if (status != QDF_STATUS_SUCCESS)
1572 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 }
Dustin Brownf660fb42016-09-09 12:04:00 -07001574
Pragaspathi Thilagaraj784c4922018-12-02 22:47:29 +05301575 ucfg_mlme_is_bmps_enabled(hdd_ctx->psoc, &is_bmps_enabled);
1576 if (is_bmps_enabled) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001577 hdd_debug("Wlan driver Entering Power save");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001578
1579 /*
1580 * Enter Power Save command received from GUI
1581 * this means DHCP is completed
1582 */
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301583 if (timeout) {
1584 status = sme_ps_enable_auto_ps_timer(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001585 adapter->vdev_id,
Yeshwanth Sriram Guntukaae03c432017-11-12 13:31:02 +05301586 timeout);
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301587 if (status != QDF_STATUS_SUCCESS)
1588 goto end;
1589 } else {
1590 status = sme_ps_enable_disable(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001591 adapter->vdev_id,
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301592 SME_PS_ENABLE);
1593 if (status != QDF_STATUS_SUCCESS)
1594 goto end;
1595 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 } else {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001597 hdd_debug("Power Save is not enabled in the cfg");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598 }
Dustin Brownf660fb42016-09-09 12:04:00 -07001599 } else {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001600 hdd_debug("Wlan driver Entering Full Power");
Dustin Brownf660fb42016-09-09 12:04:00 -07001601
1602 /*
1603 * Enter Full power command received from GUI
1604 * this means we are disconnected
1605 */
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301606 status = sme_ps_disable_auto_ps_timer(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001607 adapter->vdev_id);
Krunal Soniee6309f2018-11-27 13:20:53 -08001608
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301609 if (status != QDF_STATUS_SUCCESS)
1610 goto end;
Krunal Soniee6309f2018-11-27 13:20:53 -08001611
Pragaspathi Thilagaraj784c4922018-12-02 22:47:29 +05301612 ucfg_mlme_is_bmps_enabled(hdd_ctx->psoc, &is_bmps_enabled);
1613 if (is_bmps_enabled)
Krunal Soniee6309f2018-11-27 13:20:53 -08001614 status = sme_ps_enable_disable(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001615 adapter->vdev_id,
Krunal Soniee6309f2018-11-27 13:20:53 -08001616 SME_PS_DISABLE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001617 }
Dustin Brownf660fb42016-09-09 12:04:00 -07001618
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301619end:
1620 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001621}
1622
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001623static void wlan_hdd_print_suspend_fail_stats(struct hdd_context *hdd_ctx)
Dustin Brown105d7902016-10-03 16:27:59 -07001624{
Dustin Brownd9322482017-01-09 12:46:03 -08001625 struct suspend_resume_stats *stats = &hdd_ctx->suspend_resume_stats;
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301626
Dustin Brown105d7902016-10-03 16:27:59 -07001627 hdd_err("ipa:%d, radar:%d, roam:%d, scan:%d, initial_wakeup:%d",
Dustin Brownd9322482017-01-09 12:46:03 -08001628 stats->suspend_fail[SUSPEND_FAIL_IPA],
1629 stats->suspend_fail[SUSPEND_FAIL_RADAR],
1630 stats->suspend_fail[SUSPEND_FAIL_ROAM],
1631 stats->suspend_fail[SUSPEND_FAIL_SCAN],
1632 stats->suspend_fail[SUSPEND_FAIL_INITIAL_WAKEUP]);
Dustin Brown105d7902016-10-03 16:27:59 -07001633}
1634
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001635void wlan_hdd_inc_suspend_stats(struct hdd_context *hdd_ctx,
Dustin Brown105d7902016-10-03 16:27:59 -07001636 enum suspend_fail_reason reason)
1637{
1638 wlan_hdd_print_suspend_fail_stats(hdd_ctx);
Dustin Brownd9322482017-01-09 12:46:03 -08001639 hdd_ctx->suspend_resume_stats.suspend_fail[reason]++;
Dustin Brown105d7902016-10-03 16:27:59 -07001640 wlan_hdd_print_suspend_fail_stats(hdd_ctx);
1641}
1642
Dustin Brown5fbb1052017-08-11 17:25:51 -07001643#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1644static inline void
1645hdd_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
1646{
1647 cfg80211_sched_scan_results(wiphy);
1648}
1649#else
1650static inline void
1651hdd_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
1652{
1653 cfg80211_sched_scan_results(wiphy, reqid);
1654}
1655#endif
1656
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001657/**
1658 * __wlan_hdd_cfg80211_resume_wlan() - cfg80211 resume callback
1659 * @wiphy: Pointer to wiphy
1660 *
1661 * This API is called when cfg80211 driver resumes driver updates
1662 * latest sched_scan scan result(if any) to cfg80211 database
1663 *
1664 * Return: integer status
1665 */
1666static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
1667{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001668 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301669 QDF_STATUS status = QDF_STATUS_SUCCESS;
Dustin Brownd9322482017-01-09 12:46:03 -08001670 int exit_code;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671
Dustin Brown491d54b2018-03-14 12:39:11 -07001672 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673
Dustin Brownd9322482017-01-09 12:46:03 -08001674 if (cds_is_driver_recovering()) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001675 hdd_debug("Driver is recovering; Skipping resume");
Dustin Brownd9322482017-01-09 12:46:03 -08001676 exit_code = 0;
1677 goto exit_with_code;
1678 }
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -07001679
Jinwei Chen763f9d72019-08-07 10:45:33 +08001680 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
1681 QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
1682 hdd_err("Command not allowed in mode %d",
1683 hdd_get_conparam());
Dustin Brownd9322482017-01-09 12:46:03 -08001684 exit_code = -EINVAL;
1685 goto exit_with_code;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001686 }
1687
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001688 exit_code = wlan_hdd_validate_context(hdd_ctx);
Dustin Brownd9322482017-01-09 12:46:03 -08001689 if (exit_code) {
1690 hdd_err("Invalid HDD context");
1691 goto exit_with_code;
1692 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301693
Rajeev Kumar83592e02019-05-06 14:33:22 -07001694 if (hdd_ctx->config->is_wow_disabled) {
1695 hdd_err("wow is disabled");
1696 return -EINVAL;
1697 }
1698
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001699 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001700 hdd_debug("Driver is not enabled; Skipping resume");
Dustin Brownd9322482017-01-09 12:46:03 -08001701 exit_code = 0;
1702 goto exit_with_code;
Arun Khandavallifae92942016-08-01 13:31:08 +05301703 }
Dustin Brownd9322482017-01-09 12:46:03 -08001704
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001705 pld_request_bus_bandwidth(hdd_ctx->parent_dev, PLD_BUS_WIDTH_MEDIUM);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001706
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301707 status = hdd_resume_wlan();
1708 if (status != QDF_STATUS_SUCCESS) {
1709 exit_code = 0;
1710 goto exit_with_code;
1711 }
Rajeev Kumareada0d02016-12-08 17:44:17 -08001712 /* Resume control path scheduler */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001713 if (hdd_ctx->is_scheduler_suspended) {
Rajeev Kumar0b732952016-12-08 17:51:39 -08001714 scheduler_resume();
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001715 hdd_ctx->is_scheduler_suspended = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 }
Mohit Khanna70322002018-05-15 19:21:32 -07001717
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 /* Resume tlshim Rx thread */
Lin Baif5e8cc22018-11-05 10:57:38 +08001719 if (hdd_ctx->enable_rxthread)
1720 wlan_hdd_rx_thread_resume(hdd_ctx);
Mohit Khanna70322002018-05-15 19:21:32 -07001721
1722 if (hdd_ctx->enable_dp_rx_threads)
1723 dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
1724
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05301725 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
1726 TRACE_CODE_HDD_CFG80211_RESUME_WLAN,
1727 NO_SESSION, hdd_ctx->is_wiphy_suspended);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728
Jeff Johnson214671b2017-10-30 19:45:23 -07001729 hdd_ctx->is_wiphy_suspended = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001731 hdd_ctx->suspend_resume_stats.resumes++;
Dustin Brownd9322482017-01-09 12:46:03 -08001732 exit_code = 0;
1733
1734exit_with_code:
Dustin Browne74003f2018-03-14 12:51:58 -07001735 hdd_exit();
Dustin Brownd9322482017-01-09 12:46:03 -08001736 return exit_code;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737}
1738
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001739static int _wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
1740{
Alan Chen91525f32019-08-21 15:57:08 -07001741 void *hif_ctx;
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001742 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001743 int errno;
1744
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001745 errno = wlan_hdd_validate_context(hdd_ctx);
Alan Chen91525f32019-08-21 15:57:08 -07001746 if (errno)
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001747 return errno;
1748
1749 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1750 hdd_debug("Driver Modules not Enabled ");
1751 return 0;
1752 }
1753
Alan Chen91525f32019-08-21 15:57:08 -07001754 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001755 errno = __wlan_hdd_cfg80211_resume_wlan(wiphy);
1756 hif_pm_runtime_put(hif_ctx);
1757
1758 return errno;
1759}
1760
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001761int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
1762{
Dustin Brown363b4792019-02-05 16:11:55 -08001763 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001764 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05301765
Dustin Brown363b4792019-02-05 16:11:55 -08001766 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001767 if (errno)
1768 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001769
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001770 errno = _wlan_hdd_cfg80211_resume_wlan(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771
Dustin Brown363b4792019-02-05 16:11:55 -08001772 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001773
1774 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775}
1776
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001777static void hdd_suspend_cb(void)
1778{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001779 struct hdd_context *hdd_ctx;
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001780
1781 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1782 if (!hdd_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001783 hdd_err("HDD context is NULL");
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001784 return;
1785 }
1786
1787 complete(&hdd_ctx->mc_sus_event_var);
1788}
1789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001790/**
1791 * __wlan_hdd_cfg80211_suspend_wlan() - cfg80211 suspend callback
1792 * @wiphy: Pointer to wiphy
1793 * @wow: Pointer to wow
1794 *
1795 * This API is called when cfg80211 driver suspends
1796 *
1797 * Return: integer status
1798 */
1799static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
1800 struct cfg80211_wowlan *wow)
1801{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001802 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001803 struct hdd_adapter *adapter;
Jeff Johnson2954ded2018-06-13 16:34:49 -07001804 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805 int rc;
1806
Dustin Brown491d54b2018-03-14 12:39:11 -07001807 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808
Jinwei Chen763f9d72019-08-07 10:45:33 +08001809 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
1810 QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
1811 hdd_err("Command not allowed in mode %d",
1812 hdd_get_conparam());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001813 return -EINVAL;
1814 }
1815
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001816 rc = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301817 if (0 != rc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 return rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819
Rajeev Kumar83592e02019-05-06 14:33:22 -07001820 if (hdd_ctx->config->is_wow_disabled) {
Rajeev Kumar8ddafdf2019-10-04 13:36:16 -07001821 hdd_info_rl("wow is disabled");
Rajeev Kumar83592e02019-05-06 14:33:22 -07001822 return -EINVAL;
1823 }
Jianmin Zhu16b94b12018-08-01 09:24:52 +08001824
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001825 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001826 hdd_debug("Driver Modules not Enabled ");
Arun Khandavallifae92942016-08-01 13:31:08 +05301827 return 0;
1828 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301829
Jeff Johnson2954ded2018-06-13 16:34:49 -07001830 mac_handle = hdd_ctx->mac_handle;
1831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001832 /* If RADAR detection is in progress (HDD), prevent suspend. The flag
1833 * "dfs_cac_block_tx" is set to true when RADAR is found and stay true
1834 * until CAC is done for a SoftAP which is in started state.
1835 */
Dustin Brown920397d2017-12-13 16:27:50 -08001836 hdd_for_each_adapter(hdd_ctx, adapter) {
Jeff Johnson48363022019-02-24 16:26:51 -08001837 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown920397d2017-12-13 16:27:50 -08001838 continue;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05301839
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001840 if (QDF_SAP_MODE == adapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001841 if (BSS_START ==
Jeff Johnson0f9f87b2017-10-28 09:21:06 -07001842 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter)->bss_state &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 true ==
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001844 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001845 dfs_cac_block_tx) {
Dustin Brown2d228232016-09-22 15:06:19 -07001846 hdd_err("RADAR detection in progress, do not allow suspend");
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001847 wlan_hdd_inc_suspend_stats(hdd_ctx,
Dustin Brown105d7902016-10-03 16:27:59 -07001848 SUSPEND_FAIL_RADAR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001849 return -EAGAIN;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +05301850 } else if (!ucfg_pmo_get_enable_sap_suspend(
1851 hdd_ctx->psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001852 /* return -EOPNOTSUPP if SAP does not support
1853 * suspend
1854 */
Jeff Johnsonc3273322016-07-06 15:28:17 -07001855 hdd_err("SAP does not support suspend!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 return -EOPNOTSUPP;
1857 }
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001858 } else if (QDF_P2P_GO_MODE == adapter->device_mode) {
Rajeev Kumarafccd9a2019-05-02 12:55:14 -07001859 if (!ucfg_pmo_get_enable_sap_suspend(
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +05301860 hdd_ctx->psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 /* return -EOPNOTSUPP if GO does not support
1862 * suspend
1863 */
Jeff Johnsonc3273322016-07-06 15:28:17 -07001864 hdd_err("GO does not support suspend!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865 return -EOPNOTSUPP;
1866 }
1867 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 }
Wu Gao4a1ec8c2018-07-23 19:18:40 +08001869 /* p2p cleanup task based on scheduler */
Dustin Brown05d81302018-09-11 16:49:22 -07001870 ucfg_p2p_cleanup_tx_by_psoc(hdd_ctx->psoc);
1871 ucfg_p2p_cleanup_roc_by_psoc(hdd_ctx->psoc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001872
gaurank kathpaliae5724cc2019-08-21 16:32:25 +05301873 if (hdd_is_connection_in_progress(NULL, NULL)) {
1874 hdd_err_rl("Connection is in progress, rejecting suspend");
1875 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876 }
1877
gaurank kathpaliae5724cc2019-08-21 16:32:25 +05301878 /* abort ongoing scan and flush any pending powersave timers */
Dustin Brown6619bc22018-07-18 15:04:33 -07001879 hdd_for_each_adapter(hdd_ctx, adapter) {
gaurank kathpaliae5724cc2019-08-21 16:32:25 +05301880 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
1881 adapter->vdev_id, INVALID_SCAN_ID, false);
Jeff Johnson48363022019-02-24 16:26:51 -08001882 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown6619bc22018-07-18 15:04:33 -07001883 continue;
1884
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001885 sme_ps_timer_flush_sync(mac_handle, adapter->vdev_id);
Dustin Brown6619bc22018-07-18 15:04:33 -07001886 }
Dustin Brown84411b02017-07-21 16:44:44 -07001887
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 /*
1889 * Suspend IPA early before proceeding to suspend other entities like
1890 * firmware to avoid any race conditions.
1891 */
Dustin Brown07901ec2018-09-07 11:02:41 -07001892 if (ucfg_ipa_suspend(hdd_ctx->pdev)) {
Dustin Brown2d228232016-09-22 15:06:19 -07001893 hdd_err("IPA not ready to suspend!");
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001894 wlan_hdd_inc_suspend_stats(hdd_ctx, SUSPEND_FAIL_IPA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 return -EAGAIN;
1896 }
1897
Rajeev Kumareada0d02016-12-08 17:44:17 -08001898 /* Suspend control path scheduler */
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001899 scheduler_register_hdd_suspend_callback(hdd_suspend_cb);
Manjeet Singh1a376ce2016-10-06 19:31:10 +05301900 scheduler_set_event_mask(MC_SUSPEND_EVENT);
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001901 scheduler_wake_up_controller_thread();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902
Rajeev Kumareada0d02016-12-08 17:44:17 -08001903 /* Wait for suspend confirmation from scheduler */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001904 rc = wait_for_completion_timeout(&hdd_ctx->mc_sus_event_var,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 msecs_to_jiffies(WLAN_WAIT_TIME_MCTHREAD_SUSPEND));
1906 if (!rc) {
Manjeet Singh1a376ce2016-10-06 19:31:10 +05301907 scheduler_clear_event_mask(MC_SUSPEND_EVENT);
Jeff Johnsonc3273322016-07-06 15:28:17 -07001908 hdd_err("Failed to stop mc thread");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 goto resume_tx;
1910 }
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001911 hdd_ctx->is_scheduler_suspended = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912
Mohit Khanna70322002018-05-15 19:21:32 -07001913 if (hdd_ctx->enable_rxthread) {
Lin Baif5e8cc22018-11-05 10:57:38 +08001914 if (wlan_hdd_rx_thread_suspend(hdd_ctx))
Alok Kumar800c8462018-10-10 18:42:16 +05301915 goto resume_ol_rx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 }
Mohit Khanna70322002018-05-15 19:21:32 -07001917
1918 if (hdd_ctx->enable_dp_rx_threads)
1919 dp_txrx_suspend(cds_get_context(QDF_MODULE_ID_SOC));
1920
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05301921 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
1922 TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN,
1923 NO_SESSION, hdd_ctx->is_wiphy_suspended);
1924
Alok Kumar62bf7382018-10-08 16:53:39 +05301925 if (hdd_suspend_wlan() < 0) {
1926 hdd_err("Failed to suspend WLAN");
Alok Kumar800c8462018-10-10 18:42:16 +05301927 goto resume_dp_thread;
Alok Kumar62bf7382018-10-08 16:53:39 +05301928 }
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301929
Jeff Johnson214671b2017-10-30 19:45:23 -07001930 hdd_ctx->is_wiphy_suspended = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001932 pld_request_bus_bandwidth(hdd_ctx->parent_dev, PLD_BUS_WIDTH_NONE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933
Dustin Browne74003f2018-03-14 12:51:58 -07001934 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935 return 0;
1936
Alok Kumar800c8462018-10-10 18:42:16 +05301937resume_dp_thread:
1938 if (hdd_ctx->enable_dp_rx_threads)
1939 dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
1940
1941resume_ol_rx:
Alok Kumar62bf7382018-10-08 16:53:39 +05301942 /* Resume tlshim Rx thread */
Lin Baif5e8cc22018-11-05 10:57:38 +08001943 wlan_hdd_rx_thread_resume(hdd_ctx);
Rajeev Kumar0b732952016-12-08 17:51:39 -08001944 scheduler_resume();
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001945 hdd_ctx->is_scheduler_suspended = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946resume_tx:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 hdd_resume_wlan();
1948 return -ETIME;
1949
1950}
1951
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001952static int _wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
1953 struct cfg80211_wowlan *wow)
1954{
Alan Chen91525f32019-08-21 15:57:08 -07001955 void *hif_ctx;
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001956 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001957 int errno;
1958
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001959 errno = wlan_hdd_validate_context(hdd_ctx);
Alan Chen91525f32019-08-21 15:57:08 -07001960 if (errno)
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001961 return errno;
1962
1963 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1964 hdd_debug("Driver Modules not Enabled ");
1965 return 0;
1966 }
1967
Alan Chen91525f32019-08-21 15:57:08 -07001968 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001969 errno = hif_pm_runtime_get_sync(hif_ctx);
1970 if (errno)
1971 return errno;
1972
1973 errno = __wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
1974 if (errno) {
1975 hif_pm_runtime_put(hif_ctx);
1976 return errno;
1977 }
1978
1979 return errno;
1980}
1981
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
1983 struct cfg80211_wowlan *wow)
1984{
Dustin Brown363b4792019-02-05 16:11:55 -08001985 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001986 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05301987
Dustin Brown363b4792019-02-05 16:11:55 -08001988 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001989 if (errno)
1990 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001992 errno = _wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993
Dustin Brown363b4792019-02-05 16:11:55 -08001994 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001995
1996 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997}
1998
1999/**
Komal Seelama89be8d2016-09-29 11:09:26 +05302000 * hdd_stop_dhcp_ind() - API to stop DHCP sequence
2001 * @adapter: Adapter on which DHCP needs to be stopped
2002 *
2003 * Release the wakelock held for DHCP process and allow
2004 * the runtime pm to continue
2005 *
2006 * Return: None
2007 */
Jeff Johnson75b737d2017-08-29 14:24:41 -07002008static void hdd_stop_dhcp_ind(struct hdd_adapter *adapter)
Komal Seelama89be8d2016-09-29 11:09:26 +05302009{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07002010 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302011
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08002012 hdd_debug("DHCP stop indicated through power save");
Jeff Johnson2954ded2018-06-13 16:34:49 -07002013 sme_dhcp_stop_ind(hdd_ctx->mac_handle, adapter->device_mode,
Jeff Johnson1e851a12017-10-28 14:36:12 -07002014 adapter->mac_addr.bytes,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002015 adapter->vdev_id);
Komal Seelama89be8d2016-09-29 11:09:26 +05302016 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DHCP);
Jingxiang Geb49aa302018-01-17 20:54:15 +08002017 qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.connect);
Komal Seelama89be8d2016-09-29 11:09:26 +05302018}
2019
2020/**
2021 * hdd_start_dhcp_ind() - API to start DHCP sequence
2022 * @adapter: Adapter on which DHCP needs to be stopped
2023 *
2024 * Prevent APPS suspend and the runtime suspend during
2025 * DHCP sequence
2026 *
2027 * Return: None
2028 */
Jeff Johnson75b737d2017-08-29 14:24:41 -07002029static void hdd_start_dhcp_ind(struct hdd_adapter *adapter)
Komal Seelama89be8d2016-09-29 11:09:26 +05302030{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07002031 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05302032
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002033 hdd_debug("DHCP start indicated through power save");
Jingxiang Geb49aa302018-01-17 20:54:15 +08002034 qdf_runtime_pm_prevent_suspend(&hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -07002035 hdd_prevent_suspend_timeout(HDD_WAKELOCK_TIMEOUT_CONNECT,
2036 WIFI_POWER_EVENT_WAKELOCK_DHCP);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002037 sme_dhcp_start_ind(hdd_ctx->mac_handle, adapter->device_mode,
Jeff Johnson1e851a12017-10-28 14:36:12 -07002038 adapter->mac_addr.bytes,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002039 adapter->vdev_id);
Komal Seelama89be8d2016-09-29 11:09:26 +05302040}
2041
2042/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002043 * __wlan_hdd_cfg80211_set_power_mgmt() - set cfg80211 power management config
2044 * @wiphy: Pointer to wiphy
2045 * @dev: Pointer to network device
Dustin Brownf660fb42016-09-09 12:04:00 -07002046 * @allow_power_save: is wlan allowed to go into power save mode
2047 * @timeout: Timeout value in ms
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048 *
2049 * Return: 0 for success, non-zero for failure
2050 */
2051static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Dustin Brownf660fb42016-09-09 12:04:00 -07002052 struct net_device *dev,
2053 bool allow_power_save,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054 int timeout)
2055{
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002056 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002057 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058 int status;
2059
Dustin Brown491d54b2018-03-14 12:39:11 -07002060 hdd_enter();
Dustin Brownecfce632016-09-13 10:41:45 -07002061
Dustin Brownf660fb42016-09-09 12:04:00 -07002062 if (timeout < 0) {
Yeshwanth Sriram Guntukaae03c432017-11-12 13:31:02 +05302063 hdd_debug("User space timeout: %d; Enter full power or power save",
2064 timeout);
2065 timeout = 0;
Dustin Brownf660fb42016-09-09 12:04:00 -07002066 }
2067
Anurag Chouhan6d760662016-02-20 16:05:43 +05302068 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07002069 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 return -EINVAL;
2071 }
2072
Jeff Johnson48363022019-02-24 16:26:51 -08002073 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05302074 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05302075
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05302076 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2077 TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002078 adapter->vdev_id, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002080 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002081 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302083 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002086 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002087 hdd_debug("Driver Module not enabled return success");
Arun Khandavalli99286452016-08-22 12:13:41 +05302088 return 0;
2089 }
Arun Khandavalli99286452016-08-22 12:13:41 +05302090
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002091 status = wlan_hdd_set_powersave(adapter, allow_power_save, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002093 allow_power_save ? hdd_stop_dhcp_ind(adapter) :
2094 hdd_start_dhcp_ind(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095
Dustin Browne74003f2018-03-14 12:51:58 -07002096 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002097 return status;
2098}
2099
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Dustin Brownf660fb42016-09-09 12:04:00 -07002101 struct net_device *dev,
2102 bool allow_power_save,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002103 int timeout)
2104{
Dustin Brown1d31b082018-11-22 14:41:20 +05302105 int errno;
2106 struct osif_vdev_sync *vdev_sync;
2107
2108 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
2109 if (errno)
2110 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111
Dustin Brown1d31b082018-11-22 14:41:20 +05302112 errno = __wlan_hdd_cfg80211_set_power_mgmt(wiphy, dev, allow_power_save,
2113 timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114
Dustin Brown1d31b082018-11-22 14:41:20 +05302115 osif_vdev_sync_op_stop(vdev_sync);
2116
2117 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002118}
2119
2120/**
2121 * __wlan_hdd_cfg80211_set_txpower() - set TX power
2122 * @wiphy: Pointer to wiphy
2123 * @wdev: Pointer to network device
2124 * @type: TX power setting type
Jeff Johnson9de31c02018-10-10 11:18:43 -07002125 * @mbm: TX power in mBm
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002126 *
2127 * Return: 0 for success, non-zero for failure
2128 */
2129static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131 enum nl80211_tx_power_setting type,
Jeff Johnson9de31c02018-10-10 11:18:43 -07002132 int mbm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002133{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002134 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002135 mac_handle_t mac_handle;
hangtian8215fde2019-07-10 12:27:19 +08002136 struct hdd_adapter *adapter;
Dustin Brownce5b3d32018-01-17 15:07:38 -08002137 struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
hangtian821d12d2019-06-11 11:53:50 +08002138 struct qdf_mac_addr selfmac;
Jeff Johnson2954ded2018-06-13 16:34:49 -07002139 QDF_STATUS status;
2140 int errno;
Jeff Johnson9de31c02018-10-10 11:18:43 -07002141 int dbm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142
Dustin Brown491d54b2018-03-14 12:39:11 -07002143 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144
hangtian8215fde2019-07-10 12:27:19 +08002145 if (!wdev) {
2146 hdd_err("wdev is null, set tx power failed");
2147 return -EIO;
2148 }
2149
2150 adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
2151
Anurag Chouhan6d760662016-02-20 16:05:43 +05302152 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07002153 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002154 return -EINVAL;
2155 }
2156
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05302157 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2158 TRACE_CODE_HDD_CFG80211_SET_TXPOWER,
2159 NO_SESSION, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160
Jeff Johnson2954ded2018-06-13 16:34:49 -07002161 errno = wlan_hdd_validate_context(hdd_ctx);
2162 if (errno)
2163 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002164
hangtian821d12d2019-06-11 11:53:50 +08002165 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
2166 return -EINVAL;
2167
2168 if (adapter->device_mode == QDF_SAP_MODE ||
2169 adapter->device_mode == QDF_P2P_GO_MODE) {
2170 qdf_copy_macaddr(&bssid, &adapter->mac_addr);
2171 } else {
2172 struct hdd_station_ctx *sta_ctx =
2173 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2174
2175 if (eConnectionState_Associated ==
2176 sta_ctx->conn_info.conn_state)
2177 qdf_copy_macaddr(&bssid, &sta_ctx->conn_info.bssid);
2178 }
2179
2180 qdf_copy_macaddr(&selfmac, &adapter->mac_addr);
2181
Jeff Johnson2954ded2018-06-13 16:34:49 -07002182 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183
Jeff Johnson9de31c02018-10-10 11:18:43 -07002184 dbm = MBM_TO_DBM(mbm);
2185
2186 /*
2187 * the original implementation of this function expected power
2188 * values in dBm instead of mBm. If the conversion from mBm to
2189 * dBm is zero, then assume dBm was passed.
2190 */
2191 if (!dbm)
2192 dbm = mbm;
2193
Wu Gao5f764082019-01-04 15:54:38 +08002194 status = ucfg_mlme_set_current_tx_power_level(hdd_ctx->psoc, dbm);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002195 if (QDF_IS_STATUS_ERROR(status)) {
2196 hdd_err("sme_cfg_set_int failed for tx power %hu, %d",
2197 dbm, status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002198 return -EIO;
2199 }
2200
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002201 hdd_debug("Set tx power level %d dbm", dbm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202
2203 switch (type) {
2204 /* Automatically determine transmit power */
2205 case NL80211_TX_POWER_AUTOMATIC:
2206 /* Fall through */
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05302207 case NL80211_TX_POWER_LIMITED:
2208 /* Limit TX power by the mBm parameter */
hangtian821d12d2019-06-11 11:53:50 +08002209 status = sme_set_max_tx_power(mac_handle, bssid, selfmac, dbm);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002210 if (QDF_IS_STATUS_ERROR(status)) {
2211 hdd_err("Setting maximum tx power failed, %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 return -EIO;
2213 }
2214 break;
2215
2216 case NL80211_TX_POWER_FIXED: /* Fix TX power to the mBm parameter */
Jeff Johnsonc3273322016-07-06 15:28:17 -07002217 hdd_err("NL80211_TX_POWER_FIXED not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 return -EOPNOTSUPP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219
2220 default:
Jeff Johnsonc3273322016-07-06 15:28:17 -07002221 hdd_err("Invalid power setting type %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 return -EIO;
2223 }
2224
Dustin Browne74003f2018-03-14 12:51:58 -07002225 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002226 return 0;
2227}
2228
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002230 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002231 enum nl80211_tx_power_setting type,
Jeff Johnson9de31c02018-10-10 11:18:43 -07002232 int mbm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233{
Dustin Brown363b4792019-02-05 16:11:55 -08002234 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08002235 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05302236
Dustin Brown363b4792019-02-05 16:11:55 -08002237 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002238 if (errno)
2239 return errno;
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05302240
Dustin Brownf0f00612019-01-31 16:02:24 -08002241 errno = __wlan_hdd_cfg80211_set_txpower(wiphy, wdev, type, mbm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002242
Dustin Brown363b4792019-02-05 16:11:55 -08002243 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002244
2245 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246}
2247
Naveen Rawate8b1b822018-01-30 09:46:16 -08002248static void wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm)
Sourav Mohapatra2a67b0e2019-10-15 17:59:59 +05302249
Naveen Rawate8b1b822018-01-30 09:46:16 -08002250{
Dustin Brown89fa06e2018-09-07 10:47:27 -07002251 wlan_cfg80211_mc_cp_stats_get_tx_power(adapter->vdev, dbm);
Naveen Rawate8b1b822018-01-30 09:46:16 -08002252}
Ashish Kumar Dhanotiya0929b962019-06-04 17:31:35 +05302253
Sourav Mohapatra2a67b0e2019-10-15 17:59:59 +05302254#ifdef FEATURE_ANI_LEVEL_REQUEST
2255static void hdd_get_ani_level_cb(struct wmi_host_ani_level_event *ani,
2256 uint8_t num, void *context)
2257{
2258 struct osif_request *request;
2259 struct ani_priv *priv;
2260 uint8_t min_recv_freqs = QDF_MIN(num, MAX_NUM_FREQS_FOR_ANI_LEVEL);
2261
2262 request = osif_request_get(context);
2263 if (!request) {
2264 hdd_err("Obsolete request");
2265 return;
2266 }
2267
2268 /* propagate response back to requesting thread */
2269 priv = osif_request_priv(request);
2270 priv->ani = qdf_mem_malloc(min_recv_freqs *
2271 sizeof(struct wmi_host_ani_level_event));
2272 if (!priv->ani)
2273 goto complete;
2274
2275 priv->num_freq = min_recv_freqs;
2276 qdf_mem_copy(priv->ani, ani,
2277 min_recv_freqs * sizeof(struct wmi_host_ani_level_event));
2278
2279complete:
2280 osif_request_complete(request);
2281 osif_request_put(request);
2282}
2283
2284/**
2285 * wlan_hdd_get_ani_level_dealloc() - Dealloc mem allocated in priv data
2286 * @priv: the priv data
2287 *
2288 * Return: None
2289 */
2290static void wlan_hdd_get_ani_level_dealloc(void *priv)
2291{
2292 struct ani_priv *ani = priv;
2293
2294 if (ani->ani)
2295 qdf_mem_free(ani->ani);
2296}
2297
2298QDF_STATUS wlan_hdd_get_ani_level(struct hdd_adapter *adapter,
2299 struct wmi_host_ani_level_event *ani,
2300 uint32_t *parsed_freqs,
2301 uint8_t num_freqs)
2302{
2303 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2304 int ret;
2305 QDF_STATUS status;
2306 void *cookie;
2307 struct osif_request *request;
2308 struct ani_priv *priv;
2309 static const struct osif_request_params params = {
2310 .priv_size = sizeof(*priv),
2311 .timeout_ms = 1000,
2312 .dealloc = wlan_hdd_get_ani_level_dealloc,
2313 };
2314
2315 if (!hdd_ctx) {
2316 hdd_err("Invalid HDD context");
2317 return QDF_STATUS_E_INVAL;
2318 }
2319
2320 request = osif_request_alloc(&params);
2321 if (!request) {
2322 hdd_err("Request allocation failure");
2323 return QDF_STATUS_E_NOMEM;
2324 }
2325 cookie = osif_request_cookie(request);
2326
2327 status = sme_get_ani_level(hdd_ctx->mac_handle, parsed_freqs,
2328 num_freqs, hdd_get_ani_level_cb, cookie);
2329
2330 if (QDF_IS_STATUS_ERROR(status)) {
2331 hdd_err("Unable to retrieve ani level");
2332 goto complete;
2333 } else {
2334 /* request was sent -- wait for the response */
2335 ret = osif_request_wait_for_response(request);
2336 if (ret) {
2337 hdd_err("SME timed out while retrieving ANI level");
2338 status = QDF_STATUS_E_TIMEOUT;
2339 goto complete;
2340 }
2341 }
2342
2343 priv = osif_request_priv(request);
2344
2345 qdf_mem_copy(ani, priv->ani, sizeof(struct wmi_host_ani_level_event) *
2346 priv->num_freq);
2347
2348complete:
2349 /*
2350 * either we never sent a request, we sent a request and
2351 * received a response or we sent a request and timed out.
2352 * regardless we are done with the request.
2353 */
2354 osif_request_put(request);
2355
2356 hdd_exit();
2357 return status;
2358}
2359#endif
2360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361/**
2362 * __wlan_hdd_cfg80211_get_txpower() - get TX power
2363 * @wiphy: Pointer to wiphy
2364 * @wdev: Pointer to network device
2365 * @dbm: Pointer to TX power in dbm
2366 *
2367 * Return: 0 for success, non-zero for failure
2368 */
2369static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 struct wireless_dev *wdev,
Srinivas Girigowda5557a392017-03-09 14:28:36 -08002371 int *dbm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372{
2373
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002374 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Srinivas Girigowda5557a392017-03-09 14:28:36 -08002375 struct net_device *ndev = wdev->netdev;
Jeff Johnson75b737d2017-08-29 14:24:41 -07002376 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 int status;
Bala Venkatesh5d0fe412019-07-25 15:48:24 +05302378 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379
Dustin Brown63500612018-08-07 11:36:09 -07002380 hdd_enter_dev(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381
Anurag Chouhan6d760662016-02-20 16:05:43 +05302382 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07002383 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 return -EINVAL;
2385 }
2386
Dustin Brown63500612018-08-07 11:36:09 -07002387 *dbm = 0;
2388
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002389 status = wlan_hdd_validate_context(hdd_ctx);
Dustin Brown63500612018-08-07 11:36:09 -07002390 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392
Arun Khandavalli99286452016-08-22 12:13:41 +05302393 /* Validate adapter sessionId */
Jeff Johnson48363022019-02-24 16:26:51 -08002394 status = wlan_hdd_validate_vdev_id(adapter->vdev_id);
Dustin Brown63500612018-08-07 11:36:09 -07002395 if (status)
2396 return status;
Bala Venkatesh5d0fe412019-07-25 15:48:24 +05302397 switch (adapter->device_mode) {
2398 case QDF_STA_MODE:
2399 case QDF_P2P_CLIENT_MODE:
Paul Zhang3d7c0e62019-06-29 08:57:47 +08002400 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2401 if (sta_ctx->hdd_reassoc_scenario) {
2402 hdd_debug("Roaming is in progress, rej this req");
2403 return -EINVAL;
2404 }
Paul Zhang3d7c0e62019-06-29 08:57:47 +08002405 if (sta_ctx->conn_info.conn_state !=
2406 eConnectionState_Associated) {
2407 hdd_debug("Not associated");
2408 return 0;
2409 }
Bala Venkatesh5d0fe412019-07-25 15:48:24 +05302410 break;
2411 case QDF_SAP_MODE:
2412 case QDF_P2P_GO_MODE:
2413 if (!test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
2414 hdd_err("SAP is not started yet");
2415 return 0;
2416 }
2417 break;
2418 default:
2419 hdd_debug_rl("Current interface is not supported for get tx_power");
2420 return 0;
Abhinav Kumar50d4dc72018-06-15 16:35:50 +05302421 }
2422
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002423 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002424 hdd_debug("Driver Module not enabled return success");
Arun Khandavalli99286452016-08-22 12:13:41 +05302425 /* Send cached data to upperlayer*/
Jeff Johnson861dd4f2017-10-24 10:10:40 -07002426 *dbm = adapter->hdd_stats.class_a_stat.max_pwr;
Arun Khandavalli99286452016-08-22 12:13:41 +05302427 return 0;
2428 }
Arun Khandavalli99286452016-08-22 12:13:41 +05302429
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05302430 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2431 TRACE_CODE_HDD_CFG80211_GET_TXPOWER,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002432 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433
Naveen Rawate8b1b822018-01-30 09:46:16 -08002434 wlan_hdd_get_tx_power(adapter, dbm);
2435 hdd_debug("power: %d", *dbm);
2436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 return 0;
2438}
2439
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 int *dbm)
2443{
Dustin Brown363b4792019-02-05 16:11:55 -08002444 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08002445 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05302446
Dustin Brown363b4792019-02-05 16:11:55 -08002447 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002448 if (errno)
2449 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450
Dustin Brownf0f00612019-01-31 16:02:24 -08002451 errno = __wlan_hdd_cfg80211_get_txpower(wiphy, wdev, dbm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452
Dustin Brown363b4792019-02-05 16:11:55 -08002453 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002454
2455 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456}
Kapil Gupta6213c012016-09-02 19:39:09 +05302457
Jeff Johnson4fbee2f2017-10-03 11:19:35 -07002458int hdd_set_qpower_config(struct hdd_context *hddctx,
2459 struct hdd_adapter *adapter,
Dustin Brown10a7b712016-10-07 10:31:16 -07002460 u8 qpower)
Kapil Gupta6213c012016-09-02 19:39:09 +05302461{
Dustin Brown10a7b712016-10-07 10:31:16 -07002462 QDF_STATUS status;
Kapil Gupta6213c012016-09-02 19:39:09 +05302463
Wu Gao66454f12018-09-26 19:55:41 +08002464 if (!ucfg_pmo_get_power_save_mode(hddctx->psoc)) {
Kapil Gupta6213c012016-09-02 19:39:09 +05302465 hdd_err("qpower is disabled in configuration");
2466 return -EINVAL;
2467 }
Manjeet Singh91b7bb82017-02-10 18:35:40 +05302468 if (adapter->device_mode != QDF_STA_MODE &&
2469 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07002470 hdd_info("QPOWER only allowed in STA/P2P-Client modes:%d",
2471 adapter->device_mode);
Manjeet Singh91b7bb82017-02-10 18:35:40 +05302472 return -EINVAL;
2473 }
Dustin Brown10a7b712016-10-07 10:31:16 -07002474
Kapil Gupta6213c012016-09-02 19:39:09 +05302475 if (qpower > PS_DUTY_CYCLING_QPOWER ||
2476 qpower < PS_LEGACY_NODEEPSLEEP) {
Dustin Brown10a7b712016-10-07 10:31:16 -07002477 hdd_err("invalid qpower value: %d", qpower);
Kapil Gupta6213c012016-09-02 19:39:09 +05302478 return -EINVAL;
2479 }
Kapil Gupta6213c012016-09-02 19:39:09 +05302480
Wu Gao66454f12018-09-26 19:55:41 +08002481 if (ucfg_pmo_get_max_ps_poll(hddctx->psoc)) {
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08002482 if ((qpower == PS_QPOWER_NODEEPSLEEP) ||
2483 (qpower == PS_LEGACY_NODEEPSLEEP))
2484 qpower = PS_LEGACY_NODEEPSLEEP;
2485 else
2486 qpower = PS_LEGACY_DEEPSLEEP;
2487 hdd_info("Qpower disabled, %d", qpower);
2488 }
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002489 status = wma_set_qpower_config(adapter->vdev_id, qpower);
Dustin Brown10a7b712016-10-07 10:31:16 -07002490 if (status != QDF_STATUS_SUCCESS) {
2491 hdd_err("failed to configure qpower: %d", status);
2492 return -EINVAL;
Kapil Gupta6213c012016-09-02 19:39:09 +05302493 }
Dustin Brown10a7b712016-10-07 10:31:16 -07002494
Kapil Gupta6213c012016-09-02 19:39:09 +05302495 return 0;
2496}
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002497
Dustin Brown54096432017-02-23 13:00:44 -08002498
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002499#ifdef WLAN_SUSPEND_RESUME_TEST
Dustin Brownbc81a472016-10-26 16:56:59 -07002500static struct net_device *g_dev;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002501static struct wiphy *g_wiphy;
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002502static enum wow_resume_trigger g_resume_trigger;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002503
2504#define HDD_FA_SUSPENDED_BIT (0)
2505static unsigned long fake_apps_state;
2506
Dustin Brownd53d1a82016-10-03 12:57:33 -07002507/**
2508 * __hdd_wlan_fake_apps_resume() - The core logic for
2509 * hdd_wlan_fake_apps_resume() skipping the call to hif_fake_apps_resume(),
2510 * which is only need for non-irq resume
Dustin Brownbc81a472016-10-26 16:56:59 -07002511 * @wiphy: the kernel wiphy struct for the device being resumed
2512 * @dev: the kernel net_device struct for the device being resumed
Dustin Brownd53d1a82016-10-03 12:57:33 -07002513 *
Dustin Brownbc81a472016-10-26 16:56:59 -07002514 * Return: none, calls QDF_BUG() on failure
Dustin Brownd53d1a82016-10-03 12:57:33 -07002515 */
Dustin Brownbc81a472016-10-26 16:56:59 -07002516static void __hdd_wlan_fake_apps_resume(struct wiphy *wiphy,
2517 struct net_device *dev)
Dustin Brownd53d1a82016-10-03 12:57:33 -07002518{
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002519 struct hif_opaque_softc *hif_ctx;
Dustin Brownddb59702017-01-12 16:20:31 -08002520 qdf_device_t qdf_dev;
Dustin Brownd53d1a82016-10-03 12:57:33 -07002521
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002522 hdd_info("Unit-test resume WLAN");
Dustin Brownddb59702017-01-12 16:20:31 -08002523
2524 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
2525 if (!qdf_dev) {
2526 hdd_err("Failed to get QDF device context");
2527 QDF_BUG(0);
2528 return;
2529 }
2530
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002531 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2532 if (!hif_ctx) {
2533 hdd_err("Failed to get HIF context");
2534 return;
2535 }
2536
Dustin Brownd53d1a82016-10-03 12:57:33 -07002537 if (!test_and_clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002538 hdd_alert("Not unit-test suspended; Nothing to do");
Dustin Brownd53d1a82016-10-03 12:57:33 -07002539 return;
2540 }
2541
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002542 /* simulate kernel disable irqs */
2543 QDF_BUG(!hif_apps_wake_irq_disable(hif_ctx));
Dustin Brownd53d1a82016-10-03 12:57:33 -07002544
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002545 QDF_BUG(!wlan_hdd_bus_resume_noirq());
Dustin Brownd53d1a82016-10-03 12:57:33 -07002546
2547 /* simulate kernel enable irqs */
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002548 QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
Dustin Brownd53d1a82016-10-03 12:57:33 -07002549
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002550 QDF_BUG(!wlan_hdd_bus_resume());
Dustin Brownd53d1a82016-10-03 12:57:33 -07002551
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002552 QDF_BUG(!wlan_hdd_cfg80211_resume_wlan(wiphy));
2553
2554 if (g_resume_trigger == WOW_RESUME_TRIGGER_HTC_WAKEUP)
2555 hif_vote_link_down(hif_ctx);
Dustin Brownbc81a472016-10-26 16:56:59 -07002556
2557 dev->watchdog_timeo = HDD_TX_TIMEOUT;
Dustin Brown562b9672016-12-22 15:25:33 -08002558
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002559 hdd_alert("Unit-test resume succeeded");
Dustin Brownd53d1a82016-10-03 12:57:33 -07002560}
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002561
2562/**
2563 * hdd_wlan_fake_apps_resume_irq_callback() - Irq callback function for resuming
2564 * from unit-test initiated suspend from irq wakeup signal
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002565 *
2566 * Resume wlan after getting very 1st CE interrupt from target
2567 *
2568 * Return: none
2569 */
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002570static void hdd_wlan_fake_apps_resume_irq_callback(void)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002571{
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002572 hdd_info("Trigger unit-test resume WLAN");
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002573
2574 QDF_BUG(g_wiphy);
Dustin Brownbc81a472016-10-26 16:56:59 -07002575 QDF_BUG(g_dev);
2576 __hdd_wlan_fake_apps_resume(g_wiphy, g_dev);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002577 g_wiphy = NULL;
Dustin Brownbc81a472016-10-26 16:56:59 -07002578 g_dev = NULL;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002579}
2580
Dustin Brown54096432017-02-23 13:00:44 -08002581int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev,
2582 enum wow_interface_pause pause_setting,
2583 enum wow_resume_trigger resume_setting)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002584{
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002585 int errno;
Dustin Brownddb59702017-01-12 16:20:31 -08002586 qdf_device_t qdf_dev;
2587 struct hif_opaque_softc *hif_ctx;
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002588 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Dustin Brown54096432017-02-23 13:00:44 -08002589 struct wow_enable_params wow_params = {
2590 .is_unit_test = true,
2591 .interface_pause = pause_setting,
2592 .resume_trigger = resume_setting
2593 };
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002594
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002595 if (wlan_hdd_validate_context(hdd_ctx))
2596 return -EINVAL;
2597
2598 if (!hdd_ctx->config->is_unit_test_framework_enabled) {
2599 hdd_warn_rl("UT framework is disabled");
2600 return -EINVAL;
2601 }
2602
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002603 hdd_info("Unit-test suspend WLAN");
Dustin Brownddb59702017-01-12 16:20:31 -08002604
Dustin Brown54096432017-02-23 13:00:44 -08002605 if (pause_setting < WOW_INTERFACE_PAUSE_DEFAULT ||
2606 pause_setting >= WOW_INTERFACE_PAUSE_COUNT) {
2607 hdd_err("Invalid interface pause %d (expected range [0, 2])",
2608 pause_setting);
2609 return -EINVAL;
2610 }
2611
2612 if (resume_setting < WOW_RESUME_TRIGGER_DEFAULT ||
2613 resume_setting >= WOW_RESUME_TRIGGER_COUNT) {
2614 hdd_err("Invalid resume trigger %d (expected range [0, 2])",
2615 resume_setting);
2616 return -EINVAL;
2617 }
2618
Dustin Brownddb59702017-01-12 16:20:31 -08002619 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
2620 if (!qdf_dev) {
2621 hdd_err("Failed to get QDF device context");
2622 return -EINVAL;
2623 }
2624
2625 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2626 if (!hif_ctx) {
2627 hdd_err("Failed to get HIF context");
2628 return -EINVAL;
2629 }
2630
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002631 if (test_and_set_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002632 hdd_alert("Already unit-test suspended; Nothing to do");
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002633 return 0;
2634 }
2635
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002636 /* pci link is needed to wakeup from HTC wakeup trigger */
2637 if (resume_setting == WOW_RESUME_TRIGGER_HTC_WAKEUP)
2638 hif_vote_link_up(hif_ctx);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002639
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002640 errno = wlan_hdd_cfg80211_suspend_wlan(wiphy, NULL);
2641 if (errno)
2642 goto link_down;
2643
2644 errno = wlan_hdd_unit_test_bus_suspend(wow_params);
2645 if (errno)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002646 goto cfg80211_resume;
2647
2648 /* simulate kernel disabling irqs */
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002649 errno = hif_apps_irqs_disable(hif_ctx);
2650 if (errno)
2651 goto bus_resume;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002652
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002653 errno = wlan_hdd_bus_suspend_noirq();
2654 if (errno)
2655 goto enable_irqs;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002656
Dustin Brownbc81a472016-10-26 16:56:59 -07002657 /* pass wiphy/dev to callback via global variables */
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002658 g_wiphy = wiphy;
Dustin Brownbc81a472016-10-26 16:56:59 -07002659 g_dev = dev;
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002660 g_resume_trigger = resume_setting;
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002661 hif_ut_apps_suspend(hif_ctx, hdd_wlan_fake_apps_resume_irq_callback);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002662
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002663 /* re-enable wake irq */
2664 errno = hif_apps_wake_irq_enable(hif_ctx);
2665 if (errno)
2666 goto fake_apps_resume;
2667
Dustin Brownbc81a472016-10-26 16:56:59 -07002668 /*
2669 * Tell the kernel not to worry if TX queues aren't moving. This is
2670 * expected since we are suspending the wifi hardware, but not APPS
2671 */
2672 dev->watchdog_timeo = INT_MAX;
2673
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002674 hdd_alert("Unit-test suspend succeeded");
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002675
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002676 return 0;
2677
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002678fake_apps_resume:
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002679 hif_ut_apps_resume(hif_ctx);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002680
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002681enable_irqs:
2682 QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
2683
2684bus_resume:
2685 QDF_BUG(!wlan_hdd_bus_resume());
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002686
2687cfg80211_resume:
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002688 QDF_BUG(!wlan_hdd_cfg80211_resume_wlan(wiphy));
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002689
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002690link_down:
2691 hif_vote_link_down(hif_ctx);
2692
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002693 clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state);
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002694 hdd_err("Unit-test suspend failed: %d", errno);
2695
2696 return errno;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002697}
2698
Dustin Brownbc81a472016-10-26 16:56:59 -07002699int hdd_wlan_fake_apps_resume(struct wiphy *wiphy, struct net_device *dev)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002700{
Dustin Brownddb59702017-01-12 16:20:31 -08002701 struct hif_opaque_softc *hif_ctx;
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002702 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2703
2704 if (wlan_hdd_validate_context(hdd_ctx))
2705 return -EINVAL;
2706
2707 if (!hdd_ctx->config->is_unit_test_framework_enabled) {
2708 hdd_warn_rl("UT framework is disabled");
2709 return -EINVAL;
2710 }
Dustin Brownddb59702017-01-12 16:20:31 -08002711
2712 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2713 if (!hif_ctx) {
2714 hdd_err("Failed to get HIF context");
2715 return -EINVAL;
2716 }
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002717
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002718 hif_ut_apps_resume(hif_ctx);
Dustin Brownbc81a472016-10-26 16:56:59 -07002719 __hdd_wlan_fake_apps_resume(wiphy, dev);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002720
2721 return 0;
2722}
2723#endif