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, ¶m);
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