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