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