blob: c3bf262482929429a10891b91910b1d0cd01eab1 [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>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "hif.h"
Dustin Brown0f8dc3d2017-06-01 14:37:26 -070066#include "hif_unit_test_suspend.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080067#include "sme_power_save_api.h"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080068#include "wlan_policy_mgr_api.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080069#include "cdp_txrx_flow_ctrl_v2.h"
Yuanyuan Liu13738502016-04-06 17:41:37 -070070#include "pld_common.h"
Rajeev Kumar9bb2e852016-09-24 12:29:25 -070071#include "wlan_hdd_driver_ops.h"
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +053072#include <wlan_logging_sock_svc.h>
Krunal Sonid32c6bc2016-10-18 18:00:21 -070073#include "scheduler_api.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053074#include "cds_utils.h"
Hanumanth Reddy Pothula3def8942017-10-05 16:19:36 +053075#include "wlan_hdd_packet_filter_api.h"
Arunk Khandavallif0c0d762017-12-07 10:18:50 +053076#include "wlan_cfg80211_scan.h"
Mohit Khanna70322002018-05-15 19:21:32 -070077#include <dp_txrx.h>
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +053078#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -080079#include <wlan_cfg80211_mc_cp_stats.h>
Wu Gao4a1ec8c2018-07-23 19:18:40 +080080#include "wlan_p2p_ucfg_api.h"
Wu Gao93816212018-08-31 16:49:54 +080081#include "wlan_mlme_ucfg_api.h"
82
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083/* Preprocessor definitions and constants */
Yue Ma5fe30dd2017-05-02 15:47:40 -070084#ifdef QCA_WIFI_NAPIER_EMULATION
85#define HDD_SSR_BRING_UP_TIME 3000000
86#else
Yue Ma4ea4f052015-10-27 12:25:27 -070087#define HDD_SSR_BRING_UP_TIME 30000
Yue Ma5fe30dd2017-05-02 15:47:40 -070088#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080089
90/* Type declarations */
91
Abhishek Singhbaea27d2016-04-27 13:29:30 +053092#ifdef FEATURE_WLAN_DIAG_SUPPORT
Abhishek Singhbaea27d2016-04-27 13:29:30 +053093void hdd_wlan_suspend_resume_event(uint8_t state)
94{
95 WLAN_HOST_DIAG_EVENT_DEF(suspend_state, struct host_event_suspend);
96 qdf_mem_zero(&suspend_state, sizeof(suspend_state));
97
98 suspend_state.state = state;
99 WLAN_HOST_DIAG_EVENT_REPORT(&suspend_state, EVENT_WLAN_SUSPEND_RESUME);
100}
Abhishek Singh4aad0f72016-04-27 13:43:29 +0530101
102/**
103 * hdd_wlan_offload_event()- send offloads event
104 * @type: offload type
105 * @state: enabled or disabled
106 *
107 * This Function send offloads enable/disable diag event
108 *
109 * Return: void.
110 */
111
112void hdd_wlan_offload_event(uint8_t type, uint8_t state)
113{
114 WLAN_HOST_DIAG_EVENT_DEF(host_offload, struct host_event_offload_req);
115 qdf_mem_zero(&host_offload, sizeof(host_offload));
116
117 host_offload.offload_type = type;
118 host_offload.state = state;
119
120 WLAN_HOST_DIAG_EVENT_REPORT(&host_offload, EVENT_WLAN_OFFLOAD_REQ);
121}
Abhishek Singhbaea27d2016-04-27 13:29:30 +0530122#endif
123
Lin Baif5e8cc22018-11-05 10:57:38 +0800124#ifdef QCA_CONFIG_SMP
125
126/* timeout in msec to wait for RX_THREAD to suspend */
127#define HDD_RXTHREAD_SUSPEND_TIMEOUT 200
128
129void wlan_hdd_rx_thread_resume(struct hdd_context *hdd_ctx)
130{
131 if (hdd_ctx->is_ol_rx_thread_suspended) {
132 cds_resume_rx_thread();
133 hdd_ctx->is_ol_rx_thread_suspended = false;
134 }
135}
136
137int wlan_hdd_rx_thread_suspend(struct hdd_context *hdd_ctx)
138{
139 p_cds_sched_context cds_sched_context = get_cds_sched_ctxt();
140 int rc;
141
142 if (!cds_sched_context)
143 return 0;
144
145 /* Suspend tlshim rx thread */
146 set_bit(RX_SUSPEND_EVENT, &cds_sched_context->ol_rx_event_flag);
147 wake_up_interruptible(&cds_sched_context->ol_rx_wait_queue);
148 rc = wait_for_completion_timeout(&cds_sched_context->
149 ol_suspend_rx_event,
150 msecs_to_jiffies
151 (HDD_RXTHREAD_SUSPEND_TIMEOUT)
152 );
153 if (!rc) {
154 clear_bit(RX_SUSPEND_EVENT,
155 &cds_sched_context->ol_rx_event_flag);
156 hdd_err("Failed to stop tl_shim rx thread");
157 return -EINVAL;
158 }
159 hdd_ctx->is_ol_rx_thread_suspended = true;
160
161 return 0;
162}
163#endif /* QCA_CONFIG_SMP */
164
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165/**
Mukul Sharma3d36c392017-01-18 18:39:12 +0530166 * hdd_enable_gtk_offload() - enable GTK offload
167 * @adapter: pointer to the adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 *
Mukul Sharma3d36c392017-01-18 18:39:12 +0530169 * Central function to enable GTK offload.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 *
171 * Return: nothing
172 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700173static void hdd_enable_gtk_offload(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174{
Mukul Sharma3d36c392017-01-18 18:39:12 +0530175 QDF_STATUS status;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -0700176
Wu Gaod7dd6e42018-10-16 17:22:56 +0800177 status = ucfg_pmo_enable_gtk_offload_in_fwr(adapter->vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +0530178 if (status != QDF_STATUS_SUCCESS)
179 hdd_info("Failed to enable gtk offload");
180}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800181
Mukul Sharma3d36c392017-01-18 18:39:12 +0530182/**
183 * hdd_disable_gtk_offload() - disable GTK offload
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700184 * @adapter: pointer to the adapter
Mukul Sharma3d36c392017-01-18 18:39:12 +0530185 *
186 * Central function to disable GTK offload.
187 *
188 * Return: nothing
189 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700190static void hdd_disable_gtk_offload(struct hdd_adapter *adapter)
Mukul Sharma3d36c392017-01-18 18:39:12 +0530191{
192 struct pmo_gtk_rsp_req gtk_rsp_request;
193 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800194
Mukul Sharma3d36c392017-01-18 18:39:12 +0530195 /* ensure to get gtk rsp first before disable it*/
Dustin Brown89fa06e2018-09-07 10:47:27 -0700196 gtk_rsp_request.callback = wlan_hdd_cfg80211_update_replay_counter_cb;
197
Mukul Sharma3d36c392017-01-18 18:39:12 +0530198 /* Passing as void* as PMO does not know legacy HDD adapter type */
Dustin Brown89fa06e2018-09-07 10:47:27 -0700199 gtk_rsp_request.callback_context = (void *)adapter;
200
Wu Gaod7dd6e42018-10-16 17:22:56 +0800201 status = ucfg_pmo_get_gtk_rsp(adapter->vdev, &gtk_rsp_request);
Mukul Sharma3d36c392017-01-18 18:39:12 +0530202 if (status != QDF_STATUS_SUCCESS) {
203 hdd_err("Failed to send get gtk rsp status:%d", status);
204 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800205 }
Dustin Brown89fa06e2018-09-07 10:47:27 -0700206
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800207 hdd_debug("send get_gtk_rsp successful");
Wu Gaod7dd6e42018-10-16 17:22:56 +0800208 status = ucfg_pmo_disable_gtk_offload_in_fwr(adapter->vdev);
Mukul Sharma3d36c392017-01-18 18:39:12 +0530209 if (status != QDF_STATUS_SUCCESS)
210 hdd_info("Failed to disable gtk offload");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212
Qiwei Cai1083f5b2018-07-02 19:10:11 +0800213#ifdef WLAN_NS_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214/**
215 * __wlan_hdd_ipv6_changed() - IPv6 notifier callback function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800216 * @net_dev: net_device whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 *
218 * This is a callback function that is registered with the kernel via
219 * register_inet6addr_notifier() which allows the driver to be
220 * notified when there is an IPv6 address change.
221 *
Dustin Brown39b33ba2019-02-27 10:54:56 -0800222 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800224static void __wlan_hdd_ipv6_changed(struct net_device *net_dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800226 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700227 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700228 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229
Dustin Brown39b33ba2019-02-27 10:54:56 -0800230 hdd_enter_dev(net_dev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530231
Dustin Brownf13b8c32017-05-19 17:23:08 -0700232 errno = hdd_validate_adapter(adapter);
Dustin Brown39b33ba2019-02-27 10:54:56 -0800233 if (errno || adapter->dev != net_dev)
234 goto exit;
235
236 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
237 errno = wlan_hdd_validate_context(hdd_ctx);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700238 if (errno)
239 goto exit;
240
Dustin Brown39b33ba2019-02-27 10:54:56 -0800241 if (adapter->device_mode == QDF_STA_MODE ||
242 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
243 adapter->device_mode == QDF_NDI_MODE) {
Dustin Brownf13b8c32017-05-19 17:23:08 -0700244 hdd_debug("invoking sme_dhcp_done_ind");
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800245 sme_dhcp_done_ind(hdd_ctx->mac_handle, adapter->vdev_id);
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700246 schedule_work(&adapter->ipv6_notifier_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800247 }
248
Dustin Brownf13b8c32017-05-19 17:23:08 -0700249exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700250 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251}
252
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253int wlan_hdd_ipv6_changed(struct notifier_block *nb,
Dustin Brown39b33ba2019-02-27 10:54:56 -0800254 unsigned long data, void *context)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800255{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800256 struct inet6_ifaddr *ifa = context;
257 struct net_device *net_dev = ifa->idev->dev;
258 struct osif_vdev_sync *vdev_sync;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800259
Dustin Brown39b33ba2019-02-27 10:54:56 -0800260 if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
261 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800262
Dustin Brown39b33ba2019-02-27 10:54:56 -0800263 __wlan_hdd_ipv6_changed(net_dev);
264
265 osif_vdev_sync_op_stop(vdev_sync);
266
267 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800268}
269
270/**
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530271 * hdd_fill_ipv6_uc_addr() - fill IPv6 unicast addresses
272 * @idev: pointer to net device
273 * @ipv6addr: destination array to fill IPv6 addresses
274 * @ipv6addr_type: IPv6 Address type
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530275 * @scope_array: scope of ipv6 addr
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530276 * @count: number of IPv6 addresses
277 *
278 * This is the IPv6 utility function to populate unicast addresses.
279 *
280 * Return: 0 on success, error number otherwise.
281 */
282static int hdd_fill_ipv6_uc_addr(struct inet6_dev *idev,
Srinivas Girigowdad1e45b82019-04-15 15:08:28 -0700283 uint8_t ipv6_uc_addr[][QDF_IPV6_ADDR_SIZE],
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530284 uint8_t *ipv6addr_type,
285 enum pmo_ns_addr_scope *scope_array,
286 uint32_t *count)
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530287{
288 struct inet6_ifaddr *ifa;
289 struct list_head *p;
290 uint32_t scope;
291
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700292 read_lock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530293 list_for_each(p, &idev->addr_list) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530294 if (*count >= PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) {
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700295 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530296 return -EINVAL;
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700297 }
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530298 ifa = list_entry(p, struct inet6_ifaddr, if_list);
299 if (ifa->flags & IFA_F_DADFAILED)
300 continue;
301 scope = ipv6_addr_src_scope(&ifa->addr);
302 switch (scope) {
303 case IPV6_ADDR_SCOPE_GLOBAL:
304 case IPV6_ADDR_SCOPE_LINKLOCAL:
305 qdf_mem_copy(ipv6_uc_addr[*count], &ifa->addr.s6_addr,
306 sizeof(ifa->addr.s6_addr));
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530307 ipv6addr_type[*count] = PMO_IPV6_ADDR_UC_TYPE;
Wu Gaod7dd6e42018-10-16 17:22:56 +0800308 scope_array[*count] = ucfg_pmo_ns_addr_scope(scope);
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800309 hdd_debug("Index %d scope = %s UC-Address: %pI6",
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530310 *count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
311 "LINK LOCAL" : "GLOBAL", ipv6_uc_addr[*count]);
312 *count += 1;
313 break;
314 default:
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800315 hdd_warn("The Scope %d is not supported", scope);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530316 }
317 }
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700318
319 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530320 return 0;
321}
322
323/**
324 * hdd_fill_ipv6_ac_addr() - fill IPv6 anycast addresses
325 * @idev: pointer to net device
326 * @ipv6addr: destination array to fill IPv6 addresses
327 * @ipv6addr_type: IPv6 Address type
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530328 * @scope_array: scope of ipv6 addr
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530329 * @count: number of IPv6 addresses
330 *
331 * This is the IPv6 utility function to populate anycast addresses.
332 *
333 * Return: 0 on success, error number otherwise.
334 */
335static int hdd_fill_ipv6_ac_addr(struct inet6_dev *idev,
Srinivas Girigowdad1e45b82019-04-15 15:08:28 -0700336 uint8_t ipv6_ac_addr[][QDF_IPV6_ADDR_SIZE],
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530337 uint8_t *ipv6addr_type,
338 enum pmo_ns_addr_scope *scope_array,
339 uint32_t *count)
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530340{
341 struct ifacaddr6 *ifaca;
342 uint32_t scope;
343
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700344 read_lock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530345 for (ifaca = idev->ac_list; ifaca; ifaca = ifaca->aca_next) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530346 if (*count >= PMO_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) {
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700347 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530348 return -EINVAL;
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700349 }
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530350 /* For anycast addr no DAD */
351 scope = ipv6_addr_src_scope(&ifaca->aca_addr);
352 switch (scope) {
353 case IPV6_ADDR_SCOPE_GLOBAL:
354 case IPV6_ADDR_SCOPE_LINKLOCAL:
355 qdf_mem_copy(ipv6_ac_addr[*count], &ifaca->aca_addr,
356 sizeof(ifaca->aca_addr));
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530357 ipv6addr_type[*count] = PMO_IPV6_ADDR_AC_TYPE;
Wu Gaod7dd6e42018-10-16 17:22:56 +0800358 scope_array[*count] = ucfg_pmo_ns_addr_scope(scope);
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800359 hdd_debug("Index %d scope = %s AC-Address: %pI6",
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530360 *count, (scope == IPV6_ADDR_SCOPE_LINKLOCAL) ?
361 "LINK LOCAL" : "GLOBAL", ipv6_ac_addr[*count]);
362 *count += 1;
363 break;
364 default:
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800365 hdd_warn("The Scope %d is not supported", scope);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530366 }
367 }
Srinivas Girigowda90cdd3c2016-10-18 11:28:10 -0700368
369 read_unlock_bh(&idev->lock);
Sravan Kumar Kairamc0873582016-07-26 17:34:57 +0530370 return 0;
371}
372
Jeff Johnson75b737d2017-08-29 14:24:41 -0700373void hdd_enable_ns_offload(struct hdd_adapter *adapter,
Dustin Brownc1cdb712018-06-11 15:42:17 -0700374 enum pmo_offload_trigger trigger)
Dustin Brown2444ee62016-09-06 17:20:36 -0700375{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700376 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown05d81302018-09-11 16:49:22 -0700377 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
Dustin Brownc1cdb712018-06-11 15:42:17 -0700378 struct inet6_dev *in6_dev;
379 struct pmo_ns_req *ns_req;
380 QDF_STATUS status;
381 int errno;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530382
Dustin Brown491d54b2018-03-14 12:39:11 -0700383 hdd_enter();
Dustin Brownc1cdb712018-06-11 15:42:17 -0700384
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530385 if (!psoc) {
386 hdd_err("psoc is NULL");
387 goto out;
388 }
Dustin Brown2444ee62016-09-06 17:20:36 -0700389
390 in6_dev = __in6_dev_get(adapter->dev);
Jeff Johnsond36fa332019-03-18 13:42:25 -0700391 if (!in6_dev) {
Dustin Brown2444ee62016-09-06 17:20:36 -0700392 hdd_err("IPv6 dev does not exist. Failed to request NSOffload");
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530393 goto out;
Dustin Brown2444ee62016-09-06 17:20:36 -0700394 }
395
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530396 ns_req = qdf_mem_malloc(sizeof(*ns_req));
Min Liu74a1a502018-10-10 19:59:07 +0800397 if (!ns_req)
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530398 goto out;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530399
400 ns_req->psoc = psoc;
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800401 ns_req->vdev_id = adapter->vdev_id;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530402 ns_req->trigger = trigger;
403 ns_req->count = 0;
404
Dustin Brown2444ee62016-09-06 17:20:36 -0700405 /* Unicast Addresses */
Dustin Brownc1cdb712018-06-11 15:42:17 -0700406 errno = hdd_fill_ipv6_uc_addr(in6_dev, ns_req->ipv6_addr,
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530407 ns_req->ipv6_addr_type, ns_req->scope,
408 &ns_req->count);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700409 if (errno) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530410 hdd_disable_ns_offload(adapter, trigger);
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +0530411 hdd_debug("Max supported addresses: disabling NS offload");
Dustin Brownc1cdb712018-06-11 15:42:17 -0700412 goto free_req;
Dustin Brown2444ee62016-09-06 17:20:36 -0700413 }
414
415 /* Anycast Addresses */
Dustin Brownc1cdb712018-06-11 15:42:17 -0700416 errno = hdd_fill_ipv6_ac_addr(in6_dev, ns_req->ipv6_addr,
Rajeev Kumar Sirasanagandla85f8b022018-03-12 12:52:59 +0530417 ns_req->ipv6_addr_type, ns_req->scope,
418 &ns_req->count);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700419 if (errno) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530420 hdd_disable_ns_offload(adapter, trigger);
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +0530421 hdd_debug("Max supported addresses: disabling NS offload");
Dustin Brownc1cdb712018-06-11 15:42:17 -0700422 goto free_req;
Dustin Brown2444ee62016-09-06 17:20:36 -0700423 }
424
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530425 /* cache ns request */
Wu Gaod7dd6e42018-10-16 17:22:56 +0800426 status = ucfg_pmo_cache_ns_offload_req(ns_req);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700427 if (QDF_IS_STATUS_ERROR(status)) {
428 hdd_err("Failed to cache ns request; status:%d", status);
429 goto free_req;
Dustin Brown2444ee62016-09-06 17:20:36 -0700430 }
431
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530432 /* enable ns request */
Wu Gaod7dd6e42018-10-16 17:22:56 +0800433 status = ucfg_pmo_enable_ns_offload_in_fwr(adapter->vdev, trigger);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700434 if (QDF_IS_STATUS_ERROR(status)) {
435 hdd_err("Failed to enable ns offload; status:%d", status);
436 goto free_req;
437 }
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530438
Dustin Brownc1cdb712018-06-11 15:42:17 -0700439 hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD, SIR_OFFLOAD_ENABLE);
440
441free_req:
442 qdf_mem_free(ns_req);
443
444out:
445 hdd_exit();
Dustin Brown2444ee62016-09-06 17:20:36 -0700446}
447
Jeff Johnson75b737d2017-08-29 14:24:41 -0700448void hdd_disable_ns_offload(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530449 enum pmo_offload_trigger trigger)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800450{
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530451 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800452
Dustin Brown491d54b2018-03-14 12:39:11 -0700453 hdd_enter();
Wu Gaod7dd6e42018-10-16 17:22:56 +0800454 status = ucfg_pmo_flush_ns_offload_req(adapter->vdev);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530455 if (status != QDF_STATUS_SUCCESS) {
456 hdd_err("Failed to flush NS Offload");
457 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 }
459
Wu Gaod7dd6e42018-10-16 17:22:56 +0800460 status = ucfg_pmo_disable_ns_offload_in_fwr(adapter->vdev, trigger);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530461 if (status != QDF_STATUS_SUCCESS)
462 hdd_err("Failed to disable NS Offload");
Dustin Brown2444ee62016-09-06 17:20:36 -0700463 else
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530464 hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD,
465 SIR_OFFLOAD_DISABLE);
466out:
Dustin Browne74003f2018-03-14 12:51:58 -0700467 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800469}
470
471/**
472 * __hdd_ipv6_notifier_work_queue() - IPv6 notification work function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800473 * @adapter: adapter whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 *
475 * This function performs the work initially trigged by a callback
476 * from the IPv6 netdev notifier. Since this means there has been a
477 * change in IPv6 state for the interface, the NS offload is
478 * reconfigured.
479 *
480 * Return: None
481 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800482static void __hdd_ipv6_notifier_work_queue(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700484 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700485 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800486
Dustin Brown491d54b2018-03-14 12:39:11 -0700487 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800488
Dustin Brownf13b8c32017-05-19 17:23:08 -0700489 errno = hdd_validate_adapter(adapter);
490 if (errno)
491 goto exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492
Dustin Brownf13b8c32017-05-19 17:23:08 -0700493 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
494 errno = wlan_hdd_validate_context(hdd_ctx);
495 if (errno)
496 goto exit;
497
498 hdd_enable_ns_offload(adapter, pmo_ipv6_change_notify);
499
500exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700501 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502}
503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504void hdd_ipv6_notifier_work_queue(struct work_struct *work)
505{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800506 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
507 ipv6_notifier_work);
508 struct osif_vdev_sync *vdev_sync;
509
510 if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
511 return;
512
513 __hdd_ipv6_notifier_work_queue(adapter);
514
515 osif_vdev_sync_op_stop(vdev_sync);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800516}
Qiwei Cai1083f5b2018-07-02 19:10:11 +0800517#endif /* WLAN_NS_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518
Jeff Johnson75b737d2017-08-29 14:24:41 -0700519static void hdd_enable_hw_filter(struct hdd_adapter *adapter)
Dustin Brown1224e212017-05-12 14:02:12 -0700520{
521 QDF_STATUS status;
522
Dustin Brown491d54b2018-03-14 12:39:11 -0700523 hdd_enter();
Dustin Brown1224e212017-05-12 14:02:12 -0700524
Wu Gaod7dd6e42018-10-16 17:22:56 +0800525 status = ucfg_pmo_enable_hw_filter_in_fwr(adapter->vdev);
Dustin Brown1224e212017-05-12 14:02:12 -0700526 if (status != QDF_STATUS_SUCCESS)
527 hdd_info("Failed to enable hardware filter");
528
Dustin Browne74003f2018-03-14 12:51:58 -0700529 hdd_exit();
Dustin Brown1224e212017-05-12 14:02:12 -0700530}
531
Jeff Johnson75b737d2017-08-29 14:24:41 -0700532static void hdd_disable_hw_filter(struct hdd_adapter *adapter)
Dustin Brown1224e212017-05-12 14:02:12 -0700533{
534 QDF_STATUS status;
535
Dustin Brown491d54b2018-03-14 12:39:11 -0700536 hdd_enter();
Dustin Brown1224e212017-05-12 14:02:12 -0700537
Wu Gaod7dd6e42018-10-16 17:22:56 +0800538 status = ucfg_pmo_disable_hw_filter_in_fwr(adapter->vdev);
Dustin Brown1224e212017-05-12 14:02:12 -0700539 if (status != QDF_STATUS_SUCCESS)
540 hdd_info("Failed to disable hardware filter");
541
Dustin Browne74003f2018-03-14 12:51:58 -0700542 hdd_exit();
Dustin Brown1224e212017-05-12 14:02:12 -0700543}
544
Pragaspathi Thilagarajb40c2602019-08-21 14:17:48 +0530545static void hdd_enable_action_frame_patterns(struct hdd_adapter *adapter)
546{
547 QDF_STATUS status;
548
549 hdd_enter();
550
551 status = ucfg_pmo_enable_action_frame_patterns(adapter->vdev,
552 QDF_SYSTEM_SUSPEND);
553 if (QDF_IS_STATUS_ERROR(status))
554 hdd_info("Failed to enable action frame patterns");
555
556 hdd_exit();
557}
558
559static void hdd_disable_action_frame_patterns(struct hdd_adapter *adapter)
560{
561 QDF_STATUS status;
562
563 hdd_enter();
564
565 status = ucfg_pmo_disable_action_frame_patterns(adapter->vdev);
566 if (QDF_IS_STATUS_ERROR(status))
567 hdd_info("Failed to disable action frame patterns");
568
569 hdd_exit();
570}
571
Jeff Johnson75b737d2017-08-29 14:24:41 -0700572void hdd_enable_host_offloads(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530573 enum pmo_offload_trigger trigger)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800574{
Dustin Brown491d54b2018-03-14 12:39:11 -0700575 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530576
Dustin Brown89fa06e2018-09-07 10:47:27 -0700577 if (!ucfg_pmo_is_vdev_supports_offload(adapter->vdev)) {
Dustin Brownc1cdb712018-06-11 15:42:17 -0700578 hdd_debug("offload is not supported on vdev opmode %d",
579 adapter->device_mode);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530580 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581 }
582
Dustin Brown89fa06e2018-09-07 10:47:27 -0700583 if (!ucfg_pmo_is_vdev_connected(adapter->vdev)) {
Dustin Brownc1cdb712018-06-11 15:42:17 -0700584 hdd_debug("offload is not supported on disconnected vdevs");
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530585 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586 }
587
Dustin Brownc1cdb712018-06-11 15:42:17 -0700588 hdd_debug("enable offloads");
Mukul Sharma3d36c392017-01-18 18:39:12 +0530589 hdd_enable_gtk_offload(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530590 hdd_enable_arp_offload(adapter, trigger);
591 hdd_enable_ns_offload(adapter, trigger);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +0530592 hdd_enable_mc_addr_filtering(adapter, trigger);
Dustin Brown1224e212017-05-12 14:02:12 -0700593 hdd_enable_hw_filter(adapter);
Pragaspathi Thilagarajb40c2602019-08-21 14:17:48 +0530594 hdd_enable_action_frame_patterns(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530595out:
Dustin Browne74003f2018-03-14 12:51:58 -0700596 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598}
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530599
Jeff Johnson75b737d2017-08-29 14:24:41 -0700600void hdd_disable_host_offloads(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530601 enum pmo_offload_trigger trigger)
602{
Dustin Brown491d54b2018-03-14 12:39:11 -0700603 hdd_enter();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530604
Dustin Brown89fa06e2018-09-07 10:47:27 -0700605 if (!ucfg_pmo_is_vdev_supports_offload(adapter->vdev)) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530606 hdd_info("offload is not supported on this vdev opmode: %d",
607 adapter->device_mode);
608 goto out;
609 }
610
Dustin Brown89fa06e2018-09-07 10:47:27 -0700611 if (!ucfg_pmo_is_vdev_connected(adapter->vdev)) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530612 hdd_info("vdev is not connected");
613 goto out;
614 }
615
Dustin Brownc1cdb712018-06-11 15:42:17 -0700616 hdd_debug("disable offloads");
Mukul Sharma3d36c392017-01-18 18:39:12 +0530617 hdd_disable_gtk_offload(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530618 hdd_disable_arp_offload(adapter, trigger);
619 hdd_disable_ns_offload(adapter, trigger);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +0530620 hdd_disable_mc_addr_filtering(adapter, trigger);
Dustin Brown1224e212017-05-12 14:02:12 -0700621 hdd_disable_hw_filter(adapter);
Pragaspathi Thilagarajb40c2602019-08-21 14:17:48 +0530622 hdd_disable_action_frame_patterns(adapter);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530623out:
Dustin Browne74003f2018-03-14 12:51:58 -0700624 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530625
626}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627
628/**
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800629 * hdd_lookup_ifaddr() - Lookup interface address data by name
630 * @adapter: the adapter whose name should be searched for
631 *
632 * return in_ifaddr pointer on success, NULL for failure
633 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700634static struct in_ifaddr *hdd_lookup_ifaddr(struct hdd_adapter *adapter)
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800635{
636 struct in_ifaddr *ifa;
637 struct in_device *in_dev;
638
639 if (!adapter) {
640 hdd_err("adapter is null");
641 return NULL;
642 }
643
644 in_dev = __in_dev_get_rtnl(adapter->dev);
645 if (!in_dev) {
646 hdd_err("Failed to get in_device");
647 return NULL;
648 }
649
650 /* lookup address data by interface name */
651 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
652 if (!strcmp(adapter->dev->name, ifa->ifa_label))
653 return ifa;
654 }
655
656 return NULL;
657}
658
659/**
660 * hdd_populate_ipv4_addr() - Populates the adapter's IPv4 address
661 * @adapter: the adapter whose IPv4 address is desired
662 * @ipv4_addr: the address of the array to copy the IPv4 address into
663 *
664 * return: zero for success; non-zero for failure
665 */
Jeff Johnsond6d1f632017-10-06 20:06:10 -0700666static int hdd_populate_ipv4_addr(struct hdd_adapter *adapter,
667 uint8_t *ipv4_addr)
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800668{
669 struct in_ifaddr *ifa;
670 int i;
671
672 if (!adapter) {
673 hdd_err("adapter is null");
674 return -EINVAL;
675 }
676
677 if (!ipv4_addr) {
678 hdd_err("ipv4_addr is null");
679 return -EINVAL;
680 }
681
682 ifa = hdd_lookup_ifaddr(adapter);
683 if (!ifa || !ifa->ifa_local) {
684 hdd_err("ipv4 address not found");
685 return -EINVAL;
686 }
687
688 /* convert u32 to byte array */
689 for (i = 0; i < 4; i++)
690 ipv4_addr[i] = (ifa->ifa_local >> i * 8) & 0xff;
691
692 return 0;
693}
694
695/**
696 * hdd_set_grat_arp_keepalive() - Enable grat APR keepalive
697 * @adapter: the HDD adapter to configure
698 *
699 * This configures gratuitous APR keepalive based on the adapter's current
700 * connection information, specifically IPv4 address and BSSID
701 *
702 * return: zero for success, non-zero for failure
703 */
Jeff Johnson75b737d2017-08-29 14:24:41 -0700704static int hdd_set_grat_arp_keepalive(struct hdd_adapter *adapter)
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800705{
706 QDF_STATUS status;
707 int exit_code;
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700708 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -0700709 struct hdd_station_ctx *sta_ctx;
Jeff Johnson562ccad2019-02-06 22:10:24 -0800710 struct keep_alive_req req = {
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800711 .packetType = SIR_KEEP_ALIVE_UNSOLICIT_ARP_RSP,
Dustin Brownce5b3d32018-01-17 15:07:38 -0800712 .dest_macaddr = QDF_MAC_ADDR_BCAST_INIT,
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800713 };
714
715 if (!adapter) {
716 hdd_err("adapter is null");
717 return -EINVAL;
718 }
719
720 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
721 if (!hdd_ctx) {
722 hdd_err("hdd_ctx is null");
723 return -EINVAL;
724 }
725
726 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
727 if (!sta_ctx) {
728 hdd_err("sta_ctx is null");
729 return -EINVAL;
730 }
731
732 exit_code = hdd_populate_ipv4_addr(adapter, req.hostIpv4Addr);
733 if (exit_code) {
734 hdd_err("Failed to populate ipv4 address");
735 return exit_code;
736 }
737
Dustin Brown6b4643d2017-02-09 12:19:28 -0800738 /* according to RFC5227, sender/target ip address should be the same */
739 qdf_mem_copy(&req.destIpv4Addr, &req.hostIpv4Addr,
740 sizeof(req.destIpv4Addr));
741
Jeff Johnsone04b6992019-02-27 14:06:55 -0800742 qdf_copy_macaddr(&req.bssid, &sta_ctx->conn_info.bssid);
Dustin Brown05d81302018-09-11 16:49:22 -0700743 ucfg_mlme_get_sta_keep_alive_period(hdd_ctx->psoc, &req.timePeriod);
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800744 req.sessionId = adapter->vdev_id;
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800745
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -0800746 hdd_debug("Setting gratuitous ARP keepalive; ipv4_addr:%u.%u.%u.%u",
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800747 req.hostIpv4Addr[0], req.hostIpv4Addr[1],
748 req.hostIpv4Addr[2], req.hostIpv4Addr[3]);
749
Jeff Johnson2954ded2018-06-13 16:34:49 -0700750 status = sme_set_keep_alive(hdd_ctx->mac_handle, req.sessionId, &req);
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800751 if (QDF_IS_STATUS_ERROR(status)) {
752 hdd_err("Failed to set keepalive");
753 return qdf_status_to_os_return(status);
754 }
755
756 return 0;
757}
758
759/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760 * __hdd_ipv4_notifier_work_queue() - IPv4 notification work function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800761 * @adapter: adapter whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762 *
763 * This function performs the work initially trigged by a callback
764 * from the IPv4 netdev notifier. Since this means there has been a
765 * change in IPv4 state for the interface, the ARP offload is
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530766 * reconfigured. Also, Updates the HLP IE info with IP address info
767 * to fw if LFR3 is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768 *
769 * Return: None
770 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800771static void __hdd_ipv4_notifier_work_queue(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700773 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700774 int errno;
Jeff Johnson61b5e982018-03-15 11:33:31 -0700775 struct csr_roam_profile *roam_profile;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530776 struct in_ifaddr *ifa;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +0530777 enum station_keepalive_method val;
778 QDF_STATUS status;
Dustin Brownb6b0f182017-03-08 13:08:27 -0800779
Dustin Brown491d54b2018-03-14 12:39:11 -0700780 hdd_enter();
Dustin Brownb6b0f182017-03-08 13:08:27 -0800781
Dustin Brownf13b8c32017-05-19 17:23:08 -0700782 errno = hdd_validate_adapter(adapter);
783 if (errno)
784 goto exit;
Dustin Brownb6b0f182017-03-08 13:08:27 -0800785
786 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700787 errno = wlan_hdd_validate_context(hdd_ctx);
788 if (errno)
789 goto exit;
790
791 hdd_enable_arp_offload(adapter, pmo_ipv4_change_notify);
792
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +0530793 status = ucfg_mlme_get_sta_keepalive_method(hdd_ctx->psoc, &val);
794 if (QDF_IS_STATUS_ERROR(status))
795 goto exit;
796
797 if (val == MLME_STA_KEEPALIVE_GRAT_ARP)
Dustin Brownb6b0f182017-03-08 13:08:27 -0800798 hdd_set_grat_arp_keepalive(adapter);
799
Vignesh Viswanathan731186f2017-09-18 13:47:37 +0530800 hdd_debug("FILS Roaming support: %d",
801 hdd_ctx->is_fils_roaming_supported);
Jeff Johnsona0c1ca72018-03-18 14:52:03 -0700802 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathan731186f2017-09-18 13:47:37 +0530803
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530804 ifa = hdd_lookup_ifaddr(adapter);
Vignesh Viswanathan731186f2017-09-18 13:47:37 +0530805 if (ifa && hdd_ctx->is_fils_roaming_supported)
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800806 sme_send_hlp_ie_info(hdd_ctx->mac_handle, adapter->vdev_id,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +0530807 roam_profile, ifa->ifa_local);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700808exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700809 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810}
811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812void hdd_ipv4_notifier_work_queue(struct work_struct *work)
813{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800814 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
815 ipv4_notifier_work);
816 struct osif_vdev_sync *vdev_sync;
817
818 if (osif_vdev_sync_op_start(adapter->dev, &vdev_sync))
819 return;
820
821 __hdd_ipv4_notifier_work_queue(adapter);
822
823 osif_vdev_sync_op_stop(vdev_sync);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824}
825
826/**
827 * __wlan_hdd_ipv4_changed() - IPv4 notifier callback function
Dustin Brown39b33ba2019-02-27 10:54:56 -0800828 * @net_dev: the net_device whose IP address changed
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800829 *
830 * This is a callback function that is registered with the kernel via
831 * register_inetaddr_notifier() which allows the driver to be
832 * notified when there is an IPv4 address change.
833 *
Dustin Brown39b33ba2019-02-27 10:54:56 -0800834 * Return: None
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835 */
Dustin Brown39b33ba2019-02-27 10:54:56 -0800836static void __wlan_hdd_ipv4_changed(struct net_device *net_dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800838 struct in_ifaddr *ifa;
839 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700840 struct hdd_context *hdd_ctx;
Dustin Brownf13b8c32017-05-19 17:23:08 -0700841 int errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842
Dustin Brown39b33ba2019-02-27 10:54:56 -0800843 hdd_enter_dev(net_dev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530844
Dustin Brownf13b8c32017-05-19 17:23:08 -0700845 errno = hdd_validate_adapter(adapter);
Dustin Brown39b33ba2019-02-27 10:54:56 -0800846 if (errno || adapter->dev != net_dev)
847 goto exit;
848
849 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
850 errno = wlan_hdd_validate_context(hdd_ctx);
Dustin Brownf13b8c32017-05-19 17:23:08 -0700851 if (errno)
852 goto exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853
Dustin Brown39b33ba2019-02-27 10:54:56 -0800854 if (adapter->device_mode == QDF_STA_MODE ||
855 adapter->device_mode == QDF_P2P_CLIENT_MODE ||
856 adapter->device_mode == QDF_NDI_MODE) {
Padma, Santhosh Kumar8392fb42017-03-17 12:35:27 +0530857 hdd_debug("invoking sme_dhcp_done_ind");
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800858 sme_dhcp_done_ind(hdd_ctx->mac_handle, adapter->vdev_id);
Abhishek Singhca408032016-09-13 15:26:12 +0530859
Wu Gao66454f12018-09-26 19:55:41 +0800860 if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc)) {
861 hdd_debug("Offload not enabled");
Dustin Brownf13b8c32017-05-19 17:23:08 -0700862 goto exit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800863 }
864
Dustin Brownf13b8c32017-05-19 17:23:08 -0700865 ifa = hdd_lookup_ifaddr(adapter);
Dustin Brown3c31ceb2017-02-01 14:43:52 -0800866 if (ifa && ifa->ifa_local)
Jeff Johnsonb527ebe2017-10-28 13:14:03 -0700867 schedule_work(&adapter->ipv4_notifier_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868 }
Dustin Brownf13b8c32017-05-19 17:23:08 -0700869
870exit:
Dustin Browne74003f2018-03-14 12:51:58 -0700871 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800872}
873
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874int wlan_hdd_ipv4_changed(struct notifier_block *nb,
Dustin Brown39b33ba2019-02-27 10:54:56 -0800875 unsigned long data, void *context)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876{
Dustin Brown39b33ba2019-02-27 10:54:56 -0800877 struct in_ifaddr *ifa = context;
878 struct net_device *net_dev = ifa->ifa_dev->dev;
879 struct osif_vdev_sync *vdev_sync;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800880
Dustin Brown39b33ba2019-02-27 10:54:56 -0800881 if (osif_vdev_sync_op_start(net_dev, &vdev_sync))
882 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883
Dustin Brown39b33ba2019-02-27 10:54:56 -0800884 __wlan_hdd_ipv4_changed(net_dev);
885
886 osif_vdev_sync_op_stop(vdev_sync);
887
888 return NOTIFY_DONE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889}
890
891/**
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530892 * hdd_get_ipv4_local_interface() - get ipv4 local interafce from iface list
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700893 * @adapter: Adapter context for which ARP offload is to be configured
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 *
895 * Return:
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530896 * ifa - on successful operation,
897 * NULL - on failure of operation
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898 */
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530899static struct in_ifaddr *hdd_get_ipv4_local_interface(
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700900 struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901{
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530902 struct in_ifaddr **ifap = NULL;
903 struct in_ifaddr *ifa = NULL;
904 struct in_device *in_dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800905
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700906 in_dev = __in_dev_get_rtnl(adapter->dev);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530907 if (in_dev) {
908 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
909 ifap = &ifa->ifa_next) {
Jeff Johnsonf6d24282017-10-02 13:25:25 -0700910 if (!strcmp(adapter->dev->name, ifa->ifa_label)) {
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530911 /* if match break */
912 return ifa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800913 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 }
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530915 }
916 ifa = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530918 return ifa;
919}
920
Jeff Johnson75b737d2017-08-29 14:24:41 -0700921void hdd_enable_arp_offload(struct hdd_adapter *adapter,
Dustin Brownc1cdb712018-06-11 15:42:17 -0700922 enum pmo_offload_trigger trigger)
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530923{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -0700924 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown05d81302018-09-11 16:49:22 -0700925 struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530926 QDF_STATUS status;
Dustin Brownc1cdb712018-06-11 15:42:17 -0700927 struct pmo_arp_req *arp_req;
928 struct in_ifaddr *ifa;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530929
Dustin Brown491d54b2018-03-14 12:39:11 -0700930 hdd_enter();
Dustin Brownc1cdb712018-06-11 15:42:17 -0700931
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530932 arp_req = qdf_mem_malloc(sizeof(*arp_req));
Min Liu74a1a502018-10-10 19:59:07 +0800933 if (!arp_req)
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530934 goto out;
Jeff Johnson68755312017-02-10 11:46:55 -0800935
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530936 arp_req->psoc = psoc;
Jeff Johnson9597f3b2019-02-04 14:27:56 -0800937 arp_req->vdev_id = adapter->vdev_id;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530938 arp_req->trigger = trigger;
Jeff Johnson68755312017-02-10 11:46:55 -0800939
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530940 ifa = hdd_get_ipv4_local_interface(adapter);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700941 if (!ifa || !ifa->ifa_local) {
Dustin Brown5e89ef82018-03-14 11:50:23 -0700942 hdd_info("IP Address is not assigned");
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530943 status = QDF_STATUS_NOT_INITIALIZED;
Dustin Brownc1cdb712018-06-11 15:42:17 -0700944 goto free_req;
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530945 }
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530946
Dustin Brownc1cdb712018-06-11 15:42:17 -0700947 arp_req->ipv4_addr = (uint32_t)ifa->ifa_local;
948
Wu Gaod7dd6e42018-10-16 17:22:56 +0800949 status = ucfg_pmo_cache_arp_offload_req(arp_req);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700950 if (QDF_IS_STATUS_ERROR(status)) {
Dustin Brown0127a732018-07-19 14:06:34 -0700951 hdd_err("failed to cache arp offload req; status:%d", status);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700952 goto free_req;
953 }
954
Wu Gaod7dd6e42018-10-16 17:22:56 +0800955 status = ucfg_pmo_enable_arp_offload_in_fwr(adapter->vdev, trigger);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700956 if (QDF_IS_STATUS_ERROR(status)) {
Dustin Brown0127a732018-07-19 14:06:34 -0700957 hdd_err("failed arp offload config in fw; status:%d", status);
Dustin Brownc1cdb712018-06-11 15:42:17 -0700958 goto free_req;
959 }
960
961 hdd_wlan_offload_event(PMO_IPV4_ARP_REPLY_OFFLOAD, PMO_OFFLOAD_ENABLE);
962
963free_req:
964 qdf_mem_free(arp_req);
965
966out:
967 hdd_exit();
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530968}
969
Jeff Johnson75b737d2017-08-29 14:24:41 -0700970void hdd_disable_arp_offload(struct hdd_adapter *adapter,
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530971 enum pmo_offload_trigger trigger)
972{
973 QDF_STATUS status;
974
Dustin Brown491d54b2018-03-14 12:39:11 -0700975 hdd_enter();
Wu Gaod7dd6e42018-10-16 17:22:56 +0800976 status = ucfg_pmo_flush_arp_offload_req(adapter->vdev);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530977 if (status != QDF_STATUS_SUCCESS) {
978 hdd_err("Failed to flush arp Offload");
979 goto out;
Jeff Johnson68755312017-02-10 11:46:55 -0800980 }
981
Wu Gaod7dd6e42018-10-16 17:22:56 +0800982 status = ucfg_pmo_disable_arp_offload_in_fwr(adapter->vdev,
Jeff Johnsond6d1f632017-10-06 20:06:10 -0700983 trigger);
Mukul Sharma3ba26b82017-01-12 21:59:41 +0530984 if (status == QDF_STATUS_SUCCESS)
985 hdd_wlan_offload_event(PMO_IPV4_ARP_REPLY_OFFLOAD,
986 PMO_OFFLOAD_DISABLE);
987 else
988 hdd_info("fail to disable arp offload");
989out:
Dustin Browne74003f2018-03-14 12:51:58 -0700990 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991}
992
Jeff Johnson75b737d2017-08-29 14:24:41 -0700993void hdd_enable_mc_addr_filtering(struct hdd_adapter *adapter,
Dustin Brown0127a732018-07-19 14:06:34 -0700994 enum pmo_offload_trigger trigger)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995{
Jeff Johnson399c6272017-08-30 10:51:00 -0700996 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +0530997 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998
Dustin Brown491d54b2018-03-14 12:39:11 -0700999 hdd_enter();
Dustin Brown0127a732018-07-19 14:06:34 -07001000
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301001 if (wlan_hdd_validate_context(hdd_ctx))
1002 goto out;
Ravi Joshi24477b72016-07-19 15:45:09 -07001003
Dustin Brown0127a732018-07-19 14:06:34 -07001004 if (!hdd_adapter_is_connected_sta(adapter))
1005 goto out;
1006
Wu Gaod7dd6e42018-10-16 17:22:56 +08001007 status = ucfg_pmo_enable_mc_addr_filtering_in_fwr(hdd_ctx->psoc,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001008 adapter->vdev_id,
Dustin Brown0127a732018-07-19 14:06:34 -07001009 trigger);
Dustin Brownc1cdb712018-06-11 15:42:17 -07001010 if (QDF_IS_STATUS_ERROR(status))
Dustin Brown0127a732018-07-19 14:06:34 -07001011 hdd_err("failed to enable mc list; status:%d", status);
1012
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301013out:
Dustin Browne74003f2018-03-14 12:51:58 -07001014 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001015}
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301016
Jeff Johnson75b737d2017-08-29 14:24:41 -07001017void hdd_disable_mc_addr_filtering(struct hdd_adapter *adapter,
Dustin Brown0127a732018-07-19 14:06:34 -07001018 enum pmo_offload_trigger trigger)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301019{
Jeff Johnson399c6272017-08-30 10:51:00 -07001020 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown0127a732018-07-19 14:06:34 -07001021 QDF_STATUS status;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301022
Dustin Brown491d54b2018-03-14 12:39:11 -07001023 hdd_enter();
Dustin Brown0127a732018-07-19 14:06:34 -07001024
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301025 if (wlan_hdd_validate_context(hdd_ctx))
1026 goto out;
1027
Dustin Brown0127a732018-07-19 14:06:34 -07001028 if (!hdd_adapter_is_connected_sta(adapter))
1029 goto out;
1030
Wu Gaod7dd6e42018-10-16 17:22:56 +08001031 status = ucfg_pmo_disable_mc_addr_filtering_in_fwr(hdd_ctx->psoc,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001032 adapter->vdev_id,
Dustin Brown0127a732018-07-19 14:06:34 -07001033 trigger);
1034 if (QDF_IS_STATUS_ERROR(status))
1035 hdd_err("failed to disable mc list; status:%d", status);
Dustin Brown0f874482018-06-13 14:39:22 -07001036
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301037out:
Dustin Browne74003f2018-03-14 12:51:58 -07001038 hdd_exit();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301039}
1040
1041int hdd_cache_mc_addr_list(struct pmo_mc_addr_list_params *mc_list_config)
1042{
1043 QDF_STATUS status;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301044
Dustin Brown491d54b2018-03-14 12:39:11 -07001045 hdd_enter();
Wu Gaod7dd6e42018-10-16 17:22:56 +08001046 status = ucfg_pmo_cache_mc_addr_list(mc_list_config);
Dustin Browne74003f2018-03-14 12:51:58 -07001047 hdd_exit();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301048
Dustin Brown0f874482018-06-13 14:39:22 -07001049 return qdf_status_to_os_return(status);
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301050}
1051
Jeff Johnson75b737d2017-08-29 14:24:41 -07001052void hdd_disable_and_flush_mc_addr_list(struct hdd_adapter *adapter,
Dustin Brown0127a732018-07-19 14:06:34 -07001053 enum pmo_offload_trigger trigger)
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301054{
Jeff Johnson399c6272017-08-30 10:51:00 -07001055 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Dustin Brown0127a732018-07-19 14:06:34 -07001056 QDF_STATUS status;
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301057
Dustin Brown491d54b2018-03-14 12:39:11 -07001058 hdd_enter();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301059
Dustin Brown0127a732018-07-19 14:06:34 -07001060 if (!hdd_adapter_is_connected_sta(adapter))
1061 goto flush_mc_list;
1062
1063 /* disable mc list first because the mc list is cached in PMO */
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);
1069
1070flush_mc_list:
Wu Gaod7dd6e42018-10-16 17:22:56 +08001071 status = ucfg_pmo_flush_mc_addr_list(hdd_ctx->psoc,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001072 adapter->vdev_id);
Dustin Brown0127a732018-07-19 14:06:34 -07001073 if (QDF_IS_STATUS_ERROR(status))
Bala Venkatesha5c1eb82019-08-26 19:19:49 +05301074 hdd_debug("failed to flush mc list; status:%d", status);
Dustin Brown0f874482018-06-13 14:39:22 -07001075
Dustin Browne74003f2018-03-14 12:51:58 -07001076 hdd_exit();
Mukul Sharmaff2ac2e2017-01-16 15:51:29 +05301077}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078
1079/**
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001080 * hdd_update_conn_state_mask(): record info needed by wma_suspend_req
1081 * @adapter: adapter to get info from
1082 * @conn_state_mask: mask of connection info
1083 *
1084 * currently only need to send connection info.
1085 */
Jeff Johnsond6d1f632017-10-06 20:06:10 -07001086static void hdd_update_conn_state_mask(struct hdd_adapter *adapter,
1087 uint32_t *conn_state_mask)
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001088{
1089
Jeff Johnsone7951512019-02-27 10:02:51 -08001090 eConnectionState conn_state;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07001091 struct hdd_station_ctx *sta_ctx;
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301092
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001093 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301094
Jeff Johnsone7951512019-02-27 10:02:51 -08001095 conn_state = sta_ctx->conn_info.conn_state;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001096
Jeff Johnsone7951512019-02-27 10:02:51 -08001097 if (conn_state == eConnectionState_Associated ||
1098 conn_state == eConnectionState_IbssConnected)
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001099 *conn_state_mask |= (1 << adapter->vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001100}
1101
1102/**
1103 * hdd_suspend_wlan() - Driver suspend function
1104 * @callback: Callback function to invoke when driver is ready to suspend
1105 * @callbackContext: Context to pass back to @callback function
1106 *
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301107 * Return: 0 on success else error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 */
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301109static int
1110hdd_suspend_wlan(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001112 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301113 QDF_STATUS status;
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001114 struct hdd_adapter *adapter = NULL;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001115 uint32_t conn_state_mask = 0;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07001116
Jeff Johnsonc3273322016-07-06 15:28:17 -07001117 hdd_info("WLAN being suspended by OS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001119 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1120 if (!hdd_ctx) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001121 hdd_err("HDD context is Null");
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301122 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001123 }
1124
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +05301125 if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001126 hdd_info("Recovery in Progress. State: 0x%x Ignore suspend!!!",
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001127 cds_get_driver_state());
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301128 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001129 }
1130
Dustin Brown920397d2017-12-13 16:27:50 -08001131 hdd_for_each_adapter(hdd_ctx, adapter) {
Jeff Johnson48363022019-02-24 16:26:51 -08001132 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown920397d2017-12-13 16:27:50 -08001133 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134
1135 /* stop all TX queues before suspend */
Dustin Brownc1cdb712018-06-11 15:42:17 -07001136 hdd_debug("Disabling queues for dev mode %s",
Dustin Brown458027c2018-10-19 12:26:27 -07001137 qdf_opmode_str(adapter->device_mode));
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001138 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +05301139 WLAN_STOP_ALL_NETIF_QUEUE,
1140 WLAN_CONTROL_PATH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141
Hanumanth Reddy Pothula3def8942017-10-05 16:19:36 +05301142 if (adapter->device_mode == QDF_STA_MODE)
1143 status = hdd_enable_default_pkt_filters(adapter);
1144
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001145 /* Configure supported OffLoads */
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001146 hdd_enable_host_offloads(adapter, pmo_apps_suspend);
1147 hdd_update_conn_state_mask(adapter, &conn_state_mask);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 }
1149
Wu Gaod7dd6e42018-10-16 17:22:56 +08001150 status = ucfg_pmo_psoc_user_space_suspend_req(hdd_ctx->psoc,
1151 QDF_SYSTEM_SUSPEND);
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301152 if (status != QDF_STATUS_SUCCESS)
1153 return -EAGAIN;
Houston Hoffman7260ecb2015-10-05 18:43:07 -07001154
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001155 hdd_ctx->hdd_wlan_suspended = true;
Abhishek Singhbaea27d2016-04-27 13:29:30 +05301156 hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_SUSPEND);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301158 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001159}
1160
1161/**
1162 * hdd_resume_wlan() - Driver resume function
1163 *
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301164 * Return: 0 on success else error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 */
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301166static int hdd_resume_wlan(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001167{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001168 struct hdd_context *hdd_ctx;
Dustin Brownc1cdb712018-06-11 15:42:17 -07001169 struct hdd_adapter *adapter;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301170 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171
Dustin Brown2d228232016-09-22 15:06:19 -07001172 hdd_info("WLAN being resumed by OS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001173
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001174 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1175 if (!hdd_ctx) {
Dustin Brown2d228232016-09-22 15:06:19 -07001176 hdd_err("HDD context is Null");
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301177 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001178 }
1179
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +05301180 if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001181 hdd_info("Recovery in Progress. State: 0x%x Ignore resume!!!",
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001182 cds_get_driver_state());
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301183 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001184 }
1185
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001186 hdd_ctx->hdd_wlan_suspended = false;
Abhishek Singhbaea27d2016-04-27 13:29:30 +05301187 hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_RESUME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001188
1189 /*loop through all adapters. Concurrency */
Dustin Brown920397d2017-12-13 16:27:50 -08001190 hdd_for_each_adapter(hdd_ctx, adapter) {
Jeff Johnson48363022019-02-24 16:26:51 -08001191 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown920397d2017-12-13 16:27:50 -08001192 continue;
Dustin Brown63500612018-08-07 11:36:09 -07001193
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301194 /* Disable supported OffLoads */
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001195 hdd_disable_host_offloads(adapter, pmo_apps_resume);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196
1197 /* wake the tx queues */
Dustin Brownc1cdb712018-06-11 15:42:17 -07001198 hdd_debug("Enabling queues for dev mode %s",
Dustin Brown458027c2018-10-19 12:26:27 -07001199 qdf_opmode_str(adapter->device_mode));
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001200 wlan_hdd_netif_queue_control(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201 WLAN_WAKE_ALL_NETIF_QUEUE,
1202 WLAN_CONTROL_PATH);
1203
Hanumanth Reddy Pothula3def8942017-10-05 16:19:36 +05301204 if (adapter->device_mode == QDF_STA_MODE)
1205 status = hdd_disable_default_pkt_filters(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 }
Dustin Brown920397d2017-12-13 16:27:50 -08001207
Dustin Brown07901ec2018-09-07 11:02:41 -07001208 ucfg_ipa_resume(hdd_ctx->pdev);
Wu Gaod7dd6e42018-10-16 17:22:56 +08001209 status = ucfg_pmo_psoc_user_space_resume_req(hdd_ctx->psoc,
Dustin Brownc1cdb712018-06-11 15:42:17 -07001210 QDF_SYSTEM_SUSPEND);
1211 if (QDF_IS_STATUS_ERROR(status))
1212 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301214 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215}
1216
Komal Seelam78ff65a2016-08-18 15:25:24 +05301217void hdd_svc_fw_shutdown_ind(struct device *dev)
1218{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001219 struct hdd_context *hdd_ctx;
Komal Seelam78ff65a2016-08-18 15:25:24 +05301220
1221 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1222
1223 hdd_ctx ? wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
1224 WLAN_SVC_FW_SHUTDOWN_IND,
1225 NULL, 0) : 0;
1226}
1227
1228/**
Arun Khandavallicc544b32017-01-30 19:52:16 +05301229 * hdd_ssr_restart_sap() - restart sap on SSR
1230 * @hdd_ctx: hdd context
1231 *
1232 * Return: nothing
1233 */
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001234static void hdd_ssr_restart_sap(struct hdd_context *hdd_ctx)
Arun Khandavallicc544b32017-01-30 19:52:16 +05301235{
Jeff Johnson75b737d2017-08-29 14:24:41 -07001236 struct hdd_adapter *adapter;
Arun Khandavallicc544b32017-01-30 19:52:16 +05301237
Dustin Brown491d54b2018-03-14 12:39:11 -07001238 hdd_enter();
Arun Khandavallicc544b32017-01-30 19:52:16 +05301239
Dustin Brown920397d2017-12-13 16:27:50 -08001240 hdd_for_each_adapter(hdd_ctx, adapter) {
1241 if (adapter->device_mode == QDF_SAP_MODE) {
Manikandan Mohan0a0ac952017-02-16 15:49:31 -08001242 if (test_bit(SOFTAP_INIT_DONE, &adapter->event_flags)) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001243 hdd_debug("Restart prev SAP session");
Manikandan Mohan0a0ac952017-02-16 15:49:31 -08001244 wlan_hdd_start_sap(adapter, true);
1245 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301246 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05301247 }
1248
Dustin Browne74003f2018-03-14 12:51:58 -07001249 hdd_exit();
Arun Khandavallicc544b32017-01-30 19:52:16 +05301250}
1251
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301252QDF_STATUS hdd_wlan_shutdown(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001254 struct hdd_context *hdd_ctx;
Manikandan Mohan8b4e2012017-03-22 11:15:55 -07001255 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001257 hdd_info("WLAN driver shutting down!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 /* Get the HDD context. */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001260 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1261 if (!hdd_ctx) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001262 hdd_err("HDD context is Null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301263 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 }
1265
Rajeev Kumarc27efb62018-08-31 14:21:22 -07001266 hdd_bus_bw_compute_timer_stop(hdd_ctx);
Bala Venkatesh23561582019-09-03 17:45:45 +05301267 hdd_set_connection_in_progress(false);
Dustin Brown05d81302018-09-11 16:49:22 -07001268 policy_mgr_clear_concurrent_session_count(hdd_ctx->psoc);
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05301269
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001270 hdd_debug("Invoking packetdump deregistration API");
Himanshu Agarwalf65bd4c2016-12-05 17:21:12 +05301271 wlan_deregister_txrx_packetdump();
jitiphilfb410612018-03-26 22:37:56 +05301272
Rajeev Kumar9f461582018-09-27 18:24:47 -07001273 /* resume wlan threads before adapter reset which does vdev destroy */
1274 if (hdd_ctx->is_scheduler_suspended) {
1275 scheduler_resume();
1276 hdd_ctx->is_scheduler_suspended = false;
1277 hdd_ctx->is_wiphy_suspended = false;
1278 }
1279
Lin Baif5e8cc22018-11-05 10:57:38 +08001280 wlan_hdd_rx_thread_resume(hdd_ctx);
Rajeev Kumar9f461582018-09-27 18:24:47 -07001281
Mohit Khanna7a2116a2019-09-17 15:34:18 -07001282 dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
1283
jitiphilfb410612018-03-26 22:37:56 +05301284 /*
1285 * After SSR, FW clear its txrx stats. In host,
1286 * as adapter is intact so those counts are still
1287 * available. Now if agains Set stats command comes,
1288 * then host will increment its counts start from its
1289 * last saved value, i.e., count before SSR, and FW will
1290 * increment its count from 0. This will finally sends a
1291 * mismatch of packet counts b/w host and FW to framework
1292 * that will create ambiquity. Therfore, Resetting the host
1293 * counts here so that after SSR both FW and host start
1294 * increment their counts from 0.
1295 */
1296 hdd_reset_all_adapters_connectivity_stats(hdd_ctx);
Abhishek Singh0d0568a2018-11-22 15:01:51 +05301297 /*
1298 * Purge all active and pending list to avoid vdev destroy timeout and
1299 * thus avoid peer/vdev refcount leak.
1300 */
1301 sme_purge_pdev_all_ser_cmd_list(hdd_ctx->mac_handle);
jitiphilfb410612018-03-26 22:37:56 +05301302
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001303 hdd_reset_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001304
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05301305 ucfg_ipa_uc_ssr_cleanup(hdd_ctx->pdev);
1306
Poddar, Siddarth1ab0a3d2016-09-29 18:58:45 +05301307 /* Flush cached rx frame queue */
Manikandan Mohan8b4e2012017-03-22 11:15:55 -07001308 if (soc)
1309 cdp_flush_cache_rx_queue(soc);
Poddar, Siddarth1ab0a3d2016-09-29 18:58:45 +05301310
Arun Khandavalli4b55da72016-07-19 19:55:01 +05301311 /* De-register the HDD callbacks */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001312 hdd_deregister_cb(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001313
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001314 hdd_wlan_stop_modules(hdd_ctx, false);
Manishekar Chandrasekaranf7a1dad2016-06-23 06:43:47 +05301315
Dustin Brown86d196b2018-08-02 11:51:49 -07001316 hdd_bus_bandwidth_deinit(hdd_ctx);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001317 hdd_lpass_notify_stop(hdd_ctx);
Yuanyuan Liu3e918e52016-08-17 15:41:35 -07001318
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001319 hdd_info("WLAN driver shutdown complete");
Yue Ma2be12872017-06-02 13:06:58 -07001320
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301321 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322}
1323
Sen, Devendra154b3c42017-02-13 20:44:15 +05301324#ifdef FEATURE_WLAN_DIAG_SUPPORT
1325/**
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301326 * hdd_wlan_ssr_reinit_event()- send ssr reinit state
1327 *
1328 * This Function send send ssr reinit state diag event
1329 *
1330 * Return: void.
1331 */
Sen, Devendra154b3c42017-02-13 20:44:15 +05301332static void hdd_wlan_ssr_reinit_event(void)
1333{
1334 WLAN_HOST_DIAG_EVENT_DEF(ssr_reinit, struct host_event_wlan_ssr_reinit);
1335 qdf_mem_zero(&ssr_reinit, sizeof(ssr_reinit));
1336 ssr_reinit.status = SSR_SUB_SYSTEM_REINIT;
1337 WLAN_HOST_DIAG_EVENT_REPORT(&ssr_reinit,
1338 EVENT_WLAN_SSR_REINIT_SUBSYSTEM);
1339}
1340#else
1341static inline void hdd_wlan_ssr_reinit_event(void)
1342{
1343
1344}
1345#endif
1346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347/**
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301348 * hdd_send_default_scan_ies - send default scan ies to fw
1349 *
1350 * This function is used to send default scan ies to fw
1351 * in case of wlan re-init
1352 *
1353 * Return: void
1354 */
1355static void hdd_send_default_scan_ies(struct hdd_context *hdd_ctx)
1356{
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301357 struct hdd_adapter *adapter;
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301358
Dustin Brown920397d2017-12-13 16:27:50 -08001359 hdd_for_each_adapter(hdd_ctx, adapter) {
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301360 if (hdd_is_interface_up(adapter) &&
1361 (adapter->device_mode == QDF_STA_MODE ||
Hanumanth Reddy Pothula53dec122017-12-12 17:08:18 +05301362 adapter->device_mode == QDF_P2P_DEVICE_MODE) &&
1363 adapter->scan_info.default_scan_ies) {
Jeff Johnson2954ded2018-06-13 16:34:49 -07001364 sme_set_default_scan_ie(hdd_ctx->mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001365 adapter->vdev_id,
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301366 adapter->scan_info.default_scan_ies,
1367 adapter->scan_info.default_scan_ies_len);
1368 }
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301369 }
1370}
1371
Arunk Khandavalli987c8d52018-06-21 17:40:31 +05301372/**
1373 * hdd_is_interface_down_during_ssr - Check if the interface went down during
1374 * SSR
1375 * @hdd_ctx: HDD context
1376 *
1377 * Check if any of the interface went down while the device is recovering.
1378 * If the interface went down close the session.
1379 */
1380static void hdd_is_interface_down_during_ssr(struct hdd_context *hdd_ctx)
1381{
1382 struct hdd_adapter *adapter = NULL, *pnext = NULL;
1383 QDF_STATUS status;
1384
1385 hdd_enter();
1386
1387 status = hdd_get_front_adapter(hdd_ctx, &adapter);
1388 while (adapter && status == QDF_STATUS_SUCCESS) {
1389 if (test_bit(DOWN_DURING_SSR, &adapter->event_flags)) {
1390 clear_bit(DOWN_DURING_SSR, &adapter->event_flags);
1391 hdd_stop_adapter(hdd_ctx, adapter);
1392 hdd_deinit_adapter(hdd_ctx, adapter, true);
1393 clear_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
1394 }
1395 status = hdd_get_next_adapter(hdd_ctx, adapter, &pnext);
1396 adapter = pnext;
1397 }
1398
1399 hdd_exit();
1400}
1401
Sourav Mohapatra9036f652019-04-02 15:02:59 +05301402/**
1403 * hdd_restore_sar_config - Restore the saved SAR config after SSR
1404 * @hdd_ctx: HDD context
1405 *
1406 * Restore the SAR config that was lost during SSR.
1407 *
1408 * Return: None
1409 */
1410static void hdd_restore_sar_config(struct hdd_context *hdd_ctx)
1411{
1412 QDF_STATUS status;
1413
1414 if (!hdd_ctx->sar_cmd_params)
1415 return;
1416
1417 status = sme_set_sar_power_limits(hdd_ctx->mac_handle,
1418 hdd_ctx->sar_cmd_params);
1419 if (QDF_IS_STATUS_ERROR(status))
1420 hdd_err("Unable to configured SAR after SSR");
1421}
1422
Arun Khandavallifae92942016-08-01 13:31:08 +05301423QDF_STATUS hdd_wlan_re_init(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001424{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001425 struct hdd_context *hdd_ctx = NULL;
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001426 struct hdd_adapter *adapter;
Arun Khandavallifae92942016-08-01 13:31:08 +05301427 int ret;
Mukul Sharmaf7d62e12016-09-03 15:16:22 +05301428 bool bug_on_reinit_failure = CFG_BUG_ON_REINIT_FAILURE_DEFAULT;
Bala Venkatesh2fde2c62018-09-11 20:33:24 +05301429 bool value;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430
1431 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
1432
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001433 /* Get the HDD context */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001434 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1435 if (!hdd_ctx) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001436 hdd_err("HDD context is Null");
Sourav Mohapatrab1260132018-08-21 14:42:55 +05301437 goto err_ctx_null;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438 }
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001439 bug_on_reinit_failure = hdd_ctx->config->bug_on_reinit_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440
Sourav Mohapatra92ea8d62018-02-05 10:03:10 +05301441 adapter = hdd_get_first_valid_adapter(hdd_ctx);
1442 if (!adapter)
1443 hdd_err("Failed to get adapter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001444
Nirav Shahd21a2e32018-04-20 16:34:43 +05301445 hdd_dp_trace_init(hdd_ctx->config);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001446 hdd_bus_bandwidth_init(hdd_ctx);
Prashanth Bhattaab004382016-10-11 16:08:11 -07001447
Dustin Browne7e71d32018-05-11 16:00:08 -07001448 ret = hdd_wlan_start_modules(hdd_ctx, true);
Arun Khandavallifae92942016-08-01 13:31:08 +05301449 if (ret) {
1450 hdd_err("Failed to start wlan after error");
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +05301451 goto err_re_init;
Arun Khandavallifae92942016-08-01 13:31:08 +05301452 }
1453
Ryan Hsuaadba072018-04-20 13:01:53 -07001454 hdd_update_hw_sw_info(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001456 wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
Wu Gao36717432016-11-21 15:09:48 +08001457 WLAN_SVC_FW_CRASHED_IND, NULL, 0);
1458
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459 /* Restart all adapters */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001460 hdd_start_all_adapters(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461
Paul Zhangcb573e02018-11-06 10:37:16 +08001462 hdd_init_scan_reject_params(hdd_ctx);
Sreelakshmi Konamkib53c6292017-03-01 13:13:23 +05301463
Selvaraj, Sridhar1c487562017-04-19 14:29:07 +05301464 hdd_set_roaming_in_progress(false);
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001465 complete(&adapter->roaming_comp_var);
Jeff Johnson59b19312017-11-02 21:14:33 -07001466 hdd_ctx->bt_coex_mode_set = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 /* Allow the phone to go to sleep */
1469 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301470 /* set chip power save failure detected callback */
Jeff Johnson2954ded2018-06-13 16:34:49 -07001471 sme_set_chip_pwr_save_fail_cb(hdd_ctx->mac_handle,
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301472 hdd_chip_pwr_save_fail_detected_cb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001473
Sourav Mohapatra9036f652019-04-02 15:02:59 +05301474 hdd_restore_sar_config(hdd_ctx);
1475
yeshwanth sriram guntukaea63f632017-08-30 19:31:56 +05301476 hdd_send_default_scan_ies(hdd_ctx);
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001477 hdd_info("WLAN host driver reinitiation completed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478
Dustin Brown05d81302018-09-11 16:49:22 -07001479 ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc, &value);
Bala Venkatesh2fde2c62018-09-11 20:33:24 +05301480 if (value)
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001481 hdd_ssr_restart_sap(hdd_ctx);
Arunk Khandavalli987c8d52018-06-21 17:40:31 +05301482 hdd_is_interface_down_during_ssr(hdd_ctx);
Sen, Devendra154b3c42017-02-13 20:44:15 +05301483 hdd_wlan_ssr_reinit_event();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301484 return QDF_STATUS_SUCCESS;
Sourav Mohapatrab1260132018-08-21 14:42:55 +05301485
1486err_re_init:
1487 hdd_bus_bandwidth_deinit(hdd_ctx);
1488 qdf_dp_trace_deinit();
1489
1490err_ctx_null:
1491 /* Allow the phone to go to sleep */
1492 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_REINIT);
1493 if (bug_on_reinit_failure)
1494 QDF_BUG(0);
1495 return -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001496}
1497
Jeff Johnson75b737d2017-08-29 14:24:41 -07001498int wlan_hdd_set_powersave(struct hdd_adapter *adapter,
Dustin Brownf660fb42016-09-09 12:04:00 -07001499 bool allow_power_save, uint32_t timeout)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500{
Jeff Johnson2954ded2018-06-13 16:34:49 -07001501 mac_handle_t mac_handle;
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001502 struct hdd_context *hdd_ctx;
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301503 QDF_STATUS status = QDF_STATUS_SUCCESS;
Pragaspathi Thilagaraj784c4922018-12-02 22:47:29 +05301504 bool is_bmps_enabled;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001505
Jeff Johnsond36fa332019-03-18 13:42:25 -07001506 if (!adapter) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001507 hdd_err("Adapter NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 return -ENODEV;
1509 }
1510
1511 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1512 if (!hdd_ctx) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07001513 hdd_err("hdd context is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001514 return -EINVAL;
1515 }
1516
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001517 hdd_debug("Allow power save: %d", allow_power_save);
Jeff Johnson2954ded2018-06-13 16:34:49 -07001518 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519
Dustin Brown84411b02017-07-21 16:44:44 -07001520 /*
1521 * This is a workaround for defective AP's that send a disassoc
1522 * immediately after WPS connection completes. Defer powersave by a
1523 * small amount if the affected AP is detected.
1524 */
1525 if (allow_power_save &&
1526 adapter->device_mode == QDF_STA_MODE &&
Jeff Johnsonb9424862017-10-30 08:49:35 -07001527 !adapter->session.station.ap_supports_immediate_power_save) {
Dustin Brown84411b02017-07-21 16:44:44 -07001528 timeout = AUTO_PS_DEFER_TIMEOUT_MS;
1529 hdd_debug("Defer power-save due to AP spec non-conformance");
Krunal Soni364e0872017-05-10 21:24:34 -07001530 }
1531
Dustin Brownf660fb42016-09-09 12:04:00 -07001532 if (allow_power_save) {
1533 if (QDF_STA_MODE == adapter->device_mode ||
1534 QDF_P2P_CLIENT_MODE == adapter->device_mode) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001535 hdd_debug("Disabling Auto Power save timer");
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301536 status = sme_ps_disable_auto_ps_timer(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001537 adapter->vdev_id);
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301538 if (status != QDF_STATUS_SUCCESS)
1539 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540 }
Dustin Brownf660fb42016-09-09 12:04:00 -07001541
Pragaspathi Thilagaraj784c4922018-12-02 22:47:29 +05301542 ucfg_mlme_is_bmps_enabled(hdd_ctx->psoc, &is_bmps_enabled);
1543 if (is_bmps_enabled) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001544 hdd_debug("Wlan driver Entering Power save");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545
1546 /*
1547 * Enter Power Save command received from GUI
1548 * this means DHCP is completed
1549 */
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301550 if (timeout) {
1551 status = sme_ps_enable_auto_ps_timer(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001552 adapter->vdev_id,
Yeshwanth Sriram Guntukaae03c432017-11-12 13:31:02 +05301553 timeout);
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301554 if (status != QDF_STATUS_SUCCESS)
1555 goto end;
1556 } else {
1557 status = sme_ps_enable_disable(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001558 adapter->vdev_id,
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301559 SME_PS_ENABLE);
1560 if (status != QDF_STATUS_SUCCESS)
1561 goto end;
1562 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 } else {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001564 hdd_debug("Power Save is not enabled in the cfg");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001565 }
Dustin Brownf660fb42016-09-09 12:04:00 -07001566 } else {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001567 hdd_debug("Wlan driver Entering Full Power");
Dustin Brownf660fb42016-09-09 12:04:00 -07001568
1569 /*
1570 * Enter Full power command received from GUI
1571 * this means we are disconnected
1572 */
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301573 status = sme_ps_disable_auto_ps_timer(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001574 adapter->vdev_id);
Krunal Soniee6309f2018-11-27 13:20:53 -08001575
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301576 if (status != QDF_STATUS_SUCCESS)
1577 goto end;
Krunal Soniee6309f2018-11-27 13:20:53 -08001578
Pragaspathi Thilagaraj784c4922018-12-02 22:47:29 +05301579 ucfg_mlme_is_bmps_enabled(hdd_ctx->psoc, &is_bmps_enabled);
1580 if (is_bmps_enabled)
Krunal Soniee6309f2018-11-27 13:20:53 -08001581 status = sme_ps_enable_disable(mac_handle,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001582 adapter->vdev_id,
Krunal Soniee6309f2018-11-27 13:20:53 -08001583 SME_PS_DISABLE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 }
Dustin Brownf660fb42016-09-09 12:04:00 -07001585
Bala Venkatesha0cd1f12018-08-29 15:43:43 +05301586end:
1587 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001588}
1589
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001590static void wlan_hdd_print_suspend_fail_stats(struct hdd_context *hdd_ctx)
Dustin Brown105d7902016-10-03 16:27:59 -07001591{
Dustin Brownd9322482017-01-09 12:46:03 -08001592 struct suspend_resume_stats *stats = &hdd_ctx->suspend_resume_stats;
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05301593
Dustin Brown105d7902016-10-03 16:27:59 -07001594 hdd_err("ipa:%d, radar:%d, roam:%d, scan:%d, initial_wakeup:%d",
Dustin Brownd9322482017-01-09 12:46:03 -08001595 stats->suspend_fail[SUSPEND_FAIL_IPA],
1596 stats->suspend_fail[SUSPEND_FAIL_RADAR],
1597 stats->suspend_fail[SUSPEND_FAIL_ROAM],
1598 stats->suspend_fail[SUSPEND_FAIL_SCAN],
1599 stats->suspend_fail[SUSPEND_FAIL_INITIAL_WAKEUP]);
Dustin Brown105d7902016-10-03 16:27:59 -07001600}
1601
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001602void wlan_hdd_inc_suspend_stats(struct hdd_context *hdd_ctx,
Dustin Brown105d7902016-10-03 16:27:59 -07001603 enum suspend_fail_reason reason)
1604{
1605 wlan_hdd_print_suspend_fail_stats(hdd_ctx);
Dustin Brownd9322482017-01-09 12:46:03 -08001606 hdd_ctx->suspend_resume_stats.suspend_fail[reason]++;
Dustin Brown105d7902016-10-03 16:27:59 -07001607 wlan_hdd_print_suspend_fail_stats(hdd_ctx);
1608}
1609
Dustin Brown5fbb1052017-08-11 17:25:51 -07001610#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1611static inline void
1612hdd_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
1613{
1614 cfg80211_sched_scan_results(wiphy);
1615}
1616#else
1617static inline void
1618hdd_sched_scan_results(struct wiphy *wiphy, uint64_t reqid)
1619{
1620 cfg80211_sched_scan_results(wiphy, reqid);
1621}
1622#endif
1623
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001624/**
1625 * __wlan_hdd_cfg80211_resume_wlan() - cfg80211 resume callback
1626 * @wiphy: Pointer to wiphy
1627 *
1628 * This API is called when cfg80211 driver resumes driver updates
1629 * latest sched_scan scan result(if any) to cfg80211 database
1630 *
1631 * Return: integer status
1632 */
1633static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
1634{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001635 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301636 QDF_STATUS status = QDF_STATUS_SUCCESS;
Dustin Brownd9322482017-01-09 12:46:03 -08001637 int exit_code;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638
Dustin Brown491d54b2018-03-14 12:39:11 -07001639 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001640
Dustin Brownd9322482017-01-09 12:46:03 -08001641 if (cds_is_driver_recovering()) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001642 hdd_debug("Driver is recovering; Skipping resume");
Dustin Brownd9322482017-01-09 12:46:03 -08001643 exit_code = 0;
1644 goto exit_with_code;
1645 }
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -07001646
Jinwei Chen763f9d72019-08-07 10:45:33 +08001647 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
1648 QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
1649 hdd_err("Command not allowed in mode %d",
1650 hdd_get_conparam());
Dustin Brownd9322482017-01-09 12:46:03 -08001651 exit_code = -EINVAL;
1652 goto exit_with_code;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001653 }
1654
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001655 exit_code = wlan_hdd_validate_context(hdd_ctx);
Dustin Brownd9322482017-01-09 12:46:03 -08001656 if (exit_code) {
1657 hdd_err("Invalid HDD context");
1658 goto exit_with_code;
1659 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301660
Rajeev Kumar83592e02019-05-06 14:33:22 -07001661 if (hdd_ctx->config->is_wow_disabled) {
1662 hdd_err("wow is disabled");
1663 return -EINVAL;
1664 }
1665
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001666 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001667 hdd_debug("Driver is not enabled; Skipping resume");
Dustin Brownd9322482017-01-09 12:46:03 -08001668 exit_code = 0;
1669 goto exit_with_code;
Arun Khandavallifae92942016-08-01 13:31:08 +05301670 }
Dustin Brownd9322482017-01-09 12:46:03 -08001671
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001672 pld_request_bus_bandwidth(hdd_ctx->parent_dev, PLD_BUS_WIDTH_MEDIUM);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301674 status = hdd_resume_wlan();
1675 if (status != QDF_STATUS_SUCCESS) {
1676 exit_code = 0;
1677 goto exit_with_code;
1678 }
Rajeev Kumareada0d02016-12-08 17:44:17 -08001679 /* Resume control path scheduler */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001680 if (hdd_ctx->is_scheduler_suspended) {
Rajeev Kumar0b732952016-12-08 17:51:39 -08001681 scheduler_resume();
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001682 hdd_ctx->is_scheduler_suspended = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001683 }
Mohit Khanna70322002018-05-15 19:21:32 -07001684
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 /* Resume tlshim Rx thread */
Lin Baif5e8cc22018-11-05 10:57:38 +08001686 if (hdd_ctx->enable_rxthread)
1687 wlan_hdd_rx_thread_resume(hdd_ctx);
Mohit Khanna70322002018-05-15 19:21:32 -07001688
1689 if (hdd_ctx->enable_dp_rx_threads)
1690 dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
1691
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05301692 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
1693 TRACE_CODE_HDD_CFG80211_RESUME_WLAN,
1694 NO_SESSION, hdd_ctx->is_wiphy_suspended);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001695
Jeff Johnson214671b2017-10-30 19:45:23 -07001696 hdd_ctx->is_wiphy_suspended = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001697
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001698 hdd_ctx->suspend_resume_stats.resumes++;
Dustin Brownd9322482017-01-09 12:46:03 -08001699 exit_code = 0;
1700
1701exit_with_code:
Dustin Browne74003f2018-03-14 12:51:58 -07001702 hdd_exit();
Dustin Brownd9322482017-01-09 12:46:03 -08001703 return exit_code;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001704}
1705
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001706static int _wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
1707{
Alan Chen91525f32019-08-21 15:57:08 -07001708 void *hif_ctx;
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001709 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001710 int errno;
1711
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001712 errno = wlan_hdd_validate_context(hdd_ctx);
Alan Chen91525f32019-08-21 15:57:08 -07001713 if (errno)
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001714 return errno;
1715
1716 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1717 hdd_debug("Driver Modules not Enabled ");
1718 return 0;
1719 }
1720
Alan Chen91525f32019-08-21 15:57:08 -07001721 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001722 errno = __wlan_hdd_cfg80211_resume_wlan(wiphy);
1723 hif_pm_runtime_put(hif_ctx);
1724
1725 return errno;
1726}
1727
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
1729{
Dustin Brown363b4792019-02-05 16:11:55 -08001730 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001731 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05301732
Dustin Brown363b4792019-02-05 16:11:55 -08001733 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001734 if (errno)
1735 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001737 errno = _wlan_hdd_cfg80211_resume_wlan(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738
Dustin Brown363b4792019-02-05 16:11:55 -08001739 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001740
1741 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742}
1743
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001744static void hdd_suspend_cb(void)
1745{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001746 struct hdd_context *hdd_ctx;
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001747
1748 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1749 if (!hdd_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001750 hdd_err("HDD context is NULL");
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001751 return;
1752 }
1753
1754 complete(&hdd_ctx->mc_sus_event_var);
1755}
1756
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001757/**
1758 * __wlan_hdd_cfg80211_suspend_wlan() - cfg80211 suspend callback
1759 * @wiphy: Pointer to wiphy
1760 * @wow: Pointer to wow
1761 *
1762 * This API is called when cfg80211 driver suspends
1763 *
1764 * Return: integer status
1765 */
1766static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
1767 struct cfg80211_wowlan *wow)
1768{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001769 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001770 struct hdd_adapter *adapter;
Jeff Johnson2954ded2018-06-13 16:34:49 -07001771 mac_handle_t mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001772 int rc;
1773
Dustin Brown491d54b2018-03-14 12:39:11 -07001774 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775
Jinwei Chen763f9d72019-08-07 10:45:33 +08001776 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
1777 QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
1778 hdd_err("Command not allowed in mode %d",
1779 hdd_get_conparam());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780 return -EINVAL;
1781 }
1782
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001783 rc = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301784 if (0 != rc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001785 return rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001786
Rajeev Kumar83592e02019-05-06 14:33:22 -07001787 if (hdd_ctx->config->is_wow_disabled) {
1788 hdd_err("wow is disabled");
1789 return -EINVAL;
1790 }
Jianmin Zhu16b94b12018-08-01 09:24:52 +08001791
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001792 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08001793 hdd_debug("Driver Modules not Enabled ");
Arun Khandavallifae92942016-08-01 13:31:08 +05301794 return 0;
1795 }
Arun Khandavallifae92942016-08-01 13:31:08 +05301796
Jeff Johnson2954ded2018-06-13 16:34:49 -07001797 mac_handle = hdd_ctx->mac_handle;
1798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001799 /* If RADAR detection is in progress (HDD), prevent suspend. The flag
1800 * "dfs_cac_block_tx" is set to true when RADAR is found and stay true
1801 * until CAC is done for a SoftAP which is in started state.
1802 */
Dustin Brown920397d2017-12-13 16:27:50 -08001803 hdd_for_each_adapter(hdd_ctx, adapter) {
Jeff Johnson48363022019-02-24 16:26:51 -08001804 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown920397d2017-12-13 16:27:50 -08001805 continue;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05301806
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001807 if (QDF_SAP_MODE == adapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808 if (BSS_START ==
Jeff Johnson0f9f87b2017-10-28 09:21:06 -07001809 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter)->bss_state &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 true ==
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001811 WLAN_HDD_GET_AP_CTX_PTR(adapter)->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812 dfs_cac_block_tx) {
Dustin Brown2d228232016-09-22 15:06:19 -07001813 hdd_err("RADAR detection in progress, do not allow suspend");
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001814 wlan_hdd_inc_suspend_stats(hdd_ctx,
Dustin Brown105d7902016-10-03 16:27:59 -07001815 SUSPEND_FAIL_RADAR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 return -EAGAIN;
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +05301817 } else if (!ucfg_pmo_get_enable_sap_suspend(
1818 hdd_ctx->psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819 /* return -EOPNOTSUPP if SAP does not support
1820 * suspend
1821 */
Jeff Johnsonc3273322016-07-06 15:28:17 -07001822 hdd_err("SAP does not support suspend!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 return -EOPNOTSUPP;
1824 }
Jeff Johnsonf6d24282017-10-02 13:25:25 -07001825 } else if (QDF_P2P_GO_MODE == adapter->device_mode) {
Rajeev Kumarafccd9a2019-05-02 12:55:14 -07001826 if (!ucfg_pmo_get_enable_sap_suspend(
Sourav Mohapatra0dfe5552018-11-16 11:29:54 +05301827 hdd_ctx->psoc)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001828 /* return -EOPNOTSUPP if GO does not support
1829 * suspend
1830 */
Jeff Johnsonc3273322016-07-06 15:28:17 -07001831 hdd_err("GO does not support suspend!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001832 return -EOPNOTSUPP;
1833 }
1834 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 }
Wu Gao4a1ec8c2018-07-23 19:18:40 +08001836 /* p2p cleanup task based on scheduler */
Dustin Brown05d81302018-09-11 16:49:22 -07001837 ucfg_p2p_cleanup_tx_by_psoc(hdd_ctx->psoc);
1838 ucfg_p2p_cleanup_roc_by_psoc(hdd_ctx->psoc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001839
gaurank kathpaliae5724cc2019-08-21 16:32:25 +05301840 if (hdd_is_connection_in_progress(NULL, NULL)) {
1841 hdd_err_rl("Connection is in progress, rejecting suspend");
1842 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 }
1844
gaurank kathpaliae5724cc2019-08-21 16:32:25 +05301845 /* abort ongoing scan and flush any pending powersave timers */
Dustin Brown6619bc22018-07-18 15:04:33 -07001846 hdd_for_each_adapter(hdd_ctx, adapter) {
gaurank kathpaliae5724cc2019-08-21 16:32:25 +05301847 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
1848 adapter->vdev_id, INVALID_SCAN_ID, false);
Jeff Johnson48363022019-02-24 16:26:51 -08001849 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Dustin Brown6619bc22018-07-18 15:04:33 -07001850 continue;
1851
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001852 sme_ps_timer_flush_sync(mac_handle, adapter->vdev_id);
Dustin Brown6619bc22018-07-18 15:04:33 -07001853 }
Dustin Brown84411b02017-07-21 16:44:44 -07001854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001855 /*
1856 * Suspend IPA early before proceeding to suspend other entities like
1857 * firmware to avoid any race conditions.
1858 */
Dustin Brown07901ec2018-09-07 11:02:41 -07001859 if (ucfg_ipa_suspend(hdd_ctx->pdev)) {
Dustin Brown2d228232016-09-22 15:06:19 -07001860 hdd_err("IPA not ready to suspend!");
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001861 wlan_hdd_inc_suspend_stats(hdd_ctx, SUSPEND_FAIL_IPA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 return -EAGAIN;
1863 }
1864
Rajeev Kumareada0d02016-12-08 17:44:17 -08001865 /* Suspend control path scheduler */
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001866 scheduler_register_hdd_suspend_callback(hdd_suspend_cb);
Manjeet Singh1a376ce2016-10-06 19:31:10 +05301867 scheduler_set_event_mask(MC_SUSPEND_EVENT);
Krunal Sonid32c6bc2016-10-18 18:00:21 -07001868 scheduler_wake_up_controller_thread();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869
Rajeev Kumareada0d02016-12-08 17:44:17 -08001870 /* Wait for suspend confirmation from scheduler */
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001871 rc = wait_for_completion_timeout(&hdd_ctx->mc_sus_event_var,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001872 msecs_to_jiffies(WLAN_WAIT_TIME_MCTHREAD_SUSPEND));
1873 if (!rc) {
Manjeet Singh1a376ce2016-10-06 19:31:10 +05301874 scheduler_clear_event_mask(MC_SUSPEND_EVENT);
Jeff Johnsonc3273322016-07-06 15:28:17 -07001875 hdd_err("Failed to stop mc thread");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876 goto resume_tx;
1877 }
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001878 hdd_ctx->is_scheduler_suspended = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879
Mohit Khanna70322002018-05-15 19:21:32 -07001880 if (hdd_ctx->enable_rxthread) {
Lin Baif5e8cc22018-11-05 10:57:38 +08001881 if (wlan_hdd_rx_thread_suspend(hdd_ctx))
Alok Kumar800c8462018-10-10 18:42:16 +05301882 goto resume_ol_rx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 }
Mohit Khanna70322002018-05-15 19:21:32 -07001884
1885 if (hdd_ctx->enable_dp_rx_threads)
1886 dp_txrx_suspend(cds_get_context(QDF_MODULE_ID_SOC));
1887
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05301888 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
1889 TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN,
1890 NO_SESSION, hdd_ctx->is_wiphy_suspended);
1891
Alok Kumar62bf7382018-10-08 16:53:39 +05301892 if (hdd_suspend_wlan() < 0) {
1893 hdd_err("Failed to suspend WLAN");
Alok Kumar800c8462018-10-10 18:42:16 +05301894 goto resume_dp_thread;
Alok Kumar62bf7382018-10-08 16:53:39 +05301895 }
Mukul Sharma4c60a7e2017-03-06 19:42:18 +05301896
Jeff Johnson214671b2017-10-30 19:45:23 -07001897 hdd_ctx->is_wiphy_suspended = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001899 pld_request_bus_bandwidth(hdd_ctx->parent_dev, PLD_BUS_WIDTH_NONE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900
Dustin Browne74003f2018-03-14 12:51:58 -07001901 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 return 0;
1903
Alok Kumar800c8462018-10-10 18:42:16 +05301904resume_dp_thread:
1905 if (hdd_ctx->enable_dp_rx_threads)
1906 dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
1907
1908resume_ol_rx:
Alok Kumar62bf7382018-10-08 16:53:39 +05301909 /* Resume tlshim Rx thread */
Lin Baif5e8cc22018-11-05 10:57:38 +08001910 wlan_hdd_rx_thread_resume(hdd_ctx);
Rajeev Kumar0b732952016-12-08 17:51:39 -08001911 scheduler_resume();
Jeff Johnson1a9b9792017-09-03 09:22:08 -07001912 hdd_ctx->is_scheduler_suspended = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913resume_tx:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001914 hdd_resume_wlan();
1915 return -ETIME;
1916
1917}
1918
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001919static int _wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
1920 struct cfg80211_wowlan *wow)
1921{
Alan Chen91525f32019-08-21 15:57:08 -07001922 void *hif_ctx;
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001923 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001924 int errno;
1925
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001926 errno = wlan_hdd_validate_context(hdd_ctx);
Alan Chen91525f32019-08-21 15:57:08 -07001927 if (errno)
Rajeev Kumarf06009a2019-08-20 18:29:59 -07001928 return errno;
1929
1930 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1931 hdd_debug("Driver Modules not Enabled ");
1932 return 0;
1933 }
1934
Alan Chen91525f32019-08-21 15:57:08 -07001935 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001936 errno = hif_pm_runtime_get_sync(hif_ctx);
1937 if (errno)
1938 return errno;
1939
1940 errno = __wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
1941 if (errno) {
1942 hif_pm_runtime_put(hif_ctx);
1943 return errno;
1944 }
1945
1946 return errno;
1947}
1948
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
1950 struct cfg80211_wowlan *wow)
1951{
Dustin Brown363b4792019-02-05 16:11:55 -08001952 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08001953 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05301954
Dustin Brown363b4792019-02-05 16:11:55 -08001955 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001956 if (errno)
1957 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958
Alan Chen6ccc4fa2019-08-15 14:11:46 -07001959 errno = _wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960
Dustin Brown363b4792019-02-05 16:11:55 -08001961 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08001962
1963 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964}
1965
1966/**
Komal Seelama89be8d2016-09-29 11:09:26 +05301967 * hdd_stop_dhcp_ind() - API to stop DHCP sequence
1968 * @adapter: Adapter on which DHCP needs to be stopped
1969 *
1970 * Release the wakelock held for DHCP process and allow
1971 * the runtime pm to continue
1972 *
1973 * Return: None
1974 */
Jeff Johnson75b737d2017-08-29 14:24:41 -07001975static void hdd_stop_dhcp_ind(struct hdd_adapter *adapter)
Komal Seelama89be8d2016-09-29 11:09:26 +05301976{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001977 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05301978
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08001979 hdd_debug("DHCP stop indicated through power save");
Jeff Johnson2954ded2018-06-13 16:34:49 -07001980 sme_dhcp_stop_ind(hdd_ctx->mac_handle, adapter->device_mode,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001981 adapter->mac_addr.bytes,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08001982 adapter->vdev_id);
Komal Seelama89be8d2016-09-29 11:09:26 +05301983 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DHCP);
Jingxiang Geb49aa302018-01-17 20:54:15 +08001984 qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.connect);
Komal Seelama89be8d2016-09-29 11:09:26 +05301985}
1986
1987/**
1988 * hdd_start_dhcp_ind() - API to start DHCP sequence
1989 * @adapter: Adapter on which DHCP needs to be stopped
1990 *
1991 * Prevent APPS suspend and the runtime suspend during
1992 * DHCP sequence
1993 *
1994 * Return: None
1995 */
Jeff Johnson75b737d2017-08-29 14:24:41 -07001996static void hdd_start_dhcp_ind(struct hdd_adapter *adapter)
Komal Seelama89be8d2016-09-29 11:09:26 +05301997{
Jeff Johnsoncfb65a82017-08-28 11:45:41 -07001998 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Komal Seelama89be8d2016-09-29 11:09:26 +05301999
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002000 hdd_debug("DHCP start indicated through power save");
Jingxiang Geb49aa302018-01-17 20:54:15 +08002001 qdf_runtime_pm_prevent_suspend(&hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -07002002 hdd_prevent_suspend_timeout(HDD_WAKELOCK_TIMEOUT_CONNECT,
2003 WIFI_POWER_EVENT_WAKELOCK_DHCP);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002004 sme_dhcp_start_ind(hdd_ctx->mac_handle, adapter->device_mode,
Jeff Johnson1e851a12017-10-28 14:36:12 -07002005 adapter->mac_addr.bytes,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002006 adapter->vdev_id);
Komal Seelama89be8d2016-09-29 11:09:26 +05302007}
2008
2009/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 * __wlan_hdd_cfg80211_set_power_mgmt() - set cfg80211 power management config
2011 * @wiphy: Pointer to wiphy
2012 * @dev: Pointer to network device
Dustin Brownf660fb42016-09-09 12:04:00 -07002013 * @allow_power_save: is wlan allowed to go into power save mode
2014 * @timeout: Timeout value in ms
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 *
2016 * Return: 0 for success, non-zero for failure
2017 */
2018static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Dustin Brownf660fb42016-09-09 12:04:00 -07002019 struct net_device *dev,
2020 bool allow_power_save,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021 int timeout)
2022{
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002023 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002024 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 int status;
2026
Dustin Brown491d54b2018-03-14 12:39:11 -07002027 hdd_enter();
Dustin Brownecfce632016-09-13 10:41:45 -07002028
Dustin Brownf660fb42016-09-09 12:04:00 -07002029 if (timeout < 0) {
Yeshwanth Sriram Guntukaae03c432017-11-12 13:31:02 +05302030 hdd_debug("User space timeout: %d; Enter full power or power save",
2031 timeout);
2032 timeout = 0;
Dustin Brownf660fb42016-09-09 12:04:00 -07002033 }
2034
Anurag Chouhan6d760662016-02-20 16:05:43 +05302035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07002036 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 return -EINVAL;
2038 }
2039
Jeff Johnson48363022019-02-24 16:26:51 -08002040 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05302041 return -EINVAL;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05302042
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05302043 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2044 TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002045 adapter->vdev_id, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002047 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002048 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302050 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002053 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002054 hdd_debug("Driver Module not enabled return success");
Arun Khandavalli99286452016-08-22 12:13:41 +05302055 return 0;
2056 }
Arun Khandavalli99286452016-08-22 12:13:41 +05302057
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002058 status = wlan_hdd_set_powersave(adapter, allow_power_save, timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059
Jeff Johnsonf6d24282017-10-02 13:25:25 -07002060 allow_power_save ? hdd_stop_dhcp_ind(adapter) :
2061 hdd_start_dhcp_ind(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062
Dustin Browne74003f2018-03-14 12:51:58 -07002063 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 return status;
2065}
2066
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002067int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Dustin Brownf660fb42016-09-09 12:04:00 -07002068 struct net_device *dev,
2069 bool allow_power_save,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 int timeout)
2071{
Dustin Brown1d31b082018-11-22 14:41:20 +05302072 int errno;
2073 struct osif_vdev_sync *vdev_sync;
2074
2075 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
2076 if (errno)
2077 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078
Dustin Brown1d31b082018-11-22 14:41:20 +05302079 errno = __wlan_hdd_cfg80211_set_power_mgmt(wiphy, dev, allow_power_save,
2080 timeout);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002081
Dustin Brown1d31b082018-11-22 14:41:20 +05302082 osif_vdev_sync_op_stop(vdev_sync);
2083
2084 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085}
2086
2087/**
2088 * __wlan_hdd_cfg80211_set_txpower() - set TX power
2089 * @wiphy: Pointer to wiphy
2090 * @wdev: Pointer to network device
2091 * @type: TX power setting type
Jeff Johnson9de31c02018-10-10 11:18:43 -07002092 * @mbm: TX power in mBm
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093 *
2094 * Return: 0 for success, non-zero for failure
2095 */
2096static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002097 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002098 enum nl80211_tx_power_setting type,
Jeff Johnson9de31c02018-10-10 11:18:43 -07002099 int mbm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100{
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002101 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002102 mac_handle_t mac_handle;
hangtian8215fde2019-07-10 12:27:19 +08002103 struct hdd_adapter *adapter;
Dustin Brownce5b3d32018-01-17 15:07:38 -08002104 struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
hangtian821d12d2019-06-11 11:53:50 +08002105 struct qdf_mac_addr selfmac;
Jeff Johnson2954ded2018-06-13 16:34:49 -07002106 QDF_STATUS status;
2107 int errno;
Jeff Johnson9de31c02018-10-10 11:18:43 -07002108 int dbm;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002109
Dustin Brown491d54b2018-03-14 12:39:11 -07002110 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111
hangtian8215fde2019-07-10 12:27:19 +08002112 if (!wdev) {
2113 hdd_err("wdev is null, set tx power failed");
2114 return -EIO;
2115 }
2116
2117 adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
2118
Anurag Chouhan6d760662016-02-20 16:05:43 +05302119 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07002120 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002121 return -EINVAL;
2122 }
2123
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05302124 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2125 TRACE_CODE_HDD_CFG80211_SET_TXPOWER,
2126 NO_SESSION, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127
Jeff Johnson2954ded2018-06-13 16:34:49 -07002128 errno = wlan_hdd_validate_context(hdd_ctx);
2129 if (errno)
2130 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131
hangtian821d12d2019-06-11 11:53:50 +08002132 if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
2133 return -EINVAL;
2134
2135 if (adapter->device_mode == QDF_SAP_MODE ||
2136 adapter->device_mode == QDF_P2P_GO_MODE) {
2137 qdf_copy_macaddr(&bssid, &adapter->mac_addr);
2138 } else {
2139 struct hdd_station_ctx *sta_ctx =
2140 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2141
2142 if (eConnectionState_Associated ==
2143 sta_ctx->conn_info.conn_state)
2144 qdf_copy_macaddr(&bssid, &sta_ctx->conn_info.bssid);
2145 }
2146
2147 qdf_copy_macaddr(&selfmac, &adapter->mac_addr);
2148
Jeff Johnson2954ded2018-06-13 16:34:49 -07002149 mac_handle = hdd_ctx->mac_handle;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002150
Jeff Johnson9de31c02018-10-10 11:18:43 -07002151 dbm = MBM_TO_DBM(mbm);
2152
2153 /*
2154 * the original implementation of this function expected power
2155 * values in dBm instead of mBm. If the conversion from mBm to
2156 * dBm is zero, then assume dBm was passed.
2157 */
2158 if (!dbm)
2159 dbm = mbm;
2160
Wu Gao5f764082019-01-04 15:54:38 +08002161 status = ucfg_mlme_set_current_tx_power_level(hdd_ctx->psoc, dbm);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002162 if (QDF_IS_STATUS_ERROR(status)) {
2163 hdd_err("sme_cfg_set_int failed for tx power %hu, %d",
2164 dbm, status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165 return -EIO;
2166 }
2167
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002168 hdd_debug("Set tx power level %d dbm", dbm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002169
2170 switch (type) {
2171 /* Automatically determine transmit power */
2172 case NL80211_TX_POWER_AUTOMATIC:
2173 /* Fall through */
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05302174 case NL80211_TX_POWER_LIMITED:
2175 /* Limit TX power by the mBm parameter */
hangtian821d12d2019-06-11 11:53:50 +08002176 status = sme_set_max_tx_power(mac_handle, bssid, selfmac, dbm);
Jeff Johnson2954ded2018-06-13 16:34:49 -07002177 if (QDF_IS_STATUS_ERROR(status)) {
2178 hdd_err("Setting maximum tx power failed, %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 return -EIO;
2180 }
2181 break;
2182
2183 case NL80211_TX_POWER_FIXED: /* Fix TX power to the mBm parameter */
Jeff Johnsonc3273322016-07-06 15:28:17 -07002184 hdd_err("NL80211_TX_POWER_FIXED not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 return -EOPNOTSUPP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186
2187 default:
Jeff Johnsonc3273322016-07-06 15:28:17 -07002188 hdd_err("Invalid power setting type %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189 return -EIO;
2190 }
2191
Dustin Browne74003f2018-03-14 12:51:58 -07002192 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 return 0;
2194}
2195
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002196int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002198 enum nl80211_tx_power_setting type,
Jeff Johnson9de31c02018-10-10 11:18:43 -07002199 int mbm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200{
Dustin Brown363b4792019-02-05 16:11:55 -08002201 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08002202 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05302203
Dustin Brown363b4792019-02-05 16:11:55 -08002204 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002205 if (errno)
2206 return errno;
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +05302207
Dustin Brownf0f00612019-01-31 16:02:24 -08002208 errno = __wlan_hdd_cfg80211_set_txpower(wiphy, wdev, type, mbm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209
Dustin Brown363b4792019-02-05 16:11:55 -08002210 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002211
2212 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002213}
2214
Naveen Rawate8b1b822018-01-30 09:46:16 -08002215static void wlan_hdd_get_tx_power(struct hdd_adapter *adapter, int *dbm)
2216{
Dustin Brown89fa06e2018-09-07 10:47:27 -07002217 wlan_cfg80211_mc_cp_stats_get_tx_power(adapter->vdev, dbm);
Naveen Rawate8b1b822018-01-30 09:46:16 -08002218}
Ashish Kumar Dhanotiya0929b962019-06-04 17:31:35 +05302219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220/**
2221 * __wlan_hdd_cfg80211_get_txpower() - get TX power
2222 * @wiphy: Pointer to wiphy
2223 * @wdev: Pointer to network device
2224 * @dbm: Pointer to TX power in dbm
2225 *
2226 * Return: 0 for success, non-zero for failure
2227 */
2228static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229 struct wireless_dev *wdev,
Srinivas Girigowda5557a392017-03-09 14:28:36 -08002230 int *dbm)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002231{
2232
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002233 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Srinivas Girigowda5557a392017-03-09 14:28:36 -08002234 struct net_device *ndev = wdev->netdev;
Jeff Johnson75b737d2017-08-29 14:24:41 -07002235 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236 int status;
Bala Venkatesh5d0fe412019-07-25 15:48:24 +05302237 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238
Dustin Brown63500612018-08-07 11:36:09 -07002239 hdd_enter_dev(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240
Anurag Chouhan6d760662016-02-20 16:05:43 +05302241 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonc3273322016-07-06 15:28:17 -07002242 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002243 return -EINVAL;
2244 }
2245
Dustin Brown63500612018-08-07 11:36:09 -07002246 *dbm = 0;
2247
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002248 status = wlan_hdd_validate_context(hdd_ctx);
Dustin Brown63500612018-08-07 11:36:09 -07002249 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002250 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251
Arun Khandavalli99286452016-08-22 12:13:41 +05302252 /* Validate adapter sessionId */
Jeff Johnson48363022019-02-24 16:26:51 -08002253 status = wlan_hdd_validate_vdev_id(adapter->vdev_id);
Dustin Brown63500612018-08-07 11:36:09 -07002254 if (status)
2255 return status;
Bala Venkatesh5d0fe412019-07-25 15:48:24 +05302256 switch (adapter->device_mode) {
2257 case QDF_STA_MODE:
2258 case QDF_P2P_CLIENT_MODE:
Paul Zhang3d7c0e62019-06-29 08:57:47 +08002259 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2260 if (sta_ctx->hdd_reassoc_scenario) {
2261 hdd_debug("Roaming is in progress, rej this req");
2262 return -EINVAL;
2263 }
Paul Zhang3d7c0e62019-06-29 08:57:47 +08002264 if (sta_ctx->conn_info.conn_state !=
2265 eConnectionState_Associated) {
2266 hdd_debug("Not associated");
2267 return 0;
2268 }
Bala Venkatesh5d0fe412019-07-25 15:48:24 +05302269 break;
2270 case QDF_SAP_MODE:
2271 case QDF_P2P_GO_MODE:
2272 if (!test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
2273 hdd_err("SAP is not started yet");
2274 return 0;
2275 }
2276 break;
2277 default:
2278 hdd_debug_rl("Current interface is not supported for get tx_power");
2279 return 0;
Abhinav Kumar50d4dc72018-06-15 16:35:50 +05302280 }
2281
Jeff Johnson1a9b9792017-09-03 09:22:08 -07002282 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda5d6bde62017-03-06 18:26:02 -08002283 hdd_debug("Driver Module not enabled return success");
Arun Khandavalli99286452016-08-22 12:13:41 +05302284 /* Send cached data to upperlayer*/
Jeff Johnson861dd4f2017-10-24 10:10:40 -07002285 *dbm = adapter->hdd_stats.class_a_stat.max_pwr;
Arun Khandavalli99286452016-08-22 12:13:41 +05302286 return 0;
2287 }
Arun Khandavalli99286452016-08-22 12:13:41 +05302288
Ashish Kumar Dhanotiyaf10aa5f2018-12-28 21:29:56 +05302289 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
2290 TRACE_CODE_HDD_CFG80211_GET_TXPOWER,
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002291 adapter->vdev_id, adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002292
Naveen Rawate8b1b822018-01-30 09:46:16 -08002293 wlan_hdd_get_tx_power(adapter, dbm);
2294 hdd_debug("power: %d", *dbm);
2295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002296 return 0;
2297}
2298
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002299int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 int *dbm)
2302{
Dustin Brown363b4792019-02-05 16:11:55 -08002303 struct osif_psoc_sync *psoc_sync;
Dustin Brownf0f00612019-01-31 16:02:24 -08002304 int errno;
Arunk Khandavalli447837f2018-11-08 14:32:53 +05302305
Dustin Brown363b4792019-02-05 16:11:55 -08002306 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002307 if (errno)
2308 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309
Dustin Brownf0f00612019-01-31 16:02:24 -08002310 errno = __wlan_hdd_cfg80211_get_txpower(wiphy, wdev, dbm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311
Dustin Brown363b4792019-02-05 16:11:55 -08002312 osif_psoc_sync_op_stop(psoc_sync);
Dustin Brownf0f00612019-01-31 16:02:24 -08002313
2314 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315}
Kapil Gupta6213c012016-09-02 19:39:09 +05302316
Jeff Johnson4fbee2f2017-10-03 11:19:35 -07002317int hdd_set_qpower_config(struct hdd_context *hddctx,
2318 struct hdd_adapter *adapter,
Dustin Brown10a7b712016-10-07 10:31:16 -07002319 u8 qpower)
Kapil Gupta6213c012016-09-02 19:39:09 +05302320{
Dustin Brown10a7b712016-10-07 10:31:16 -07002321 QDF_STATUS status;
Kapil Gupta6213c012016-09-02 19:39:09 +05302322
Wu Gao66454f12018-09-26 19:55:41 +08002323 if (!ucfg_pmo_get_power_save_mode(hddctx->psoc)) {
Kapil Gupta6213c012016-09-02 19:39:09 +05302324 hdd_err("qpower is disabled in configuration");
2325 return -EINVAL;
2326 }
Manjeet Singh91b7bb82017-02-10 18:35:40 +05302327 if (adapter->device_mode != QDF_STA_MODE &&
2328 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07002329 hdd_info("QPOWER only allowed in STA/P2P-Client modes:%d",
2330 adapter->device_mode);
Manjeet Singh91b7bb82017-02-10 18:35:40 +05302331 return -EINVAL;
2332 }
Dustin Brown10a7b712016-10-07 10:31:16 -07002333
Kapil Gupta6213c012016-09-02 19:39:09 +05302334 if (qpower > PS_DUTY_CYCLING_QPOWER ||
2335 qpower < PS_LEGACY_NODEEPSLEEP) {
Dustin Brown10a7b712016-10-07 10:31:16 -07002336 hdd_err("invalid qpower value: %d", qpower);
Kapil Gupta6213c012016-09-02 19:39:09 +05302337 return -EINVAL;
2338 }
Kapil Gupta6213c012016-09-02 19:39:09 +05302339
Wu Gao66454f12018-09-26 19:55:41 +08002340 if (ucfg_pmo_get_max_ps_poll(hddctx->psoc)) {
Kiran Kumar Lokere7006e0a2017-03-07 19:28:36 -08002341 if ((qpower == PS_QPOWER_NODEEPSLEEP) ||
2342 (qpower == PS_LEGACY_NODEEPSLEEP))
2343 qpower = PS_LEGACY_NODEEPSLEEP;
2344 else
2345 qpower = PS_LEGACY_DEEPSLEEP;
2346 hdd_info("Qpower disabled, %d", qpower);
2347 }
Jeff Johnson9597f3b2019-02-04 14:27:56 -08002348 status = wma_set_qpower_config(adapter->vdev_id, qpower);
Dustin Brown10a7b712016-10-07 10:31:16 -07002349 if (status != QDF_STATUS_SUCCESS) {
2350 hdd_err("failed to configure qpower: %d", status);
2351 return -EINVAL;
Kapil Gupta6213c012016-09-02 19:39:09 +05302352 }
Dustin Brown10a7b712016-10-07 10:31:16 -07002353
Kapil Gupta6213c012016-09-02 19:39:09 +05302354 return 0;
2355}
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002356
Dustin Brown54096432017-02-23 13:00:44 -08002357
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002358#ifdef WLAN_SUSPEND_RESUME_TEST
Dustin Brownbc81a472016-10-26 16:56:59 -07002359static struct net_device *g_dev;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002360static struct wiphy *g_wiphy;
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002361static enum wow_resume_trigger g_resume_trigger;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002362
2363#define HDD_FA_SUSPENDED_BIT (0)
2364static unsigned long fake_apps_state;
2365
Dustin Brownd53d1a82016-10-03 12:57:33 -07002366/**
2367 * __hdd_wlan_fake_apps_resume() - The core logic for
2368 * hdd_wlan_fake_apps_resume() skipping the call to hif_fake_apps_resume(),
2369 * which is only need for non-irq resume
Dustin Brownbc81a472016-10-26 16:56:59 -07002370 * @wiphy: the kernel wiphy struct for the device being resumed
2371 * @dev: the kernel net_device struct for the device being resumed
Dustin Brownd53d1a82016-10-03 12:57:33 -07002372 *
Dustin Brownbc81a472016-10-26 16:56:59 -07002373 * Return: none, calls QDF_BUG() on failure
Dustin Brownd53d1a82016-10-03 12:57:33 -07002374 */
Dustin Brownbc81a472016-10-26 16:56:59 -07002375static void __hdd_wlan_fake_apps_resume(struct wiphy *wiphy,
2376 struct net_device *dev)
Dustin Brownd53d1a82016-10-03 12:57:33 -07002377{
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002378 struct hif_opaque_softc *hif_ctx;
Dustin Brownddb59702017-01-12 16:20:31 -08002379 qdf_device_t qdf_dev;
Dustin Brownd53d1a82016-10-03 12:57:33 -07002380
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002381 hdd_info("Unit-test resume WLAN");
Dustin Brownddb59702017-01-12 16:20:31 -08002382
2383 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
2384 if (!qdf_dev) {
2385 hdd_err("Failed to get QDF device context");
2386 QDF_BUG(0);
2387 return;
2388 }
2389
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002390 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2391 if (!hif_ctx) {
2392 hdd_err("Failed to get HIF context");
2393 return;
2394 }
2395
Dustin Brownd53d1a82016-10-03 12:57:33 -07002396 if (!test_and_clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002397 hdd_alert("Not unit-test suspended; Nothing to do");
Dustin Brownd53d1a82016-10-03 12:57:33 -07002398 return;
2399 }
2400
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002401 /* simulate kernel disable irqs */
2402 QDF_BUG(!hif_apps_wake_irq_disable(hif_ctx));
Dustin Brownd53d1a82016-10-03 12:57:33 -07002403
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002404 QDF_BUG(!wlan_hdd_bus_resume_noirq());
Dustin Brownd53d1a82016-10-03 12:57:33 -07002405
2406 /* simulate kernel enable irqs */
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002407 QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
Dustin Brownd53d1a82016-10-03 12:57:33 -07002408
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002409 QDF_BUG(!wlan_hdd_bus_resume());
Dustin Brownd53d1a82016-10-03 12:57:33 -07002410
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002411 QDF_BUG(!wlan_hdd_cfg80211_resume_wlan(wiphy));
2412
2413 if (g_resume_trigger == WOW_RESUME_TRIGGER_HTC_WAKEUP)
2414 hif_vote_link_down(hif_ctx);
Dustin Brownbc81a472016-10-26 16:56:59 -07002415
2416 dev->watchdog_timeo = HDD_TX_TIMEOUT;
Dustin Brown562b9672016-12-22 15:25:33 -08002417
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002418 hdd_alert("Unit-test resume succeeded");
Dustin Brownd53d1a82016-10-03 12:57:33 -07002419}
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002420
2421/**
2422 * hdd_wlan_fake_apps_resume_irq_callback() - Irq callback function for resuming
2423 * from unit-test initiated suspend from irq wakeup signal
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002424 *
2425 * Resume wlan after getting very 1st CE interrupt from target
2426 *
2427 * Return: none
2428 */
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002429static void hdd_wlan_fake_apps_resume_irq_callback(void)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002430{
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002431 hdd_info("Trigger unit-test resume WLAN");
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002432
2433 QDF_BUG(g_wiphy);
Dustin Brownbc81a472016-10-26 16:56:59 -07002434 QDF_BUG(g_dev);
2435 __hdd_wlan_fake_apps_resume(g_wiphy, g_dev);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002436 g_wiphy = NULL;
Dustin Brownbc81a472016-10-26 16:56:59 -07002437 g_dev = NULL;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002438}
2439
Dustin Brown54096432017-02-23 13:00:44 -08002440int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy, struct net_device *dev,
2441 enum wow_interface_pause pause_setting,
2442 enum wow_resume_trigger resume_setting)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002443{
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002444 int errno;
Dustin Brownddb59702017-01-12 16:20:31 -08002445 qdf_device_t qdf_dev;
2446 struct hif_opaque_softc *hif_ctx;
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002447 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Dustin Brown54096432017-02-23 13:00:44 -08002448 struct wow_enable_params wow_params = {
2449 .is_unit_test = true,
2450 .interface_pause = pause_setting,
2451 .resume_trigger = resume_setting
2452 };
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002453
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002454 if (wlan_hdd_validate_context(hdd_ctx))
2455 return -EINVAL;
2456
2457 if (!hdd_ctx->config->is_unit_test_framework_enabled) {
2458 hdd_warn_rl("UT framework is disabled");
2459 return -EINVAL;
2460 }
2461
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002462 hdd_info("Unit-test suspend WLAN");
Dustin Brownddb59702017-01-12 16:20:31 -08002463
Dustin Brown54096432017-02-23 13:00:44 -08002464 if (pause_setting < WOW_INTERFACE_PAUSE_DEFAULT ||
2465 pause_setting >= WOW_INTERFACE_PAUSE_COUNT) {
2466 hdd_err("Invalid interface pause %d (expected range [0, 2])",
2467 pause_setting);
2468 return -EINVAL;
2469 }
2470
2471 if (resume_setting < WOW_RESUME_TRIGGER_DEFAULT ||
2472 resume_setting >= WOW_RESUME_TRIGGER_COUNT) {
2473 hdd_err("Invalid resume trigger %d (expected range [0, 2])",
2474 resume_setting);
2475 return -EINVAL;
2476 }
2477
Dustin Brownddb59702017-01-12 16:20:31 -08002478 qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
2479 if (!qdf_dev) {
2480 hdd_err("Failed to get QDF device context");
2481 return -EINVAL;
2482 }
2483
2484 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2485 if (!hif_ctx) {
2486 hdd_err("Failed to get HIF context");
2487 return -EINVAL;
2488 }
2489
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002490 if (test_and_set_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002491 hdd_alert("Already unit-test suspended; Nothing to do");
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002492 return 0;
2493 }
2494
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002495 /* pci link is needed to wakeup from HTC wakeup trigger */
2496 if (resume_setting == WOW_RESUME_TRIGGER_HTC_WAKEUP)
2497 hif_vote_link_up(hif_ctx);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002498
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002499 errno = wlan_hdd_cfg80211_suspend_wlan(wiphy, NULL);
2500 if (errno)
2501 goto link_down;
2502
2503 errno = wlan_hdd_unit_test_bus_suspend(wow_params);
2504 if (errno)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002505 goto cfg80211_resume;
2506
2507 /* simulate kernel disabling irqs */
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002508 errno = hif_apps_irqs_disable(hif_ctx);
2509 if (errno)
2510 goto bus_resume;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002511
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002512 errno = wlan_hdd_bus_suspend_noirq();
2513 if (errno)
2514 goto enable_irqs;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002515
Dustin Brownbc81a472016-10-26 16:56:59 -07002516 /* pass wiphy/dev to callback via global variables */
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002517 g_wiphy = wiphy;
Dustin Brownbc81a472016-10-26 16:56:59 -07002518 g_dev = dev;
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002519 g_resume_trigger = resume_setting;
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002520 hif_ut_apps_suspend(hif_ctx, hdd_wlan_fake_apps_resume_irq_callback);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002521
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002522 /* re-enable wake irq */
2523 errno = hif_apps_wake_irq_enable(hif_ctx);
2524 if (errno)
2525 goto fake_apps_resume;
2526
Dustin Brownbc81a472016-10-26 16:56:59 -07002527 /*
2528 * Tell the kernel not to worry if TX queues aren't moving. This is
2529 * expected since we are suspending the wifi hardware, but not APPS
2530 */
2531 dev->watchdog_timeo = INT_MAX;
2532
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002533 hdd_alert("Unit-test suspend succeeded");
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002534
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002535 return 0;
2536
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002537fake_apps_resume:
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002538 hif_ut_apps_resume(hif_ctx);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002539
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002540enable_irqs:
2541 QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
2542
2543bus_resume:
2544 QDF_BUG(!wlan_hdd_bus_resume());
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002545
2546cfg80211_resume:
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002547 QDF_BUG(!wlan_hdd_cfg80211_resume_wlan(wiphy));
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002548
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002549link_down:
2550 hif_vote_link_down(hif_ctx);
2551
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002552 clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state);
Dustin Brown3ed3e9b2017-03-23 12:57:58 -07002553 hdd_err("Unit-test suspend failed: %d", errno);
2554
2555 return errno;
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002556}
2557
Dustin Brownbc81a472016-10-26 16:56:59 -07002558int hdd_wlan_fake_apps_resume(struct wiphy *wiphy, struct net_device *dev)
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002559{
Dustin Brownddb59702017-01-12 16:20:31 -08002560 struct hif_opaque_softc *hif_ctx;
Rajeev Kumar15b40a22018-04-12 11:45:24 -07002561 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
2562
2563 if (wlan_hdd_validate_context(hdd_ctx))
2564 return -EINVAL;
2565
2566 if (!hdd_ctx->config->is_unit_test_framework_enabled) {
2567 hdd_warn_rl("UT framework is disabled");
2568 return -EINVAL;
2569 }
Dustin Brownddb59702017-01-12 16:20:31 -08002570
2571 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
2572 if (!hif_ctx) {
2573 hdd_err("Failed to get HIF context");
2574 return -EINVAL;
2575 }
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002576
Dustin Brown0f8dc3d2017-06-01 14:37:26 -07002577 hif_ut_apps_resume(hif_ctx);
Dustin Brownbc81a472016-10-26 16:56:59 -07002578 __hdd_wlan_fake_apps_resume(wiphy, dev);
Rajeev Kumar9bb2e852016-09-24 12:29:25 -07002579
2580 return 0;
2581}
2582#endif