1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 /**
20  * DOC: target_if_pmo_static.c
21  *
22  * Target interface file for pmo component to
23  * send suspend / resume related cmd and process event.
24  */
25 
26 #include "wma.h"
27 #include "target_if.h"
28 #include "target_if_pmo.h"
29 #include "wmi_unified_api.h"
30 #include "qdf_types.h"
31 #include "pld_common.h"
32 #include <cds_api.h>
33 #include <cdp_txrx_cmn.h>
34 
35 #define TGT_WILDCARD_PDEV_ID 0x0
36 
target_if_pmo_send_vdev_update_param_req(struct wlan_objmgr_vdev * vdev,uint32_t param_id,uint32_t param_value)37 QDF_STATUS target_if_pmo_send_vdev_update_param_req(
38 		struct wlan_objmgr_vdev *vdev,
39 		uint32_t param_id, uint32_t param_value)
40 {
41 	uint8_t vdev_id;
42 	struct wlan_objmgr_psoc *psoc;
43 	struct vdev_set_params param = {0};
44 	wmi_unified_t wmi_handle;
45 
46 	if (!vdev) {
47 		target_if_err("vdev ptr passed is NULL");
48 		return QDF_STATUS_E_INVAL;
49 	}
50 
51 	psoc = wlan_vdev_get_psoc(vdev);
52 	vdev_id = wlan_vdev_get_id(vdev);
53 	if (!psoc) {
54 		target_if_err("psoc handle is NULL");
55 		return QDF_STATUS_E_INVAL;
56 	}
57 
58 	/* Any new param_id added here please also add it to
59 	 * wmi_tag_vdev_set_cmd to be tagged for runtime PM feature
60 	 * so that it will not invoke runtime PM "get" which will
61 	 * result resume right after suspend (WOW_ENABLE).
62 	 */
63 
64 	switch (param_id) {
65 	case pmo_vdev_param_listen_interval:
66 		param_id = wmi_vdev_param_listen_interval;
67 		break;
68 	case pmo_vdev_param_dtim_policy:
69 		param_id = wmi_vdev_param_dtim_policy;
70 		break;
71 	case pmo_vdev_param_forced_dtim_count:
72 		param_id = wmi_vdev_param_force_dtim_cnt;
73 		break;
74 	case pmo_vdev_param_moddtim:
75 		param_id = wmi_vdev_param_moddtim_cnt;
76 		break;
77 	default:
78 		target_if_err("invalid vdev param id %d", param_id);
79 		return QDF_STATUS_E_INVAL;
80 	}
81 
82 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
83 	if (!wmi_handle) {
84 		target_if_err("Invalid wmi handle");
85 		return QDF_STATUS_E_INVAL;
86 	}
87 
88 	param.vdev_id = vdev_id;
89 	param.param_id = param_id;
90 	param.param_value = param_value;
91 	target_if_debug("set vdev param vdev_id: %d value: %d for param_id: %d",
92 			vdev_id, param_value, param_id);
93 	return wmi_unified_vdev_set_param_send(wmi_handle, &param);
94 }
95 
96 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
target_if_pmo_send_igmp_offload_req(struct wlan_objmgr_vdev * vdev,struct pmo_igmp_offload_req * pmo_igmp_req)97 QDF_STATUS target_if_pmo_send_igmp_offload_req(
98 			struct wlan_objmgr_vdev *vdev,
99 			struct pmo_igmp_offload_req *pmo_igmp_req)
100 {
101 	struct wlan_objmgr_psoc *psoc;
102 	wmi_unified_t wmi_handle;
103 
104 	if (!vdev) {
105 		target_if_err("vdev ptr passed is NULL");
106 		return QDF_STATUS_E_INVAL;
107 	}
108 
109 	psoc = wlan_vdev_get_psoc(vdev);
110 	if (!psoc) {
111 		target_if_err("psoc handle is NULL");
112 		return QDF_STATUS_E_INVAL;
113 	}
114 
115 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
116 	if (!wmi_handle) {
117 		target_if_err("Invalid wmi handle");
118 		return QDF_STATUS_E_INVAL;
119 	}
120 
121 	return wmi_unified_send_igmp_offload_cmd(wmi_handle,
122 						 pmo_igmp_req);
123 }
124 #endif
125 
target_if_pmo_send_vdev_ps_param_req(struct wlan_objmgr_vdev * vdev,uint32_t param_id,uint32_t param_value)126 QDF_STATUS target_if_pmo_send_vdev_ps_param_req(
127 		struct wlan_objmgr_vdev *vdev,
128 		uint32_t param_id,
129 		uint32_t param_value)
130 {
131 	uint8_t vdev_id;
132 	struct wlan_objmgr_psoc *psoc;
133 	QDF_STATUS status;
134 	struct sta_ps_params sta_ps_param = {0};
135 	wmi_unified_t wmi_handle;
136 
137 	if (!vdev) {
138 		target_if_err("vdev ptr passed is NULL");
139 		return QDF_STATUS_E_INVAL;
140 	}
141 
142 	psoc = wlan_vdev_get_psoc(vdev);
143 	vdev_id = wlan_vdev_get_id(vdev);
144 	if (!psoc) {
145 		target_if_err("psoc handle is NULL");
146 		return QDF_STATUS_E_INVAL;
147 	}
148 
149 	/*
150 	 * Any new param_id added here must be added to
151 	 * wmi_tag_sta_powersave_cmd() to be tagged for runtime PM feature
152 	 * so that it will not invoke runtime PM "get" which will
153 	 * result resume right after suspend (WOW_ENABLE).
154 	 */
155 	switch (param_id) {
156 	case pmo_sta_ps_enable_advanced_power:
157 		param_id = WMI_STA_PS_ENABLE_OPM;
158 		break;
159 	case pmo_sta_ps_param_inactivity_time:
160 		param_id = WMI_STA_PS_PARAM_INACTIVITY_TIME;
161 		break;
162 	case pmo_sta_ps_param_ito_repeat_count:
163 		param_id = WMI_STA_PS_PARAM_MAX_RESET_ITO_COUNT_ON_TIM_NO_TXRX;
164 		break;
165 	case pmo_sta_ps_param_spec_wake_interval:
166 		param_id = WMI_STA_PS_PARAM_SPEC_WAKE_INTERVAL;
167 		break;
168 	default:
169 		target_if_err("invalid vdev param id %d", param_id);
170 		return QDF_STATUS_E_INVAL;
171 	}
172 
173 	sta_ps_param.vdev_id = vdev_id;
174 	sta_ps_param.param_id = param_id;
175 	sta_ps_param.value = param_value;
176 	target_if_debug("set vdev param vdev_id: %d value: %d for param_id: %d",
177 			vdev_id, param_value, param_id);
178 
179 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
180 	if (!wmi_handle) {
181 		target_if_err("Invalid wmi handle");
182 		return QDF_STATUS_E_INVAL;
183 	}
184 
185 	status = wmi_unified_sta_ps_cmd_send(wmi_handle, &sta_ps_param);
186 	if (QDF_IS_STATUS_ERROR(status))
187 		return status;
188 
189 	return status;
190 }
191 
target_if_pmo_psoc_update_bus_suspend(struct wlan_objmgr_psoc * psoc,uint8_t value)192 void target_if_pmo_psoc_update_bus_suspend(struct wlan_objmgr_psoc *psoc,
193 		uint8_t value)
194 {
195 	wmi_unified_t wmi_handle;
196 
197 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
198 	if (!wmi_handle) {
199 		target_if_err("Invalid wmi handle");
200 		return;
201 	}
202 
203 	wmi_set_is_wow_bus_suspended(wmi_handle, value);
204 }
205 
target_if_pmo_psoc_get_host_credits(struct wlan_objmgr_psoc * psoc)206 int target_if_pmo_psoc_get_host_credits(struct wlan_objmgr_psoc *psoc)
207 {
208 	wmi_unified_t wmi_handle;
209 
210 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
211 	if (!wmi_handle) {
212 		target_if_err("Invalid wmi handle");
213 		return 0;
214 	}
215 
216 	return wmi_get_host_credits(wmi_handle);
217 }
218 
target_if_pmo_psoc_get_pending_cmnds(struct wlan_objmgr_psoc * psoc)219 int target_if_pmo_psoc_get_pending_cmnds(struct wlan_objmgr_psoc *psoc)
220 {
221 	wmi_unified_t wmi_handle;
222 
223 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
224 	if (!wmi_handle) {
225 		target_if_err("Invalid wmi handle");
226 		return 0;
227 	}
228 
229 	return wmi_get_pending_cmds(wmi_handle);
230 }
231 
target_if_pmo_update_target_suspend_flag(struct wlan_objmgr_psoc * psoc,uint8_t value)232 void target_if_pmo_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc,
233 		uint8_t value)
234 {
235 	wmi_unified_t wmi_handle;
236 
237 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
238 	if (!wmi_handle) {
239 		target_if_err("Invalid wmi handle");
240 		return;
241 	}
242 
243 	wmi_set_target_suspend(wmi_handle, value);
244 }
245 
target_if_pmo_update_target_suspend_acked_flag(struct wlan_objmgr_psoc * psoc,uint8_t value)246 void target_if_pmo_update_target_suspend_acked_flag(
247 					struct wlan_objmgr_psoc *psoc,
248 					uint8_t value)
249 {
250 	wmi_unified_t wmi_handle;
251 
252 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
253 	if (!wmi_handle) {
254 		target_if_err("Invalid wmi handle");
255 		return;
256 	}
257 
258 	wmi_set_target_suspend_acked(wmi_handle, value);
259 }
260 
target_if_pmo_is_target_suspended(struct wlan_objmgr_psoc * psoc)261 bool target_if_pmo_is_target_suspended(struct wlan_objmgr_psoc *psoc)
262 {
263 	wmi_unified_t wmi_handle;
264 
265 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
266 	if (!wmi_handle) {
267 		target_if_err("Invalid wmi handle");
268 		return false;
269 	}
270 
271 	return wmi_is_target_suspended(wmi_handle);
272 }
273 
target_if_pmo_psoc_send_wow_enable_req(struct wlan_objmgr_psoc * psoc,struct pmo_wow_cmd_params * param)274 QDF_STATUS target_if_pmo_psoc_send_wow_enable_req(
275 		struct wlan_objmgr_psoc *psoc,
276 		struct pmo_wow_cmd_params *param)
277 {
278 	wmi_unified_t wmi_handle;
279 
280 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
281 	if (!wmi_handle) {
282 		target_if_err("Invalid wmi handle");
283 		return QDF_STATUS_E_INVAL;
284 	}
285 
286 	wma_check_and_set_wake_timer(INSTALL_KEY_TIMEOUT_MS);
287 	return wmi_unified_wow_enable_send(wmi_handle,
288 					   (struct wow_cmd_params *)param,
289 					   TGT_WILDCARD_PDEV_ID);
290 }
291 
target_if_pmo_psoc_send_suspend_req(struct wlan_objmgr_psoc * psoc,struct pmo_suspend_params * param)292 QDF_STATUS target_if_pmo_psoc_send_suspend_req(
293 		struct wlan_objmgr_psoc *psoc,
294 		struct pmo_suspend_params *param)
295 {
296 	wmi_unified_t wmi_handle;
297 
298 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
299 	if (!wmi_handle) {
300 		target_if_err("Invalid wmi handle");
301 		return QDF_STATUS_E_INVAL;
302 	}
303 
304 	return wmi_unified_suspend_send(wmi_handle,
305 					(struct suspend_params *) param,
306 					TGT_WILDCARD_PDEV_ID);
307 }
308 
target_if_pmo_set_runtime_pm_in_progress(struct wlan_objmgr_psoc * psoc,bool value)309 void target_if_pmo_set_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc,
310 					      bool value)
311 {
312 	wmi_unified_t wmi_handle;
313 
314 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
315 	if (!wmi_handle) {
316 		target_if_err("Invalid wmi handle");
317 		return;
318 	}
319 
320 	return wmi_set_runtime_pm_inprogress(wmi_handle, value);
321 }
322 
target_if_pmo_get_runtime_pm_in_progress(struct wlan_objmgr_psoc * psoc)323 bool target_if_pmo_get_runtime_pm_in_progress(
324 		struct wlan_objmgr_psoc *psoc)
325 {
326 	wmi_unified_t wmi_handle;
327 
328 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
329 	if (!wmi_handle) {
330 		target_if_err("Invalid wmi handle");
331 		return false;
332 	}
333 
334 	return wmi_get_runtime_pm_inprogress(wmi_handle);
335 }
336 
337 #ifdef HOST_WAKEUP_OVER_QMI
target_if_pmo_psoc_send_host_wakeup_ind(struct wlan_objmgr_psoc * psoc)338 QDF_STATUS target_if_pmo_psoc_send_host_wakeup_ind(
339 		struct wlan_objmgr_psoc *psoc)
340 {
341 	qdf_device_t qdf_dev;
342 	int ret;
343 
344 	qdf_dev = wlan_psoc_get_qdf_dev(psoc);
345 	if (!qdf_dev)
346 		return QDF_STATUS_E_INVAL;
347 
348 	ret = pld_exit_power_save(qdf_dev->dev);
349 	if (ret) {
350 		target_if_err("Failed to exit power save, ret: %d", ret);
351 		return qdf_status_from_os_return(ret);
352 	}
353 
354 	return QDF_STATUS_SUCCESS;
355 }
356 #else
target_if_pmo_psoc_send_host_wakeup_ind(struct wlan_objmgr_psoc * psoc)357 QDF_STATUS target_if_pmo_psoc_send_host_wakeup_ind(
358 		struct wlan_objmgr_psoc *psoc)
359 {
360 	wmi_unified_t wmi_handle;
361 	bool tx_pending_ind = false;
362 
363 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
364 	if (!wmi_handle) {
365 		target_if_err("Invalid wmi handle");
366 		return QDF_STATUS_E_INVAL;
367 	}
368 
369 	if (cdp_get_tx_inqueue(cds_get_context(QDF_MODULE_ID_SOC)))
370 		tx_pending_ind = true;
371 
372 	return wmi_unified_host_wakeup_ind_to_fw_cmd(wmi_handle,
373 						     tx_pending_ind);
374 }
375 #endif
376 
target_if_pmo_psoc_send_target_resume_req(struct wlan_objmgr_psoc * psoc)377 QDF_STATUS target_if_pmo_psoc_send_target_resume_req(
378 		struct wlan_objmgr_psoc *psoc)
379 {
380 	wmi_unified_t wmi_handle;
381 
382 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
383 	if (!wmi_handle) {
384 		target_if_err("Invalid wmi handle");
385 		return QDF_STATUS_E_INVAL;
386 	}
387 
388 	return wmi_unified_resume_send(wmi_handle, TGT_WILDCARD_PDEV_ID);
389 }
390 
391 QDF_STATUS
target_if_pmo_psoc_send_idle_monitor_cmd(struct wlan_objmgr_psoc * psoc,uint8_t val)392 target_if_pmo_psoc_send_idle_monitor_cmd(struct wlan_objmgr_psoc *psoc,
393 					 uint8_t val)
394 {
395 	wmi_unified_t wmi_handle;
396 
397 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
398 	if (!wmi_handle) {
399 		target_if_err("Invalid wmi handle");
400 		return QDF_STATUS_E_INVAL;
401 	}
402 
403 	return wmi_unified_send_idle_trigger_monitor(wmi_handle, val);
404 }
405 
406 #ifdef FEATURE_WLAN_D0WOW
target_if_pmo_psoc_send_d0wow_enable_req(struct wlan_objmgr_psoc * psoc)407 QDF_STATUS target_if_pmo_psoc_send_d0wow_enable_req(
408 		struct wlan_objmgr_psoc *psoc)
409 {
410 	wmi_unified_t wmi_handle;
411 
412 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
413 	if (!wmi_handle) {
414 		target_if_err("Invalid wmi handle");
415 		return QDF_STATUS_E_INVAL;
416 	}
417 
418 	return wmi_unified_d0wow_enable_send(wmi_handle, TGT_WILDCARD_PDEV_ID);
419 }
420 
target_if_pmo_psoc_send_d0wow_disable_req(struct wlan_objmgr_psoc * psoc)421 QDF_STATUS target_if_pmo_psoc_send_d0wow_disable_req(
422 		struct wlan_objmgr_psoc *psoc)
423 {
424 	wmi_unified_t wmi_handle;
425 
426 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
427 	if (!wmi_handle) {
428 		target_if_err("Invalid wmi handle");
429 		return QDF_STATUS_E_INVAL;
430 	}
431 
432 	return wmi_unified_d0wow_disable_send(wmi_handle, TGT_WILDCARD_PDEV_ID);
433 }
434 #else
target_if_pmo_psoc_send_d0wow_enable_req(struct wlan_objmgr_psoc * psoc)435 QDF_STATUS target_if_pmo_psoc_send_d0wow_enable_req(
436 		struct wlan_objmgr_psoc *psoc)
437 {
438 	return QDF_STATUS_E_INVAL;
439 }
440 
target_if_pmo_psoc_send_d0wow_disable_req(struct wlan_objmgr_psoc * psoc)441 QDF_STATUS target_if_pmo_psoc_send_d0wow_disable_req(
442 		struct wlan_objmgr_psoc *psoc)
443 {
444 	return QDF_STATUS_E_INVAL;
445 }
446 #endif
447 
target_if_pmo_set_wow_enable_ack_failed(struct wlan_objmgr_psoc * psoc)448 void target_if_pmo_set_wow_enable_ack_failed(struct wlan_objmgr_psoc *psoc)
449 {
450 	wmi_unified_t wmi_handle;
451 
452 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
453 	if (!wmi_handle) {
454 		target_if_err("Invalid wmi handle");
455 		return;
456 	}
457 
458 	return wmi_set_wow_enable_ack_failed(wmi_handle);
459 }
460 
461