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