1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: reg_priv_objs.c
22  * This file defines the APIs to create regulatory private PSOC and PDEV
23  * objects.
24  */
25 
26 #include <wlan_cmn.h>
27 #include <reg_services_public_struct.h>
28 #include <wlan_objmgr_psoc_obj.h>
29 #include <wlan_objmgr_pdev_obj.h>
30 #include <qdf_lock.h>
31 #include "reg_priv_objs.h"
32 #include "reg_utils.h"
33 #include "reg_services_common.h"
34 #include "reg_build_chan_list.h"
35 #include "reg_host_11d.h"
36 #include "reg_callbacks.h"
37 #ifdef CONFIG_AFC_SUPPORT
38 #include <cfg_ucfg_api.h>
39 #endif
40 
reg_get_psoc_obj(struct wlan_objmgr_psoc * psoc)41 struct wlan_regulatory_psoc_priv_obj *reg_get_psoc_obj(
42 		struct wlan_objmgr_psoc *psoc)
43 {
44 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
45 
46 	if (!psoc) {
47 		reg_alert("psoc is NULL");
48 		return NULL;
49 	}
50 	psoc_priv_obj = wlan_objmgr_psoc_get_comp_private_obj(
51 			psoc, WLAN_UMAC_COMP_REGULATORY);
52 
53 	return psoc_priv_obj;
54 }
55 
reg_get_pdev_obj(struct wlan_objmgr_pdev * pdev)56 struct wlan_regulatory_pdev_priv_obj *reg_get_pdev_obj(
57 		struct wlan_objmgr_pdev *pdev)
58 {
59 	struct wlan_regulatory_pdev_priv_obj *pdev_reg;
60 
61 	if (!pdev) {
62 		reg_alert("pdev is NULL");
63 		return NULL;
64 	}
65 
66 	pdev_reg = wlan_objmgr_pdev_get_comp_private_obj(
67 			pdev, WLAN_UMAC_COMP_REGULATORY);
68 
69 	return pdev_reg;
70 }
71 
72 /*
73  * reg_set_5dot9_ghz_chan_in_master_mode - Set 5.9GHz channels to operate
74  * in master mode.
75  * @soc_reg_obj - Pointer to soc_reg_obj.
76  *
77  * Return: void
78  *
79  */
80 #ifdef CONFIG_REG_CLIENT
81 static void
reg_set_5dot9_ghz_chan_in_master_mode(struct wlan_regulatory_psoc_priv_obj * soc_reg_obj)82 reg_set_5dot9_ghz_chan_in_master_mode(struct wlan_regulatory_psoc_priv_obj
83 				      *soc_reg_obj)
84 {
85 	soc_reg_obj->enable_5dot9_ghz_chan_in_master_mode = false;
86 }
87 #else
88 static void
reg_set_5dot9_ghz_chan_in_master_mode(struct wlan_regulatory_psoc_priv_obj * soc_reg_obj)89 reg_set_5dot9_ghz_chan_in_master_mode(struct wlan_regulatory_psoc_priv_obj
90 				      *soc_reg_obj)
91 {
92 	soc_reg_obj->enable_5dot9_ghz_chan_in_master_mode = true;
93 }
94 #endif
95 
wlan_regulatory_psoc_obj_created_notification(struct wlan_objmgr_psoc * psoc,void * arg_list)96 QDF_STATUS wlan_regulatory_psoc_obj_created_notification(
97 		struct wlan_objmgr_psoc *psoc, void *arg_list)
98 {
99 	struct wlan_regulatory_psoc_priv_obj *soc_reg_obj;
100 	struct regulatory_channel *mas_chan_list;
101 	enum channel_enum chan_enum;
102 	QDF_STATUS status;
103 	uint8_t i;
104 	uint8_t phy_cnt;
105 
106 	soc_reg_obj = qdf_mem_common_alloc(sizeof(*soc_reg_obj));
107 	if (!soc_reg_obj)
108 		return QDF_STATUS_E_NOMEM;
109 
110 	soc_reg_obj->offload_enabled = false;
111 	soc_reg_obj->psoc_ptr = psoc;
112 	soc_reg_obj->dfs_enabled = true;
113 	soc_reg_obj->band_capability = (BIT(REG_BAND_2G) | BIT(REG_BAND_5G) |
114 					BIT(REG_BAND_6G));
115 	soc_reg_obj->enable_11d_supp = false;
116 	soc_reg_obj->indoor_chan_enabled = true;
117 	soc_reg_obj->force_ssc_disable_indoor_channel = false;
118 	soc_reg_obj->vdev_cnt_11d = 0;
119 	soc_reg_obj->vdev_id_for_11d_scan = INVALID_VDEV_ID;
120 	soc_reg_obj->restart_beaconing = CH_AVOID_RULE_RESTART;
121 	soc_reg_obj->enable_srd_chan_in_master_mode = 0xFF;
122 	soc_reg_obj->enable_11d_in_world_mode = false;
123 	soc_reg_obj->five_dot_nine_ghz_supported = false;
124 	reg_set_5dot9_ghz_chan_in_master_mode(soc_reg_obj);
125 	soc_reg_obj->retain_nol_across_regdmn_update = false;
126 	soc_reg_obj->is_ext_tpc_supported = false;
127 	soc_reg_obj->sta_sap_scc_on_indoor_channel = true;
128 	soc_reg_obj->set_fcc_channel = false;
129 	soc_reg_obj->p2p_indoor_ch_support = false;
130 
131 	for (i = 0; i < MAX_STA_VDEV_CNT; i++)
132 		soc_reg_obj->vdev_ids_11d[i] = INVALID_VDEV_ID;
133 
134 	qdf_spinlock_create(&soc_reg_obj->cbk_list_lock);
135 
136 	for (phy_cnt = 0; phy_cnt < PSOC_MAX_PHY_REG_CAP; phy_cnt++) {
137 		mas_chan_list =
138 			soc_reg_obj->mas_chan_params[phy_cnt].mas_chan_list;
139 		soc_reg_obj->chan_list_recvd[phy_cnt] = false;
140 
141 		for (chan_enum = 0; chan_enum < NUM_CHANNELS; chan_enum++) {
142 			mas_chan_list[chan_enum].chan_flags |=
143 				REGULATORY_CHAN_DISABLED;
144 			mas_chan_list[chan_enum].state = CHANNEL_STATE_DISABLE;
145 			mas_chan_list[chan_enum].nol_chan = false;
146 		}
147 	}
148 
149 	status = wlan_objmgr_psoc_component_obj_attach(
150 			psoc, WLAN_UMAC_COMP_REGULATORY, soc_reg_obj,
151 			QDF_STATUS_SUCCESS);
152 	if (QDF_IS_STATUS_ERROR(status)) {
153 		qdf_spinlock_destroy(&soc_reg_obj->cbk_list_lock);
154 		qdf_mem_common_free(soc_reg_obj);
155 		reg_err("Obj attach failed");
156 		return status;
157 	}
158 
159 	reg_debug("reg psoc obj created with status %d", status);
160 
161 	return status;
162 }
163 
wlan_regulatory_psoc_obj_destroyed_notification(struct wlan_objmgr_psoc * psoc,void * arg_list)164 QDF_STATUS wlan_regulatory_psoc_obj_destroyed_notification(
165 	struct wlan_objmgr_psoc *psoc, void *arg_list)
166 {
167 	QDF_STATUS status;
168 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
169 
170 	psoc_priv_obj = reg_get_psoc_obj(psoc);
171 	if (!psoc_priv_obj) {
172 		reg_err_rl("NULL reg psoc priv obj");
173 		return QDF_STATUS_E_FAULT;
174 	}
175 
176 	psoc_priv_obj->psoc_ptr = NULL;
177 	qdf_spinlock_destroy(&psoc_priv_obj->cbk_list_lock);
178 
179 	status = wlan_objmgr_psoc_component_obj_detach(
180 			psoc, WLAN_UMAC_COMP_REGULATORY, psoc_priv_obj);
181 
182 	if (status != QDF_STATUS_SUCCESS)
183 		reg_err_rl("psoc_priv_obj private obj detach failed");
184 
185 	reg_debug("reg psoc obj detached");
186 
187 	qdf_mem_common_free(psoc_priv_obj);
188 
189 	return status;
190 }
191 
192 #ifdef DISABLE_UNII_SHARED_BANDS
193 /**
194  * reg_reset_unii_5g_bitmap() - Reset the value of unii_5g_bitmap.
195  * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj.
196  *
197  * Return : void
198  */
199 static void
reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)200 reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
201 {
202 	pdev_priv_obj->unii_5g_bitmap = 0x0;
203 }
204 #else
205 static void inline
reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)206 reg_reset_unii_5g_bitmap(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
207 {
208 }
209 #endif
210 
211 #if defined(CONFIG_BAND_6GHZ)
212 #if defined(CONFIG_REG_CLIENT)
213 /**
214  * reg_init_def_client_type() - Initialize the regulatory 6G client type.
215  *
216  * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj.
217  *
218  * Return : void
219  */
220 static void
reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)221 reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
222 {
223 	pdev_priv_obj->reg_cur_6g_client_mobility_type = REG_DEFAULT_CLIENT;
224 }
225 #else
226 static void
reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)227 reg_init_def_client_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
228 {
229 	pdev_priv_obj->reg_cur_6g_client_mobility_type = REG_SUBORDINATE_CLIENT;
230 }
231 #endif
232 
233 /**
234  * reg_init_6g_vars() - Initialize the regulatory 6G variables viz.
235  * AP power type, client mobility type, rnr tpe usable and unspecified ap
236  * usable.
237  * @pdev_priv_obj: pointer to wlan_regulatory_pdev_priv_obj.
238  *
239  * Return : void
240  */
241 static void
reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)242 reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
243 {
244 	reg_set_ap_pwr_type(pdev_priv_obj);
245 	pdev_priv_obj->reg_rnr_tpe_usable = false;
246 	pdev_priv_obj->reg_unspecified_ap_usable = false;
247 	reg_init_def_client_type(pdev_priv_obj);
248 }
249 #else
250 static void
reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)251 reg_init_6g_vars(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
252 {
253 }
254 #endif
255 
256 #ifdef CONFIG_AFC_SUPPORT
257 static void
reg_create_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)258 reg_create_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
259 {
260 	qdf_spinlock_create(&pdev_priv_obj->afc_cb_lock);
261 }
262 
263 static void
reg_destroy_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)264 reg_destroy_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
265 {
266 	qdf_spinlock_destroy(&pdev_priv_obj->afc_cb_lock);
267 }
268 
269 static void
reg_init_afc_vars(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)270 reg_init_afc_vars(struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
271 		  struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
272 {
273 	pdev_priv_obj->is_reg_noaction_on_afc_pwr_evt =
274 			psoc_priv_obj->is_afc_reg_noaction;
275 }
276 
277 static inline void
reg_set_pdev_afc_dev_type(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj,struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj)278 reg_set_pdev_afc_dev_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
279 			  struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj)
280 {
281 	pdev_priv_obj->reg_afc_dev_deployment_type =
282 		psoc_priv_obj->reg_afc_dev_type;
283 }
284 #else
285 static inline void
reg_create_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)286 reg_create_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
287 {
288 }
289 
290 static inline void
reg_destroy_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)291 reg_destroy_afc_cb_spinlock(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
292 {
293 }
294 
295 static void
reg_init_afc_vars(struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj,struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)296 reg_init_afc_vars(struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj,
297 		  struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
298 {
299 }
300 
301 static inline void
reg_set_pdev_afc_dev_type(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj,struct wlan_regulatory_psoc_priv_obj * psoc_priv_obj)302 reg_set_pdev_afc_dev_type(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
303 			  struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj)
304 {
305 }
306 #endif
307 
wlan_regulatory_pdev_obj_created_notification(struct wlan_objmgr_pdev * pdev,void * arg_list)308 QDF_STATUS wlan_regulatory_pdev_obj_created_notification(
309 	struct wlan_objmgr_pdev *pdev, void *arg_list)
310 {
311 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
312 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
313 	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr;
314 	struct wlan_objmgr_psoc *parent_psoc;
315 	uint8_t pdev_id;
316 	uint8_t phy_id;
317 	uint32_t cnt;
318 	uint32_t range_2g_low, range_2g_high;
319 	uint32_t range_5g_low, range_5g_high;
320 	QDF_STATUS status;
321 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
322 	enum direction dir;
323 	wlan_objmgr_ref_dbgid dbg_id;
324 
325 	pdev_priv_obj = qdf_mem_common_alloc(sizeof(*pdev_priv_obj));
326 	if (!pdev_priv_obj)
327 		return QDF_STATUS_E_NOMEM;
328 
329 	parent_psoc = wlan_pdev_get_psoc(pdev);
330 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
331 	tx_ops = reg_get_psoc_tx_ops(parent_psoc);
332 
333 	if (tx_ops->get_phy_id_from_pdev_id)
334 		tx_ops->get_phy_id_from_pdev_id(parent_psoc, pdev_id, &phy_id);
335 	else
336 		phy_id = pdev_id;
337 
338 	psoc_priv_obj = reg_get_psoc_obj(parent_psoc);
339 	if (!psoc_priv_obj) {
340 		reg_err("reg psoc private obj is NULL");
341 		qdf_mem_common_free(pdev_priv_obj);
342 		return QDF_STATUS_E_FAULT;
343 	}
344 
345 	pdev_priv_obj->pdev_ptr = pdev;
346 	pdev_priv_obj->dfs_enabled = psoc_priv_obj->dfs_enabled;
347 	pdev_priv_obj->set_fcc_channel = psoc_priv_obj->set_fcc_channel;
348 	pdev_priv_obj->band_capability = psoc_priv_obj->band_capability;
349 	pdev_priv_obj->indoor_chan_enabled =
350 		psoc_priv_obj->indoor_chan_enabled;
351 	reg_set_keep_6ghz_sta_cli_connection(pdev, false);
352 
353 	reg_set_pdev_afc_dev_type(pdev_priv_obj, psoc_priv_obj);
354 
355 	pdev_priv_obj->en_chan_144 = true;
356 	reg_reset_unii_5g_bitmap(pdev_priv_obj);
357 
358 	qdf_spinlock_create(&pdev_priv_obj->reg_rules_lock);
359 	reg_create_afc_cb_spinlock(pdev_priv_obj);
360 
361 	reg_cap_ptr = psoc_priv_obj->reg_cap;
362 	pdev_priv_obj->force_ssc_disable_indoor_channel =
363 		psoc_priv_obj->force_ssc_disable_indoor_channel;
364 	pdev_priv_obj->sta_sap_scc_on_indoor_channel =
365 		psoc_priv_obj->sta_sap_scc_on_indoor_channel;
366 	pdev_priv_obj->p2p_indoor_ch_support =
367 		psoc_priv_obj->p2p_indoor_ch_support;
368 
369 	for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) {
370 		if (!reg_cap_ptr) {
371 			qdf_mem_common_free(pdev_priv_obj);
372 			reg_err("reg cap ptr is NULL");
373 			return QDF_STATUS_E_FAULT;
374 		}
375 
376 		if (reg_cap_ptr->phy_id == phy_id)
377 			break;
378 		reg_cap_ptr++;
379 	}
380 
381 	if (cnt == PSOC_MAX_PHY_REG_CAP) {
382 		qdf_mem_common_free(pdev_priv_obj);
383 		reg_err("extended capabilities not found for pdev");
384 		return QDF_STATUS_E_FAULT;
385 	}
386 
387 	range_2g_low = reg_cap_ptr->low_2ghz_chan;
388 	range_2g_high = reg_cap_ptr->high_2ghz_chan;
389 	range_5g_low = reg_cap_ptr->low_5ghz_chan;
390 	range_5g_high = reg_cap_ptr->high_5ghz_chan;
391 
392 	pdev_priv_obj->range_2g_low = range_2g_low;
393 	pdev_priv_obj->range_2g_high = range_2g_high;
394 	pdev_priv_obj->range_5g_low = range_5g_low;
395 	pdev_priv_obj->range_5g_high = range_5g_high;
396 	pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes;
397 	reg_init_6g_vars(pdev_priv_obj);
398 	pdev_priv_obj->chan_list_recvd =
399 		psoc_priv_obj->chan_list_recvd[phy_id];
400 
401 	status = wlan_objmgr_pdev_component_obj_attach(
402 			pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj,
403 			QDF_STATUS_SUCCESS);
404 	if (QDF_IS_STATUS_ERROR(status)) {
405 		reg_err("Obj attach failed");
406 		qdf_mem_common_free(pdev_priv_obj);
407 		return status;
408 	}
409 
410 	if (psoc_priv_obj->offload_enabled) {
411 		dbg_id = WLAN_REGULATORY_NB_ID;
412 		dir = NORTHBOUND;
413 	} else {
414 		dbg_id = WLAN_REGULATORY_SB_ID;
415 		dir = SOUTHBOUND;
416 	}
417 
418 	wlan_objmgr_pdev_get_ref(pdev, dbg_id);
419 	reg_propagate_mas_chan_list_to_pdev(parent_psoc, pdev, &dir);
420 	wlan_objmgr_pdev_release_ref(pdev, dbg_id);
421 
422 	reg_init_afc_vars(psoc_priv_obj, pdev_priv_obj);
423 
424 	if (!psoc_priv_obj->is_11d_offloaded)
425 		reg_11d_host_scan_init(parent_psoc);
426 
427 	reg_debug("reg pdev obj created with status %d", status);
428 
429 	return status;
430 }
431 
432 #ifdef CONFIG_AFC_SUPPORT
433 /**
434  * reg_free_chan_obj() - Free the AFC chan object and chan eirp object
435  * information
436  * @afc_chan_info: Pointer to afc_chan_info
437  *
438  * Return: void
439  */
reg_free_chan_obj(struct afc_chan_obj * afc_chan_info)440 static void reg_free_chan_obj(struct afc_chan_obj *afc_chan_info)
441 {
442 	if (afc_chan_info->chan_eirp_info)
443 		qdf_mem_free(afc_chan_info->chan_eirp_info);
444 }
445 
446 /**
447  * reg_free_afc_pwr_info() - Free the AFC power information object
448  * @pdev_priv_obj: Pointer to pdev_priv_obj
449  *
450  * Return: void
451  */
452 void
reg_free_afc_pwr_info(struct wlan_regulatory_pdev_priv_obj * pdev_priv_obj)453 reg_free_afc_pwr_info(struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
454 {
455 	struct reg_fw_afc_power_event *power_info;
456 	uint8_t i;
457 
458 	power_info = pdev_priv_obj->power_info;
459 	if (!power_info)
460 		return;
461 
462 	if (power_info->afc_freq_info)
463 		qdf_mem_free(power_info->afc_freq_info);
464 
465 	if (!power_info->afc_chan_info)
466 		return;
467 
468 	for (i = 0; i < power_info->num_chan_objs; i++)
469 		reg_free_chan_obj(&power_info->afc_chan_info[i]);
470 
471 	if (power_info->afc_chan_info)
472 		qdf_mem_free(power_info->afc_chan_info);
473 
474 	qdf_mem_free(power_info);
475 	pdev_priv_obj->power_info = NULL;
476 }
477 #endif
478 
wlan_regulatory_pdev_obj_destroyed_notification(struct wlan_objmgr_pdev * pdev,void * arg_list)479 QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification(
480 		struct wlan_objmgr_pdev *pdev, void *arg_list)
481 {
482 	QDF_STATUS status;
483 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
484 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
485 	uint32_t pdev_id;
486 
487 	pdev_priv_obj = reg_get_pdev_obj(pdev);
488 
489 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
490 
491 	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
492 		reg_err("reg pdev private obj is NULL");
493 		return QDF_STATUS_E_FAILURE;
494 	}
495 
496 	psoc_priv_obj = reg_get_psoc_obj(wlan_pdev_get_psoc(pdev));
497 	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
498 		reg_err("reg psoc private obj is NULL");
499 		return QDF_STATUS_E_FAILURE;
500 	}
501 
502 	if (!psoc_priv_obj->is_11d_offloaded)
503 		reg_11d_host_scan_deinit(wlan_pdev_get_psoc(pdev));
504 
505 	reg_free_afc_pwr_info(pdev_priv_obj);
506 	pdev_priv_obj->pdev_ptr = NULL;
507 
508 	status = wlan_objmgr_pdev_component_obj_detach(
509 			pdev, WLAN_UMAC_COMP_REGULATORY, pdev_priv_obj);
510 
511 	if (status != QDF_STATUS_SUCCESS)
512 		reg_err("reg pdev private obj detach failed");
513 
514 	reg_debug("reg pdev obj deleted");
515 
516 	qdf_spin_lock_bh(&pdev_priv_obj->reg_rules_lock);
517 	reg_reset_reg_rules(&pdev_priv_obj->reg_rules);
518 	qdf_spin_unlock_bh(&pdev_priv_obj->reg_rules_lock);
519 
520 	reg_destroy_afc_cb_spinlock(pdev_priv_obj);
521 	qdf_spinlock_destroy(&pdev_priv_obj->reg_rules_lock);
522 
523 	qdf_mem_common_free(pdev_priv_obj);
524 
525 	return status;
526 }
527