1 /*
2 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-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 * 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
tgt_cfr_info_send(struct wlan_objmgr_pdev * pdev,void * head,size_t hlen,void * data,size_t dlen,void * tail,size_t tlen)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
tgt_cfr_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)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 *
wlan_psoc_get_cfr_txops(struct wlan_objmgr_psoc * psoc)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
tgt_cfr_get_target_type(struct wlan_objmgr_psoc * psoc)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
tgt_cfr_validate_period(struct wlan_objmgr_psoc * psoc,u_int32_t period)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_QCA5332 ||
157 target_type == TARGET_TYPE_QCN9224 ||
158 target_type == TARGET_TYPE_QCN6432) {
159 /* No additional check required for these targets */
160 status = 1;
161 } else {
162 if (!(period % CFR_MOD_PRD)) {
163 status = 1;
164 } else {
165 cfr_err("Invalid period value. Value must be mod of %d",
166 CFR_MOD_PRD);
167 }
168 }
169 return status;
170 }
171
tgt_cfr_init_pdev(struct wlan_objmgr_pdev * pdev)172 QDF_STATUS tgt_cfr_init_pdev(struct wlan_objmgr_pdev *pdev)
173 {
174 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
175 QDF_STATUS status = QDF_STATUS_SUCCESS;
176 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
177
178 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
179
180 if (cfr_tx_ops->cfr_init_pdev)
181 status = cfr_tx_ops->cfr_init_pdev(psoc, pdev);
182
183 if (QDF_IS_STATUS_ERROR(status))
184 cfr_err("Error occurred with exit code %d\n", status);
185
186 return status;
187 }
188
tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev * pdev)189 QDF_STATUS tgt_cfr_deinit_pdev(struct wlan_objmgr_pdev *pdev)
190 {
191 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
192 QDF_STATUS status = QDF_STATUS_SUCCESS;
193 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
194
195 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
196
197 if (cfr_tx_ops->cfr_deinit_pdev)
198 status = cfr_tx_ops->cfr_deinit_pdev(psoc, pdev);
199
200 if (QDF_IS_STATUS_ERROR(status))
201 cfr_err("Error occurred with exit code %d\n", status);
202
203 return status;
204 }
205
tgt_cfr_start_capture(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_peer * peer,struct cfr_capture_params * cfr_params)206 int tgt_cfr_start_capture(struct wlan_objmgr_pdev *pdev,
207 struct wlan_objmgr_peer *peer,
208 struct cfr_capture_params *cfr_params)
209 {
210 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
211 int status = 0;
212 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
213
214 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
215
216 if (cfr_tx_ops->cfr_start_capture)
217 status = cfr_tx_ops->cfr_start_capture(pdev, peer, cfr_params);
218
219 if (status != 0)
220 cfr_err("Error occurred with exit code %d\n", status);
221
222 return status;
223 }
224
tgt_cfr_stop_capture(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_peer * peer)225 int tgt_cfr_stop_capture(struct wlan_objmgr_pdev *pdev,
226 struct wlan_objmgr_peer *peer)
227 {
228 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
229 int status = 0;
230 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
231
232 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
233
234 if (cfr_tx_ops->cfr_stop_capture)
235 status = cfr_tx_ops->cfr_stop_capture(pdev, peer);
236
237 if (status != 0)
238 cfr_err("Error occurred with exit code %d\n", status);
239
240 return status;
241 }
242
243 int
tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev * pdev,uint32_t cfr_timer)244 tgt_cfr_enable_cfr_timer(struct wlan_objmgr_pdev *pdev, uint32_t cfr_timer)
245 {
246 int status = 0;
247 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
248 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
249
250 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
251
252 if (cfr_tx_ops->cfr_enable_cfr_timer)
253 status = cfr_tx_ops->cfr_enable_cfr_timer(pdev, cfr_timer);
254
255 if (status != 0)
256 cfr_err("Error occurred with exit code %d\n", status);
257
258 return status;
259 }
260
261 #ifdef WLAN_ENH_CFR_ENABLE
262 QDF_STATUS
tgt_cfr_config_rcc(struct wlan_objmgr_pdev * pdev,struct cfr_rcc_param * rcc_param)263 tgt_cfr_config_rcc(struct wlan_objmgr_pdev *pdev,
264 struct cfr_rcc_param *rcc_param)
265 {
266 QDF_STATUS status = QDF_STATUS_SUCCESS;
267 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
268 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
269
270 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
271
272 if (cfr_tx_ops->cfr_config_rcc)
273 status = cfr_tx_ops->cfr_config_rcc(pdev, rcc_param);
274
275 if (status != QDF_STATUS_SUCCESS)
276 cfr_err("Error occurred with exit code %d\n", status);
277
278 return status;
279 }
280
tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev * pdev)281 void tgt_cfr_start_lut_age_timer(struct wlan_objmgr_pdev *pdev)
282 {
283 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
284 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
285
286 if (!psoc) {
287 cfr_err("Invalid PSOC: Flush LUT Timer cannot be started\n");
288 return;
289 }
290
291 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
292
293 if (cfr_tx_ops->cfr_start_lut_timer)
294 cfr_tx_ops->cfr_start_lut_timer(pdev);
295 }
296
tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev * pdev)297 void tgt_cfr_stop_lut_age_timer(struct wlan_objmgr_pdev *pdev)
298 {
299 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
300 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
301
302 if (!psoc) {
303 cfr_err("Invalid PSOC: Flush LUT Timer cannot be stopped\n");
304 return;
305 }
306
307 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
308
309 if (cfr_tx_ops->cfr_stop_lut_timer)
310 cfr_tx_ops->cfr_stop_lut_timer(pdev);
311 }
312
tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev * pdev,struct cfr_rcc_param * rcc_param,bool allvalid,uint16_t reset_cfg)313 void tgt_cfr_default_ta_ra_cfg(struct wlan_objmgr_pdev *pdev,
314 struct cfr_rcc_param *rcc_param,
315 bool allvalid, uint16_t reset_cfg)
316 {
317 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
318 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
319
320 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
321
322 if (cfr_tx_ops->cfr_default_ta_ra_cfg)
323 cfr_tx_ops->cfr_default_ta_ra_cfg(rcc_param,
324 allvalid, reset_cfg);
325 }
326
tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev * pdev)327 void tgt_cfr_dump_lut_enh(struct wlan_objmgr_pdev *pdev)
328 {
329 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
330 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
331
332 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
333
334 if (cfr_tx_ops->cfr_dump_lut_enh)
335 cfr_tx_ops->cfr_dump_lut_enh(pdev);
336 }
337
tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev * pdev,void * nbuf)338 void tgt_cfr_rx_tlv_process(struct wlan_objmgr_pdev *pdev, void *nbuf)
339 {
340 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
341 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
342
343 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
344
345 if (cfr_tx_ops->cfr_rx_tlv_process)
346 cfr_tx_ops->cfr_rx_tlv_process(pdev, nbuf);
347 }
348
tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev * pdev)349 void tgt_cfr_update_global_cfg(struct wlan_objmgr_pdev *pdev)
350 {
351 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
352 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
353
354 if (!psoc) {
355 cfr_err("Invalid PSOC:Cannot update global config.\n");
356 return;
357 }
358
359 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
360
361 if (cfr_tx_ops->cfr_update_global_cfg)
362 cfr_tx_ops->cfr_update_global_cfg(pdev);
363 }
364
tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev * pdev,bool is_subscribe)365 QDF_STATUS tgt_cfr_subscribe_ppdu_desc(struct wlan_objmgr_pdev *pdev,
366 bool is_subscribe)
367 {
368 struct wlan_lmac_if_cfr_tx_ops *cfr_tx_ops = NULL;
369 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
370
371 if (!psoc) {
372 cfr_err("Invalid psoc\n");
373 return QDF_STATUS_E_INVAL;
374 }
375
376 cfr_tx_ops = wlan_psoc_get_cfr_txops(psoc);
377
378 if (cfr_tx_ops->cfr_subscribe_ppdu_desc)
379 return cfr_tx_ops->cfr_subscribe_ppdu_desc(pdev,
380 is_subscribe);
381
382 return QDF_STATUS_SUCCESS;
383 }
384
385 QDF_STATUS
tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)386 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
387 uint32_t value)
388 {
389 struct psoc_cfr *cfr_sc;
390
391 if (!psoc) {
392 cfr_err("CFR: NULL PSOC!!");
393 return QDF_STATUS_E_INVAL;
394 }
395
396 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
397 WLAN_UMAC_COMP_CFR);
398
399 if (!cfr_sc) {
400 cfr_err("Failed to get CFR component priv obj!!");
401 return QDF_STATUS_E_INVAL;
402 }
403
404 cfr_sc->is_cap_interval_mode_sel_support = !!value;
405 cfr_debug("CFR: cap_interval_mode_sel_support is %s\n",
406 (cfr_sc->is_cap_interval_mode_sel_support) ?
407 "enabled" :
408 "disabled");
409
410 return QDF_STATUS_SUCCESS;
411 }
412
413 QDF_STATUS
tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)414 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
415 {
416 struct psoc_cfr *cfr_sc;
417
418 if (!psoc) {
419 cfr_err("CFR: NULL PSOC!!");
420 return QDF_STATUS_E_INVAL;
421 }
422
423 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
424 WLAN_UMAC_COMP_CFR);
425 if (!cfr_sc) {
426 cfr_err("Failed to get CFR component priv obj!!");
427 return QDF_STATUS_E_INVAL;
428 }
429
430 cfr_sc->is_mo_marking_support = !!value;
431 cfr_debug("CFR: mo_marking_support is %s\n",
432 (cfr_sc->is_mo_marking_support) ? "enabled" : "disabled");
433
434 return QDF_STATUS_SUCCESS;
435 }
436
437 QDF_STATUS
tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)438 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
439 {
440 struct psoc_cfr *cfr_sc;
441
442 if (!psoc) {
443 cfr_err("CFR: NULL PSOC!!");
444 return QDF_STATUS_E_INVAL;
445 }
446
447 cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
448 WLAN_UMAC_COMP_CFR);
449
450 if (!cfr_sc) {
451 cfr_err("Failed to get CFR component priv obj!!");
452 return QDF_STATUS_E_INVAL;
453 }
454
455 cfr_sc->is_aoa_for_rcc_support = !!value;
456 cfr_debug("CFR: aoa_for_rcc_support is %s\n",
457 (cfr_sc->is_aoa_for_rcc_support) ? "enabled" : "disabled");
458
459 return QDF_STATUS_SUCCESS;
460 }
461 #else
462 QDF_STATUS
tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)463 tgt_cfr_capture_count_support_set(struct wlan_objmgr_psoc *psoc,
464 uint32_t value)
465 {
466 return QDF_STATUS_E_NOSUPPORT;
467 }
468
469 QDF_STATUS
tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)470 tgt_cfr_mo_marking_support_set(struct wlan_objmgr_psoc *psoc,
471 uint32_t value)
472 {
473 return QDF_STATUS_E_NOSUPPORT;
474 }
475
476 QDF_STATUS
tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc * psoc,uint32_t value)477 tgt_cfr_aoa_for_rcc_support_set(struct wlan_objmgr_psoc *psoc, uint32_t value)
478 {
479 return QDF_STATUS_E_NOSUPPORT;
480 }
481 #endif
482