浏览代码

qcacmn: Implement chan_list processing for new WMI event

Add functions to handle the new WMI event,
WMI_REG_CHAN_LIST_CC_EXT_EVENTID. This includes processing new
data regarding standard power, low power indoor, and very low
power Clients and APs.

Process the regulatory rules from FW to populate the new 6G
channel lists. Fill in the current channel list with the
correct 6G master channel list. Copy other information from
the event into the regulatory private objects as needed.

Change-Id: I0c2001d809e4f0b292bac866780faa2850b1a8b1
CRs-fixed: 2799403
Lincoln Tran 4 年之前
父节点
当前提交
c8d397e920

+ 155 - 1
target_if/regulatory/src/target_if_reg.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -323,6 +323,141 @@ static QDF_STATUS tgt_if_regulatory_unregister_master_list_handler(
 			wmi_handle, wmi_reg_chan_list_cc_event_id);
 }
 
+#ifdef CONFIG_BAND_6GHZ
+/**
+ * tgt_reg_chan_list_ext_update_handler() - Extended channel list update handler
+ * @handle: scn handle
+ * @event_buf: pointer to event buffer
+ * @len: buffer length
+ *
+ * Return: 0 on success
+ */
+static int tgt_reg_chan_list_ext_update_handler(ol_scn_t handle,
+						uint8_t *event_buf,
+						uint32_t len)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_lmac_if_reg_rx_ops *reg_rx_ops;
+	struct cur_regulatory_info *reg_info;
+	QDF_STATUS status;
+	struct wmi_unified *wmi_handle;
+	int ret_val = 0;
+	uint32_t i;
+
+	TARGET_IF_ENTER();
+
+	psoc = target_if_get_psoc_from_scn_hdl(handle);
+	if (!psoc) {
+		target_if_err("psoc ptr is NULL");
+		return -EINVAL;
+	}
+
+	reg_rx_ops = target_if_regulatory_get_rx_ops(psoc);
+	if (!reg_rx_ops) {
+		target_if_err("reg_rx_ops is NULL");
+		return -EINVAL;
+	}
+
+	if (!reg_rx_ops->master_list_ext_handler) {
+		target_if_err("master_list_ext_handler is NULL");
+		return -EINVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("invalid wmi handle");
+		return -EINVAL;
+	}
+
+	reg_info = qdf_mem_malloc(sizeof(*reg_info));
+	if (!reg_info)
+		return -ENOMEM;
+
+	status = wmi_extract_reg_chan_list_ext_update_event(wmi_handle,
+							    event_buf,
+							    reg_info, len);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		target_if_err("Extraction of ext channel list event failed");
+		ret_val = -EFAULT;
+		goto clean;
+	}
+
+	if (reg_info->phy_id >= PSOC_MAX_PHY_REG_CAP) {
+		target_if_err_rl("phy_id %d is out of bounds",
+				 reg_info->phy_id);
+		ret_val = -EFAULT;
+		goto clean;
+	}
+
+	reg_info->psoc = psoc;
+
+	status = reg_rx_ops->master_list_ext_handler(reg_info);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		target_if_err("Failed to process master ext channel list handler");
+		ret_val = -EFAULT;
+	}
+
+clean:
+	qdf_mem_free(reg_info->reg_rules_2g_ptr);
+	qdf_mem_free(reg_info->reg_rules_5g_ptr);
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		qdf_mem_free(reg_info->reg_rules_6g_ap_ptr[i]);
+		qdf_mem_free(reg_info->
+			reg_rules_6g_client_ptr[i][REG_DEFAULT_CLIENT]);
+		qdf_mem_free(reg_info->
+			reg_rules_6g_client_ptr[i][REG_SUBORDINATE_CLIENT]);
+	}
+
+	qdf_mem_free(reg_info);
+
+	TARGET_IF_EXIT();
+
+	return ret_val;
+}
+
+/**
+ * tgt_if_regulatory_register_master_list_ext_handler() - Register extended
+ * master channel list event handler
+ * @psoc: Pointer to psoc
+ * @arg: Pointer to argument list
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS tgt_if_regulatory_register_master_list_ext_handler(
+	struct wlan_objmgr_psoc *psoc, void *arg)
+{
+	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+
+	if (!wmi_handle)
+		return QDF_STATUS_E_FAILURE;
+
+	return wmi_unified_register_event_handler(
+			wmi_handle, wmi_reg_chan_list_cc_ext_event_id,
+			tgt_reg_chan_list_ext_update_handler, WMI_RX_WORK_CTX);
+}
+
+/**
+ * tgt_if_regulatory_unregister_master_list_ext_handler() - Unregister extended
+ * master channel list event handler
+ * @psoc: Pointer to psoc
+ * @arg: Pointer to argument list
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS tgt_if_regulatory_unregister_master_list_ext_handler(
+	struct wlan_objmgr_psoc *psoc, void *arg)
+{
+	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+
+	if (!wmi_handle)
+		return QDF_STATUS_E_FAILURE;
+
+	return wmi_unified_unregister_event_handler(
+			wmi_handle, wmi_reg_chan_list_cc_ext_event_id);
+}
+#endif
+
 /**
  * tgt_if_regulatory_set_country_code() - Set country code
  * @psoc: Pointer to psoc
@@ -510,6 +645,23 @@ static QDF_STATUS tgt_if_regulatory_get_pdev_id_from_phy_id(
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef CONFIG_BAND_6GHZ
+static void target_if_register_master_ext_handler(
+				struct wlan_lmac_if_reg_tx_ops *reg_ops)
+{
+	reg_ops->register_master_ext_handler =
+		tgt_if_regulatory_register_master_list_ext_handler;
+
+	reg_ops->unregister_master_ext_handler =
+		tgt_if_regulatory_unregister_master_list_ext_handler;
+}
+#else
+static inline void
+target_if_register_master_ext_handler(struct wlan_lmac_if_reg_tx_ops *reg_ops)
+{
+}
+#endif
+
 QDF_STATUS target_if_register_regulatory_tx_ops(
 		struct wlan_lmac_if_tx_ops *tx_ops)
 {
@@ -521,6 +673,8 @@ QDF_STATUS target_if_register_regulatory_tx_ops(
 	reg_ops->unregister_master_handler =
 		tgt_if_regulatory_unregister_master_list_handler;
 
+	target_if_register_master_ext_handler(reg_ops);
+
 	reg_ops->set_country_code = tgt_if_regulatory_set_country_code;
 
 	reg_ops->fill_umac_legacy_chanlist = NULL;

+ 12 - 1
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -817,6 +817,8 @@ struct wlan_lmac_if_ftm_rx_ops {
  *                  pointers for regulatory component
  * @register_master_handler: pointer to register event handler
  * @unregister_master_handler:  pointer to unregister event handler
+ * @register_master_ext_handler: pointer to register ext event handler
+ * @unregister_master_ext_handler: pointer to unregister ext event handler
  * @register_11d_new_cc_handler: pointer to register 11d cc event handler
  * @unregister_11d_new_cc_handler:  pointer to unregister 11d cc event handler
  * @send_ctl_info: call-back function to send CTL info to firmware
@@ -826,7 +828,12 @@ struct wlan_lmac_if_reg_tx_ops {
 					      void *arg);
 	QDF_STATUS (*unregister_master_handler)(struct wlan_objmgr_psoc *psoc,
 						void *arg);
-
+#ifdef CONFIG_BAND_6GHZ
+	QDF_STATUS (*register_master_ext_handler)(struct wlan_objmgr_psoc *psoc,
+						  void *arg);
+	QDF_STATUS (*unregister_master_ext_handler)
+				(struct wlan_objmgr_psoc *psoc, void *arg);
+#endif
 	QDF_STATUS (*set_country_code)(struct wlan_objmgr_psoc *psoc,
 						void *arg);
 	QDF_STATUS (*fill_umac_legacy_chanlist)(struct wlan_objmgr_pdev *pdev,
@@ -1163,6 +1170,10 @@ struct wlan_lmac_if_mgmt_txrx_rx_ops {
 struct wlan_lmac_if_reg_rx_ops {
 	QDF_STATUS (*master_list_handler)(struct cur_regulatory_info
 					  *reg_info);
+#ifdef CONFIG_BAND_6GHZ
+	QDF_STATUS (*master_list_ext_handler)(struct cur_regulatory_info
+					      *reg_info);
+#endif
 	QDF_STATUS (*reg_11d_new_cc_handler)(struct wlan_objmgr_psoc *psoc,
 			struct reg_11d_new_country *reg_11d_new_cc);
 	QDF_STATUS (*reg_set_regdb_offloaded)(struct wlan_objmgr_psoc *psoc,

+ 17 - 1
umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -289,12 +289,28 @@ static void wlan_lmac_if_umac_rx_ops_register_wifi_pos(
 }
 #endif /* WIFI_POS_CONVERGED */
 
+#ifdef CONFIG_BAND_6GHZ
+static void wlan_lmac_if_register_master_list_ext_handler(
+					struct wlan_lmac_if_rx_ops *rx_ops)
+{
+	rx_ops->reg_rx_ops.master_list_ext_handler =
+		tgt_reg_process_master_chan_list_ext;
+}
+#else
+static inline void wlan_lmac_if_register_master_list_ext_handler(
+					struct wlan_lmac_if_rx_ops *rx_ops)
+{
+}
+#endif
+
 static void wlan_lmac_if_umac_reg_rx_ops_register(
 	struct wlan_lmac_if_rx_ops *rx_ops)
 {
 	rx_ops->reg_rx_ops.master_list_handler =
 		tgt_reg_process_master_chan_list;
 
+	wlan_lmac_if_register_master_list_ext_handler(rx_ops);
+
 	rx_ops->reg_rx_ops.reg_11d_new_cc_handler =
 		tgt_reg_process_11d_new_country;
 

+ 735 - 36
umac/regulatory/core/src/reg_build_chan_list.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -40,6 +40,23 @@
 #define MAX_PWR_FCC_CHAN_13 2
 #define CHAN_144_CENT_FREQ 5720
 
+#ifdef CONFIG_BAND_6GHZ
+static void reg_fill_psd_info(enum channel_enum chan_enum,
+			      struct cur_reg_rule *reg_rule,
+			      struct regulatory_channel *master_list)
+{
+	master_list[chan_enum].psd_flag = reg_rule->psd_flag;
+
+	master_list[chan_enum].psd_eirp = reg_rule->psd_eirp;
+}
+#else
+static inline void reg_fill_psd_info(enum channel_enum chan_enum,
+				     struct cur_reg_rule *reg_rule,
+				     struct regulatory_channel *master_list)
+{
+}
+#endif
+
 /**
  * reg_fill_channel_info() - Populate TX power, antenna gain, channel state,
  * channel flags, min and max bandwidth to master channel list.
@@ -55,6 +72,7 @@ static void reg_fill_channel_info(enum channel_enum chan_enum,
 {
 	master_list[chan_enum].chan_flags &= ~REGULATORY_CHAN_DISABLED;
 
+	reg_fill_psd_info(chan_enum, reg_rule, master_list);
 	master_list[chan_enum].tx_power = reg_rule->reg_power;
 	master_list[chan_enum].ant_gain = reg_rule->ant_gain;
 	master_list[chan_enum].state = CHANNEL_STATE_ENABLE;
@@ -81,6 +99,82 @@ static void reg_fill_channel_info(enum channel_enum chan_enum,
 		master_list[chan_enum].max_bw = reg_rule->max_bw;
 }
 
+#ifdef CONFIG_BAND_6GHZ
+/**
+ * reg_populate_band_channels_ext_for_6g() - For all the valid regdb channels in
+ *	the master channel list, find the regulatory rules and call
+ *	reg_fill_channel_info() to populate master channel list with txpower,
+ *	antennagain, BW info, etc.
+ * @start_idx: Start channel range in list
+ * @end_idx: End channel range in list
+ * @rule_start_ptr: Pointer to regulatory rules
+ * @num_reg_rules: Number of regulatory rules
+ * @min_reg_bw: Minimum regulatory bandwidth
+ * @mas_chan_list: Pointer to master channel list
+ */
+static void reg_populate_band_channels_ext_for_6g(uint16_t start_idx,
+				       uint16_t end_idx,
+				       struct cur_reg_rule *rule_start_ptr,
+				       uint32_t num_reg_rules,
+				       uint16_t min_reg_bw,
+				       struct regulatory_channel *mas_chan_list)
+{
+	struct cur_reg_rule *found_rule_ptr;
+	struct cur_reg_rule *cur_rule_ptr;
+	struct regulatory_channel;
+	uint32_t rule_num, bw;
+	uint16_t i, min_bw, max_bw;
+
+	for (i = start_idx; i <= end_idx; i++) {
+		found_rule_ptr = NULL;
+
+		max_bw = QDF_MIN((uint16_t)20,
+				 channel_map[MIN_6GHZ_CHANNEL + i].max_bw);
+		min_bw = QDF_MAX(min_reg_bw,
+				 channel_map[MIN_6GHZ_CHANNEL + i].min_bw);
+
+		if (channel_map[MIN_6GHZ_CHANNEL + i].chan_num ==
+		    INVALID_CHANNEL_NUM)
+			continue;
+
+		for (bw = max_bw; bw >= min_bw; bw = bw / 2) {
+			for (rule_num = 0, cur_rule_ptr = rule_start_ptr;
+			     rule_num < num_reg_rules;
+			     cur_rule_ptr++, rule_num++) {
+				if ((cur_rule_ptr->start_freq <=
+				     mas_chan_list[i].center_freq -
+				     bw / 2) &&
+				    (cur_rule_ptr->end_freq >=
+				     mas_chan_list[i].center_freq +
+				     bw / 2) && (min_bw <= bw)) {
+					found_rule_ptr = cur_rule_ptr;
+					break;
+				}
+			}
+
+			if (found_rule_ptr)
+				break;
+		}
+
+		if (found_rule_ptr) {
+			mas_chan_list[i].max_bw = bw;
+			reg_fill_channel_info(i, found_rule_ptr,
+					      mas_chan_list, min_bw);
+		}
+	}
+}
+#else
+static inline void
+reg_populate_band_channels_ext_for_6g(enum channel_enum start_chan,
+				      enum channel_enum end_chan,
+				      struct cur_reg_rule *rule_start_ptr,
+				      uint32_t num_reg_rules,
+				      uint16_t min_reg_bw,
+				      struct regulatory_channel *mas_chan_list)
+{
+}
+#endif
+
 /**
  * reg_populate_band_channels() - For all the valid regdb channels in the master
  * channel list, find the regulatory rules and call reg_fill_channel_info() to
@@ -538,6 +632,54 @@ reg_modify_chan_list_for_freq_range(struct regulatory_channel *chan_list,
 	}
 }
 
+#ifdef CONFIG_BAND_6GHZ
+/**
+ * reg_propagate_6g_mas_channel_list() - Copy master chan list from PSOC to PDEV
+ * @pdev_priv_obj: Pointer to pdev
+ * @mas_chan_params: Master channel parameters
+ *
+ * Return: None
+ */
+static void reg_propagate_6g_mas_channel_list(
+		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
+		struct mas_chan_params *mas_chan_params)
+{
+	uint8_t i, j;
+	struct regulatory_channel *src_6g_chan, *dst_6g_chan;
+	uint32_t size_of_6g_chan_list =
+		NUM_6GHZ_CHANNELS * sizeof(struct regulatory_channel);
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		qdf_mem_copy(pdev_priv_obj->mas_chan_list_6g_ap[i],
+			     mas_chan_params->mas_chan_list_6g_ap[i],
+			     size_of_6g_chan_list);
+
+		for (j = 0; j < REG_MAX_CLIENT_TYPE; j++) {
+			dst_6g_chan =
+				pdev_priv_obj->mas_chan_list_6g_client[i][j];
+			src_6g_chan =
+				mas_chan_params->mas_chan_list_6g_client[i][j];
+			qdf_mem_copy(dst_6g_chan, src_6g_chan,
+				     size_of_6g_chan_list);
+		}
+	}
+
+	pdev_priv_obj->reg_cur_6g_client_mobility_type =
+				mas_chan_params->client_type;
+	pdev_priv_obj->reg_rnr_tpe_usable = mas_chan_params->rnr_tpe_usable;
+	pdev_priv_obj->reg_unspecified_ap_usable =
+				mas_chan_params->unspecified_ap_usable;
+	pdev_priv_obj->is_6g_channel_list_populated =
+		mas_chan_params->is_6g_channel_list_populated;
+}
+#else
+static inline void reg_propagate_6g_mas_channel_list(
+		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
+		struct mas_chan_params *mas_chan_params)
+{
+}
+#endif
+
 void reg_init_pdev_mas_chan_list(
 		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj,
 		struct mas_chan_params *mas_chan_params)
@@ -546,6 +688,8 @@ void reg_init_pdev_mas_chan_list(
 		     mas_chan_params->mas_chan_list,
 		     NUM_CHANNELS * sizeof(struct regulatory_channel));
 
+	reg_propagate_6g_mas_channel_list(pdev_priv_obj, mas_chan_params);
+
 	pdev_priv_obj->dfs_region = mas_chan_params->dfs_region;
 
 	pdev_priv_obj->phybitmap = mas_chan_params->phybitmap;
@@ -827,9 +971,60 @@ reg_modify_disable_chan_list_for_unii1_and_unii2a(
 }
 #endif
 
+#ifdef CONFIG_BAND_6GHZ
+#ifdef CONFIG_REG_CLIENT
+static void
+reg_append_mas_chan_list_for_6g(struct wlan_regulatory_pdev_priv_obj
+				*pdev_priv_obj)
+{
+	struct regulatory_channel *master_chan_list_6g_client =
+		pdev_priv_obj->mas_chan_list_6g_client
+			[pdev_priv_obj->reg_cur_6g_ap_pwr_type]
+			[pdev_priv_obj->reg_cur_6g_client_mobility_type];
+
+		qdf_mem_copy(&pdev_priv_obj->mas_chan_list[MIN_6GHZ_CHANNEL],
+			     master_chan_list_6g_client,
+			     NUM_6GHZ_CHANNELS *
+			     sizeof(struct regulatory_channel));
+}
+#else
+static void
+reg_append_mas_chan_list_for_6g(struct wlan_regulatory_pdev_priv_obj
+				*pdev_priv_obj)
+{
+	enum reg_6g_ap_type ap_pwr_type = pdev_priv_obj->reg_cur_6g_ap_pwr_type;
+
+	qdf_mem_copy(&pdev_priv_obj->mas_chan_list[MIN_6GHZ_CHANNEL],
+		     pdev_priv_obj->mas_chan_list_6g_ap[ap_pwr_type],
+		     NUM_6GHZ_CHANNELS * sizeof(struct regulatory_channel));
+}
+#endif /* CONFIG_REG_CLIENT */
+
+static void reg_copy_6g_cur_mas_chan_list_to_cmn(
+			struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
+{
+	if (pdev_priv_obj->is_6g_channel_list_populated)
+		reg_append_mas_chan_list_for_6g(pdev_priv_obj);
+}
+#else
+static inline void
+reg_copy_6g_cur_mas_chan_list_to_cmn(
+			struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
+{
+}
+
+static inline void
+reg_append_mas_chan_list_for_6g(
+			struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
+{
+}
+#endif /* CONFIG_BAND_6GHZ */
+
 void reg_compute_pdev_current_chan_list(struct wlan_regulatory_pdev_priv_obj
 					*pdev_priv_obj)
 {
+	reg_copy_6g_cur_mas_chan_list_to_cmn(pdev_priv_obj);
+
 	qdf_mem_copy(pdev_priv_obj->cur_chan_list, pdev_priv_obj->mas_chan_list,
 		     NUM_CHANNELS * sizeof(struct regulatory_channel));
 
@@ -875,6 +1070,39 @@ void reg_reset_reg_rules(struct reg_rule_info *reg_rules)
 	qdf_mem_zero(reg_rules, sizeof(*reg_rules));
 }
 
+#ifdef CONFIG_BAND_6GHZ
+static void reg_copy_6g_reg_rules(struct reg_rule_info *pdev_reg_rules,
+				  struct reg_rule_info *psoc_reg_rules)
+{
+	uint32_t reg_rule_len_6g_ap, reg_rule_len_6g_client;
+	uint8_t i;
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		pdev_reg_rules->num_of_6g_ap_reg_rules[i] =
+			psoc_reg_rules->num_of_6g_ap_reg_rules[i];
+		reg_rule_len_6g_ap = psoc_reg_rules->num_of_6g_ap_reg_rules[i] *
+						sizeof(struct cur_reg_rule);
+		qdf_mem_copy(pdev_reg_rules->reg_rules_6g_ap[i],
+			     psoc_reg_rules->reg_rules_6g_ap[i],
+			     reg_rule_len_6g_ap);
+
+		pdev_reg_rules->num_of_6g_client_reg_rules[i] =
+			psoc_reg_rules->num_of_6g_client_reg_rules[i];
+		reg_rule_len_6g_client =
+			psoc_reg_rules->num_of_6g_client_reg_rules[i] *
+						sizeof(struct cur_reg_rule);
+		qdf_mem_copy(pdev_reg_rules->reg_rules_6g_client[i],
+			     psoc_reg_rules->reg_rules_6g_client[i],
+			     reg_rule_len_6g_client);
+	}
+}
+#else
+static inline void reg_copy_6g_reg_rules(struct reg_rule_info *pdev_reg_rules,
+					 struct reg_rule_info *psoc_reg_rules)
+{
+}
+#endif
+
 void reg_save_reg_rules_to_pdev(
 		struct reg_rule_info *psoc_reg_rules,
 		struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj)
@@ -899,6 +1127,8 @@ void reg_save_reg_rules_to_pdev(
 	qdf_mem_copy(pdev_reg_rules->reg_rules, psoc_reg_rules->reg_rules,
 		     reg_rule_len);
 
+	reg_copy_6g_reg_rules(pdev_reg_rules, psoc_reg_rules);
+
 	qdf_mem_copy(pdev_reg_rules->alpha2, pdev_priv_obj->current_country,
 		     REG_ALPHA2_LEN + 1);
 	pdev_reg_rules->dfs_region = pdev_priv_obj->dfs_region;
@@ -1104,6 +1334,504 @@ reg_send_ctl_info(struct wlan_regulatory_psoc_priv_obj *soc_reg,
 }
 #endif
 
+/**
+ * reg_soc_vars_reset_on_failure() - Reset the PSOC private object variables
+ *	when there is a failure
+ * @status_code: status code of CC setting event
+ * @soc_reg: soc private object for regulatory
+ * @tx_ops: send operations for regulatory component
+ * @psoc: pointer to PSOC object
+ * @dbg_id: object manager reference debug ID
+ * @phy_id: physical ID
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+reg_soc_vars_reset_on_failure(enum cc_setting_code status_code,
+			      struct wlan_regulatory_psoc_priv_obj *soc_reg,
+			      struct wlan_lmac_if_reg_tx_ops *tx_ops,
+			      struct wlan_objmgr_psoc *psoc,
+			      wlan_objmgr_ref_dbgid dbg_id,
+			      uint8_t phy_id)
+{
+	struct wlan_objmgr_pdev *pdev;
+
+	if (status_code != REG_SET_CC_STATUS_PASS) {
+		reg_err("Set country code failed, status code %d",
+			status_code);
+
+		pdev = wlan_objmgr_get_pdev_by_id(psoc, phy_id, dbg_id);
+		if (!pdev) {
+			reg_err("pdev is NULL");
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		if (tx_ops->set_country_failed)
+			tx_ops->set_country_failed(pdev);
+
+		wlan_objmgr_pdev_release_ref(pdev, dbg_id);
+
+		if (status_code != REG_CURRENT_ALPHA2_NOT_FOUND)
+			return QDF_STATUS_E_FAILURE;
+
+		soc_reg->new_user_ctry_pending[phy_id] = false;
+		soc_reg->new_11d_ctry_pending[phy_id] = false;
+		soc_reg->world_country_pending[phy_id] = true;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * reg_init_chan() - Initialize the channel list from the channel_map global
+ *	list
+ * @dst_list: list to initialize
+ * @beg_enum: starting point in list(inclusive)
+ * @end_enum: ending point in list(inclusive)
+ * @dst_idx_adj: offset between channel_map and dst_list
+ * @soc_reg: soc private object for regulatory
+ *
+ * Return: none
+ */
+static void reg_init_chan(struct regulatory_channel *dst_list,
+			  enum channel_enum beg_enum,
+			  enum channel_enum end_enum, uint8_t dst_idx_adj,
+			  struct wlan_regulatory_psoc_priv_obj *soc_reg)
+{
+	enum channel_enum chan_enum;
+	uint8_t dst_idx;
+
+	for (chan_enum = beg_enum; chan_enum <= end_enum; chan_enum++) {
+		dst_idx = chan_enum - dst_idx_adj;
+
+		dst_list[dst_idx].chan_num = channel_map[chan_enum].chan_num;
+		dst_list[dst_idx].center_freq =
+					channel_map[chan_enum].center_freq;
+		dst_list[dst_idx].chan_flags = REGULATORY_CHAN_DISABLED;
+		dst_list[dst_idx].state = CHANNEL_STATE_DISABLE;
+		if (!soc_reg->retain_nol_across_regdmn_update)
+			dst_list[dst_idx].nol_chan = false;
+	}
+}
+
+static void reg_init_legacy_master_chan(struct regulatory_channel *dst_list,
+				struct wlan_regulatory_psoc_priv_obj *soc_reg)
+{
+	reg_init_chan(dst_list, 0, NUM_CHANNELS - 1, 0, soc_reg);
+}
+
+#ifdef CONFIG_BAND_6GHZ
+static void reg_init_2g_5g_master_chan(struct regulatory_channel *dst_list,
+				struct wlan_regulatory_psoc_priv_obj *soc_reg)
+{
+	reg_init_chan(dst_list, 0, MAX_5GHZ_CHANNEL, 0, soc_reg);
+}
+
+static void reg_init_6g_master_chan(struct regulatory_channel *dst_list,
+				struct wlan_regulatory_psoc_priv_obj *soc_reg)
+{
+	reg_init_chan(dst_list, MIN_6GHZ_CHANNEL, MAX_6GHZ_CHANNEL,
+		      MIN_6GHZ_CHANNEL, soc_reg);
+}
+
+/**
+ * reg_store_regulatory_ext_info_to_socpriv() - Copy ext info from regulatory
+ *	to regulatory PSOC private obj
+ * @soc_reg: soc private object for regulatory
+ * @regulat_info: regulatory info from CC event
+ * @phy_id: physical ID
+ *
+ * Return: none
+ */
+static void reg_store_regulatory_ext_info_to_socpriv(
+				struct wlan_regulatory_psoc_priv_obj *soc_reg,
+				struct cur_regulatory_info *regulat_info,
+				uint8_t phy_id)
+{
+	uint32_t i;
+
+	soc_reg->num_phy = regulat_info->num_phy;
+	soc_reg->mas_chan_params[phy_id].phybitmap = regulat_info->phybitmap;
+	soc_reg->mas_chan_params[phy_id].dfs_region = regulat_info->dfs_region;
+	soc_reg->mas_chan_params[phy_id].ctry_code = regulat_info->ctry_code;
+	soc_reg->mas_chan_params[phy_id].reg_dmn_pair =
+		regulat_info->reg_dmn_pair;
+	qdf_mem_copy(soc_reg->mas_chan_params[phy_id].current_country,
+		     regulat_info->alpha2,
+		     REG_ALPHA2_LEN + 1);
+	qdf_mem_copy(soc_reg->cur_country,
+		     regulat_info->alpha2,
+		     REG_ALPHA2_LEN + 1);
+	reg_debug("set cur_country %.2s", soc_reg->cur_country);
+
+	soc_reg->mas_chan_params[phy_id].ap_pwr_type = REG_INDOOR_AP;
+	soc_reg->mas_chan_params[phy_id].client_type =
+					regulat_info->client_type;
+	soc_reg->mas_chan_params[phy_id].rnr_tpe_usable =
+					regulat_info->rnr_tpe_usable;
+	soc_reg->mas_chan_params[phy_id].unspecified_ap_usable =
+					regulat_info->unspecified_ap_usable;
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		soc_reg->domain_code_6g_ap[i] =
+			regulat_info->domain_code_6g_ap[i];
+
+		if (soc_reg->domain_code_6g_ap[i])
+			soc_reg->mas_chan_params[phy_id].
+				is_6g_channel_list_populated = true;
+
+		qdf_mem_copy(soc_reg->domain_code_6g_client[i],
+			     regulat_info->domain_code_6g_client[i],
+			     REG_MAX_CLIENT_TYPE * sizeof(uint8_t));
+	}
+}
+
+/**
+ * reg_fill_master_channels() - Fill the master channel lists based on the
+ *	regulatory rules
+ * @regulat_info: regulatory info
+ * @reg_rules: regulatory rules
+ * @client_mobility_type: client mobility type
+ * @mas_chan_list_2g_5g: master chan list to fill with 2GHz and 5GHz channels
+ * @mas_chan_list_6g_ap: master AP chan list to fill with 6GHz channels
+ * @mas_chan_list_6g_client: master client chan list to fill with 6GHz channels
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+reg_fill_master_channels(struct cur_regulatory_info *regulat_info,
+			 struct reg_rule_info *reg_rules,
+			 enum reg_6g_client_type client_mobility_type,
+			 struct regulatory_channel *mas_chan_list_2g_5g,
+	struct regulatory_channel *mas_chan_list_6g_ap[REG_CURRENT_MAX_AP_TYPE],
+	struct regulatory_channel *mas_chan_list_6g_client
+		[REG_CURRENT_MAX_AP_TYPE][REG_MAX_CLIENT_TYPE])
+{
+	uint32_t i, j, k, curr_reg_rule_location;
+	uint32_t num_2g_reg_rules, num_5g_reg_rules;
+	uint32_t num_6g_reg_rules_ap[REG_CURRENT_MAX_AP_TYPE];
+	uint32_t *num_6g_reg_rules_client[REG_CURRENT_MAX_AP_TYPE];
+	struct cur_reg_rule *reg_rule_2g, *reg_rule_5g,
+		*reg_rule_6g_ap[REG_CURRENT_MAX_AP_TYPE],
+		**reg_rule_6g_client[REG_CURRENT_MAX_AP_TYPE];
+	uint32_t min_bw_2g, max_bw_2g, min_bw_5g, max_bw_5g,
+		min_bw_6g_ap[REG_CURRENT_MAX_AP_TYPE],
+		max_bw_6g_ap[REG_CURRENT_MAX_AP_TYPE],
+		*min_bw_6g_client[REG_CURRENT_MAX_AP_TYPE],
+		*max_bw_6g_client[REG_CURRENT_MAX_AP_TYPE];
+
+	min_bw_2g = regulat_info->min_bw_2g;
+	max_bw_2g = regulat_info->max_bw_2g;
+	reg_rule_2g = regulat_info->reg_rules_2g_ptr;
+	num_2g_reg_rules = regulat_info->num_2g_reg_rules;
+	reg_update_max_bw_per_rule(num_2g_reg_rules, reg_rule_2g, max_bw_2g);
+
+	min_bw_5g = regulat_info->min_bw_5g;
+	max_bw_5g = regulat_info->max_bw_5g;
+	reg_rule_5g = regulat_info->reg_rules_5g_ptr;
+	num_5g_reg_rules = regulat_info->num_5g_reg_rules;
+	reg_update_max_bw_per_rule(num_5g_reg_rules, reg_rule_5g, max_bw_5g);
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		min_bw_6g_ap[i] = regulat_info->min_bw_6g_ap[i];
+		max_bw_6g_ap[i] = regulat_info->max_bw_6g_ap[i];
+		reg_rule_6g_ap[i] = regulat_info->reg_rules_6g_ap_ptr[i];
+		num_6g_reg_rules_ap[i] = regulat_info->num_6g_reg_rules_ap[i];
+		reg_update_max_bw_per_rule(num_6g_reg_rules_ap[i],
+					   reg_rule_6g_ap[i], max_bw_6g_ap[i]);
+	}
+
+	for (j = 0; j < REG_CURRENT_MAX_AP_TYPE; j++) {
+		min_bw_6g_client[j] = regulat_info->min_bw_6g_client[j];
+		max_bw_6g_client[j] = regulat_info->max_bw_6g_client[j];
+		reg_rule_6g_client[j] =
+			regulat_info->reg_rules_6g_client_ptr[j];
+		num_6g_reg_rules_client[j] =
+			regulat_info->num_6g_reg_rules_client[j];
+		for (k = 0; k < REG_MAX_CLIENT_TYPE; k++) {
+			reg_update_max_bw_per_rule(
+						num_6g_reg_rules_client[j][k],
+						reg_rule_6g_client[j][k],
+						max_bw_6g_client[j][k]);
+		}
+	}
+
+	reg_reset_reg_rules(reg_rules);
+
+	reg_rules->num_of_reg_rules = num_5g_reg_rules + num_2g_reg_rules;
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		reg_rules->num_of_6g_ap_reg_rules[i] = num_6g_reg_rules_ap[i];
+		if (num_6g_reg_rules_ap[i] > MAX_6G_REG_RULES) {
+			reg_err("number of reg rules for 6g ap exceeds limit");
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		reg_rules->num_of_6g_client_reg_rules[i] =
+			num_6g_reg_rules_client[i][client_mobility_type];
+		for (j = 0; j < REG_MAX_CLIENT_TYPE; j++) {
+			if (num_6g_reg_rules_client[i][j] > MAX_6G_REG_RULES) {
+				reg_err("number of reg rules for 6g client exceeds limit");
+				return QDF_STATUS_E_FAILURE;
+			}
+		}
+	}
+
+	if (reg_rules->num_of_reg_rules > MAX_REG_RULES) {
+		reg_err("number of reg rules exceeds limit");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (reg_rules->num_of_reg_rules) {
+		if (num_2g_reg_rules)
+			qdf_mem_copy(reg_rules->reg_rules,
+				     reg_rule_2g, num_2g_reg_rules *
+				     sizeof(struct cur_reg_rule));
+		curr_reg_rule_location = num_2g_reg_rules;
+		if (num_5g_reg_rules)
+			qdf_mem_copy(reg_rules->reg_rules +
+				     curr_reg_rule_location, reg_rule_5g,
+				     num_5g_reg_rules *
+				     sizeof(struct cur_reg_rule));
+	}
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		if (num_6g_reg_rules_ap[i])
+			qdf_mem_copy(reg_rules->reg_rules_6g_ap[i],
+				     reg_rule_6g_ap[i],
+				     num_6g_reg_rules_ap[i] *
+				     sizeof(struct cur_reg_rule));
+
+		if (num_6g_reg_rules_client[i][client_mobility_type])
+			qdf_mem_copy(reg_rules->reg_rules_6g_client[i],
+				reg_rule_6g_client[i][client_mobility_type],
+				num_6g_reg_rules_client[i]
+				[client_mobility_type] *
+				sizeof(struct cur_reg_rule));
+	}
+
+
+	if (num_5g_reg_rules)
+		reg_do_auto_bw_correction(num_5g_reg_rules,
+					  reg_rule_5g, max_bw_5g);
+
+	if (num_2g_reg_rules)
+		reg_populate_band_channels(MIN_24GHZ_CHANNEL, MAX_24GHZ_CHANNEL,
+					   reg_rule_2g, num_2g_reg_rules,
+					   min_bw_2g, mas_chan_list_2g_5g);
+
+	if (num_5g_reg_rules) {
+		reg_populate_band_channels(MIN_5GHZ_CHANNEL, MAX_5GHZ_CHANNEL,
+					   reg_rule_5g, num_5g_reg_rules,
+					   min_bw_5g, mas_chan_list_2g_5g);
+		reg_populate_band_channels(MIN_49GHZ_CHANNEL,
+					   MAX_49GHZ_CHANNEL,
+					   reg_rule_5g, num_5g_reg_rules,
+					   min_bw_5g, mas_chan_list_2g_5g);
+	}
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		if (num_6g_reg_rules_ap[i])
+			reg_populate_band_channels_ext_for_6g(0,
+							NUM_6GHZ_CHANNELS - 1,
+							reg_rule_6g_ap[i],
+							num_6g_reg_rules_ap[i],
+							min_bw_6g_ap[i],
+							mas_chan_list_6g_ap[i]);
+
+		for (j = 0; j < REG_MAX_CLIENT_TYPE; j++) {
+			if (num_6g_reg_rules_client[i][j])
+				reg_populate_band_channels_ext_for_6g(0,
+						NUM_6GHZ_CHANNELS - 1,
+						reg_rule_6g_client[i][j],
+						num_6g_reg_rules_client[i][j],
+						min_bw_6g_client[i][j],
+						mas_chan_list_6g_client[i][j]);
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * reg_set_socpriv_vars() - Set the regulatory PSOC variables based on
+ *	pending country status
+ * @soc_reg: regulatory PSOC private object
+ * @regulat_info: regulatory info
+ * @psoc: pointer to PSOC object
+ * @phy_id: physical ID
+ *
+ * Return: none
+ */
+static void reg_set_socpriv_vars(struct wlan_regulatory_psoc_priv_obj *soc_reg,
+				 struct cur_regulatory_info *regulat_info,
+				 struct wlan_objmgr_psoc *psoc,
+				 uint8_t phy_id)
+{
+	soc_reg->chan_list_recvd[phy_id] = true;
+
+	if (soc_reg->new_user_ctry_pending[phy_id]) {
+		soc_reg->new_user_ctry_pending[phy_id] = false;
+		soc_reg->cc_src = SOURCE_USERSPACE;
+		soc_reg->user_ctry_set = true;
+		reg_debug("new user country is set");
+		reg_run_11d_state_machine(psoc);
+	} else if (soc_reg->new_init_ctry_pending[phy_id]) {
+		soc_reg->new_init_ctry_pending[phy_id] = false;
+		soc_reg->cc_src = SOURCE_USERSPACE;
+		reg_debug("new init country is set");
+	} else if (soc_reg->new_11d_ctry_pending[phy_id]) {
+		soc_reg->new_11d_ctry_pending[phy_id] = false;
+		soc_reg->cc_src = SOURCE_11D;
+		soc_reg->user_ctry_set = false;
+		reg_run_11d_state_machine(psoc);
+	} else if (soc_reg->world_country_pending[phy_id]) {
+		soc_reg->world_country_pending[phy_id] = false;
+		soc_reg->cc_src = SOURCE_CORE;
+		soc_reg->user_ctry_set = false;
+		reg_run_11d_state_machine(psoc);
+	} else {
+		if (soc_reg->cc_src == SOURCE_UNKNOWN &&
+		    soc_reg->num_phy == phy_id + 1)
+			soc_reg->cc_src = SOURCE_DRIVER;
+
+		qdf_mem_copy(soc_reg->mas_chan_params[phy_id].default_country,
+			     regulat_info->alpha2,
+			     REG_ALPHA2_LEN + 1);
+
+		soc_reg->mas_chan_params[phy_id].def_country_code =
+			regulat_info->ctry_code;
+		soc_reg->mas_chan_params[phy_id].def_region_domain =
+			regulat_info->reg_dmn_pair;
+
+		if (soc_reg->cc_src == SOURCE_DRIVER) {
+			qdf_mem_copy(soc_reg->def_country,
+				     regulat_info->alpha2,
+				     REG_ALPHA2_LEN + 1);
+
+			soc_reg->def_country_code = regulat_info->ctry_code;
+			soc_reg->def_region_domain =
+				regulat_info->reg_dmn_pair;
+
+			if (reg_is_world_alpha2(regulat_info->alpha2)) {
+				soc_reg->cc_src = SOURCE_CORE;
+				reg_run_11d_state_machine(psoc);
+			}
+		}
+	}
+}
+
+QDF_STATUS reg_process_master_chan_list_ext(
+		struct cur_regulatory_info *regulat_info)
+{
+	struct wlan_regulatory_psoc_priv_obj *soc_reg;
+	uint32_t i, j;
+	struct regulatory_channel *mas_chan_list_2g_5g,
+		*mas_chan_list_6g_ap[REG_CURRENT_MAX_AP_TYPE],
+		*mas_chan_list_6g_client[REG_CURRENT_MAX_AP_TYPE]
+							[REG_MAX_CLIENT_TYPE];
+	struct wlan_objmgr_psoc *psoc;
+	wlan_objmgr_ref_dbgid dbg_id;
+	enum direction dir;
+	uint8_t phy_id;
+	uint8_t pdev_id;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_lmac_if_reg_tx_ops *tx_ops;
+	QDF_STATUS status;
+	struct mas_chan_params *this_mchan_params;
+
+	psoc = regulat_info->psoc;
+	soc_reg = reg_get_psoc_obj(psoc);
+
+	if (!IS_VALID_PSOC_REG_OBJ(soc_reg)) {
+		reg_err("psoc reg component is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	tx_ops = reg_get_psoc_tx_ops(psoc);
+	phy_id = regulat_info->phy_id;
+
+	if (tx_ops->get_pdev_id_from_phy_id)
+		tx_ops->get_pdev_id_from_phy_id(psoc, phy_id, &pdev_id);
+	else
+		pdev_id = phy_id;
+
+	if (reg_ignore_default_country(soc_reg, regulat_info)) {
+		status = reg_set_curr_country(soc_reg, regulat_info, tx_ops);
+		if (QDF_IS_STATUS_SUCCESS(status)) {
+			reg_debug("WLAN restart - Ignore default CC for phy_id: %u",
+				  phy_id);
+			return QDF_STATUS_SUCCESS;
+		}
+	}
+
+	reg_debug("process reg master chan extended list");
+
+	if (soc_reg->offload_enabled) {
+		dbg_id = WLAN_REGULATORY_NB_ID;
+		dir = NORTHBOUND;
+	} else {
+		dbg_id = WLAN_REGULATORY_SB_ID;
+		dir = SOUTHBOUND;
+	}
+
+	status = reg_soc_vars_reset_on_failure(regulat_info->status_code,
+					       soc_reg, tx_ops, psoc, dbg_id,
+					       phy_id);
+
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		return status;
+
+	this_mchan_params = &soc_reg->mas_chan_params[phy_id];
+	mas_chan_list_2g_5g = this_mchan_params->mas_chan_list;
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		mas_chan_list_6g_ap[i] =
+			this_mchan_params->mas_chan_list_6g_ap[i];
+
+		for (j = 0; j < REG_MAX_CLIENT_TYPE; j++)
+			mas_chan_list_6g_client[i][j] =
+				this_mchan_params->mas_chan_list_6g_client[i][j];
+	}
+
+	reg_init_channel_map(regulat_info->dfs_region);
+
+	reg_init_2g_5g_master_chan(mas_chan_list_2g_5g, soc_reg);
+
+	for (i = 0; i < REG_CURRENT_MAX_AP_TYPE; i++) {
+		reg_init_6g_master_chan(mas_chan_list_6g_ap[i], soc_reg);
+		for (j = 0; j < REG_MAX_CLIENT_TYPE; j++)
+			reg_init_6g_master_chan(mas_chan_list_6g_client[i][j],
+						soc_reg);
+	}
+
+	reg_store_regulatory_ext_info_to_socpriv(soc_reg, regulat_info, phy_id);
+
+	status = reg_fill_master_channels(regulat_info,
+					  &this_mchan_params->reg_rules,
+					  this_mchan_params->client_type,
+					  mas_chan_list_2g_5g,
+					  mas_chan_list_6g_ap,
+					  mas_chan_list_6g_client);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		return status;
+
+	status = reg_send_ctl_info(soc_reg, regulat_info, tx_ops);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		return status;
+
+	reg_set_socpriv_vars(soc_reg, regulat_info, psoc, phy_id);
+
+	pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, dbg_id);
+	if (pdev) {
+		reg_propagate_mas_chan_list_to_pdev(psoc, pdev, &dir);
+		wlan_objmgr_pdev_release_ref(pdev, dbg_id);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* CONFIG_BAND_6GHZ */
+
 QDF_STATUS reg_process_master_chan_list(
 		struct cur_regulatory_info *regulat_info)
 {
@@ -1113,7 +1841,6 @@ QDF_STATUS reg_process_master_chan_list(
 	uint16_t min_bw_2g, max_bw_2g, min_bw_5g, max_bw_5g;
 	struct regulatory_channel *mas_chan_list;
 	struct wlan_objmgr_psoc *psoc;
-	enum channel_enum chan_enum;
 	wlan_objmgr_ref_dbgid dbg_id;
 	enum direction dir;
 	uint8_t phy_id;
@@ -1158,46 +1885,18 @@ QDF_STATUS reg_process_master_chan_list(
 		dir = SOUTHBOUND;
 	}
 
-	if (regulat_info->status_code != REG_SET_CC_STATUS_PASS) {
-		reg_err("Set country code failed, status code %d",
-			regulat_info->status_code);
+	status = reg_soc_vars_reset_on_failure(regulat_info->status_code,
+					       soc_reg, tx_ops, psoc, dbg_id,
+					       phy_id);
 
-		pdev = wlan_objmgr_get_pdev_by_id(psoc, phy_id, dbg_id);
-		if (!pdev) {
-			reg_err("pdev is NULL");
-			return QDF_STATUS_E_FAILURE;
-		}
-
-		if (tx_ops->set_country_failed)
-			tx_ops->set_country_failed(pdev);
-
-		wlan_objmgr_pdev_release_ref(pdev, dbg_id);
-
-		if (regulat_info->status_code != REG_CURRENT_ALPHA2_NOT_FOUND)
-			return QDF_STATUS_E_FAILURE;
-
-		soc_reg->new_user_ctry_pending[phy_id] = false;
-		soc_reg->new_11d_ctry_pending[phy_id] = false;
-		soc_reg->world_country_pending[phy_id] = true;
-	}
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		return status;
 
 	mas_chan_list = soc_reg->mas_chan_params[phy_id].mas_chan_list;
 
 	reg_init_channel_map(regulat_info->dfs_region);
 
-	for (chan_enum = 0; chan_enum < NUM_CHANNELS;
-	     chan_enum++) {
-		mas_chan_list[chan_enum].chan_num =
-			channel_map[chan_enum].chan_num;
-		mas_chan_list[chan_enum].center_freq =
-			channel_map[chan_enum].center_freq;
-		mas_chan_list[chan_enum].chan_flags =
-			REGULATORY_CHAN_DISABLED;
-		mas_chan_list[chan_enum].state =
-			CHANNEL_STATE_DISABLE;
-		if (!soc_reg->retain_nol_across_regdmn_update)
-			mas_chan_list[chan_enum].nol_chan = false;
-	}
+	reg_init_legacy_master_chan(mas_chan_list, soc_reg);
 
 	soc_reg->num_phy = regulat_info->num_phy;
 	soc_reg->mas_chan_params[phy_id].phybitmap =

+ 12 - 1
umac/regulatory/core/src/reg_build_chan_list.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -70,6 +70,17 @@ void reg_compute_pdev_current_chan_list(
 void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc,
 					 void *object, void *arg);
 
+#ifdef CONFIG_BAND_6GHZ
+/**
+ * reg_process_master_chan_list_ext() - Compute master channel extended list
+ * based on the regulatory rules.
+ * @reg_info: Pointer to regulatory info
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+reg_process_master_chan_list_ext(struct cur_regulatory_info *reg_info);
+#endif
 /**
  * reg_process_master_chan_list() - Compute master channel list based on the
  * regulatory rules.

+ 18 - 1
umac/regulatory/dispatcher/inc/wlan_reg_tgt_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -26,9 +26,26 @@
 #ifndef __WLAN_REG_TGT_API_H
 #define __WLAN_REG_TGT_API_H
 
+/**
+ * tgt_process_master_chan_list() - process master channel list
+ * @reg_info: regulatory info
+ *
+ * Return: QDF_STATUS
+ */
 QDF_STATUS tgt_reg_process_master_chan_list(struct cur_regulatory_info
 					    *reg_info);
 
+#ifdef CONFIG_BAND_6GHZ
+/**
+ * tgt_reg_process_master_chan_list_ext() - process master ext channel list
+ * @reg_info: regulatory info
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS tgt_reg_process_master_chan_list_ext(struct cur_regulatory_info
+						*reg_info);
+#endif
+
 /**
  * tgt_reg_process_11d_new_country() - process new 11d country event
  * @psoc: pointer to psoc

+ 33 - 1
umac/regulatory/dispatcher/src/wlan_reg_services_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -440,6 +440,36 @@ QDF_STATUS wlan_regulatory_deinit(void)
 	return ret_status;
 }
 
+#ifdef CONFIG_BAND_6GHZ
+static void
+regulatory_assign_register_master_ext_handler(struct wlan_objmgr_psoc *psoc,
+					struct wlan_lmac_if_reg_tx_ops *tx_ops)
+{
+	if (tx_ops->register_master_ext_handler)
+		tx_ops->register_master_ext_handler(psoc, NULL);
+}
+
+static void
+regulatory_assign_unregister_master_ext_handler(struct wlan_objmgr_psoc *psoc,
+					struct wlan_lmac_if_reg_tx_ops *tx_ops)
+{
+	if (tx_ops->unregister_master_ext_handler)
+		tx_ops->unregister_master_ext_handler(psoc, NULL);
+}
+#else
+static inline void
+regulatory_assign_register_master_ext_handler(struct wlan_objmgr_psoc *psoc,
+					struct wlan_lmac_if_reg_tx_ops *tx_ops)
+{
+}
+
+static inline void
+regulatory_assign_unregister_master_ext_handler(struct wlan_objmgr_psoc *psoc,
+					struct wlan_lmac_if_reg_tx_ops *tx_ops)
+{
+}
+#endif
+
 QDF_STATUS regulatory_psoc_open(struct wlan_objmgr_psoc *psoc)
 {
 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
@@ -447,6 +477,7 @@ QDF_STATUS regulatory_psoc_open(struct wlan_objmgr_psoc *psoc)
 	tx_ops = reg_get_psoc_tx_ops(psoc);
 	if (tx_ops->register_master_handler)
 		tx_ops->register_master_handler(psoc, NULL);
+	regulatory_assign_register_master_ext_handler(psoc, tx_ops);
 	if (tx_ops->register_11d_new_cc_handler)
 		tx_ops->register_11d_new_cc_handler(psoc, NULL);
 	if (tx_ops->register_ch_avoid_event_handler)
@@ -464,6 +495,7 @@ QDF_STATUS regulatory_psoc_close(struct wlan_objmgr_psoc *psoc)
 		tx_ops->unregister_11d_new_cc_handler(psoc, NULL);
 	if (tx_ops->unregister_master_handler)
 		tx_ops->unregister_master_handler(psoc, NULL);
+	regulatory_assign_unregister_master_ext_handler(psoc, tx_ops);
 	if (tx_ops->unregister_ch_avoid_event_handler)
 		tx_ops->unregister_ch_avoid_event_handler(psoc, NULL);
 

+ 23 - 7
umac/regulatory/dispatcher/src/wlan_reg_tgt_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
@@ -35,12 +35,6 @@
 #include <../../core/src/reg_build_chan_list.h>
 #include <../../core/src/reg_offload_11d_scan.h>
 
-/**
- * tgt_process_master_chan_list() - process master channel list
- * @reg_info: regulatory info
- *
- * Return: QDF_STATUS
- */
 QDF_STATUS tgt_reg_process_master_chan_list(struct cur_regulatory_info
 					    *reg_info)
 {
@@ -61,6 +55,28 @@ QDF_STATUS tgt_reg_process_master_chan_list(struct cur_regulatory_info
 	return reg_process_master_chan_list(reg_info);
 }
 
+#ifdef CONFIG_BAND_6GHZ
+QDF_STATUS tgt_reg_process_master_chan_list_ext(struct cur_regulatory_info
+						*reg_info)
+{
+	struct wlan_regulatory_psoc_priv_obj *soc_reg;
+	struct wlan_objmgr_psoc *psoc;
+
+	psoc = reg_info->psoc;
+	soc_reg = reg_get_psoc_obj(psoc);
+
+	if (!IS_VALID_PSOC_REG_OBJ(soc_reg)) {
+		reg_err("psoc reg component is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!soc_reg->offload_enabled)
+		return QDF_STATUS_SUCCESS;
+
+	return reg_process_master_chan_list_ext(reg_info);
+}
+#endif
+
 QDF_STATUS tgt_reg_process_11d_new_country(struct wlan_objmgr_psoc *psoc,
 		struct reg_11d_new_country *reg_11d_new_cc)
 {