1 /*
2 * Copyright (c) 2018-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 * DOC: This file contains ocb north bound interface definitions
21 */
22
23 #include <scheduler_api.h>
24 #include <wlan_defs.h>
25 #include <wlan_objmgr_pdev_obj.h>
26 #include <wlan_reg_services_api.h>
27 #include <wlan_objmgr_psoc_obj.h>
28 #include <wlan_objmgr_global_obj.h>
29 #include <wlan_ocb_public_structs.h>
30 #include <wlan_ocb_ucfg_api.h>
31 #include <wlan_ocb_tgt_api.h>
32 #include <wlan_lmac_if_def.h>
33 #include "wlan_ocb_main.h"
34 #include "reg_services_public_struct.h"
35
36 /**
37 * wlan_ocb_get_tx_ops() - get target interface tx operations
38 * @pdev: pdev handle
39 *
40 * Return: fp to target interface operations
41 */
42 static struct wlan_ocb_tx_ops *
wlan_ocb_get_tx_ops(struct wlan_objmgr_pdev * pdev)43 wlan_ocb_get_tx_ops(struct wlan_objmgr_pdev *pdev)
44 {
45 struct ocb_pdev_obj *ocb_obj;
46
47 ocb_obj = wlan_get_pdev_ocb_obj(pdev);
48 if (!ocb_obj) {
49 ocb_err("failed to get OCB pdev object");
50 return NULL;
51 }
52
53 return &ocb_obj->ocb_txops;
54 }
55
ucfg_ocb_init(void)56 QDF_STATUS ucfg_ocb_init(void)
57 {
58 QDF_STATUS status;
59
60 ocb_notice("ocb module dispatcher init");
61 status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_OCB,
62 ocb_pdev_obj_create_notification, NULL);
63
64 if (QDF_IS_STATUS_ERROR(status)) {
65 ocb_err("Failed to register pdev create handler for ocb");
66
67 return status;
68 }
69
70 status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_OCB,
71 ocb_pdev_obj_destroy_notification, NULL);
72
73 if (QDF_IS_STATUS_ERROR(status)) {
74 ocb_err("Failed to register pdev destroy handler for ocb");
75 goto fail_delete_pdev;
76 }
77
78 return status;
79
80 fail_delete_pdev:
81 wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_OCB,
82 ocb_pdev_obj_create_notification, NULL);
83
84 return status;
85 }
86
ucfg_ocb_deinit(void)87 QDF_STATUS ucfg_ocb_deinit(void)
88 {
89 QDF_STATUS status;
90
91 ocb_notice("ocb module dispatcher deinit");
92 status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_OCB,
93 ocb_pdev_obj_destroy_notification, NULL);
94 if (QDF_IS_STATUS_ERROR(status))
95 ocb_err("Failed to unregister pdev destroy handler");
96
97 status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_OCB,
98 ocb_pdev_obj_create_notification, NULL);
99 if (QDF_IS_STATUS_ERROR(status))
100 ocb_err("Failed to unregister pdev create handler");
101
102 return status;
103 }
104
ocb_psoc_enable(struct wlan_objmgr_psoc * psoc)105 QDF_STATUS ocb_psoc_enable(struct wlan_objmgr_psoc *psoc)
106 {
107 struct wlan_objmgr_pdev *pdev;
108
109 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
110 WLAN_OCB_NB_ID);
111 if (!pdev) {
112 ocb_err("Failed to get pdev handle");
113
114 return QDF_STATUS_E_FAILURE;
115 }
116 tgt_ocb_register_ev_handler(pdev);
117 wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
118
119 return QDF_STATUS_SUCCESS;
120 }
121
ocb_psoc_disable(struct wlan_objmgr_psoc * psoc)122 QDF_STATUS ocb_psoc_disable(struct wlan_objmgr_psoc *psoc)
123 {
124 struct wlan_objmgr_pdev *pdev;
125
126 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
127 WLAN_OCB_NB_ID);
128 if (!pdev) {
129 ocb_err("Failed to get pdev handle");
130 return QDF_STATUS_E_FAILURE;
131 }
132 tgt_ocb_unregister_ev_handler(pdev);
133 wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
134
135 return QDF_STATUS_SUCCESS;
136 }
137
ucfg_ocb_set_txrx_pdev_id(struct wlan_objmgr_psoc * psoc,uint8_t pdev_id)138 QDF_STATUS ucfg_ocb_set_txrx_pdev_id(struct wlan_objmgr_psoc *psoc,
139 uint8_t pdev_id)
140 {
141 struct wlan_objmgr_pdev *pdev;
142 struct ocb_pdev_obj *ocb_obj;
143
144 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
145 WLAN_OCB_NB_ID);
146 if (!pdev) {
147 ocb_err("Failed to get pdev handle");
148 return QDF_STATUS_E_FAILURE;
149 }
150 ocb_obj = wlan_get_pdev_ocb_obj(pdev);
151 wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
152 if (!ocb_obj) {
153 ocb_err("OCB object is NULL");
154 return QDF_STATUS_E_FAILURE;
155 }
156 ocb_obj->dp_pdev_id = pdev_id;
157
158 return QDF_STATUS_SUCCESS;
159 }
160
ucfg_ocb_update_dp_handle(struct wlan_objmgr_psoc * psoc,void * dp_soc)161 QDF_STATUS ucfg_ocb_update_dp_handle(struct wlan_objmgr_psoc *psoc,
162 void *dp_soc)
163 {
164 struct wlan_objmgr_pdev *pdev;
165 struct ocb_pdev_obj *ocb_obj;
166
167 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
168 WLAN_OCB_NB_ID);
169 if (!pdev) {
170 ocb_err("Failed to get pdev handle");
171 return QDF_STATUS_E_FAILURE;
172 }
173 ocb_obj = wlan_get_pdev_ocb_obj(pdev);
174 wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
175 if (!ocb_obj) {
176 ocb_err("OCB object is NULL");
177 return QDF_STATUS_E_FAILURE;
178 }
179 ocb_obj->dp_soc = dp_soc;
180
181 return QDF_STATUS_SUCCESS;
182 }
183
ucfg_ocb_config_channel(struct wlan_objmgr_pdev * pdev)184 QDF_STATUS ucfg_ocb_config_channel(struct wlan_objmgr_pdev *pdev)
185 {
186 QDF_STATUS status;
187 struct ocb_config *config;
188 struct ocb_pdev_obj *ocb_obj;
189 struct wlan_objmgr_psoc *psoc;
190 struct wlan_ocb_tx_ops *tx_ops;
191
192 ocb_obj = wlan_get_pdev_ocb_obj(pdev);
193 if (!ocb_obj || !ocb_obj->channel_config) {
194 ocb_alert("The request could not be found");
195 return QDF_STATUS_E_FAILURE;
196 }
197
198 config = ocb_obj->channel_config;
199 ocb_debug("Set config to vdev%d", config->vdev_id);
200 psoc = wlan_pdev_get_psoc(pdev);
201 if (!psoc) {
202 ocb_err("Null pointer for psoc");
203 return QDF_STATUS_E_INVAL;
204 }
205 tx_ops = wlan_ocb_get_tx_ops(pdev);
206 if (tx_ops && tx_ops->ocb_set_config)
207 status = tx_ops->ocb_set_config(psoc, ocb_obj->channel_config);
208 else
209 status = QDF_STATUS_E_IO;
210
211 if (QDF_IS_STATUS_SUCCESS(status)) {
212 ocb_debug("Set channel cmd is sent to southbound");
213 } else {
214 ocb_err("Failed to set channel config to southbound");
215
216 if (ocb_obj->channel_config) {
217 /*
218 * On success case, backup parameters will be released
219 * after channel info is synced to DP
220 */
221 ocb_info("release the backed config parameters");
222 qdf_mem_free(ocb_obj->channel_config);
223 ocb_obj->channel_config = NULL;
224 }
225 }
226
227 return status;
228 }
229
ucfg_ocb_set_channel_config(struct wlan_objmgr_vdev * vdev,struct ocb_config * config,ocb_sync_callback set_config_cb,void * arg)230 QDF_STATUS ucfg_ocb_set_channel_config(struct wlan_objmgr_vdev *vdev,
231 struct ocb_config *config,
232 ocb_sync_callback set_config_cb,
233 void *arg)
234 {
235 QDF_STATUS status;
236 enum wlan_vdev_state state;
237 uint32_t i;
238 struct wlan_objmgr_pdev *pdev;
239 struct wlan_objmgr_psoc *psoc;
240 struct wlan_ocb_tx_ops *tx_ops;
241 struct ocb_pdev_obj *ocb_obj;
242 struct ocb_callbacks *ocb_cbs;
243
244 pdev = wlan_vdev_get_pdev(vdev);
245 if (!pdev) {
246 ocb_err("Null pointer for pdev");
247 return QDF_STATUS_E_INVAL;
248 }
249 ocb_obj = wlan_get_pdev_ocb_obj(pdev);
250 if (!ocb_obj) {
251 ocb_alert("Failed to get OCB vdev object");
252 return QDF_STATUS_E_IO;
253 }
254
255 if (!config) {
256 ocb_err("Invalid config input");
257 return QDF_STATUS_E_FAILURE;
258 }
259
260 for (i = 0; i < config->channel_count; i++) {
261 if (wlan_reg_freq_to_band(config->channels[i].chan_freq)
262 == REG_BAND_2G)
263 config->channels[i].ch_mode = MODE_11G;
264 else
265 config->channels[i].ch_mode = MODE_11A;
266 }
267
268 /*
269 * backup the new configuration,
270 * it will be released after target's response
271 */
272 ocb_obj->channel_config = ocb_copy_config(config);
273 if (!ocb_obj->channel_config) {
274 ocb_err("Failed to backup config");
275 return QDF_STATUS_E_NOMEM;
276 }
277
278 ocb_cbs = &ocb_obj->ocb_cbs;
279 ocb_cbs->ocb_set_config_callback = set_config_cb;
280 ocb_cbs->ocb_set_config_context = arg;
281
282 state = wlan_vdev_mlme_get_state(vdev);
283 if (state != WLAN_VDEV_S_START) {
284 /* Vdev is not started, start it */
285 ocb_debug("OCB vdev%d is not up", config->vdev_id);
286 status = ocb_vdev_start(ocb_obj);
287 } else {
288 psoc = wlan_vdev_get_psoc(vdev);
289 tx_ops = wlan_ocb_get_tx_ops(pdev);
290 if (tx_ops && tx_ops->ocb_set_config)
291 status = tx_ops->ocb_set_config(psoc, config);
292 else
293 status = QDF_STATUS_E_IO;
294
295 ocb_debug("Set config to vdev%d", config->vdev_id);
296 if (QDF_IS_STATUS_SUCCESS(status))
297 ocb_debug("Set channel cmd is sent to southbound");
298 else
299 ocb_err("Failed to set channel config to southbound");
300 }
301
302 if (QDF_IS_STATUS_ERROR(status) && ocb_obj->channel_config) {
303 /*
304 * On success case, backup parameters will be released
305 * after channel info is synced to DP
306 */
307 ocb_info("release the backed config parameters");
308 qdf_mem_free(ocb_obj->channel_config);
309 ocb_obj->channel_config = NULL;
310 }
311
312 return status;
313 }
314
ucfg_ocb_set_utc_time(struct wlan_objmgr_vdev * vdev,struct ocb_utc_param * utc)315 QDF_STATUS ucfg_ocb_set_utc_time(struct wlan_objmgr_vdev *vdev,
316 struct ocb_utc_param *utc)
317 {
318 QDF_STATUS status;
319 struct wlan_objmgr_psoc *psoc;
320 struct wlan_objmgr_pdev *pdev;
321 struct wlan_ocb_tx_ops *tx_ops;
322
323 psoc = wlan_vdev_get_psoc(vdev);
324 pdev = wlan_vdev_get_pdev(vdev);
325 if (!psoc || !pdev) {
326 ocb_err("Null pointer for psoc/pdev");
327 return QDF_STATUS_E_INVAL;
328 }
329 tx_ops = wlan_ocb_get_tx_ops(pdev);
330
331 if (!tx_ops) {
332 ocb_alert("tx_ops is null");
333 return QDF_STATUS_E_IO;
334 }
335 if (!tx_ops->ocb_set_utc_time) {
336 ocb_alert("ocb_set_utc_time is null");
337 return QDF_STATUS_E_IO;
338 }
339
340 status = tx_ops->ocb_set_utc_time(psoc, utc);
341 if (QDF_IS_STATUS_ERROR(status))
342 ocb_err("Failed to set UTC time to southbound");
343 else
344 ocb_debug("UTC time is sent to southbound");
345
346 return status;
347 }
348
ucfg_ocb_start_timing_advert(struct wlan_objmgr_vdev * vdev,struct ocb_timing_advert_param * ta)349 QDF_STATUS ucfg_ocb_start_timing_advert(struct wlan_objmgr_vdev *vdev,
350 struct ocb_timing_advert_param *ta)
351 {
352 QDF_STATUS status;
353 struct wlan_objmgr_psoc *psoc;
354 struct wlan_objmgr_pdev *pdev;
355 struct wlan_ocb_tx_ops *tx_ops;
356
357 psoc = wlan_vdev_get_psoc(vdev);
358 pdev = wlan_vdev_get_pdev(vdev);
359 if (!psoc || !pdev) {
360 ocb_err("Null pointer for psoc/pdev");
361 return QDF_STATUS_E_INVAL;
362 }
363 tx_ops = wlan_ocb_get_tx_ops(pdev);
364 if (!tx_ops) {
365 ocb_alert("tx_ops is null");
366 return QDF_STATUS_E_IO;
367 }
368 if (!tx_ops->ocb_start_timing_advert) {
369 ocb_alert("ocb_start_timing_advert is null");
370 return QDF_STATUS_E_IO;
371 }
372 status = tx_ops->ocb_start_timing_advert(psoc, ta);
373 if (QDF_IS_STATUS_ERROR(status))
374 ocb_err("Failed to sent start timing advert to southbound");
375 else
376 ocb_debug("Start timing advert is sent to southbound");
377
378 return status;
379 }
380
ucfg_ocb_stop_timing_advert(struct wlan_objmgr_vdev * vdev,struct ocb_timing_advert_param * ta)381 QDF_STATUS ucfg_ocb_stop_timing_advert(struct wlan_objmgr_vdev *vdev,
382 struct ocb_timing_advert_param *ta)
383 {
384 QDF_STATUS status;
385 struct wlan_objmgr_psoc *psoc;
386 struct wlan_objmgr_pdev *pdev;
387 struct wlan_ocb_tx_ops *tx_ops;
388
389 psoc = wlan_vdev_get_psoc(vdev);
390 pdev = wlan_vdev_get_pdev(vdev);
391 if (!psoc || !pdev) {
392 ocb_err("Null pointer for psoc/pdev");
393 return QDF_STATUS_E_INVAL;
394 }
395 tx_ops = wlan_ocb_get_tx_ops(pdev);
396 if (!tx_ops) {
397 ocb_alert("tx_ops is null");
398 return QDF_STATUS_E_IO;
399 }
400 if (!tx_ops->ocb_stop_timing_advert) {
401 ocb_alert("ocb_stop_timing_advert is null");
402 return QDF_STATUS_E_IO;
403 }
404 status = tx_ops->ocb_stop_timing_advert(psoc, ta);
405 if (QDF_IS_STATUS_ERROR(status))
406 ocb_err("Failed to sent start timing advert to southbound");
407 else
408 ocb_debug("Start timing advert is sent to southbound");
409
410 return status;
411 }
412
ucfg_ocb_get_tsf_timer(struct wlan_objmgr_vdev * vdev,struct ocb_get_tsf_timer_param * req,ocb_sync_callback get_tsf_cb,void * arg)413 QDF_STATUS ucfg_ocb_get_tsf_timer(struct wlan_objmgr_vdev *vdev,
414 struct ocb_get_tsf_timer_param *req,
415 ocb_sync_callback get_tsf_cb,
416 void *arg)
417 {
418 QDF_STATUS status;
419 struct wlan_objmgr_psoc *psoc;
420 struct ocb_get_tsf_timer_param request;
421 struct wlan_ocb_tx_ops *tx_ops;
422 struct ocb_callbacks *ocb_cbs;
423 struct wlan_objmgr_pdev *pdev;
424
425 pdev = wlan_vdev_get_pdev(vdev);
426 if (!pdev) {
427 ocb_err("Null pointer for pdev");
428 return QDF_STATUS_E_INVAL;
429 }
430
431 tx_ops = wlan_ocb_get_tx_ops(pdev);
432 if (!tx_ops) {
433 ocb_alert("tx_ops is null");
434 return QDF_STATUS_E_IO;
435 }
436 if (!tx_ops->ocb_get_tsf_timer) {
437 ocb_alert("ocb_get_tsf_timer is null");
438 return QDF_STATUS_E_IO;
439 }
440
441 ocb_cbs = wlan_ocb_get_callbacks(pdev);
442 ocb_cbs->ocb_get_tsf_timer_context = arg;
443 ocb_cbs->ocb_get_tsf_timer_callback = get_tsf_cb;
444 request.vdev_id = req->vdev_id;
445 psoc = wlan_vdev_get_psoc(vdev);
446 if (!psoc) {
447 ocb_err("Null pointer for psoc");
448 return QDF_STATUS_E_INVAL;
449 }
450 status = tx_ops->ocb_get_tsf_timer(psoc, &request);
451 if (QDF_IS_STATUS_ERROR(status))
452 ocb_err("Failed to sent get tsf timer to southbound");
453 else
454 ocb_debug("Get tsf timer is sent to southbound");
455
456 return status;
457 }
458
ucfg_ocb_dcc_get_stats(struct wlan_objmgr_vdev * vdev,struct ocb_dcc_get_stats_param * request,ocb_sync_callback dcc_get_stats_cb,void * arg)459 QDF_STATUS ucfg_ocb_dcc_get_stats(struct wlan_objmgr_vdev *vdev,
460 struct ocb_dcc_get_stats_param *request,
461 ocb_sync_callback dcc_get_stats_cb,
462 void *arg)
463 {
464 QDF_STATUS status;
465 struct wlan_objmgr_psoc *psoc;
466 struct wlan_objmgr_pdev *pdev;
467 struct ocb_callbacks *ocb_cbs;
468 struct wlan_ocb_tx_ops *tx_ops;
469
470 pdev = wlan_vdev_get_pdev(vdev);
471 if (!pdev) {
472 ocb_err("Null pointer for pdev");
473 return QDF_STATUS_E_INVAL;
474 }
475 ocb_cbs = wlan_ocb_get_callbacks(pdev);
476 ocb_cbs->ocb_dcc_get_stats_context = arg;
477 ocb_cbs->ocb_dcc_get_stats_callback = dcc_get_stats_cb;
478
479 tx_ops = wlan_ocb_get_tx_ops(pdev);
480 if (!tx_ops) {
481 ocb_alert("tx_ops is null");
482 return QDF_STATUS_E_IO;
483 }
484
485 if (!tx_ops->ocb_dcc_get_stats) {
486 ocb_alert("ocb_dcc_get_stats is null");
487 return QDF_STATUS_E_IO;
488 }
489
490 psoc = wlan_vdev_get_psoc(vdev);
491 if (!psoc) {
492 ocb_err("Null pointer for psoc");
493 return QDF_STATUS_E_INVAL;
494 }
495 status = tx_ops->ocb_dcc_get_stats(psoc, request);
496 if (QDF_IS_STATUS_ERROR(status))
497 ocb_err("Failed to sent get dcc stats to southbound");
498 else
499 ocb_debug("Get dcc stats is sent to southbound");
500
501 return status;
502 }
503
ucfg_ocb_dcc_clear_stats(struct wlan_objmgr_vdev * vdev,uint16_t vdev_id,uint32_t bitmap)504 QDF_STATUS ucfg_ocb_dcc_clear_stats(struct wlan_objmgr_vdev *vdev,
505 uint16_t vdev_id,
506 uint32_t bitmap)
507 {
508 QDF_STATUS status;
509 struct wlan_objmgr_psoc *psoc;
510 struct wlan_objmgr_pdev *pdev;
511 struct wlan_ocb_tx_ops *tx_ops;
512 struct ocb_dcc_clear_stats_param clear_stats_param;
513
514 pdev = wlan_vdev_get_pdev(vdev);
515 if (!pdev) {
516 ocb_err("Null pointer for pdev");
517 return QDF_STATUS_E_INVAL;
518 }
519 tx_ops = wlan_ocb_get_tx_ops(pdev);
520 if (!tx_ops) {
521 ocb_alert("tx_ops is null");
522 return QDF_STATUS_E_IO;
523 }
524
525 if (!tx_ops->ocb_dcc_clear_stats) {
526 ocb_alert("ocb_dcc_clear_stats is null");
527 return QDF_STATUS_E_IO;
528 }
529
530 clear_stats_param.vdev_id = vdev_id;
531 clear_stats_param.dcc_stats_bitmap = bitmap;
532
533 psoc = wlan_vdev_get_psoc(vdev);
534 if (!psoc) {
535 ocb_err("Null pointer for psoc");
536 return QDF_STATUS_E_INVAL;
537 }
538 status = tx_ops->ocb_dcc_clear_stats(psoc, &clear_stats_param);
539 if (QDF_IS_STATUS_ERROR(status))
540 ocb_err("Failed to sent clear dcc stats to southbound");
541 else
542 ocb_debug("clear dcc stats is sent to southbound");
543
544 return status;
545 }
546
ucfg_ocb_dcc_update_ndl(struct wlan_objmgr_vdev * vdev,struct ocb_dcc_update_ndl_param * request,ocb_sync_callback dcc_update_ndl_cb,void * arg)547 QDF_STATUS ucfg_ocb_dcc_update_ndl(struct wlan_objmgr_vdev *vdev,
548 struct ocb_dcc_update_ndl_param *request,
549 ocb_sync_callback dcc_update_ndl_cb,
550 void *arg)
551 {
552 QDF_STATUS status;
553 struct wlan_objmgr_psoc *psoc;
554 struct ocb_callbacks *ocb_cbs;
555 struct wlan_objmgr_pdev *pdev;
556 struct wlan_ocb_tx_ops *tx_ops;
557
558 pdev = wlan_vdev_get_pdev(vdev);
559 if (!pdev) {
560 ocb_err("Null pointer for pdev");
561 return QDF_STATUS_E_INVAL;
562 }
563 ocb_cbs = wlan_ocb_get_callbacks(pdev);
564 ocb_cbs->ocb_dcc_update_ndl_context = arg;
565 ocb_cbs->ocb_dcc_update_ndl_callback = dcc_update_ndl_cb;
566
567 tx_ops = wlan_ocb_get_tx_ops(pdev);
568 if (!tx_ops) {
569 ocb_alert("tx_ops is null");
570 return QDF_STATUS_E_IO;
571 }
572 if (!tx_ops->ocb_dcc_update_ndl) {
573 ocb_alert("dcc_update_ndl is null");
574 return QDF_STATUS_E_IO;
575 }
576
577 psoc = wlan_vdev_get_psoc(vdev);
578 if (!psoc) {
579 ocb_err("Null pointer for psoc");
580 return QDF_STATUS_E_INVAL;
581 }
582 status = tx_ops->ocb_dcc_update_ndl(psoc, request);
583 if (QDF_IS_STATUS_ERROR(status))
584 ocb_err("Failed to sent update ndl to southbound");
585 else
586 ocb_debug("Update ndl is sent to southbound");
587
588 return status;
589 }
590
ucfg_ocb_register_for_dcc_stats_event(struct wlan_objmgr_pdev * pdev,void * ctx,ocb_sync_callback dcc_stats_cb)591 QDF_STATUS ucfg_ocb_register_for_dcc_stats_event(struct wlan_objmgr_pdev *pdev,
592 void *ctx, ocb_sync_callback dcc_stats_cb)
593 {
594 struct ocb_callbacks *ocb_cbs;
595
596 if (!pdev) {
597 ocb_err("Null pointer for pdev");
598 return QDF_STATUS_E_INVAL;
599 }
600 ocb_cbs = wlan_ocb_get_callbacks(pdev);
601
602 if (!ocb_cbs) {
603 ocb_err("Failed to register dcc stats callback");
604 return QDF_STATUS_E_FAILURE;
605 }
606 ocb_cbs->ocb_dcc_stats_event_context = ctx;
607 ocb_cbs->ocb_dcc_stats_event_callback = dcc_stats_cb;
608
609 return QDF_STATUS_SUCCESS;
610 }
611
ucfg_ocb_register_vdev_start(struct wlan_objmgr_pdev * pdev,QDF_STATUS (* ocb_start)(struct ocb_config *))612 QDF_STATUS ucfg_ocb_register_vdev_start(struct wlan_objmgr_pdev *pdev,
613 QDF_STATUS (*ocb_start)(struct ocb_config *))
614 {
615 struct ocb_callbacks *ocb_cbs;
616
617 if (!pdev) {
618 ocb_err("Null pointer for pdev");
619 return QDF_STATUS_E_INVAL;
620 }
621 ocb_cbs = wlan_ocb_get_callbacks(pdev);
622
623 if (!ocb_cbs) {
624 ocb_err("Failed to register dcc stats callback");
625 return QDF_STATUS_E_FAILURE;
626 }
627 ocb_cbs->start_ocb_vdev = ocb_start;
628
629 return QDF_STATUS_SUCCESS;
630 }
631