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