1 /*
2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024, Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: Implement various notification handlers which are accessed
20 * internally in pre_cac component only.
21 */
22
23 #include "wlan_pre_cac_main.h"
24 #include "wlan_objmgr_global_obj.h"
25 #include "wlan_policy_mgr_api.h"
26 #include "wlan_reg_services_api.h"
27 #include "wlan_mlme_api.h"
28
29 struct pre_cac_ops *glbl_pre_cac_ops;
30
pre_cac_stop(struct wlan_objmgr_psoc * psoc)31 void pre_cac_stop(struct wlan_objmgr_psoc *psoc)
32 {
33 struct pre_cac_psoc_priv *psoc_priv = pre_cac_psoc_get_priv(psoc);
34
35 if (!psoc_priv)
36 return;
37 pre_cac_debug("flush pre_cac_work");
38 if (psoc_priv->pre_cac_work.fn)
39 qdf_flush_work(&psoc_priv->pre_cac_work);
40 }
41
pre_cac_set_freq(struct wlan_objmgr_vdev * vdev,qdf_freq_t freq)42 void pre_cac_set_freq(struct wlan_objmgr_vdev *vdev,
43 qdf_freq_t freq)
44 {
45 struct pre_cac_vdev_priv *vdev_priv;
46
47 vdev_priv = pre_cac_vdev_get_priv(vdev);
48 if (!vdev_priv)
49 return;
50
51 vdev_priv->pre_cac_freq = freq;
52 }
53
pre_cac_get_freq(struct wlan_objmgr_vdev * vdev)54 qdf_freq_t pre_cac_get_freq(struct wlan_objmgr_vdev *vdev)
55 {
56 struct pre_cac_vdev_priv *vdev_priv;
57
58 vdev_priv = pre_cac_vdev_get_priv(vdev);
59 if (!vdev_priv)
60 return 0;
61
62 return vdev_priv->pre_cac_freq;
63 }
64
pre_cac_set_freq_before_pre_cac(struct wlan_objmgr_vdev * vdev,qdf_freq_t freq)65 void pre_cac_set_freq_before_pre_cac(struct wlan_objmgr_vdev *vdev,
66 qdf_freq_t freq)
67 {
68 struct pre_cac_vdev_priv *vdev_priv;
69
70 vdev_priv = pre_cac_vdev_get_priv(vdev);
71 if (!vdev_priv)
72 return;
73
74 vdev_priv->freq_before_pre_cac = freq;
75 }
76
pre_cac_get_freq_before_pre_cac(struct wlan_objmgr_vdev * vdev)77 qdf_freq_t pre_cac_get_freq_before_pre_cac(struct wlan_objmgr_vdev *vdev)
78 {
79 struct pre_cac_vdev_priv *vdev_priv;
80
81 vdev_priv = pre_cac_vdev_get_priv(vdev);
82 if (!vdev_priv)
83 return 0;
84
85 return vdev_priv->freq_before_pre_cac;
86 }
87
pre_cac_adapter_set(struct wlan_objmgr_vdev * vdev,bool status)88 void pre_cac_adapter_set(struct wlan_objmgr_vdev *vdev,
89 bool status)
90 {
91 struct pre_cac_vdev_priv *vdev_priv;
92
93 if (!vdev) {
94 pre_cac_debug("vdev is NULL");
95 return;
96 }
97
98 vdev_priv = pre_cac_vdev_get_priv(vdev);
99 if (!vdev_priv)
100 return;
101
102 vdev_priv->is_pre_cac_adapter = status;
103 }
104
pre_cac_adapter_is_active(struct wlan_objmgr_vdev * vdev)105 bool pre_cac_adapter_is_active(struct wlan_objmgr_vdev *vdev)
106 {
107 struct pre_cac_vdev_priv *vdev_priv;
108
109 if (!vdev) {
110 pre_cac_debug("vdev is NULL");
111 return false;
112 }
113
114 vdev_priv = pre_cac_vdev_get_priv(vdev);
115 if (!vdev_priv)
116 return false;
117
118 return vdev_priv->is_pre_cac_adapter;
119 }
120
pre_cac_complete_set(struct wlan_objmgr_vdev * vdev,bool status)121 void pre_cac_complete_set(struct wlan_objmgr_vdev *vdev,
122 bool status)
123 {
124 struct pre_cac_vdev_priv *vdev_priv;
125
126 if (!vdev) {
127 pre_cac_debug("vdev is NULL");
128 return;
129 }
130
131 vdev_priv = pre_cac_vdev_get_priv(vdev);
132 if (!vdev_priv)
133 return;
134
135 vdev_priv->pre_cac_complete = status;
136 }
137
pre_cac_complete_get(struct wlan_objmgr_vdev * vdev)138 bool pre_cac_complete_get(struct wlan_objmgr_vdev *vdev)
139 {
140 struct pre_cac_vdev_priv *vdev_priv;
141
142 vdev_priv = pre_cac_vdev_get_priv(vdev);
143 if (!vdev_priv)
144 return false;
145
146 return vdev_priv->pre_cac_complete;
147 }
148
pre_cac_complete(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,QDF_STATUS status)149 static void pre_cac_complete(struct wlan_objmgr_psoc *psoc,
150 uint8_t vdev_id,
151 QDF_STATUS status)
152 {
153 if (glbl_pre_cac_ops &&
154 glbl_pre_cac_ops->pre_cac_complete_cb)
155 glbl_pre_cac_ops->pre_cac_complete_cb(psoc, vdev_id, status);
156 }
157
pre_cac_handle_success(void * data)158 static void pre_cac_handle_success(void *data)
159 {
160 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)data;
161 struct pre_cac_psoc_priv *psoc_priv;
162
163 psoc_priv = pre_cac_psoc_get_priv(psoc);
164 if (!psoc_priv) {
165 pre_cac_err("Invalid psoc priv");
166 return;
167 }
168 pre_cac_debug("vdev id %d", psoc_priv->pre_cac_vdev_id);
169 pre_cac_complete(psoc, psoc_priv->pre_cac_vdev_id, QDF_STATUS_SUCCESS);
170 }
171
pre_cac_conditional_csa_ind(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,bool status)172 static void pre_cac_conditional_csa_ind(struct wlan_objmgr_psoc *psoc,
173 uint8_t vdev_id, bool status)
174 {
175 if (glbl_pre_cac_ops &&
176 glbl_pre_cac_ops->pre_cac_conditional_csa_ind_cb)
177 glbl_pre_cac_ops->pre_cac_conditional_csa_ind_cb(psoc,
178 vdev_id, status);
179 }
180
pre_cac_handle_failure(void * data)181 static void pre_cac_handle_failure(void *data)
182 {
183 struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)data;
184 struct pre_cac_psoc_priv *psoc_priv;
185
186 psoc_priv = pre_cac_psoc_get_priv(psoc);
187 if (!psoc_priv) {
188 pre_cac_err("Invalid psoc priv");
189 return;
190 }
191 pre_cac_debug("vdev id %d", psoc_priv->pre_cac_vdev_id);
192 pre_cac_complete(psoc, psoc_priv->pre_cac_vdev_id,
193 QDF_STATUS_E_FAILURE);
194 }
195
pre_cac_clean_up(struct wlan_objmgr_psoc * psoc)196 void pre_cac_clean_up(struct wlan_objmgr_psoc *psoc)
197 {
198 struct pre_cac_psoc_priv *psoc_priv = pre_cac_psoc_get_priv(psoc);
199 uint8_t vdev_id;
200
201 if (!psoc_priv) {
202 pre_cac_err("invalid psoc");
203 return;
204 }
205
206 if (!pre_cac_is_active(psoc))
207 return;
208
209 if (pre_cac_is_active(psoc) && psoc_priv->pre_cac_work.fn) {
210 pre_cac_debug("pre_cac_work already shceduled");
211 return;
212 }
213 pre_cac_get_vdev_id(psoc, &vdev_id);
214 pre_cac_debug("schedue pre_cac_work vdev %d", vdev_id);
215 psoc_priv->pre_cac_vdev_id = vdev_id;
216 qdf_create_work(0, &psoc_priv->pre_cac_work,
217 pre_cac_handle_failure,
218 psoc);
219 qdf_sched_work(0, &psoc_priv->pre_cac_work);
220 }
221
pre_cac_handle_radar_ind(struct wlan_objmgr_vdev * vdev)222 void pre_cac_handle_radar_ind(struct wlan_objmgr_vdev *vdev)
223 {
224 struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
225 struct pre_cac_psoc_priv *psoc_priv = pre_cac_psoc_get_priv(psoc);
226
227 if (!psoc_priv) {
228 pre_cac_err("invalid psoc");
229 return;
230 }
231
232 pre_cac_conditional_csa_ind(psoc, wlan_vdev_get_id(vdev), false);
233
234 pre_cac_debug("schedue pre_cac_work vdev %d", wlan_vdev_get_id(vdev));
235 psoc_priv->pre_cac_vdev_id = wlan_vdev_get_id(vdev);
236 qdf_create_work(0, &psoc_priv->pre_cac_work,
237 pre_cac_handle_failure,
238 psoc);
239 qdf_sched_work(0, &psoc_priv->pre_cac_work);
240 }
241
pre_cac_handle_cac_end(struct wlan_objmgr_vdev * vdev)242 void pre_cac_handle_cac_end(struct wlan_objmgr_vdev *vdev)
243 {
244 struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
245 struct pre_cac_psoc_priv *psoc_priv = pre_cac_psoc_get_priv(psoc);
246
247 if (!psoc_priv) {
248 pre_cac_err("invalid psoc");
249 return;
250 }
251
252 pre_cac_conditional_csa_ind(psoc, wlan_vdev_get_id(vdev), true);
253
254 pre_cac_debug("schedue pre_cac_work vdev %d", wlan_vdev_get_id(vdev));
255 psoc_priv->pre_cac_vdev_id = wlan_vdev_get_id(vdev);
256 qdf_create_work(0, &psoc_priv->pre_cac_work,
257 pre_cac_handle_success,
258 psoc);
259 qdf_sched_work(0, &psoc_priv->pre_cac_work);
260 }
261
pre_cac_get_vdev_id_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * args)262 static void pre_cac_get_vdev_id_handler(struct wlan_objmgr_psoc *psoc,
263 void *obj, void *args)
264 {
265 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
266 struct pre_cac_vdev_priv *vdev_priv;
267 uint8_t *vdev_id = (uint8_t *)args;
268
269 vdev_priv = pre_cac_vdev_get_priv(vdev);
270 if (!vdev_priv)
271 return;
272
273 if (vdev_priv->is_pre_cac_on)
274 *vdev_id = vdev->vdev_objmgr.vdev_id;
275 }
276
pre_cac_get_vdev_id(struct wlan_objmgr_psoc * psoc,uint8_t * vdev_id)277 void pre_cac_get_vdev_id(struct wlan_objmgr_psoc *psoc,
278 uint8_t *vdev_id)
279 {
280 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
281 pre_cac_get_vdev_id_handler,
282 vdev_id, true, WLAN_PRE_CAC_ID);
283 }
284
pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev * pdev,uint32_t chan_freq,uint32_t * pre_cac_chan_freq,enum phy_ch_width cac_ch_width)285 int pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
286 uint32_t chan_freq,
287 uint32_t *pre_cac_chan_freq,
288 enum phy_ch_width cac_ch_width)
289 {
290 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
291 uint32_t len = CFG_VALID_CHANNEL_LIST_LEN;
292 uint8_t pcl_weights[NUM_CHANNELS] = {0};
293 uint32_t freq_list[NUM_CHANNELS] = {0};
294 uint32_t weight_len = 0;
295 QDF_STATUS status;
296 uint32_t i;
297 bool is_ch_dfs = false;
298 struct ch_params ch_params;
299
300 pre_cac_stop(psoc);
301
302 if (pre_cac_is_active(psoc)) {
303 pre_cac_err("pre cac is already in progress");
304 return -EINVAL;
305 }
306
307 if (!chan_freq) {
308 /* Channel is not obtained from PCL because PCL may not have
309 * the entire channel list. For example: if SAP is up on
310 * channel 6 and PCL is queried for the next SAP interface,
311 * if SCC is preferred, the PCL will contain only the channel
312 * 6. But, we are in need of a DFS channel. So, going with the
313 * first channel from the valid channel list.
314 */
315 status = policy_mgr_get_valid_chans(psoc,
316 freq_list, &len);
317 if (QDF_IS_STATUS_ERROR(status)) {
318 pre_cac_err("Failed to get channel list");
319 return -EINVAL;
320 }
321
322 policy_mgr_update_with_safe_channel_list(psoc,
323 freq_list, &len,
324 pcl_weights,
325 weight_len);
326 try_next_bw:
327 for (i = 0; i < len; i++) {
328 is_ch_dfs = false;
329 qdf_mem_zero(&ch_params, sizeof(ch_params));
330 ch_params.ch_width = cac_ch_width;
331 wlan_reg_set_create_punc_bitmap(&ch_params, true);
332 if (wlan_reg_is_5ghz_ch_freq(freq_list[i]) &&
333 wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
334 pdev, freq_list[i], &ch_params,
335 REG_CURRENT_PWR_MODE) == CHANNEL_STATE_DFS)
336 is_ch_dfs = true;
337
338 if (is_ch_dfs) {
339 *pre_cac_chan_freq = freq_list[i];
340 break;
341 }
342 }
343
344 if (*pre_cac_chan_freq == 0 &&
345 cac_ch_width != CH_WIDTH_20MHZ &&
346 wlan_get_next_lower_bandwidth(cac_ch_width)
347 != CH_WIDTH_INVALID) {
348 cac_ch_width =
349 wlan_get_next_lower_bandwidth(cac_ch_width);
350 pre_cac_debug("try next bw %d", cac_ch_width);
351 goto try_next_bw;
352 }
353
354 if (*pre_cac_chan_freq == 0) {
355 pre_cac_err("unable to find outdoor channel");
356 return -EINVAL;
357 }
358 } else {
359 qdf_mem_zero(&ch_params, sizeof(ch_params));
360 ch_params.ch_width = cac_ch_width;
361 wlan_reg_set_create_punc_bitmap(&ch_params, true);
362 if (wlan_reg_is_5ghz_ch_freq(chan_freq) &&
363 wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
364 pdev, chan_freq, &ch_params,
365 REG_CURRENT_PWR_MODE) == CHANNEL_STATE_DFS)
366 is_ch_dfs = true;
367
368 /* Only when driver selects a channel, check is done for
369 * unnsafe and NOL channels. When user provides a fixed channel
370 * the user is expected to take care of this.
371 */
372 if (!wlan_mlme_is_channel_valid(psoc, chan_freq) ||
373 !is_ch_dfs) {
374 pre_cac_err("Invalid channel for pre cac:%d dfs %d",
375 chan_freq, is_ch_dfs);
376 return -EINVAL;
377 }
378 *pre_cac_chan_freq = chan_freq;
379 }
380
381 pre_cac_debug("selected pre cac channel:%d bw %d", *pre_cac_chan_freq,
382 cac_ch_width);
383
384 return 0;
385 }
386
pre_cac_set_status(struct wlan_objmgr_vdev * vdev,bool status)387 QDF_STATUS pre_cac_set_status(struct wlan_objmgr_vdev *vdev, bool status)
388 {
389 struct pre_cac_vdev_priv *vdev_priv;
390
391 vdev_priv = pre_cac_vdev_get_priv(vdev);
392 if (!vdev_priv)
393 return QDF_STATUS_E_INVAL;
394
395 vdev_priv->is_pre_cac_on = status;
396
397 return QDF_STATUS_SUCCESS;
398 }
399
pre_cac_is_active_vdev_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * args)400 static void pre_cac_is_active_vdev_handler(struct wlan_objmgr_psoc *psoc,
401 void *obj, void *args)
402 {
403 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj;
404 struct pre_cac_vdev_priv *vdev_priv;
405 bool *is_pre_cac_on = (bool *)args;
406
407 vdev_priv = pre_cac_vdev_get_priv(vdev);
408 if (!vdev_priv)
409 return;
410
411 *is_pre_cac_on = vdev_priv->is_pre_cac_on;
412 }
413
pre_cac_is_active(struct wlan_objmgr_psoc * psoc)414 bool pre_cac_is_active(struct wlan_objmgr_psoc *psoc)
415 {
416 bool is_pre_cac_on = false;
417
418 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
419 pre_cac_is_active_vdev_handler,
420 &is_pre_cac_on, true, WLAN_PRE_CAC_ID);
421 return is_pre_cac_on;
422 }
423
pre_cac_clear_work(struct wlan_objmgr_psoc * psoc)424 void pre_cac_clear_work(struct wlan_objmgr_psoc *psoc)
425 {
426 struct pre_cac_psoc_priv *psoc_priv = pre_cac_psoc_get_priv(psoc);
427
428 if (!psoc_priv)
429 return;
430
431 psoc_priv->pre_cac_work.fn = NULL;
432 psoc_priv->pre_cac_work.arg = NULL;
433
434 return;
435 }
436
437 struct pre_cac_vdev_priv *
pre_cac_vdev_get_priv_fl(struct wlan_objmgr_vdev * vdev,const char * func,uint32_t line)438 pre_cac_vdev_get_priv_fl(struct wlan_objmgr_vdev *vdev,
439 const char *func, uint32_t line)
440 {
441 struct pre_cac_vdev_priv *vdev_priv;
442
443 vdev_priv = wlan_objmgr_vdev_get_comp_private_obj(vdev,
444 WLAN_UMAC_COMP_PRE_CAC);
445 if (!vdev_priv) {
446 pre_cac_nofl_err("%s:%u: vdev id: %d, vdev_priv is NULL",
447 func, line, wlan_vdev_get_id(vdev));
448 }
449
450 return vdev_priv;
451 }
452
453 struct pre_cac_psoc_priv *
pre_cac_psoc_get_priv_fl(struct wlan_objmgr_psoc * psoc,const char * func,uint32_t line)454 pre_cac_psoc_get_priv_fl(struct wlan_objmgr_psoc *psoc,
455 const char *func, uint32_t line)
456 {
457 struct pre_cac_psoc_priv *psoc_priv;
458
459 psoc_priv = wlan_objmgr_psoc_get_comp_private_obj(psoc,
460 WLAN_UMAC_COMP_PRE_CAC);
461 if (!psoc_priv)
462 pre_cac_nofl_err("%s:%u: psoc_priv is NULL", func, line);
463
464 return psoc_priv;
465 }
466
pre_cac_set_osif_cb(struct pre_cac_ops * osif_pre_cac_ops)467 void pre_cac_set_osif_cb(struct pre_cac_ops *osif_pre_cac_ops)
468 {
469 glbl_pre_cac_ops = osif_pre_cac_ops;
470 }
471
472 QDF_STATUS
pre_cac_vdev_create_notification(struct wlan_objmgr_vdev * vdev,void * arg)473 pre_cac_vdev_create_notification(struct wlan_objmgr_vdev *vdev, void *arg)
474 {
475 struct pre_cac_vdev_priv *vdev_priv;
476 QDF_STATUS status;
477
478 vdev_priv = qdf_mem_malloc(sizeof(*vdev_priv));
479 if (!vdev_priv) {
480 status = QDF_STATUS_E_NOMEM;
481 goto exit;
482 }
483
484 status = wlan_objmgr_vdev_component_obj_attach(
485 vdev, WLAN_UMAC_COMP_PRE_CAC,
486 (void *)vdev_priv, QDF_STATUS_SUCCESS);
487 if (QDF_IS_STATUS_ERROR(status)) {
488 pre_cac_err("Failed to attach priv with vdev");
489 goto free_vdev_priv;
490 }
491
492 goto exit;
493
494 free_vdev_priv:
495 qdf_mem_free(vdev_priv);
496 status = QDF_STATUS_E_INVAL;
497 exit:
498 return status;
499 }
500
501 QDF_STATUS
pre_cac_vdev_destroy_notification(struct wlan_objmgr_vdev * vdev,void * arg)502 pre_cac_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg)
503 {
504 struct pre_cac_vdev_priv *vdev_priv = NULL;
505 QDF_STATUS status = QDF_STATUS_E_FAILURE;
506
507 vdev_priv = pre_cac_vdev_get_priv(vdev);
508 if (!vdev_priv) {
509 pre_cac_err("vdev priv is NULL");
510 goto exit;
511 }
512
513 status = wlan_objmgr_vdev_component_obj_detach(
514 vdev, WLAN_UMAC_COMP_PRE_CAC,
515 (void *)vdev_priv);
516 if (QDF_IS_STATUS_ERROR(status))
517 pre_cac_err("Failed to detach priv with vdev");
518
519 qdf_mem_free(vdev_priv);
520 vdev_priv = NULL;
521
522 exit:
523 return status;
524 }
525
526 QDF_STATUS
pre_cac_psoc_create_notification(struct wlan_objmgr_psoc * psoc,void * arg)527 pre_cac_psoc_create_notification(struct wlan_objmgr_psoc *psoc, void *arg)
528 {
529 struct pre_cac_psoc_priv *psoc_priv;
530 QDF_STATUS status;
531
532 psoc_priv = qdf_mem_malloc(sizeof(*psoc_priv));
533 if (!psoc_priv)
534 return QDF_STATUS_E_NOMEM;
535
536 status = wlan_objmgr_psoc_component_obj_attach(psoc,
537 WLAN_UMAC_COMP_PRE_CAC,
538 psoc_priv, QDF_STATUS_SUCCESS);
539 if (QDF_IS_STATUS_ERROR(status)) {
540 pre_cac_err("Failed to attach psoc component obj");
541 goto free_psoc_priv;
542 }
543
544 return status;
545
546 free_psoc_priv:
547 qdf_mem_free(psoc_priv);
548 return status;
549 }
550
551 QDF_STATUS
pre_cac_psoc_destroy_notification(struct wlan_objmgr_psoc * psoc,void * arg)552 pre_cac_psoc_destroy_notification(struct wlan_objmgr_psoc *psoc, void *arg)
553 {
554 struct pre_cac_psoc_priv *psoc_priv;
555 QDF_STATUS status;
556
557 psoc_priv = pre_cac_psoc_get_priv(psoc);
558 if (!psoc_priv) {
559 pre_cac_err("psoc priv is NULL");
560 return QDF_STATUS_E_FAILURE;
561 }
562
563 status = wlan_objmgr_psoc_component_obj_detach(psoc,
564 WLAN_UMAC_COMP_PRE_CAC,
565 psoc_priv);
566 if (QDF_IS_STATUS_ERROR(status)) {
567 pre_cac_err("Failed to detach psoc component obj");
568 return status;
569 }
570
571 qdf_mem_free(psoc_priv);
572 return status;
573 }
574
pre_cac_init(void)575 QDF_STATUS pre_cac_init(void)
576 {
577 QDF_STATUS status;
578
579 status = wlan_objmgr_register_psoc_create_handler(
580 WLAN_UMAC_COMP_PRE_CAC,
581 pre_cac_psoc_create_notification,
582 NULL);
583 if (QDF_IS_STATUS_ERROR(status)) {
584 pre_cac_err("Failed to register psoc create handler");
585 return status;
586 }
587
588 status = wlan_objmgr_register_psoc_destroy_handler(
589 WLAN_UMAC_COMP_PRE_CAC,
590 pre_cac_psoc_destroy_notification,
591 NULL);
592 if (QDF_IS_STATUS_ERROR(status)) {
593 pre_cac_err("Failed to register psoc delete handler");
594 goto fail_destroy_psoc;
595 }
596
597 status = wlan_objmgr_register_vdev_create_handler(
598 WLAN_UMAC_COMP_PRE_CAC,
599 pre_cac_vdev_create_notification, NULL);
600 if (QDF_IS_STATUS_ERROR(status)) {
601 pre_cac_err("Failed to register vdev create handler");
602 goto fail_create_vdev;
603 }
604
605 status = wlan_objmgr_register_vdev_destroy_handler(
606 WLAN_UMAC_COMP_PRE_CAC,
607 pre_cac_vdev_destroy_notification, NULL);
608 if (QDF_IS_STATUS_ERROR(status)) {
609 pre_cac_err("Failed to register vdev destroy handler");
610 goto fail_destroy_vdev;
611 }
612 return status;
613
614 fail_destroy_vdev:
615 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_PRE_CAC,
616 pre_cac_vdev_create_notification, NULL);
617
618 fail_create_vdev:
619 wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_PRE_CAC,
620 pre_cac_psoc_destroy_notification, NULL);
621
622 fail_destroy_psoc:
623 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_PRE_CAC,
624 pre_cac_psoc_create_notification, NULL);
625
626 return status;
627 }
628
pre_cac_deinit(void)629 void pre_cac_deinit(void)
630 {
631 QDF_STATUS status;
632
633 status = wlan_objmgr_unregister_vdev_destroy_handler(
634 WLAN_UMAC_COMP_PRE_CAC,
635 pre_cac_vdev_destroy_notification,
636 NULL);
637 if (QDF_IS_STATUS_ERROR(status))
638 pre_cac_err("Failed to unregister vdev destroy handler");
639
640 status = wlan_objmgr_unregister_vdev_create_handler(
641 WLAN_UMAC_COMP_PRE_CAC,
642 pre_cac_vdev_create_notification, NULL);
643 if (QDF_IS_STATUS_ERROR(status))
644 pre_cac_err("Failed to unregister vdev create handler");
645
646 status = wlan_objmgr_unregister_psoc_destroy_handler(
647 WLAN_UMAC_COMP_PRE_CAC,
648 pre_cac_psoc_destroy_notification,
649 NULL);
650 if (QDF_IS_STATUS_ERROR(status))
651 pre_cac_err("Failed to unregister psoc destroy handler");
652
653 status = wlan_objmgr_unregister_psoc_create_handler(
654 WLAN_UMAC_COMP_PRE_CAC,
655 pre_cac_psoc_create_notification,
656 NULL);
657 if (QDF_IS_STATUS_ERROR(status))
658 pre_cac_err("Failed to unregister psoc create handler");
659 }
660