xref: /freebsd/sys/contrib/dev/athk/ath11k/wow.c (revision dd4f32ae62426a10a84b4322756d82c06c202c4e)
1*dd4f32aeSBjoern A. Zeeb // SPDX-License-Identifier: BSD-3-Clause-Clear
2*dd4f32aeSBjoern A. Zeeb /*
3*dd4f32aeSBjoern A. Zeeb  * Copyright (c) 2020 The Linux Foundation. All rights reserved.
4*dd4f32aeSBjoern A. Zeeb  */
5*dd4f32aeSBjoern A. Zeeb 
6*dd4f32aeSBjoern A. Zeeb #include <linux/delay.h>
7*dd4f32aeSBjoern A. Zeeb 
8*dd4f32aeSBjoern A. Zeeb #include "mac.h"
9*dd4f32aeSBjoern A. Zeeb #include "core.h"
10*dd4f32aeSBjoern A. Zeeb #include "hif.h"
11*dd4f32aeSBjoern A. Zeeb #include "debug.h"
12*dd4f32aeSBjoern A. Zeeb #include "wmi.h"
13*dd4f32aeSBjoern A. Zeeb #include "wow.h"
14*dd4f32aeSBjoern A. Zeeb 
15*dd4f32aeSBjoern A. Zeeb int ath11k_wow_enable(struct ath11k_base *ab)
16*dd4f32aeSBjoern A. Zeeb {
17*dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
18*dd4f32aeSBjoern A. Zeeb 	int i, ret;
19*dd4f32aeSBjoern A. Zeeb 
20*dd4f32aeSBjoern A. Zeeb 	clear_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
21*dd4f32aeSBjoern A. Zeeb 
22*dd4f32aeSBjoern A. Zeeb 	for (i = 0; i < ATH11K_WOW_RETRY_NUM; i++) {
23*dd4f32aeSBjoern A. Zeeb 		reinit_completion(&ab->htc_suspend);
24*dd4f32aeSBjoern A. Zeeb 
25*dd4f32aeSBjoern A. Zeeb 		ret = ath11k_wmi_wow_enable(ar);
26*dd4f32aeSBjoern A. Zeeb 		if (ret) {
27*dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab, "failed to issue wow enable: %d\n", ret);
28*dd4f32aeSBjoern A. Zeeb 			return ret;
29*dd4f32aeSBjoern A. Zeeb 		}
30*dd4f32aeSBjoern A. Zeeb 
31*dd4f32aeSBjoern A. Zeeb 		ret = wait_for_completion_timeout(&ab->htc_suspend, 3 * HZ);
32*dd4f32aeSBjoern A. Zeeb 		if (ret == 0) {
33*dd4f32aeSBjoern A. Zeeb 			ath11k_warn(ab,
34*dd4f32aeSBjoern A. Zeeb 				    "timed out while waiting for htc suspend completion\n");
35*dd4f32aeSBjoern A. Zeeb 			return -ETIMEDOUT;
36*dd4f32aeSBjoern A. Zeeb 		}
37*dd4f32aeSBjoern A. Zeeb 
38*dd4f32aeSBjoern A. Zeeb 		if (test_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags))
39*dd4f32aeSBjoern A. Zeeb 			/* success, suspend complete received */
40*dd4f32aeSBjoern A. Zeeb 			return 0;
41*dd4f32aeSBjoern A. Zeeb 
42*dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "htc suspend not complete, retrying (try %d)\n",
43*dd4f32aeSBjoern A. Zeeb 			    i);
44*dd4f32aeSBjoern A. Zeeb 		msleep(ATH11K_WOW_RETRY_WAIT_MS);
45*dd4f32aeSBjoern A. Zeeb 	}
46*dd4f32aeSBjoern A. Zeeb 
47*dd4f32aeSBjoern A. Zeeb 	ath11k_warn(ab, "htc suspend not complete, failing after %d tries\n", i);
48*dd4f32aeSBjoern A. Zeeb 
49*dd4f32aeSBjoern A. Zeeb 	return -ETIMEDOUT;
50*dd4f32aeSBjoern A. Zeeb }
51*dd4f32aeSBjoern A. Zeeb 
52*dd4f32aeSBjoern A. Zeeb int ath11k_wow_wakeup(struct ath11k_base *ab)
53*dd4f32aeSBjoern A. Zeeb {
54*dd4f32aeSBjoern A. Zeeb 	struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
55*dd4f32aeSBjoern A. Zeeb 	int ret;
56*dd4f32aeSBjoern A. Zeeb 
57*dd4f32aeSBjoern A. Zeeb 	reinit_completion(&ab->wow.wakeup_completed);
58*dd4f32aeSBjoern A. Zeeb 
59*dd4f32aeSBjoern A. Zeeb 	ret = ath11k_wmi_wow_host_wakeup_ind(ar);
60*dd4f32aeSBjoern A. Zeeb 	if (ret) {
61*dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "failed to send wow wakeup indication: %d\n",
62*dd4f32aeSBjoern A. Zeeb 			    ret);
63*dd4f32aeSBjoern A. Zeeb 		return ret;
64*dd4f32aeSBjoern A. Zeeb 	}
65*dd4f32aeSBjoern A. Zeeb 
66*dd4f32aeSBjoern A. Zeeb 	ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ);
67*dd4f32aeSBjoern A. Zeeb 	if (ret == 0) {
68*dd4f32aeSBjoern A. Zeeb 		ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n");
69*dd4f32aeSBjoern A. Zeeb 		return -ETIMEDOUT;
70*dd4f32aeSBjoern A. Zeeb 	}
71*dd4f32aeSBjoern A. Zeeb 
72*dd4f32aeSBjoern A. Zeeb 	return 0;
73*dd4f32aeSBjoern A. Zeeb }
74