1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 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 /**
21  * DOC: Implements public API for pmo to interact with target/WMI
22  */
23 
24 #include "wlan_pmo_tgt_api.h"
25 #include "wlan_pmo_wow.h"
26 #include "wlan_pmo_obj_mgmt_public_struct.h"
27 #include "wlan_pmo_main.h"
28 
pmo_tgt_vdev_update_param_req(struct wlan_objmgr_vdev * vdev,enum pmo_vdev_param_id param_id,uint32_t param_value)29 QDF_STATUS pmo_tgt_vdev_update_param_req(struct wlan_objmgr_vdev *vdev,
30 		enum pmo_vdev_param_id param_id, uint32_t param_value)
31 {
32 	QDF_STATUS status;
33 	struct wlan_objmgr_psoc *psoc;
34 	struct wlan_pmo_tx_ops pmo_tx_ops;
35 
36 	pmo_enter();
37 
38 	psoc = pmo_vdev_get_psoc(vdev);
39 
40 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
41 	if (!pmo_tx_ops.send_vdev_param_update_req) {
42 		pmo_err("send_vdev_param_update_req is null");
43 		status = QDF_STATUS_E_NULL_VALUE;
44 		goto out;
45 	}
46 
47 	status = pmo_tx_ops.send_vdev_param_update_req(vdev, param_id,
48 			param_value);
49 out:
50 	pmo_exit();
51 
52 	return status;
53 }
54 
55 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
56 QDF_STATUS
pmo_tgt_send_igmp_offload_req(struct wlan_objmgr_vdev * vdev,struct pmo_igmp_offload_req * pmo_igmp_req)57 pmo_tgt_send_igmp_offload_req(struct wlan_objmgr_vdev *vdev,
58 			      struct pmo_igmp_offload_req *pmo_igmp_req)
59 {
60 	QDF_STATUS status;
61 	struct wlan_objmgr_psoc *psoc;
62 	struct wlan_pmo_tx_ops pmo_tx_ops;
63 
64 	psoc = pmo_vdev_get_psoc(vdev);
65 
66 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
67 	if (!pmo_tx_ops.send_igmp_offload_req) {
68 		pmo_err("send_vdev_param_set_req is null");
69 		return QDF_STATUS_E_NULL_VALUE;
70 	}
71 
72 	status = pmo_tx_ops.send_igmp_offload_req(vdev, pmo_igmp_req);
73 
74 	return status;
75 }
76 #endif
77 
pmo_tgt_send_vdev_sta_ps_param(struct wlan_objmgr_vdev * vdev,enum pmo_sta_powersave_param ps_param,uint32_t param_value)78 QDF_STATUS pmo_tgt_send_vdev_sta_ps_param(struct wlan_objmgr_vdev *vdev,
79 		enum pmo_sta_powersave_param ps_param, uint32_t param_value)
80 {
81 	QDF_STATUS status;
82 	struct wlan_objmgr_psoc *psoc;
83 	struct wlan_pmo_tx_ops pmo_tx_ops;
84 
85 	psoc = pmo_vdev_get_psoc(vdev);
86 
87 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
88 	if (!pmo_tx_ops.send_vdev_sta_ps_param_req) {
89 		pmo_err("send_vdev_param_set_req is null");
90 		status = QDF_STATUS_E_NULL_VALUE;
91 		goto out;
92 	}
93 
94 	status = pmo_tx_ops.send_vdev_sta_ps_param_req(vdev, ps_param,
95 			param_value);
96 out:
97 	return status;
98 }
99 
pmo_tgt_psoc_update_wow_bus_suspend_state(struct wlan_objmgr_psoc * psoc,uint8_t val)100 void pmo_tgt_psoc_update_wow_bus_suspend_state(struct wlan_objmgr_psoc *psoc,
101 		uint8_t val)
102 {
103 	struct wlan_pmo_tx_ops pmo_tx_ops;
104 
105 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
106 	if (!pmo_tx_ops.psoc_update_wow_bus_suspend) {
107 		pmo_err("psoc_update_wow_bus_suspend is null");
108 		return;
109 	}
110 	pmo_tx_ops.psoc_update_wow_bus_suspend(psoc, val);
111 }
112 
pmo_tgt_psoc_get_host_credits(struct wlan_objmgr_psoc * psoc)113 int pmo_tgt_psoc_get_host_credits(struct wlan_objmgr_psoc *psoc)
114 {
115 
116 	struct wlan_pmo_tx_ops pmo_tx_ops;
117 
118 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
119 	if (!pmo_tx_ops.psoc_get_host_credits) {
120 		pmo_err("psoc_get_host_credits is null");
121 		return 0;
122 	}
123 
124 	return pmo_tx_ops.psoc_get_host_credits(psoc);
125 }
126 
pmo_tgt_psoc_get_pending_cmnds(struct wlan_objmgr_psoc * psoc)127 int pmo_tgt_psoc_get_pending_cmnds(struct wlan_objmgr_psoc *psoc)
128 {
129 
130 	struct wlan_pmo_tx_ops pmo_tx_ops;
131 
132 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
133 	if (!pmo_tx_ops.psoc_get_pending_cmnds) {
134 		pmo_err("psoc_get_pending_cmnds is null");
135 		return -EAGAIN;
136 	}
137 
138 	return pmo_tx_ops.psoc_get_pending_cmnds(psoc);
139 }
140 
pmo_tgt_update_target_suspend_flag(struct wlan_objmgr_psoc * psoc,uint8_t val)141 void pmo_tgt_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc,
142 		uint8_t val)
143 {
144 	struct wlan_pmo_tx_ops pmo_tx_ops;
145 
146 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
147 	if (!pmo_tx_ops.update_target_suspend_flag) {
148 		pmo_err("update_target_suspend_flag is null");
149 		return;
150 	}
151 	pmo_tx_ops.update_target_suspend_flag(psoc, val);
152 }
153 
pmo_tgt_update_target_suspend_acked_flag(struct wlan_objmgr_psoc * psoc,uint8_t val)154 void pmo_tgt_update_target_suspend_acked_flag(struct wlan_objmgr_psoc *psoc,
155 					      uint8_t val)
156 {
157 	struct wlan_pmo_tx_ops pmo_tx_ops;
158 
159 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
160 	if (!pmo_tx_ops.update_target_suspend_acked_flag) {
161 		pmo_err("update_target_suspend_acked_flag is null");
162 		return;
163 	}
164 	pmo_tx_ops.update_target_suspend_acked_flag(psoc, val);
165 }
166 
pmo_tgt_is_target_suspended(struct wlan_objmgr_psoc * psoc)167 bool pmo_tgt_is_target_suspended(struct wlan_objmgr_psoc *psoc)
168 {
169 	struct wlan_pmo_tx_ops pmo_tx_ops;
170 
171 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
172 	if (!pmo_tx_ops.is_target_suspended) {
173 		pmo_err("is_target_suspended is null");
174 		return false;
175 	}
176 	return pmo_tx_ops.is_target_suspended(psoc);
177 }
178 
pmo_tgt_psoc_send_wow_enable_req(struct wlan_objmgr_psoc * psoc,struct pmo_wow_cmd_params * param)179 QDF_STATUS pmo_tgt_psoc_send_wow_enable_req(struct wlan_objmgr_psoc *psoc,
180 	struct pmo_wow_cmd_params *param)
181 {
182 	struct pmo_psoc_priv_obj *psoc_ctx;
183 	struct wlan_pmo_tx_ops pmo_tx_ops;
184 
185 	psoc_ctx = pmo_psoc_get_priv(psoc);
186 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
187 
188 	if (psoc_ctx->wow.wow_state == pmo_wow_state_legacy_d0) {
189 		if (!pmo_tx_ops.psoc_send_d0wow_enable_req) {
190 			pmo_err("psoc_send_d0wow_enable_req is null");
191 			return QDF_STATUS_E_NULL_VALUE;
192 		}
193 		pmo_debug("Sending D0WOW enable command...");
194 		return pmo_tx_ops.psoc_send_d0wow_enable_req(psoc);
195 	}
196 
197 	if (!pmo_tx_ops.psoc_send_wow_enable_req) {
198 		pmo_err("psoc_send_wow_enable_req is null");
199 		return QDF_STATUS_E_NULL_VALUE;
200 	}
201 	return pmo_tx_ops.psoc_send_wow_enable_req(psoc, param);
202 }
203 
pmo_tgt_psoc_send_supend_req(struct wlan_objmgr_psoc * psoc,struct pmo_suspend_params * param)204 QDF_STATUS pmo_tgt_psoc_send_supend_req(struct wlan_objmgr_psoc *psoc,
205 		struct pmo_suspend_params *param)
206 {
207 	struct wlan_pmo_tx_ops pmo_tx_ops;
208 
209 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
210 	if (!pmo_tx_ops.psoc_send_supend_req) {
211 		pmo_err("psoc_send_supend_req is null");
212 		return QDF_STATUS_E_NULL_VALUE;
213 	}
214 
215 	return pmo_tx_ops.psoc_send_supend_req(psoc, param);
216 }
217 
pmo_tgt_psoc_set_runtime_pm_inprogress(struct wlan_objmgr_psoc * psoc,bool value)218 QDF_STATUS pmo_tgt_psoc_set_runtime_pm_inprogress(struct wlan_objmgr_psoc *psoc,
219 						  bool value)
220 {
221 	struct wlan_pmo_tx_ops pmo_tx_ops;
222 
223 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
224 	if (!pmo_tx_ops.psoc_set_runtime_pm_in_progress) {
225 		pmo_err("pmo ops is null");
226 		return QDF_STATUS_E_NULL_VALUE;
227 	}
228 
229 	pmo_tx_ops.psoc_set_runtime_pm_in_progress(psoc, value);
230 
231 	return QDF_STATUS_SUCCESS;
232 }
233 
pmo_tgt_psoc_get_runtime_pm_in_progress(struct wlan_objmgr_psoc * psoc)234 bool pmo_tgt_psoc_get_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc)
235 {
236 	struct wlan_pmo_tx_ops pmo_tx_ops;
237 
238 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
239 	if (!pmo_tx_ops.psoc_get_runtime_pm_in_progress) {
240 		pmo_err("psoc_get_runtime_pm_in_progress is null");
241 		return QDF_STATUS_E_NULL_VALUE;
242 	}
243 
244 	return pmo_tx_ops.psoc_get_runtime_pm_in_progress(psoc);
245 }
246 
pmo_tgt_psoc_send_host_wakeup_ind(struct wlan_objmgr_psoc * psoc)247 QDF_STATUS pmo_tgt_psoc_send_host_wakeup_ind(struct wlan_objmgr_psoc *psoc)
248 {
249 	struct pmo_psoc_priv_obj *psoc_ctx;
250 	struct wlan_pmo_tx_ops pmo_tx_ops;
251 
252 	psoc_ctx = pmo_psoc_get_priv(psoc);
253 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
254 
255 	if (psoc_ctx->psoc_cfg.d0_wow_supported &&
256 	    psoc_ctx->wow.wow_state == pmo_wow_state_legacy_d0) {
257 		if (!pmo_tx_ops.psoc_send_d0wow_disable_req) {
258 			pmo_err("psoc_send_d0wow_disable_req is null");
259 			return QDF_STATUS_E_NULL_VALUE;
260 		}
261 		pmo_debug("Sending D0WOW disable command...");
262 		return pmo_tx_ops.psoc_send_d0wow_disable_req(psoc);
263 	}
264 
265 	if (!pmo_tx_ops.psoc_send_host_wakeup_ind) {
266 		pmo_err("psoc_send_host_wakeup_ind is null");
267 		return QDF_STATUS_E_NULL_VALUE;
268 	}
269 	return pmo_tx_ops.psoc_send_host_wakeup_ind(psoc);
270 }
271 
pmo_tgt_psoc_send_target_resume_req(struct wlan_objmgr_psoc * psoc)272 QDF_STATUS pmo_tgt_psoc_send_target_resume_req(struct wlan_objmgr_psoc *psoc)
273 {
274 	struct wlan_pmo_tx_ops pmo_tx_ops;
275 
276 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
277 	if (!pmo_tx_ops.psoc_send_target_resume_req) {
278 		pmo_err("send_target_resume_req is null");
279 		return QDF_STATUS_E_NULL_VALUE;
280 	}
281 
282 	return pmo_tx_ops.psoc_send_target_resume_req(psoc);
283 }
284 
pmo_tgt_psoc_send_idle_roam_monitor(struct wlan_objmgr_psoc * psoc,uint8_t val)285 QDF_STATUS pmo_tgt_psoc_send_idle_roam_monitor(struct wlan_objmgr_psoc *psoc,
286 					       uint8_t val)
287 {
288 	struct wlan_pmo_tx_ops pmo_tx_ops;
289 
290 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
291 	if (!pmo_tx_ops.psoc_send_idle_roam_suspend_mode) {
292 		pmo_err("NULL fp");
293 		return QDF_STATUS_E_NULL_VALUE;
294 	}
295 	return pmo_tx_ops.psoc_send_idle_roam_suspend_mode(psoc, val);
296 }
297 
pmo_tgt_psoc_set_wow_enable_ack_failed(struct wlan_objmgr_psoc * psoc)298 QDF_STATUS pmo_tgt_psoc_set_wow_enable_ack_failed(struct wlan_objmgr_psoc *psoc)
299 {
300 	struct wlan_pmo_tx_ops pmo_tx_ops;
301 
302 	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
303 	if (!pmo_tx_ops.psoc_set_wow_enable_ack_failed) {
304 		pmo_err("pmo ops is null");
305 		return QDF_STATUS_E_NULL_VALUE;
306 	}
307 
308 	pmo_tx_ops.psoc_set_wow_enable_ack_failed(psoc);
309 
310 	return QDF_STATUS_SUCCESS;
311 }
312