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