xref: /wlan-dirver/qca-wifi-host-cmn/umac/cfr/dispatcher/src/wlan_cfr_tgt_api.c (revision 2b23d2e388c3e0ba9ac6113a9da98706fc6be2fd)
1 /*
2  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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  * Layer b/w umac and target_if (ol) txops
22  * It contains wrapers for txops
23  */
24 
25 #include <wlan_cfr_tgt_api.h>
26 #include <wlan_cfr_utils_api.h>
27 #include <target_type.h>
28 #include <cfr_defs_i.h>
29 
30 uint32_t tgt_cfr_info_send(struct wlan_objmgr_pdev *pdev, void *head,
31 			   size_t hlen, void *data, size_t dlen, void *tail,
32 			   size_t tlen)
33 {
34 	struct pdev_cfr *pa;
35 	uint32_t status, total_len;
36 	uint8_t *nl_data = NULL;
37 
38 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
39 
40 	if (pa == NULL) {
41 		cfr_err("pdev_cfr is NULL\n");
42 		return -1;
43 	}
44 
45 	/* If CFR data transport mode is NL event then send single event*/
46 	if (pa->nl_cb.cfr_nl_cb) {
47 		total_len = hlen + dlen + tlen;
48 
49 		nl_data = qdf_mem_malloc(total_len);
50 		if (!nl_data) {
51 			cfr_err("failed to alloc memory, len %d, vdev_id %d",
52 				total_len, pa->nl_cb.vdev_id);
53 			return QDF_STATUS_E_FAILURE;
54 		}
55 
56 		if (hlen)
57 			qdf_mem_copy(nl_data, head, hlen);
58 
59 		if (dlen)
60 			qdf_mem_copy(nl_data + hlen, data, dlen);
61 
62 		if (tlen)
63 			qdf_mem_copy(nl_data + hlen + dlen, tail, tlen);
64 
65 		pa->nl_cb.cfr_nl_cb(pa->nl_cb.vdev_id, pa->nl_cb.pid,
66 				    (const void *)nl_data, total_len);
67 		qdf_mem_free(nl_data);
68 
69 		return QDF_STATUS_SUCCESS;
70 	}
71 
72 	if (head)
73 		status = cfr_streamfs_write(pa, (const void *)head, hlen);
74 
75 	if (data)
76 		status = cfr_streamfs_write(pa, (const void *)data, dlen);
77 
78 	if (tail)
79 		status = cfr_streamfs_write(pa, (const void *)tail, tlen);
80 
81 
82 	/* finalise the write */
83 	status = cfr_streamfs_flush(pa);
84 
85 	return status;
86 }
87 
88 void tgt_cfr_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
89 {
90 	struct psoc_cfr *cfr_sc;
91 
92 	if (psoc == NULL)
93 		return;
94 
95 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
96 					WLAN_UMAC_COMP_CFR);
97 	if (cfr_sc == NULL)
98 		return;
99 
100 	cfr_sc->is_cfr_capable = !!value;
101 	cfr_debug("CFR: FW support advert=%d", cfr_sc->is_cfr_capable);
102 }
103 
104 static inline struct wlan_lmac_if_cfr_tx_ops *
105 	wlan_psoc_get_cfr_txops(struct wlan_objmgr_psoc *psoc)
106 {
107 	struct wlan_lmac_if_tx_ops *tx_ops;
108 
109 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
110 	if (!tx_ops) {
111 		cfr_err("tx_ops is NULL");
112 		return NULL;
113 	}
114 	return &tx_ops->cfr_tx_ops;
115 }
116 
117 int tgt_cfr_get_target_type(struct wlan_objmgr_psoc *psoc)
118 {
119 	uint32_t target_type = 0;
120 	struct wlan_lmac_if_target_tx_ops *target_type_tx_ops;
121 	struct wlan_lmac_if_tx_ops *tx_ops;
122 
123 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
124 	if (!tx_ops) {
125 		cfr_err("tx_ops is NULL");
126 		return target_type;
127 	}
128 	target_type_tx_ops = &tx_ops->target_tx_ops;
129 
130 	if (target_type_tx_ops->tgt_get_tgt_type)
131 		target_type = target_type_tx_ops->tgt_get_tgt_type(psoc);
132 
133 	return target_type;
134 }
135 
136 int tgt_cfr_validate_period(struct wlan_objmgr_psoc *psoc, u_int32_t period)
137 {
138 	uint32_t target_type = tgt_cfr_get_target_type(psoc);
139 	int status = 0;
140 
141 	if (target_type == TARGET_TYPE_UNKNOWN) {
142 		cfr_err("cfr period validation fail due to invalid target type");
143 		return status;
144 	}
145 
146 	/* Basic check is the period should be between 0 and MAX_CFR_PRD */
147 	if ((period < 0) || (period > MAX_CFR_PRD)) {
148 		cfr_err("Invalid period value: %d\n", period);
149 		return status;
150 	}
151 
152 	if (target_type == TARGET_TYPE_QCN9000 ||
153 	    target_type == TARGET_TYPE_QCA6018 ||
154 	    target_type == TARGET_TYPE_QCA8074V2 ||
155 	    target_type == TARGET_TYPE_QCA5018 ||
156 	    target_type == TARGET_TYPE_QCN9224) {
157 		/* No additional check required for these targets */
158 		status = 1;
159 	} else {
160 		if (!(period % CFR_MOD_PRD)) {
161 			status = 1;
162 		} else {
163 			cfr_err("Invalid period value. Value must be mod of %d",
164 				CFR_MOD_PRD);
165 		}
166 	}
167 	return status;
168 }
169 
170 QDF_STATUS tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev)
171 {
172 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
173 	QDF_STATUS status = QDF_STATUS_SUCCESS;
174 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
175 
176 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
177 
178 	if (cfr_tx_ops->cfr_init_pdev)
179 		status = cfr_tx_ops->cfr_init_pdev(psoc, pdev);
180 
181 	if (QDF_IS_STATUS_ERROR(status))
182 		cfr_err("Error occurred with exit code %d\n", status);
183 
184 	return status;
185 }
186 
187 QDF_STATUS tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev)
188 {
189 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
190 	QDF_STATUS status = QDF_STATUS_SUCCESS;
191 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
192 
193 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
194 
195 	if (cfr_tx_ops->cfr_deinit_pdev)
196 		status = cfr_tx_ops->cfr_deinit_pdev(psoc, pdev);
197 
198 	if (QDF_IS_STATUS_ERROR(status))
199 		cfr_err("Error occurred with exit code %d\n", status);
200 
201 	return status;
202 }
203 
204 int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev,
205 			  struct wlan_objmgr_peer *peer,
206 			  struct cfr_capture_params *cfr_params)
207 {
208 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
209 	int status = 0;
210 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
211 
212 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
213 
214 	if (cfr_tx_ops->cfr_start_capture)
215 		status = cfr_tx_ops->cfr_start_capture(pdev, peer, cfr_params);
216 
217 	if (status != 0)
218 		cfr_err("Error occurred with exit code %d\n", status);
219 
220 	return status;
221 }
222 
223 int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev,
224 			 struct wlan_objmgr_peer *peer)
225 {
226 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
227 	int status = 0;
228 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
229 
230 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
231 
232 	if (cfr_tx_ops->cfr_stop_capture)
233 		status = cfr_tx_ops->cfr_stop_capture(pdev, peer);
234 
235 	if (status != 0)
236 		cfr_err("Error occurred with exit code %d\n", status);
237 
238 	return status;
239 }
240 
241 int
242 tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer)
243 {
244 	int status = 0;
245 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
246 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
247 
248 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
249 
250 	if (cfr_tx_ops->cfr_enable_cfr_timer)
251 		status = cfr_tx_ops->cfr_enable_cfr_timer(pdev, cfr_timer);
252 
253 	if (status != 0)
254 		cfr_err("Error occurred with exit code %d\n", status);
255 
256 	return status;
257 }
258 
259 #ifdef WLAN_ENH_CFR_ENABLE
260 QDF_STATUS
261 tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev,
262 		   struct cfr_rcc_param *rcc_param)
263 {
264 	QDF_STATUS status = QDF_STATUS_SUCCESS;
265 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
266 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
267 
268 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
269 
270 	if (cfr_tx_ops->cfr_config_rcc)
271 		status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param);
272 
273 	if (status != QDF_STATUS_SUCCESS)
274 		cfr_err("Error occurred with exit code %d\n", status);
275 
276 	return status;
277 }
278 
279 void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev)
280 {
281 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
282 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
283 
284 	if (!psoc) {
285 		cfr_err("Invalid PSOC: Flush LUT Timer cannot be started\n");
286 		return;
287 	}
288 
289 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
290 
291 	if (cfr_tx_ops->cfr_start_lut_timer)
292 		cfr_tx_ops->cfr_start_lut_timer(pdev);
293 }
294 
295 void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev)
296 {
297 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
298 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
299 
300 	if (!psoc) {
301 		cfr_err("Invalid PSOC: Flush LUT Timer cannot be stopped\n");
302 		return;
303 	}
304 
305 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
306 
307 	if (cfr_tx_ops->cfr_stop_lut_timer)
308 		cfr_tx_ops->cfr_stop_lut_timer(pdev);
309 }
310 
311 void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev,
312 			       struct cfr_rcc_param *rcc_param,
313 			       bool allvalid, uint16_t reset_cfg)
314 {
315 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
316 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
317 
318 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
319 
320 	if (cfr_tx_ops->cfr_default_ta_ra_cfg)
321 		cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param,
322 						 allvalid, reset_cfg);
323 }
324 
325 void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev)
326 {
327 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
328 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
329 
330 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
331 
332 	if (cfr_tx_ops->cfr_dump_lut_enh)
333 		cfr_tx_ops->cfr_dump_lut_enh(pdev);
334 }
335 
336 void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf)
337 {
338 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
339 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
340 
341 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
342 
343 	if (cfr_tx_ops->cfr_rx_tlv_process)
344 		cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf);
345 }
346 
347 void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev)
348 {
349 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
350 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
351 
352 	if (!psoc) {
353 		cfr_err("Invalid PSOC:Cannot update global config.\n");
354 		return;
355 	}
356 
357 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
358 
359 	if (cfr_tx_ops->cfr_update_global_cfg)
360 		cfr_tx_ops->cfr_update_global_cfg(pdev);
361 }
362 
363 QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev,
364 				       bool is_subscribe)
365 {
366 	struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
367 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
368 
369 	if (!psoc) {
370 		cfr_err("Invalid psoc\n");
371 		return QDF_STATUS_E_INVAL;
372 	}
373 
374 	cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
375 
376 	if (cfr_tx_ops->cfr_subscribe_ppdu_desc)
377 		return cfr_tx_ops->cfr_subscribe_ppdu_desc(pdev,
378 							   is_subscribe);
379 
380 	return QDF_STATUS_SUCCESS;
381 }
382 
383 QDF_STATUS
384 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
385 				  uint32_t value)
386 {
387 	struct psoc_cfr *cfr_sc;
388 
389 	if (!psoc) {
390 		cfr_err("CFR: NULL PSOC!!");
391 		return QDF_STATUS_E_INVAL;
392 	}
393 
394 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
395 						       WLAN_UMAC_COMP_CFR);
396 
397 	if (!cfr_sc) {
398 		cfr_err("Failed to get CFR component priv obj!!");
399 		return QDF_STATUS_E_INVAL;
400 	}
401 
402 	cfr_sc->is_cap_interval_mode_sel_support = !!value;
403 	cfr_debug("CFR: cap_interval_mode_sel_support is %s\n",
404 		  (cfr_sc->is_cap_interval_mode_sel_support) ?
405 		  "enabled" :
406 		  "disabled");
407 
408 	return QDF_STATUS_SUCCESS;
409 }
410 
411 QDF_STATUS
412 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
413 {
414 	struct psoc_cfr *cfr_sc;
415 
416 	if (!psoc) {
417 		cfr_err("CFR: NULL PSOC!!");
418 		return QDF_STATUS_E_INVAL;
419 	}
420 
421 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
422 						       WLAN_UMAC_COMP_CFR);
423 	if (!cfr_sc) {
424 		cfr_err("Failed to get CFR component priv obj!!");
425 		return QDF_STATUS_E_INVAL;
426 	}
427 
428 	cfr_sc->is_mo_marking_support = !!value;
429 	cfr_debug("CFR: mo_marking_support is %s\n",
430 		  (cfr_sc->is_mo_marking_support) ? "enabled" : "disabled");
431 
432 	return QDF_STATUS_SUCCESS;
433 }
434 
435 QDF_STATUS
436 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
437 {
438 	struct psoc_cfr *cfr_sc;
439 
440 	if (!psoc) {
441 		cfr_err("CFR: NULL PSOC!!");
442 		return QDF_STATUS_E_INVAL;
443 	}
444 
445 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
446 						       WLAN_UMAC_COMP_CFR);
447 
448 	if (!cfr_sc) {
449 		cfr_err("Failed to get CFR component priv obj!!");
450 		return QDF_STATUS_E_INVAL;
451 	}
452 
453 	cfr_sc->is_aoa_for_rcc_support = !!value;
454 	cfr_debug("CFR: aoa_for_rcc_support is %s\n",
455 		  (cfr_sc->is_aoa_for_rcc_support) ? "enabled" : "disabled");
456 
457 	return QDF_STATUS_SUCCESS;
458 }
459 #else
460 QDF_STATUS
461 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
462 				  uint32_t value)
463 {
464 	return QDF_STATUS_E_NOSUPPORT;
465 }
466 
467 QDF_STATUS
468 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc,
469 			       uint32_t value)
470 {
471 	return QDF_STATUS_E_NOSUPPORT;
472 }
473 
474 QDF_STATUS
475 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
476 {
477 	return QDF_STATUS_E_NOSUPPORT;
478 }
479 #endif
480