Ver Fonte

qcacmn: Support extended avoid frequency list updating

Add regulatory API to support updating extended avoid
frequency list from HDD to regulatory component. Then
populate the new final current channel list and secondary
channel list.

Change-Id: Icda683c30bd7f8e51a5fd930712658ce35eff418
CRs-Fixed: 2975136
Chaoli Zhou há 4 anos atrás
pai
commit
6f15f8170e

+ 327 - 0
umac/regulatory/core/src/reg_build_chan_list.c

@@ -1118,6 +1118,331 @@ reg_populate_secondary_cur_chan_list(struct wlan_regulatory_pdev_priv_obj
 #endif /* CONFIG_REG_CLIENT */
 #endif /* CONFIG_BAND_6GHZ */
 
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+struct chan_5g_center_freq center_5g[MAX_5G_CHAN_NUM] = {
+	/*36*/
+	{5180, 5190, 5210, 5250},
+	/*40*/
+	{5200, 5190, 5210, 5250},
+	/*44*/
+	{5220, 5230, 5210, 5250},
+	/*48*/
+	{5240, 5230, 5210, 5250},
+
+	/*52*/
+	{5260, 5270, 5290, 5250},
+	/*56*/
+	{5280, 5270, 5290, 5250},
+	/*60*/
+	{5300, 5310, 5290, 5250},
+	/*64*/
+	{5320, 5310, 5290, 5250},
+
+	/*100*/
+	{5500, 5510, 5530, 5570},
+	/*104*/
+	{5520, 5510, 5530, 5570},
+	/*108*/
+	{5540, 5550, 5530, 5570},
+	/*112*/
+	{5560, 5550, 5530, 5570},
+
+	/*116*/
+	{5580, 5590, 5610, 5570},
+	/*120*/
+	{5600, 5590, 5610, 5570},
+	/*124*/
+	{5620, 5630, 5610, 5570},
+	/*128*/
+	{5640, 5630, 5610, 5570},
+
+	/*132*/
+	{5660, 5670, 5690, INVALID_CENTER_FREQ},
+	/*136*/
+	{5680, 5670, 5690, INVALID_CENTER_FREQ},
+	/*140*/
+	{5700, 5710, 5690, INVALID_CENTER_FREQ},
+	/*144*/
+	{5720, 5710, 5690, INVALID_CENTER_FREQ},
+
+	/*149*/
+	{5745, 5755, 5775, 5815},
+	/*153*/
+	{5765, 5755, 5775, 5815},
+	/*157*/
+	{5785, 5795, 5775, 5815},
+	/*161*/
+	{5805, 5795, 5775, 5815},
+
+	/*165*/
+	{5825, 5835, 5855, 5815},
+	/*169*/
+	{5845, 5835, 5855, 5815},
+	/*173*/
+	{5865, 5875, 5855, 5815},
+	/*177*/
+	{5885, 5875, 5855, 5815},
+};
+
+/**
+ * reg_modify_5g_maxbw() - Update the max bandwidth for 5G channel
+ * @chan: Pointer to current channel
+ * @avoid_freq: current avoid frequency range
+ *
+ * This function updates the max bandwidth for the 5G channels if
+ * it has overlap with avoid frequency range. For example, if the
+ * avoid frequency range is []5755-5775], and current channel is 149 with
+ * max bandwidth 80Mhz by default, then has to change the max bandwidth
+ * to 20Mhz, since both 40Mhz [5735-5775] and 80M [5735-5815] has
+ * overlap with avoid frequency [5755-5775].
+ *
+ * Return: void.
+ */
+static void
+reg_modify_5g_maxbw(struct regulatory_channel *chan,
+		    struct ch_avoid_freq_type *avoid_freq)
+{
+	int i;
+	qdf_freq_t start, end, cur;
+	bool found = false;
+
+	for (i = 0; i < MAX_5G_CHAN_NUM; i++) {
+		cur = center_5g[i].center_freq_20;
+		if (chan->center_freq == cur) {
+			while (!found) {
+				uint16_t h_bw;
+
+				if (chan->max_bw < 20 ||
+				    chan->max_bw > 160)
+					break;
+
+				switch (chan->max_bw) {
+				case 160:
+					cur = center_5g[i].center_freq_160;
+					if (!cur) {
+						chan->max_bw = chan->max_bw / 2;
+						break;
+					}
+					start = cur - HALF_160MHZ_BW;
+					end = cur + HALF_160MHZ_BW;
+					break;
+				case 80:
+					cur = center_5g[i].center_freq_80;
+					start = cur - HALF_80MHZ_BW;
+					end = cur + HALF_80MHZ_BW;
+					break;
+				case 40:
+					cur = center_5g[i].center_freq_40;
+					start = cur - HALF_40MHZ_BW;
+					end = cur + HALF_40MHZ_BW;
+					break;
+				case 20:
+					cur = center_5g[i].center_freq_20;
+					start = cur - HALF_20MHZ_BW;
+					end = cur + HALF_20MHZ_BW;
+					break;
+				default:
+					break;
+				}
+
+				if (avoid_freq->end_freq <= end &&
+				    avoid_freq->start_freq >= start) {
+					/* avoid freq inside */
+					h_bw = chan->max_bw / 2;
+					chan->max_bw = min(chan->max_bw, h_bw);
+					continue;
+				} else if ((avoid_freq->start_freq > start &&
+					   avoid_freq->start_freq < end) ||
+					   (avoid_freq->end_freq > start &&
+					   avoid_freq->end_freq < end)) {
+					/* avoid freq part overlap */
+					h_bw = chan->max_bw / 2;
+					chan->max_bw = min(chan->max_bw, h_bw);
+					continue;
+				} else if (avoid_freq->start_freq >= end ||
+					   avoid_freq->end_freq <= start) {
+					/* beyond the range freq */
+					found = true;
+				}
+			}
+		}
+	}
+}
+
+/**
+ * reg_modify_chan_list_for_avoid_chan_ext() - Update the state and bandwidth
+ * for each channel in the current channel list.
+ * @pdev_priv_obj: Pointer to wlan regulatory pdev private object.
+ *
+ * This function update the state and bandwidth for each channel in the current
+ * channel list if it is affected by avoid frequency list.
+ * For 2.4G/5G, all the center frequency of specific channel in the
+ * avoid_chan_ext_list (avoid frequency list) will be disabled.
+ * For example, avoid frequency list include [2412,2417,2422],
+ * then channel 1, 2 and 3 will be disabled. Same logic apply for 5g.
+ * For 5G, if the max bandwidth of the channel affected by avoid frequency
+ * range then need to reduce the bandwidth or finally disabled.
+ * For other bands, to-do in furture if need.
+ *
+ * Return: void.
+ */
+static void
+reg_modify_chan_list_for_avoid_chan_ext(struct wlan_regulatory_pdev_priv_obj
+				     *pdev_priv_obj)
+{
+	uint32_t i, j, k;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
+	uint32_t num_avoid_channels;
+	struct regulatory_channel *chan_list = pdev_priv_obj->cur_chan_list;
+	struct regulatory_channel *sec_chan_list;
+	uint16_t *avoid_chan_ext_list;
+	uint32_t num_avoid_freq;
+	struct ch_avoid_freq_type *avoid_freq_ext, *avoid_freq_ext_t;
+
+	sec_chan_list = pdev_priv_obj->secondary_cur_chan_list;
+
+	avoid_chan_ext_list = pdev_priv_obj->avoid_chan_ext_list.chan_freq_list;
+	num_avoid_channels = pdev_priv_obj->avoid_chan_ext_list.chan_cnt;
+
+	psoc = wlan_pdev_get_psoc(pdev_priv_obj->pdev_ptr);
+	if (!psoc)
+		return;
+
+	psoc_priv_obj = reg_get_psoc_obj(psoc);
+	if (!psoc_priv_obj)
+		return;
+
+	if (!num_avoid_channels || !psoc_priv_obj->ch_avoid_ext_ind)
+		return;
+
+	num_avoid_freq = psoc_priv_obj->avoid_freq_ext_list.ch_avoid_range_cnt;
+	avoid_freq_ext = psoc_priv_obj->avoid_freq_ext_list.avoid_freq_range;
+
+	for (i = 0; i < num_avoid_channels; i++)
+		for (j = 0; j < NUM_CHANNELS; j++) {
+			qdf_freq_t c_freq, avoid_tmp = avoid_chan_ext_list[i];
+
+			if (chan_list[j].state == CHANNEL_STATE_DISABLE)
+				goto second_chan_handle;
+
+			/* For 2.4G, just only disable the channel if center
+			 * frequecy is in avoid_chan_ext_list.
+			 * For 5G, customer ask for bandwidth reduction if
+			 * it affect by the nearby channel that in the
+			 * avoid_chan_ext_list.
+			 * For example, if block out frequency range is
+			 * [5755-5775], then except for channel 153 need
+			 * to be disabled, and 149 has to change max 80Mhz
+			 * to 20Mhz, since 149 only has [5735-5755] available.
+			 * channel 157/161 [5775-5815] has to change max 80
+			 * to 40.
+			 * For 6G: to-do in future.
+			 */
+			c_freq = chan_list[j].center_freq;
+			if (avoid_tmp == c_freq) {
+				chan_list[j].state = CHANNEL_STATE_DISABLE;
+				chan_list[j].chan_flags |=
+					REGULATORY_CHAN_DISABLED;
+			} else if (reg_is_5ghz_ch_freq(c_freq)) {
+				for (k = 0; k < num_avoid_freq; k++) {
+					qdf_freq_t s_freq, e_freq;
+
+					avoid_freq_ext_t = &avoid_freq_ext[k];
+					s_freq = avoid_freq_ext_t->start_freq;
+					e_freq = avoid_freq_ext_t->end_freq;
+
+					/* need to cover [5170-5190] case*/
+					if ((!reg_is_5ghz_ch_freq(s_freq) &&
+					     ((s_freq + HALF_20MHZ_BW) <
+					       reg_min_5ghz_chan_freq())) ||
+					    (!reg_is_5ghz_ch_freq(e_freq) &&
+					      ((e_freq - HALF_20MHZ_BW) >
+					       reg_max_5ghz_chan_freq())))
+						continue;
+
+					/* if current center freq is in the
+					 * avoid rang, then skip it, it will be
+					 * handled in the branch (avoid_tmp
+					 * == c_freq)
+					 */
+					if ((c_freq > s_freq &&
+					     c_freq < e_freq))
+						continue;
+
+					reg_modify_5g_maxbw(&chan_list[j],
+							    avoid_freq_ext_t);
+
+					if (chan_list[j].max_bw <
+					    HALF_40MHZ_BW) {
+						chan_list[j].state =
+							CHANNEL_STATE_DISABLE;
+						chan_list[j].chan_flags |=
+						REGULATORY_CHAN_DISABLED;
+						break;
+					}
+				}
+			}
+second_chan_handle:
+
+			if (sec_chan_list[j].state ==
+			   CHANNEL_STATE_DISABLE)
+				continue;
+
+			c_freq = sec_chan_list[j].center_freq;
+			if (avoid_tmp == c_freq) {
+				sec_chan_list[j].state = CHANNEL_STATE_DISABLE;
+				sec_chan_list[j].chan_flags |=
+					REGULATORY_CHAN_DISABLED;
+			} else if (reg_is_5ghz_ch_freq(c_freq)) {
+				for (k = 0; k < num_avoid_freq; k++) {
+					qdf_freq_t s_freq, e_freq;
+
+					avoid_freq_ext_t = &avoid_freq_ext[k];
+					s_freq = avoid_freq_ext_t->start_freq;
+					e_freq = avoid_freq_ext_t->end_freq;
+
+					/* need to cover [5170-5190] case*/
+					if ((!reg_is_5ghz_ch_freq(s_freq) &&
+					     ((s_freq + HALF_20MHZ_BW) <
+					       reg_min_5ghz_chan_freq())) ||
+					    (!reg_is_5ghz_ch_freq(e_freq) &&
+					      ((e_freq - HALF_20MHZ_BW) >
+					       reg_max_5ghz_chan_freq())))
+						continue;
+
+					/* if current center freq is in the
+					 * avoid rang, then skip it, it will be
+					 * handled in the branch (avoid_tmp
+					 * == c_freq)
+					 */
+					if ((c_freq > s_freq &&
+					     c_freq < e_freq))
+						continue;
+
+					reg_modify_5g_maxbw(&sec_chan_list[j],
+							    avoid_freq_ext_t);
+
+					if (sec_chan_list[j].max_bw <
+					    HALF_40MHZ_BW) {
+						sec_chan_list[j].state =
+							CHANNEL_STATE_DISABLE;
+						sec_chan_list[j].chan_flags |=
+						REGULATORY_CHAN_DISABLED;
+						break;
+					}
+				}
+			}
+		}
+}
+#else
+static inline void
+reg_modify_chan_list_for_avoid_chan_ext(struct wlan_regulatory_pdev_priv_obj
+				     *pdev_priv_obj)
+{
+}
+#endif
+
 void reg_compute_pdev_current_chan_list(struct wlan_regulatory_pdev_priv_obj
 					*pdev_priv_obj)
 {
@@ -1164,6 +1489,8 @@ void reg_compute_pdev_current_chan_list(struct wlan_regulatory_pdev_priv_obj
 						  cur_chan_list);
 
 	reg_populate_secondary_cur_chan_list(pdev_priv_obj);
+
+	reg_modify_chan_list_for_avoid_chan_ext(pdev_priv_obj);
 }
 
 void reg_reset_reg_rules(struct reg_rule_info *reg_rules)

+ 10 - 0
umac/regulatory/core/src/reg_priv_objs.h

@@ -109,6 +109,8 @@ struct chan_change_cbk_entry {
  * supported
  * @is_upper_6g_edge_ch_disabled: whether upper 6ghz edge channel 7115MHz is
  * disabled
+ * @ch_avoid_ext_ind: whether need to update extended channel frequency list
+ * @avoid_freq_ext_list: the extended avoid channel frequency list
  */
 struct wlan_regulatory_psoc_priv_obj {
 	struct mas_chan_params mas_chan_params[PSOC_MAX_PHY_REG_CAP];
@@ -170,6 +172,10 @@ struct wlan_regulatory_psoc_priv_obj {
 	bool is_lower_6g_edge_ch_supported;
 	bool is_upper_6g_edge_ch_disabled;
 #endif
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+	bool ch_avoid_ext_ind;
+	struct ch_avoid_ind_type avoid_freq_ext_list;
+#endif
 };
 
 /**
@@ -194,6 +200,7 @@ struct wlan_regulatory_psoc_priv_obj {
  * 802.11 standard.
  * @max_phymode: The maximum phymode supported by the device and regulatory.
  * @max_chwidth: The maximum bandwidth corresponding to the maximum phymode.
+ * @avoid_chan_ext_list: the extended avoid frequency list.
  */
 struct wlan_regulatory_pdev_priv_obj {
 	struct regulatory_channel cur_chan_list[NUM_CHANNELS];
@@ -251,6 +258,9 @@ struct wlan_regulatory_pdev_priv_obj {
 	enum reg_phymode max_phymode;
 	enum phy_ch_width max_chwidth;
 #endif
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+	avoid_ch_ext_list avoid_chan_ext_list;
+#endif
 };
 
 /**

+ 213 - 0
umac/regulatory/core/src/reg_services_common.c

@@ -5163,3 +5163,216 @@ bool reg_is_upper_6g_edge_ch_disabled(struct wlan_objmgr_psoc *psoc)
 	return psoc_priv_obj->is_upper_6g_edge_ch_disabled;
 }
 #endif
+
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+/**
+ * reg_process_ch_avoid_freq_ext() - Update extended avoid frequencies in
+ * psoc_priv_obj
+ * @psoc: Pointer to psoc structure
+ * @pdev: pointer to pdev object
+ *
+ * Return: None
+ */
+static QDF_STATUS
+reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc,
+			      struct wlan_objmgr_pdev *pdev)
+{
+	uint32_t i;
+	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
+	uint8_t start_channel;
+	uint8_t end_channel;
+	struct ch_avoid_freq_type *range;
+	enum channel_enum ch_loop;
+	enum channel_enum start_ch_idx;
+	enum channel_enum end_ch_idx;
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!pdev_priv_obj) {
+		reg_err("reg pdev private obj is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+	psoc_priv_obj = reg_get_psoc_obj(psoc);
+	if (!psoc_priv_obj) {
+		reg_err("reg psoc private obj is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt > 0) {
+		uint32_t len;
+
+		len = sizeof(pdev_priv_obj->avoid_chan_ext_list.chan_freq_list);
+		pdev_priv_obj->avoid_chan_ext_list.chan_cnt = 0;
+		qdf_mem_zero(&pdev_priv_obj->avoid_chan_ext_list.chan_freq_list,
+			     len);
+	}
+
+	for (i = 0; i < psoc_priv_obj->avoid_freq_ext_list.ch_avoid_range_cnt;
+		i++) {
+		if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt >=
+		    NUM_CHANNELS) {
+			reg_debug("ext avoid channel list full");
+			break;
+		}
+
+		start_ch_idx = INVALID_CHANNEL;
+		end_ch_idx = INVALID_CHANNEL;
+		range = &psoc_priv_obj->avoid_freq_ext_list.avoid_freq_range[i];
+
+		start_channel = reg_freq_to_chan(pdev, range->start_freq);
+		end_channel = reg_freq_to_chan(pdev, range->end_freq);
+		reg_debug("start: freq %d, ch %d, end: freq %d, ch %d",
+			  range->start_freq, start_channel, range->end_freq,
+			  end_channel);
+
+		/* do not process frequency bands that are not mapped to
+		 * predefined channels
+		 */
+		if (start_channel == 0 || end_channel == 0)
+			continue;
+
+		for (ch_loop = 0; ch_loop < NUM_CHANNELS;
+			ch_loop++) {
+			if (REG_CH_TO_FREQ(ch_loop) >= range->start_freq) {
+				start_ch_idx = ch_loop;
+				break;
+			}
+		}
+		for (ch_loop = 0; ch_loop < NUM_CHANNELS;
+			ch_loop++) {
+			if (REG_CH_TO_FREQ(ch_loop) >= range->end_freq) {
+				end_ch_idx = ch_loop;
+				if (REG_CH_TO_FREQ(ch_loop) > range->end_freq)
+					end_ch_idx--;
+				break;
+			}
+		}
+
+		if (start_ch_idx == INVALID_CHANNEL ||
+		    end_ch_idx == INVALID_CHANNEL)
+			continue;
+
+		for (ch_loop = start_ch_idx; ch_loop <= end_ch_idx;
+			ch_loop++) {
+			pdev_priv_obj->avoid_chan_ext_list.chan_freq_list
+			[pdev_priv_obj->avoid_chan_ext_list.chan_cnt++] =
+			REG_CH_TO_FREQ(ch_loop);
+
+			if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt >=
+				NUM_CHANNELS) {
+				reg_debug("avoid freq ext list full");
+				break;
+			}
+		}
+		/* if start == end for 5G, meanwhile it only have one valid
+		 * channel updated, then disable 20M by default around
+		 * this center freq. For example input [5805-5805], it
+		 * will disable 20Mhz around 5805, then the range change
+		 * to [5705-5815], otherwise, not sure about how many width
+		 * need to disabled for such case.
+		 */
+		if ((ch_loop - start_ch_idx) == 1 &&
+		    (range->end_freq - range->start_freq == 0) &&
+			reg_is_5ghz_ch_freq(range->start_freq)) {
+			range->start_freq = range->start_freq - HALF_20MHZ_BW;
+			range->end_freq = range->end_freq + HALF_20MHZ_BW;
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * reg_update_avoid_ch_ext() - Updates the current channel list that block out
+ * by extended avoid frequency list
+ * @psoc: Pointer to psoc structure
+ * @object: Pointer to pdev structure
+ * @arg: List of arguments
+ *
+ * Return: None
+ */
+static void
+reg_update_avoid_ch_ext(struct wlan_objmgr_psoc *psoc,
+			void *object, void *arg)
+{
+	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object;
+	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+	QDF_STATUS status;
+
+	psoc_priv_obj = reg_get_psoc_obj(psoc);
+	if (!psoc_priv_obj) {
+		reg_err("reg psoc private obj is NULL");
+		return;
+	}
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("reg pdev priv obj is NULL");
+		return;
+	}
+
+	if (psoc_priv_obj->ch_avoid_ext_ind) {
+		status = reg_process_ch_avoid_freq_ext(psoc, pdev);
+		if (QDF_IS_STATUS_ERROR(status))
+			psoc_priv_obj->ch_avoid_ext_ind = false;
+	}
+
+	reg_compute_pdev_current_chan_list(pdev_priv_obj);
+	status = reg_send_scheduler_msg_sb(psoc, pdev);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		reg_err("channel change msg schedule failed");
+}
+
+QDF_STATUS
+reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
+			       struct ch_avoid_ind_type *ch_avoid_event)
+{
+	uint32_t i;
+	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
+	QDF_STATUS status;
+	struct ch_avoid_freq_type *range;
+
+	psoc_priv_obj = reg_get_psoc_obj(psoc);
+	if (!psoc_priv_obj) {
+		reg_err("reg psoc private obj is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	reg_debug("freq range count %d", ch_avoid_event->ch_avoid_range_cnt);
+
+	qdf_mem_zero(&psoc_priv_obj->avoid_freq_ext_list,
+		     sizeof(struct ch_avoid_ind_type));
+
+	for (i = 0; i < ch_avoid_event->ch_avoid_range_cnt; i++) {
+		range = &psoc_priv_obj->avoid_freq_ext_list.avoid_freq_range[i];
+		range->start_freq =
+			ch_avoid_event->avoid_freq_range[i].start_freq;
+		range->end_freq =
+			ch_avoid_event->avoid_freq_range[i].end_freq;
+	}
+	psoc_priv_obj->avoid_freq_ext_list.ch_avoid_range_cnt =
+		ch_avoid_event->ch_avoid_range_cnt;
+
+	psoc_priv_obj->ch_avoid_ext_ind = true;
+
+	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		reg_err("error taking psoc ref cnt");
+		return status;
+	}
+
+	status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
+					      reg_update_avoid_ch_ext,
+					      NULL, 1,
+					      WLAN_REGULATORY_SB_ID);
+
+	wlan_objmgr_psoc_release_ref(psoc, WLAN_REGULATORY_SB_ID);
+
+	return status;
+}
+#endif

+ 24 - 0
umac/regulatory/core/src/reg_services_common.h

@@ -71,6 +71,9 @@
  */
 #define HALF_5MHZ_BW     2
 #define HALF_20MHZ_BW    10
+#define HALF_40MHZ_BW    20
+#define HALF_80MHZ_BW    40
+#define HALF_160MHZ_BW   80
 
 #define TWO_GIG_STARTING_EDGE_FREQ (channel_map_global[MIN_24GHZ_CHANNEL]. \
 				  center_freq - HALF_20MHZ_BW)
@@ -1571,4 +1574,25 @@ bool reg_is_lower_6g_edge_ch_supp(struct wlan_objmgr_psoc *psoc);
  */
 bool reg_is_upper_6g_edge_ch_disabled(struct wlan_objmgr_psoc *psoc);
 #endif
+
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+/**
+ * reg_process_ch_avoid_ext_event() - Process channel avoid extended event
+ * @psoc: psoc for country information
+ * @ch_avoid_event: channel avoid extended event buffer
+ *
+ * Return: QDF_STATUS
+ */
+
+QDF_STATUS
+reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
+			       struct ch_avoid_ind_type *ch_avoid_event);
+#else
+static inline QDF_STATUS
+reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
+			       struct ch_avoid_ind_type *ch_avoid_event)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #endif

+ 22 - 0
umac/regulatory/dispatcher/inc/reg_services_public_struct.h

@@ -1474,4 +1474,26 @@ struct reg_tpc_power_info {
 	struct chan_power_info chan_power_info[MAX_NUM_PWR_LEVEL];
 };
 
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+typedef struct unsafe_ch_list avoid_ch_ext_list;
+/**
+ * struct chan_5g_center_freq
+ * @center_freq_20: center frequency of max 200Mhz
+ * @center_freq_40: center frequency of max 40Mhz
+ * @center_freq_80: center frequency of max 80Mhz
+ * @center_freq_160: center frequency of max 160Mhz
+ */
+struct chan_5g_center_freq {
+	qdf_freq_t center_freq_20;
+	qdf_freq_t center_freq_40;
+	qdf_freq_t center_freq_80;
+	qdf_freq_t center_freq_160;
+};
+
+#define INVALID_CENTER_FREQ 0
+/*MAX 5g channel numbers, not include dsrc*/
+#define MAX_5G_CHAN_NUM 28
+
+#endif
+
 #endif

+ 15 - 0
umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h

@@ -354,6 +354,21 @@ void ucfg_reg_unit_simulate_ch_avoid(struct wlan_objmgr_psoc *psoc,
 void ucfg_reg_ch_avoid(struct wlan_objmgr_psoc *psoc,
 		       struct ch_avoid_ind_type *ch_avoid);
 
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+/**
+ * ucfg_reg_ch_avoid_ext () - Send channel avoid extend cmd to regulatory
+ * @psoc: psoc ptr
+ * @ch_avoid: ch_avoid_ind_type ranges
+ *
+ * This function send channel avoid extend cmd to regulatory from
+ * os_if/upper layer
+ *
+ * Return: void
+ */
+void ucfg_reg_ch_avoid_ext(struct wlan_objmgr_psoc *psoc,
+			   struct ch_avoid_ind_type *ch_avoid);
+#endif
+
 /**
  * ucfg_reg_11d_vdev_delete_update() - update vdev delete to regulatory
  * @vdev: vdev ptr

+ 8 - 0
umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c

@@ -259,6 +259,14 @@ void ucfg_reg_ch_avoid(struct wlan_objmgr_psoc *psoc,
 	reg_process_ch_avoid_event(psoc, ch_avoid);
 }
 
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+void ucfg_reg_ch_avoid_ext(struct wlan_objmgr_psoc *psoc,
+			   struct ch_avoid_ind_type *ch_avoid)
+{
+	reg_process_ch_avoid_ext_event(psoc, ch_avoid);
+}
+#endif
+
 QDF_STATUS ucfg_reg_11d_vdev_delete_update(struct wlan_objmgr_vdev *vdev)
 {
 	return reg_11d_vdev_delete_update(vdev);