xref: /wlan-driver/qca-wifi-host-cmn/target_if/green_ap/src/target_if_green_ap.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2017-2020 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 /**
21  * DOC: offload lmac interface APIs definitions for Green ap
22  */
23 
24 #include <target_if_green_ap.h>
25 #include <wlan_green_ap_api.h>
26 #include <../../core/src/wlan_green_ap_main_i.h>
27 #include <target_if.h>
28 #include <wmi_unified_api.h>
29 
30 #ifdef WLAN_SUPPORT_GAP_LL_PS_MODE
31 /**
32  * target_if_green_ap_ll_ps_cmd() - Green AP low latency power save mode
33  * cmd api
34  * @vdev: vdev object
35  * @ll_ps_params: low latency power save command parameter
36  *
37  * Return: QDF_STATUS_SUCCESS for success, otherwise appropriate failure reason
38  */
39 static QDF_STATUS
target_if_green_ap_ll_ps_cmd(struct wlan_objmgr_vdev * vdev,struct green_ap_ll_ps_cmd_param * ll_ps_params)40 target_if_green_ap_ll_ps_cmd(struct wlan_objmgr_vdev *vdev,
41 			     struct green_ap_ll_ps_cmd_param *ll_ps_params)
42 {
43 	struct wlan_objmgr_pdev *pdev;
44 	wmi_unified_t wmi_hdl;
45 
46 	pdev = wlan_vdev_get_pdev(vdev);
47 	if (!pdev) {
48 		green_ap_err("pdev context passed is NULL");
49 		return QDF_STATUS_E_INVAL;
50 	}
51 
52 	wmi_hdl = GET_WMI_HDL_FROM_PDEV(pdev);
53 	if (!wmi_hdl) {
54 		green_ap_err("null wmi_hdl");
55 		return QDF_STATUS_E_FAILURE;
56 	}
57 
58 	return wmi_unified_green_ap_ll_ps_send(wmi_hdl, ll_ps_params);
59 }
60 
target_if_register_ll_ps_tx_ops(struct wlan_lmac_if_green_ap_tx_ops * tx_ops)61 static inline void target_if_register_ll_ps_tx_ops(
62 		struct wlan_lmac_if_green_ap_tx_ops *tx_ops)
63 {
64 	tx_ops->ll_ps = target_if_green_ap_ll_ps_cmd;
65 }
66 #else
target_if_register_ll_ps_tx_ops(struct wlan_lmac_if_green_ap_tx_ops * tx_ops)67 static inline void target_if_register_ll_ps_tx_ops(
68 		struct wlan_lmac_if_green_ap_tx_ops *tx_ops)
69 {
70 }
71 #endif
72 
target_if_register_green_ap_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)73 QDF_STATUS target_if_register_green_ap_tx_ops(
74 		struct wlan_lmac_if_tx_ops *tx_ops)
75 {
76 	struct wlan_lmac_if_green_ap_tx_ops *green_ap_tx_ops;
77 
78 	if (!tx_ops) {
79 		target_if_err("invalid tx_ops");
80 		return QDF_STATUS_E_FAILURE;
81 	}
82 
83 	green_ap_tx_ops = &tx_ops->green_ap_tx_ops;
84 
85 	green_ap_tx_ops->enable_egap = target_if_green_ap_enable_egap;
86 	green_ap_tx_ops->ps_on_off_send = target_if_green_ap_set_ps_on_off;
87 	green_ap_tx_ops->reset_dev = NULL;
88 	green_ap_tx_ops->get_current_channel = NULL;
89 	green_ap_tx_ops->get_current_channel_flags = NULL;
90 	green_ap_tx_ops->get_capab = NULL;
91 
92 	target_if_register_ll_ps_tx_ops(green_ap_tx_ops);
93 
94 	return QDF_STATUS_SUCCESS;
95 }
96 
97 #ifdef WLAN_SUPPORT_GAP_LL_PS_MODE
98 /**
99  * target_if_green_ap_ll_ps_event() - Green AP low latency
100  * Power save event handler
101  * @scn: pointer to scn handle
102  * @evt_buf: pointer to event buffer
103  * @data_len: data len of the event buffer
104  *
105  * Return: 0 for success, otherwise appropriate error code
106  */
target_if_green_ap_ll_ps_event(ol_scn_t scn,uint8_t * evt_buf,uint32_t data_len)107 static int target_if_green_ap_ll_ps_event(ol_scn_t scn, uint8_t *evt_buf,
108 					  uint32_t data_len)
109 {
110 	QDF_STATUS status;
111 	int err = 0;
112 	struct wlan_objmgr_pdev *pdev;
113 	struct wlan_green_ap_ll_ps_event_param *ll_ps_param;
114 	void *wmi_hdl;
115 	struct wlan_objmgr_psoc *psoc;
116 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
117 
118 	psoc = target_if_get_psoc_from_scn_hdl(scn);
119 	if (!psoc) {
120 		green_ap_err("psoc is null");
121 		return -ENOMEM;
122 	}
123 
124 	pdev = target_if_get_pdev_from_scn_hdl(scn);
125 	if (!pdev) {
126 		green_ap_err("pdev is null");
127 		return -ENOMEM;
128 	}
129 
130 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
131 			pdev, WLAN_UMAC_COMP_GREEN_AP);
132 	if (!green_ap_ctx) {
133 		green_ap_err("green_ap_ctx not found");
134 		return -ENOMEM;
135 	}
136 
137 	ll_ps_param = qdf_mem_malloc(sizeof(*ll_ps_param));
138 	if (!ll_ps_param) {
139 		green_ap_err("Unable to allocate memory");
140 		return -ENOMEM;
141 	}
142 
143 	qdf_mem_zero(ll_ps_param, sizeof(*ll_ps_param));
144 
145 	wmi_hdl = GET_WMI_HDL_FROM_PDEV(pdev);
146 	if (!wmi_hdl) {
147 		green_ap_err("null wmi_hdl");
148 		err = -EINVAL;
149 		goto free_event_param;
150 	}
151 
152 	if (wmi_unified_extract_green_ap_ll_ps_param(wmi_hdl,
153 						     evt_buf,
154 						     ll_ps_param)) {
155 		green_ap_err("unable to extract green ap ll ps event params");
156 		err = -EINVAL;
157 		goto free_event_param;
158 	}
159 
160 	if ((ll_ps_param->dialog_token % 2))
161 		ll_ps_param->bcn_mult = green_ap_ctx->bcn_mult;
162 	else
163 		ll_ps_param->bcn_mult = 1;
164 
165 	green_ap_debug("Next TSF: %llu Dialog Token: %u bcn_mult: %u",
166 		       ll_ps_param->next_tsf,
167 		       ll_ps_param->dialog_token,
168 		       ll_ps_param->bcn_mult);
169 
170 	status = wlan_green_ap_send_ll_ps_event_params(pdev,
171 						       ll_ps_param);
172 	if (status != QDF_STATUS_SUCCESS) {
173 		wmi_err("wlan_green_ap_send_ll_ps_event failed");
174 		err = -EINVAL;
175 		goto free_event_param;
176 	}
177 
178 free_event_param:
179 	qdf_mem_free(ll_ps_param);
180 	return err;
181 }
182 
target_if_green_ap_register_ll_ps_event_handler(struct wlan_objmgr_pdev * pdev)183 QDF_STATUS target_if_green_ap_register_ll_ps_event_handler(
184 				struct wlan_objmgr_pdev *pdev)
185 {
186 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
187 	QDF_STATUS ret;
188 	wmi_unified_t wmi_hdl;
189 
190 	if (!pdev) {
191 		green_ap_err("pdev is null");
192 		return QDF_STATUS_E_INVAL;
193 		}
194 
195 	wmi_hdl = GET_WMI_HDL_FROM_PDEV(pdev);
196 	if (!wmi_hdl) {
197 		green_ap_err("null wmi_hdl");
198 		return QDF_STATUS_E_FAILURE;
199 	}
200 
201 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
202 			pdev, WLAN_UMAC_COMP_GREEN_AP);
203 	if (!green_ap_ctx) {
204 		green_ap_err("green ap context obtained is NULL");
205 		return QDF_STATUS_E_FAILURE;
206 	}
207 
208 	ret = wmi_unified_register_event_handler(
209 			wmi_hdl,
210 			wmi_xgap_enable_complete_eventid,
211 			target_if_green_ap_ll_ps_event,
212 			WMI_RX_UMAC_CTX);
213 
214 	if (QDF_IS_STATUS_ERROR(ret))
215 		green_ap_err("Failed to register Enhance Green AP event");
216 	else
217 		green_ap_debug("Set the Enhance Green AP event handler");
218 
219 	return QDF_STATUS_SUCCESS;
220 }
221 #endif
222 
223 /**
224  * target_if_green_ap_egap_status_info_event() - egap status info event
225  * @scn: pointer to scn handle
226  * @evt_buf: pointer to event buffer
227  * @data_len: data len of the event buffer
228  *
229  * Return: 0 for success, otherwise appropriate error code
230  */
target_if_green_ap_egap_status_info_event(ol_scn_t scn,uint8_t * evt_buf,uint32_t data_len)231 static int target_if_green_ap_egap_status_info_event(
232 		ol_scn_t scn, uint8_t *evt_buf, uint32_t data_len)
233 {
234 	struct wlan_objmgr_pdev *pdev;
235 	struct wlan_green_ap_egap_status_info egap_status_info_params;
236 	void *wmi_hdl;
237 
238 	pdev = target_if_get_pdev_from_scn_hdl(scn);
239 	if (!pdev) {
240 		green_ap_err("pdev is null");
241 		return QDF_STATUS_E_FAILURE;
242 	}
243 
244 	wmi_hdl = GET_WMI_HDL_FROM_PDEV(pdev);
245 	if (!wmi_hdl) {
246 		green_ap_err("null wmi_hdl");
247 		return QDF_STATUS_E_FAILURE;
248 	}
249 
250 	if (wmi_extract_green_ap_egap_status_info(wmi_hdl,
251 						  evt_buf,
252 						  &egap_status_info_params) !=
253 						  QDF_STATUS_SUCCESS) {
254 		green_ap_err("unable to extract green ap egap status info");
255 		return QDF_STATUS_E_FAILURE;
256 	}
257 
258 	green_ap_debug("mac_id: %d, status: %d, tx_mask: %x, rx_mask: %d",
259 		       egap_status_info_params.mac_id,
260 		       egap_status_info_params.status,
261 		       egap_status_info_params.tx_chainmask,
262 		       egap_status_info_params.rx_chainmask);
263 
264 	return 0;
265 }
266 
target_if_green_ap_register_egap_event_handler(struct wlan_objmgr_pdev * pdev)267 QDF_STATUS target_if_green_ap_register_egap_event_handler(
268 			struct wlan_objmgr_pdev *pdev)
269 {
270 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
271 	struct wlan_green_ap_egap_params *egap_params;
272 	QDF_STATUS ret;
273 	wmi_unified_t wmi_hdl;
274 
275 	if (!pdev) {
276 		green_ap_err("pdev is null");
277 		return QDF_STATUS_E_INVAL;
278 	}
279 
280 	wmi_hdl = GET_WMI_HDL_FROM_PDEV(pdev);
281 	if (!wmi_hdl) {
282 		green_ap_err("null wmi_hdl");
283 		return QDF_STATUS_E_FAILURE;
284 	}
285 
286 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
287 			pdev, WLAN_UMAC_COMP_GREEN_AP);
288 	if (!green_ap_ctx) {
289 		green_ap_err("green ap context obtained is NULL");
290 		return QDF_STATUS_E_FAILURE;
291 	}
292 	egap_params = &green_ap_ctx->egap_params;
293 
294 	ret = wmi_unified_register_event_handler(
295 			wmi_hdl,
296 			wmi_ap_ps_egap_info_event_id,
297 			target_if_green_ap_egap_status_info_event,
298 			WMI_RX_UMAC_CTX);
299 	if (QDF_IS_STATUS_ERROR(ret)) {
300 		green_ap_err("Failed to register Enhance Green AP event");
301 		egap_params->fw_egap_support = false;
302 	} else {
303 		green_ap_info("Set the Enhance Green AP event handler");
304 		egap_params->fw_egap_support = true;
305 	}
306 
307 	return QDF_STATUS_SUCCESS;
308 }
309 
target_if_green_ap_enable_egap(struct wlan_objmgr_pdev * pdev,struct wlan_green_ap_egap_params * egap_params)310 QDF_STATUS target_if_green_ap_enable_egap(
311 		struct wlan_objmgr_pdev *pdev,
312 		struct wlan_green_ap_egap_params *egap_params)
313 {
314 	struct wlan_pdev_green_ap_ctx *green_ap_ctx;
315 	wmi_unified_t wmi_hdl;
316 
317 	if (!pdev) {
318 		green_ap_err("pdev context passed is NULL");
319 		return QDF_STATUS_E_INVAL;
320 	}
321 
322 	wmi_hdl = GET_WMI_HDL_FROM_PDEV(pdev);
323 	if (!wmi_hdl) {
324 		green_ap_err("null wmi_hdl");
325 		return QDF_STATUS_E_FAILURE;
326 	}
327 
328 	green_ap_ctx = wlan_objmgr_pdev_get_comp_private_obj(
329 			pdev, WLAN_UMAC_COMP_GREEN_AP);
330 	if (!green_ap_ctx) {
331 		green_ap_err("green ap context obtained is NULL");
332 		return QDF_STATUS_E_FAILURE;
333 	}
334 
335 	qdf_spin_lock_bh(&green_ap_ctx->lock);
336 	if (!wlan_is_egap_enabled(green_ap_ctx)) {
337 		green_ap_info("enhanced green ap support is not present");
338 		qdf_spin_unlock_bh(&green_ap_ctx->lock);
339 		return QDF_STATUS_SUCCESS;
340 	}
341 	qdf_spin_unlock_bh(&green_ap_ctx->lock);
342 
343 	return wmi_unified_egap_conf_params_cmd(wmi_hdl,
344 							egap_params);
345 }
346 
target_if_green_ap_set_ps_on_off(struct wlan_objmgr_pdev * pdev,bool value,uint8_t pdev_id)347 QDF_STATUS target_if_green_ap_set_ps_on_off(struct wlan_objmgr_pdev *pdev,
348 					    bool value, uint8_t pdev_id)
349 {
350 	wmi_unified_t wmi_hdl;
351 
352 	if (!pdev) {
353 		green_ap_err("pdev context passed is NULL");
354 		return QDF_STATUS_E_INVAL;
355 	}
356 
357 	wmi_hdl = GET_WMI_HDL_FROM_PDEV(pdev);
358 	if (!wmi_hdl) {
359 		green_ap_err("null wmi_hdl");
360 		return QDF_STATUS_E_FAILURE;
361 	}
362 
363 	return wmi_unified_green_ap_ps_send(wmi_hdl,
364 					    value, pdev_id);
365 }
366