1 /*
2  * Copyright (c) 2018, 2020 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: offload lmac interface APIs for ocb
21  *
22  */
23 
24 #include <qdf_mem.h>
25 #include <target_if.h>
26 #include <qdf_status.h>
27 #include <wmi_unified_api.h>
28 #include <wmi_unified_priv.h>
29 #include <wmi_unified_param.h>
30 #include <wlan_objmgr_psoc_obj.h>
31 #include <wlan_utility.h>
32 #include <wlan_defs.h>
33 #include <wlan_ocb_public_structs.h>
34 #include <wlan_ocb_main.h>
35 #include <target_if_ocb.h>
36 
37 /**
38  * target_if_ocb_get_rx_ops() - get target interface RX operations
39  * @pdev: pdev handle
40  *
41  * Return: fp to target interface RX operations
42  */
43 static inline struct wlan_ocb_rx_ops *
target_if_ocb_get_rx_ops(struct wlan_objmgr_pdev * pdev)44 target_if_ocb_get_rx_ops(struct wlan_objmgr_pdev *pdev)
45 {
46 	struct ocb_pdev_obj *ocb_obj;
47 
48 	ocb_obj = wlan_get_pdev_ocb_obj(pdev);
49 
50 	return &ocb_obj->ocb_rxops;
51 }
52 
53 /**
54  * target_if_ocb_set_config() - send the OCB config to the FW
55  * @psoc: pointer to PSOC object
56  * @config: OCB channel configuration
57  *
58  * Return: QDF_STATUS_SUCCESS on success
59  */
target_if_ocb_set_config(struct wlan_objmgr_psoc * psoc,struct ocb_config * config)60 static QDF_STATUS target_if_ocb_set_config(struct wlan_objmgr_psoc *psoc,
61 					   struct ocb_config *config)
62 {
63 	QDF_STATUS status;
64 
65 	status = wmi_unified_ocb_set_config(get_wmi_unified_hdl_from_psoc(psoc),
66 					    config);
67 	if (status)
68 		target_if_err("Failed to set OCB config %d", status);
69 
70 	return status;
71 }
72 
73 /**
74  * target_if_ocb_set_utc_time() - send the UTC time to the firmware
75  * @psoc: pointer to PSOC object
76  * @utc: pointer to the UTC time structure
77  *
78  * Return: QDF_STATUS_SUCCESS on success
79  */
target_if_ocb_set_utc_time(struct wlan_objmgr_psoc * psoc,struct ocb_utc_param * utc)80 static QDF_STATUS target_if_ocb_set_utc_time(struct wlan_objmgr_psoc *psoc,
81 					     struct ocb_utc_param *utc)
82 {
83 	QDF_STATUS status;
84 
85 	status = wmi_unified_ocb_set_utc_time_cmd(
86 			get_wmi_unified_hdl_from_psoc(psoc), utc);
87 	if (status)
88 		target_if_err("Failed to set OCB UTC time %d", status);
89 
90 	return status;
91 }
92 
93 /**
94  * target_if_ocb_start_timing_advert() - start sending the timing
95  *  advertisement frame on a channel
96  * @psoc: pointer to PSOC object
97  * @ta: pointer to the timing advertisement
98  *
99  * Return: QDF_STATUS_SUCCESS on success
100  */
101 static QDF_STATUS
target_if_ocb_start_timing_advert(struct wlan_objmgr_psoc * psoc,struct ocb_timing_advert_param * ta)102 target_if_ocb_start_timing_advert(struct wlan_objmgr_psoc *psoc,
103 				  struct ocb_timing_advert_param *ta)
104 {
105 	QDF_STATUS status;
106 
107 	status = wmi_unified_ocb_start_timing_advert(
108 			get_wmi_unified_hdl_from_psoc(psoc), ta);
109 	if (status)
110 		target_if_err("Failed to start OCB timing advert %d", status);
111 
112 	return status;
113 }
114 
115 /**
116  * target_if_ocb_stop_timing_advert() - stop sending the timing
117  *   advertisement frame on a channel
118  * @psoc: pointer to PSOC object
119  * @ta: pointer to the timing advertisement
120  *
121  * Return: QDF_STATUS_SUCCESS on success
122  */
123 static QDF_STATUS
target_if_ocb_stop_timing_advert(struct wlan_objmgr_psoc * psoc,struct ocb_timing_advert_param * ta)124 target_if_ocb_stop_timing_advert(struct wlan_objmgr_psoc *psoc,
125 				 struct ocb_timing_advert_param *ta)
126 {
127 	QDF_STATUS status;
128 
129 	status =
130 		wmi_unified_ocb_stop_timing_advert(
131 				get_wmi_unified_hdl_from_psoc(psoc), ta);
132 	if (status)
133 		target_if_err("Failed to stop OCB timing advert %d", status);
134 
135 	return status;
136 }
137 
138 /**
139  * target_if_ocb_get_tsf_timer() - get tsf timer
140  * @psoc: pointer to PSOC object
141  * @request: pointer to the request
142  *
143  * Return: QDF_STATUS_SUCCESS on success
144  */
145 static QDF_STATUS
target_if_ocb_get_tsf_timer(struct wlan_objmgr_psoc * psoc,struct ocb_get_tsf_timer_param * request)146 target_if_ocb_get_tsf_timer(struct wlan_objmgr_psoc *psoc,
147 			    struct ocb_get_tsf_timer_param *request)
148 {
149 	QDF_STATUS status;
150 
151 	status = wmi_unified_ocb_get_tsf_timer(
152 			get_wmi_unified_hdl_from_psoc(psoc), request);
153 	if (status)
154 		target_if_err("Failed to send get tsf timer cmd: %d", status);
155 
156 	return status;
157 }
158 
159 /**
160  * target_if_dcc_get_stats() - get the DCC channel stats
161  * @psoc: pointer to PSOC object
162  * @get_stats_param: pointer to the dcc stats request
163  *
164  * Return: QDF_STATUS_SUCCESS on success
165  */
166 static QDF_STATUS
target_if_dcc_get_stats(struct wlan_objmgr_psoc * psoc,struct ocb_dcc_get_stats_param * get_stats_param)167 target_if_dcc_get_stats(struct wlan_objmgr_psoc *psoc,
168 			struct ocb_dcc_get_stats_param *get_stats_param)
169 {
170 	QDF_STATUS status;
171 
172 	status = wmi_unified_dcc_get_stats_cmd(
173 			get_wmi_unified_hdl_from_psoc(psoc), get_stats_param);
174 	if (status)
175 		target_if_err("Failed to send get DCC stats cmd: %d", status);
176 
177 	return status;
178 }
179 
180 /**
181  * target_if_dcc_clear_stats() - send command to clear the DCC stats
182  * @psoc: pointer to PSOC object
183  * @clear_stats_param: parameters to the command
184  *
185  * Return: QDF_STATUS_SUCCESS on success
186  */
187 static QDF_STATUS
target_if_dcc_clear_stats(struct wlan_objmgr_psoc * psoc,struct ocb_dcc_clear_stats_param * clear_stats_param)188 target_if_dcc_clear_stats(struct wlan_objmgr_psoc *psoc,
189 			  struct ocb_dcc_clear_stats_param *clear_stats_param)
190 {
191 	QDF_STATUS status;
192 
193 	status = wmi_unified_dcc_clear_stats(
194 			get_wmi_unified_hdl_from_psoc(psoc), clear_stats_param);
195 	if (status)
196 		target_if_err("Failed to send clear DCC stats cmd: %d", status);
197 
198 	return status;
199 }
200 
201 /**
202  * target_if_dcc_update_ndl() - command to update the NDL data
203  * @psoc: pointer to PSOC object
204  * @update_ndl_param: pointer to the request parameters
205  *
206  * Return: QDF_STATUS_SUCCESS on success
207  */
208 static QDF_STATUS
target_if_dcc_update_ndl(struct wlan_objmgr_psoc * psoc,struct ocb_dcc_update_ndl_param * update_ndl_param)209 target_if_dcc_update_ndl(struct wlan_objmgr_psoc *psoc,
210 			 struct ocb_dcc_update_ndl_param *update_ndl_param)
211 {
212 	QDF_STATUS status;
213 
214 	/* Send the WMI command */
215 	status = wmi_unified_dcc_update_ndl(get_wmi_unified_hdl_from_psoc(psoc),
216 					    update_ndl_param);
217 	if (status)
218 		target_if_err("Failed to send NDL update cmd: %d", status);
219 
220 	return status;
221 }
222 
223 /**
224  * target_if_ocb_set_config_resp() - handler for channel config response
225  * @scn: scn handle
226  * @event_buf: pointer to the event buffer
227  * @len: length of the buffer
228  *
229  * Return: 0 on success
230  */
231 static int
target_if_ocb_set_config_resp(ol_scn_t scn,uint8_t * event_buf,uint32_t len)232 target_if_ocb_set_config_resp(ol_scn_t scn, uint8_t *event_buf,
233 			      uint32_t len)
234 {
235 	int rc;
236 	QDF_STATUS status;
237 	uint32_t resp;
238 	struct wlan_objmgr_pdev *pdev;
239 	struct wlan_objmgr_psoc *psoc;
240 	struct wlan_ocb_rx_ops *ocb_rx_ops;
241 
242 	target_if_debug("scn:%pK, data:%pK, datalen:%d",
243 			scn, event_buf, len);
244 	if (!scn || !event_buf) {
245 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
246 		return -EINVAL;
247 	}
248 
249 	psoc = target_if_get_psoc_from_scn_hdl(scn);
250 	if (!psoc) {
251 		target_if_err("null psoc");
252 		return -EINVAL;
253 	}
254 
255 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
256 					  WLAN_OCB_SB_ID);
257 	if (!pdev) {
258 		target_if_err("pdev is NULL");
259 		return -EINVAL;
260 	}
261 
262 	ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
263 	if (ocb_rx_ops->ocb_set_config_status) {
264 		status = wmi_extract_ocb_set_channel_config_resp(
265 					get_wmi_unified_hdl_from_psoc(psoc),
266 					event_buf, &resp);
267 		if (QDF_IS_STATUS_ERROR(status)) {
268 			target_if_err("Failed to extract config status");
269 			rc = -EINVAL;
270 			goto exit;
271 		}
272 		status = ocb_rx_ops->ocb_set_config_status(psoc, resp);
273 		if (status != QDF_STATUS_SUCCESS) {
274 			target_if_err("ocb_set_config_status failed.");
275 			rc = -EINVAL;
276 			goto exit;
277 		}
278 		rc = 0;
279 	} else {
280 		target_if_fatal("No ocb_set_config_status callback");
281 		rc = -EINVAL;
282 	}
283 exit:
284 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
285 
286 	return rc;
287 };
288 
289 /**
290  * target_if_ocb_get_tsf_timer_resp() - handler for TSF timer response
291  * @scn: scn handle
292  * @event_buf: pointer to the event buffer
293  * @len: length of the buffer
294  *
295  * Return: 0 on success
296  */
target_if_ocb_get_tsf_timer_resp(ol_scn_t scn,uint8_t * event_buf,uint32_t len)297 static int target_if_ocb_get_tsf_timer_resp(ol_scn_t scn,
298 					    uint8_t *event_buf,
299 					    uint32_t len)
300 {
301 	int rc;
302 	QDF_STATUS status;
303 	struct wlan_objmgr_pdev *pdev;
304 	struct wlan_objmgr_psoc *psoc;
305 	struct ocb_get_tsf_timer_response response;
306 	struct wlan_ocb_rx_ops *ocb_rx_ops;
307 
308 	target_if_debug("scn:%pK, data:%pK, datalen:%d",
309 			scn, event_buf, len);
310 
311 	if (!scn || !event_buf) {
312 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
313 		return -EINVAL;
314 	}
315 
316 	psoc = target_if_get_psoc_from_scn_hdl(scn);
317 	if (!psoc) {
318 		target_if_err("null psoc");
319 		return -EINVAL;
320 	}
321 
322 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
323 					  WLAN_OCB_SB_ID);
324 	if (!pdev) {
325 		target_if_err("pdev is NULL");
326 		return -EINVAL;
327 	}
328 
329 	ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
330 	if (ocb_rx_ops->ocb_tsf_timer) {
331 		status = wmi_extract_ocb_tsf_timer(
332 			get_wmi_unified_hdl_from_psoc(psoc),
333 			event_buf, &response);
334 		if (QDF_IS_STATUS_ERROR(status)) {
335 			target_if_err("Failed to extract tsf timer");
336 			rc = -EINVAL;
337 			goto exit;
338 		}
339 		status = ocb_rx_ops->ocb_tsf_timer(psoc, &response);
340 		if (status != QDF_STATUS_SUCCESS) {
341 			target_if_err("ocb_tsf_timer failed.");
342 			rc = -EINVAL;
343 			goto exit;
344 		}
345 		rc = 0;
346 	} else {
347 		target_if_fatal("No ocb_tsf_timer callback");
348 		rc = -EINVAL;
349 	}
350 exit:
351 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
352 
353 	return rc;
354 }
355 
356 /**
357  * target_if_dcc_update_ndl_resp() - handler for update NDL response
358  * @scn: scn handle
359  * @event_buf: pointer to the event buffer
360  * @len: length of the buffer
361  *
362  * Return: 0 on success
363  */
target_if_dcc_update_ndl_resp(ol_scn_t scn,uint8_t * event_buf,uint32_t len)364 static int target_if_dcc_update_ndl_resp(ol_scn_t scn,
365 					 uint8_t *event_buf,
366 					 uint32_t len)
367 {
368 	int rc;
369 	QDF_STATUS status;
370 	struct wlan_objmgr_pdev *pdev;
371 	struct wlan_objmgr_psoc *psoc;
372 	struct ocb_dcc_update_ndl_response *resp;
373 	struct wlan_ocb_rx_ops *ocb_rx_ops;
374 
375 	target_if_debug("scn:%pK, data:%pK, datalen:%d",
376 			scn, event_buf, len);
377 
378 	if (!scn || !event_buf) {
379 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
380 		return -EINVAL;
381 	}
382 
383 	psoc = target_if_get_psoc_from_scn_hdl(scn);
384 	if (!psoc) {
385 		target_if_err("null psoc");
386 		return -EINVAL;
387 	}
388 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
389 					  WLAN_OCB_SB_ID);
390 	if (!pdev) {
391 		target_if_err("pdev is NULL");
392 		return -EINVAL;
393 	}
394 
395 	/* Allocate and populate the response */
396 	resp = qdf_mem_malloc(sizeof(*resp));
397 	if (!resp) {
398 		rc = -ENOMEM;
399 		goto exit;
400 	}
401 
402 	ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
403 	if (ocb_rx_ops->ocb_dcc_ndl_update) {
404 		status = wmi_extract_dcc_update_ndl_resp(
405 					get_wmi_unified_hdl_from_psoc(psoc),
406 					event_buf, resp);
407 		if (QDF_IS_STATUS_ERROR(status)) {
408 			target_if_err("Failed to extract ndl status");
409 			rc = -EINVAL;
410 			goto exit;
411 		}
412 		status = ocb_rx_ops->ocb_dcc_ndl_update(psoc, resp);
413 		if (status != QDF_STATUS_SUCCESS) {
414 			target_if_err("dcc_ndl_update failed.");
415 			rc = -EINVAL;
416 			goto exit;
417 		}
418 		rc = 0;
419 	} else {
420 		target_if_fatal("No dcc_ndl_update callback");
421 		rc = -EINVAL;
422 	}
423 exit:
424 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
425 	if (resp)
426 		qdf_mem_free(resp);
427 
428 	return rc;
429 }
430 
431 /**
432  * target_if_dcc_get_stats_resp() - handler for get stats response
433  * @scn: scn handle
434  * @event_buf: pointer to the event buffer
435  * @len: length of the buffer
436  *
437  * Return: 0 on success
438  */
target_if_dcc_get_stats_resp(ol_scn_t scn,uint8_t * event_buf,uint32_t len)439 static int target_if_dcc_get_stats_resp(ol_scn_t scn,
440 					uint8_t *event_buf,
441 					uint32_t len)
442 {
443 	int rc;
444 	QDF_STATUS status;
445 	struct wlan_objmgr_pdev *pdev;
446 	struct wlan_objmgr_psoc *psoc;
447 	struct ocb_dcc_get_stats_response *response;
448 	struct wlan_ocb_rx_ops *ocb_rx_ops;
449 
450 	target_if_debug("scn:%pK, data:%pK, datalen:%d",
451 			scn, event_buf, len);
452 
453 	if (!scn || !event_buf) {
454 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
455 		return -EINVAL;
456 	}
457 
458 	psoc = target_if_get_psoc_from_scn_hdl(scn);
459 	if (!psoc) {
460 		target_if_err("null psoc");
461 		return -EINVAL;
462 	}
463 
464 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
465 					  WLAN_OCB_SB_ID);
466 	if (!pdev) {
467 		target_if_err("pdev is NULL");
468 		return -EINVAL;
469 	}
470 
471 	ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
472 	if (ocb_rx_ops->ocb_dcc_stats_indicate) {
473 		status = wmi_extract_dcc_stats(
474 			get_wmi_unified_hdl_from_psoc(psoc),
475 			event_buf, &response);
476 		if (!response || QDF_IS_STATUS_ERROR(status)) {
477 			target_if_err("Cannot get DCC stats");
478 			rc = -ENOMEM;
479 			goto exit;
480 		}
481 
482 		status = ocb_rx_ops->ocb_dcc_stats_indicate(psoc,
483 							    response,
484 							    true);
485 		if (QDF_IS_STATUS_ERROR(status)) {
486 			target_if_err("dcc_stats_indicate failed.");
487 			rc = -EINVAL;
488 			goto exit;
489 		}
490 		rc = 0;
491 	} else {
492 		target_if_fatal("No dcc_stats_indicate callback");
493 		rc = -EINVAL;
494 	}
495 exit:
496 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
497 	if (response)
498 		qdf_mem_free(response);
499 
500 	return rc;
501 }
502 
503 /**
504  * target_if_dcc_stats_resp() - handler for DCC stats indication event
505  * @scn: scn handle
506  * @event_buf: pointer to the event buffer
507  * @len: length of the buffer
508  *
509  * Return: 0 on success
510  */
target_if_dcc_stats_resp(ol_scn_t scn,uint8_t * event_buf,uint32_t len)511 static int target_if_dcc_stats_resp(ol_scn_t scn, uint8_t *event_buf,
512 				    uint32_t len)
513 {
514 	int rc;
515 	QDF_STATUS status;
516 	struct wlan_objmgr_pdev *pdev;
517 	struct wlan_objmgr_psoc *psoc;
518 	struct ocb_dcc_get_stats_response *response;
519 	struct wlan_ocb_rx_ops *ocb_rx_ops;
520 
521 	target_if_debug("scn:%pK, data:%pK, datalen:%d",
522 			scn, event_buf, len);
523 
524 	if (!scn || !event_buf) {
525 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
526 		return -EINVAL;
527 	}
528 
529 	psoc = target_if_get_psoc_from_scn_hdl(scn);
530 	if (!psoc) {
531 		target_if_err("null psoc");
532 		return -EINVAL;
533 	}
534 
535 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
536 					  WLAN_OCB_SB_ID);
537 	if (!pdev) {
538 		target_if_err("pdev is NULL");
539 		return -EINVAL;
540 	}
541 
542 	ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
543 	if (ocb_rx_ops->ocb_dcc_stats_indicate) {
544 		status = wmi_extract_dcc_stats(
545 			get_wmi_unified_hdl_from_psoc(psoc),
546 			event_buf, &response);
547 		if (!response || QDF_IS_STATUS_ERROR(status)) {
548 			target_if_err("Cannot get DCC stats");
549 			rc = -ENOMEM;
550 			goto exit;
551 		}
552 		status = ocb_rx_ops->ocb_dcc_stats_indicate(psoc,
553 							    response,
554 							    false);
555 		if (QDF_IS_STATUS_ERROR(status)) {
556 			target_if_err("dcc_stats_indicate failed.");
557 			rc = -EINVAL;
558 			goto exit;
559 		}
560 		rc = 0;
561 	} else {
562 		target_if_fatal("dcc_stats_indicate failed.");
563 		response = NULL;
564 		rc = -EINVAL;
565 	}
566 exit:
567 	wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
568 	if (response)
569 		qdf_mem_free(response);
570 
571 	return rc;
572 }
573 
target_if_ocb_register_event_handler(struct wlan_objmgr_psoc * psoc,void * arg)574 QDF_STATUS target_if_ocb_register_event_handler(struct wlan_objmgr_psoc *psoc,
575 						void *arg)
576 {
577 	QDF_STATUS rc;
578 
579 	/* Initialize the members in WMA used by wma_ocb */
580 	rc = wmi_unified_register_event(get_wmi_unified_hdl_from_psoc(psoc),
581 			wmi_ocb_set_config_resp_event_id,
582 			target_if_ocb_set_config_resp);
583 	if (QDF_IS_STATUS_ERROR(rc)) {
584 		target_if_err("Failed to register OCB config resp event cb");
585 		return QDF_STATUS_E_FAILURE;
586 	}
587 
588 	rc = wmi_unified_register_event(
589 			get_wmi_unified_hdl_from_psoc(psoc),
590 			wmi_ocb_get_tsf_timer_resp_event_id,
591 			target_if_ocb_get_tsf_timer_resp);
592 	if (QDF_IS_STATUS_ERROR(rc)) {
593 		target_if_err("Failed to register OCB TSF resp event cb");
594 		goto unreg_set_config;
595 	}
596 
597 	rc = wmi_unified_register_event(
598 			get_wmi_unified_hdl_from_psoc(psoc),
599 			wmi_dcc_get_stats_resp_event_id,
600 			target_if_dcc_get_stats_resp);
601 	if (QDF_IS_STATUS_ERROR(rc)) {
602 		target_if_err("Failed to register DCC get stats resp event cb");
603 		goto unreg_tsf_timer;
604 	}
605 
606 	rc = wmi_unified_register_event(
607 			get_wmi_unified_hdl_from_psoc(psoc),
608 			wmi_dcc_update_ndl_resp_event_id,
609 			target_if_dcc_update_ndl_resp);
610 	if (QDF_IS_STATUS_ERROR(rc)) {
611 		target_if_err("Failed to register NDL update event cb");
612 		goto unreg_get_stats;
613 	}
614 
615 	rc = wmi_unified_register_event(get_wmi_unified_hdl_from_psoc(psoc),
616 			wmi_dcc_stats_event_id,
617 			target_if_dcc_stats_resp);
618 	if (QDF_IS_STATUS_ERROR(rc)) {
619 		target_if_err("Failed to register DCC stats event cb");
620 		goto unreg_ndl;
621 	}
622 
623 	return QDF_STATUS_SUCCESS;
624 
625 unreg_ndl:
626 	wmi_unified_unregister_event_handler(
627 			get_wmi_unified_hdl_from_psoc(psoc),
628 			wmi_dcc_update_ndl_resp_event_id);
629 unreg_get_stats:
630 	wmi_unified_unregister_event_handler(
631 			get_wmi_unified_hdl_from_psoc(psoc),
632 			wmi_dcc_get_stats_resp_event_id);
633 unreg_tsf_timer:
634 	wmi_unified_unregister_event_handler(
635 			get_wmi_unified_hdl_from_psoc(psoc),
636 			wmi_ocb_get_tsf_timer_resp_event_id);
637 unreg_set_config:
638 	wmi_unified_unregister_event(get_wmi_unified_hdl_from_psoc(psoc),
639 			wmi_ocb_set_config_resp_event_id);
640 
641 	return QDF_STATUS_E_FAILURE;
642 }
643 
644 QDF_STATUS
target_if_ocb_unregister_event_handler(struct wlan_objmgr_psoc * psoc,void * arg)645 target_if_ocb_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
646 				       void *arg)
647 {
648 	QDF_STATUS rc;
649 
650 	rc = wmi_unified_unregister_event_handler(
651 			get_wmi_unified_hdl_from_psoc(psoc),
652 			wmi_dcc_stats_event_id);
653 
654 	if (QDF_IS_STATUS_ERROR(rc))
655 		target_if_err("Failed to unregister DCC stats event cb");
656 
657 	rc = wmi_unified_unregister_event_handler(
658 			get_wmi_unified_hdl_from_psoc(psoc),
659 			wmi_dcc_update_ndl_resp_event_id);
660 
661 	if (QDF_IS_STATUS_ERROR(rc))
662 		target_if_err("Failed to unregister NDL update event cb");
663 
664 	rc = wmi_unified_unregister_event_handler(
665 			get_wmi_unified_hdl_from_psoc(psoc),
666 			wmi_dcc_get_stats_resp_event_id);
667 
668 	if (QDF_IS_STATUS_ERROR(rc))
669 		target_if_err("Failed to unregister DCC get stats resp cb");
670 
671 	rc = wmi_unified_unregister_event_handler(
672 			get_wmi_unified_hdl_from_psoc(psoc),
673 			wmi_ocb_get_tsf_timer_resp_event_id);
674 
675 	if (QDF_IS_STATUS_ERROR(rc))
676 		target_if_err("Failed to unregister OCB TSF resp event cb");
677 
678 	rc = wmi_unified_unregister_event(get_wmi_unified_hdl_from_psoc(psoc),
679 			wmi_ocb_set_config_resp_event_id);
680 
681 	if (QDF_IS_STATUS_ERROR(rc))
682 		target_if_err("Failed to unregister OCB config resp event cb");
683 
684 	return QDF_STATUS_SUCCESS;
685 }
686 
687 QDF_STATUS
target_if_ocb_register_tx_ops(struct wlan_ocb_tx_ops * ocb_txops)688 target_if_ocb_register_tx_ops(struct wlan_ocb_tx_ops *ocb_txops)
689 {
690 	ocb_txops->ocb_set_config = target_if_ocb_set_config;
691 	ocb_txops->ocb_set_utc_time = target_if_ocb_set_utc_time;
692 	ocb_txops->ocb_start_timing_advert = target_if_ocb_start_timing_advert;
693 	ocb_txops->ocb_stop_timing_advert = target_if_ocb_stop_timing_advert;
694 	ocb_txops->ocb_get_tsf_timer = target_if_ocb_get_tsf_timer;
695 	ocb_txops->ocb_dcc_get_stats = target_if_dcc_get_stats;
696 	ocb_txops->ocb_dcc_clear_stats = target_if_dcc_clear_stats;
697 	ocb_txops->ocb_dcc_update_ndl = target_if_dcc_update_ndl;
698 	ocb_txops->ocb_reg_ev_handler = target_if_ocb_register_event_handler;
699 	ocb_txops->ocb_unreg_ev_handler =
700 			target_if_ocb_unregister_event_handler;
701 
702 	return QDF_STATUS_SUCCESS;
703 }
704