xref: /wlan-dirver/qca-wifi-host-cmn/target_if/mlme/psoc/src/target_if_psoc_wake_lock.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
3  *
4  * 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 
19 /**
20  * DOC: target_if_psoc_wake_lock.c
21  *
22  * This file provide definition for APIs related to wake lock
23  */
24 
25 #include "qdf_lock.h"
26 #include <target_if_psoc_wake_lock.h>
27 #include <wlan_lmac_if_def.h>
28 #include <host_diag_core_event.h>
29 #include <wlan_objmgr_psoc_obj.h>
30 #include <target_if.h>
31 #include <target_if_vdev_mgr_rx_ops.h>
32 #include <wlan_reg_services_api.h>
33 #include "init_deinit_lmac.h"
34 
35 void target_if_wake_lock_init(struct wlan_objmgr_psoc *psoc)
36 {
37 	struct psoc_mlme_wakelock *psoc_wakelock;
38 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
39 
40 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
41 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
42 		mlme_err("psoc_id:%d No Rx Ops",
43 			 wlan_psoc_get_id(psoc));
44 		return;
45 	}
46 
47 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
48 
49 	qdf_wake_lock_create(&psoc_wakelock->start_wakelock, "vdev_start");
50 	qdf_wake_lock_create(&psoc_wakelock->stop_wakelock, "vdev_stop");
51 	qdf_wake_lock_create(&psoc_wakelock->delete_wakelock, "vdev_delete");
52 
53 	qdf_runtime_lock_init(&psoc_wakelock->wmi_cmd_rsp_runtime_lock);
54 	qdf_runtime_lock_init(&psoc_wakelock->prevent_runtime_lock);
55 	psoc_wakelock->is_link_up = false;
56 }
57 
58 void target_if_wake_lock_deinit(struct wlan_objmgr_psoc *psoc)
59 {
60 	struct psoc_mlme_wakelock *psoc_wakelock;
61 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
62 
63 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
64 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
65 		mlme_err("psoc_id:%d No Rx Ops",
66 			 wlan_psoc_get_id(psoc));
67 		return;
68 	}
69 
70 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
71 
72 	qdf_wake_lock_destroy(&psoc_wakelock->start_wakelock);
73 	qdf_wake_lock_destroy(&psoc_wakelock->stop_wakelock);
74 	qdf_wake_lock_destroy(&psoc_wakelock->delete_wakelock);
75 
76 	qdf_runtime_lock_deinit(&psoc_wakelock->wmi_cmd_rsp_runtime_lock);
77 	qdf_runtime_lock_deinit(&psoc_wakelock->prevent_runtime_lock);
78 }
79 
80 QDF_STATUS target_if_wake_lock_timeout_acquire(
81 				struct wlan_objmgr_psoc *psoc,
82 				enum wakelock_mode mode)
83 {
84 	struct psoc_mlme_wakelock *psoc_wakelock;
85 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
86 
87 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
88 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
89 		mlme_err("psoc_id:%d No Rx Ops",
90 			 wlan_psoc_get_id(psoc));
91 		return QDF_STATUS_E_INVAL;
92 	}
93 
94 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
95 	switch (mode) {
96 	case START_WAKELOCK:
97 		qdf_wake_lock_timeout_acquire(&psoc_wakelock->start_wakelock,
98 					      START_RESPONSE_TIMER);
99 		break;
100 	case STOP_WAKELOCK:
101 		qdf_wake_lock_timeout_acquire(&psoc_wakelock->stop_wakelock,
102 					      STOP_RESPONSE_TIMER);
103 		break;
104 	case DELETE_WAKELOCK:
105 		qdf_wake_lock_timeout_acquire(&psoc_wakelock->delete_wakelock,
106 					      DELETE_RESPONSE_TIMER);
107 		break;
108 	default:
109 		target_if_err("operation mode is invalid");
110 		return QDF_STATUS_E_FAILURE;
111 	}
112 
113 	qdf_runtime_pm_prevent_suspend(
114 				&psoc_wakelock->wmi_cmd_rsp_runtime_lock);
115 
116 	return QDF_STATUS_SUCCESS;
117 }
118 
119 QDF_STATUS target_if_wake_lock_timeout_release(
120 				struct wlan_objmgr_psoc *psoc,
121 				enum wakelock_mode mode)
122 {
123 	struct psoc_mlme_wakelock *psoc_wakelock;
124 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
125 
126 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
127 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
128 		mlme_err("psoc_id:%d No Rx Ops", wlan_psoc_get_id(psoc));
129 		return QDF_STATUS_E_INVAL;
130 	}
131 
132 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
133 	switch (mode) {
134 	case START_WAKELOCK:
135 		qdf_wake_lock_release(&psoc_wakelock->start_wakelock,
136 				      WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
137 		break;
138 	case STOP_WAKELOCK:
139 		qdf_wake_lock_release(&psoc_wakelock->stop_wakelock,
140 				      WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
141 		break;
142 	case DELETE_WAKELOCK:
143 		qdf_wake_lock_release(&psoc_wakelock->delete_wakelock,
144 				      WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
145 		break;
146 	default:
147 		target_if_err("operation mode is invalid");
148 		return QDF_STATUS_E_FAILURE;
149 	}
150 
151 	qdf_runtime_pm_allow_suspend(&psoc_wakelock->wmi_cmd_rsp_runtime_lock);
152 
153 	return QDF_STATUS_SUCCESS;
154 }
155 
156 static void
157 target_if_vote_for_link_down(struct wlan_objmgr_psoc *psoc,
158 			     struct psoc_mlme_wakelock *psoc_wakelock)
159 {
160 	void *htc_handle;
161 
162 	htc_handle = lmac_get_htc_hdl(psoc);
163 	if (!htc_handle) {
164 		mlme_err("HTC handle is NULL");
165 		return;
166 	}
167 
168 	if (psoc_wakelock->is_link_up) {
169 		htc_vote_link_down(htc_handle);
170 		qdf_runtime_pm_allow_suspend(&psoc_wakelock->prevent_runtime_lock);
171 		psoc_wakelock->is_link_up = false;
172 	}
173 }
174 
175 static void
176 target_if_vote_for_link_up(struct wlan_objmgr_psoc *psoc,
177 			   struct psoc_mlme_wakelock *psoc_wakelock)
178 {
179 	void *htc_handle;
180 
181 	htc_handle = lmac_get_htc_hdl(psoc);
182 	if (!htc_handle) {
183 		mlme_err("HTC handle is NULL");
184 		return;
185 	}
186 
187 	if (!psoc_wakelock->is_link_up) {
188 		htc_vote_link_up(htc_handle);
189 		qdf_runtime_pm_prevent_suspend(&psoc_wakelock->prevent_runtime_lock);
190 		psoc_wakelock->is_link_up = true;
191 	}
192 }
193 
194 void target_if_vdev_start_link_handler(struct wlan_objmgr_vdev *vdev,
195 				       uint32_t cfreq1, uint32_t cfreq2)
196 {
197 	struct wlan_objmgr_psoc *psoc;
198 	struct wlan_objmgr_pdev *pdev;
199 	struct psoc_mlme_wakelock *psoc_wakelock;
200 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
201 
202 	psoc = wlan_vdev_get_psoc(vdev);
203 	pdev = wlan_vdev_get_pdev(vdev);
204 
205 	if (!pdev) {
206 		mlme_err("pdev is NULL");
207 		return;
208 	}
209 
210 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
211 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
212 		mlme_err("psoc_id:%d No Rx Ops",
213 			 wlan_psoc_get_id(psoc));
214 		return;
215 	}
216 
217 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
218 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
219 		if ((wlan_reg_chan_has_dfs_attribute_for_freq(pdev,
220 							      cfreq1)) ||
221 		    (wlan_reg_chan_has_dfs_attribute_for_freq(pdev,
222 							      cfreq2)))
223 			target_if_vote_for_link_up(psoc, psoc_wakelock);
224 		else
225 			target_if_vote_for_link_down(psoc, psoc_wakelock);
226 	}
227 }
228 
229 void target_if_vdev_stop_link_handler(struct wlan_objmgr_vdev *vdev)
230 {
231 	struct wlan_objmgr_psoc *psoc;
232 	struct psoc_mlme_wakelock *psoc_wakelock;
233 	struct wlan_lmac_if_mlme_rx_ops *rx_ops;
234 
235 	psoc = wlan_vdev_get_psoc(vdev);
236 	rx_ops = target_if_vdev_mgr_get_rx_ops(psoc);
237 	if (!rx_ops || !rx_ops->psoc_get_wakelock_info) {
238 		mlme_err("psoc_id:%d No Rx Ops",
239 			 wlan_psoc_get_id(psoc));
240 		return;
241 	}
242 
243 	psoc_wakelock = rx_ops->psoc_get_wakelock_info(psoc);
244 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
245 		target_if_vote_for_link_down(psoc, psoc_wakelock);
246 }
247 
248