瀏覽代碼

qcacmn: Get opclass details for current hwmode

Iterate through the opclass table and fetch the opclass
details for the channel widths supported by the current
hardware mode.

CRs-Fixed: 3168892
Change-Id: I9b418999e3745529e3db5bae3a46569e0d1bdc02
Priyadarshnee Srinivasan 3 年之前
父節點
當前提交
2534a0683e

+ 157 - 11
umac/regulatory/core/src/reg_opclass.c

@@ -35,6 +35,7 @@
 #include "reg_build_chan_list.h"
 #include "reg_opclass.h"
 #include "reg_services_common.h"
+#include <wlan_objmgr_pdev_obj.h>
 
 #ifdef HOST_OPCLASS
 static struct reg_dmn_supp_op_classes reg_dmn_curr_supp_opp_classes = { 0 };
@@ -1598,6 +1599,8 @@ static bool reg_is_cfi_supported(struct wlan_objmgr_pdev *pdev,
  * @pdev: Pointer to pdev
  * @cap: Pointer to regdmn_ap_cap_opclass_t
  * @op_class_tbl: Pointer to op_class_tbl
+ * @in_opclass_conf: input opclass configuration
+ * Supported or not-supported by current HW mode
  *
  * Populate channels from opclass map to regdmn_ap_cap_opclass_t as supported
  * and non-supported channels for 6Ghz.
@@ -1607,7 +1610,8 @@ static bool reg_is_cfi_supported(struct wlan_objmgr_pdev *pdev,
 static void reg_get_cfis_from_opclassmap_for_6g(
 			struct wlan_objmgr_pdev *pdev,
 			struct regdmn_ap_cap_opclass_t *cap,
-			const struct reg_dmn_op_class_map_t *op_class_tbl)
+			const struct reg_dmn_op_class_map_t *op_class_tbl,
+			enum opclass_config in_opclass_conf)
 {
 	uint8_t n_sup_chans = 0, n_unsup_chans = 0, j;
 	const struct c_freq_lst *p_cfi_lst = op_class_tbl->p_cfi_lst_obj;
@@ -1624,7 +1628,9 @@ static void reg_get_cfis_from_opclassmap_for_6g(
 							cfi_freq,
 							bw,
 							op_class_tbl->op_class);
-		if (is_cfi_supported) {
+		if (is_cfi_supported &&
+		    (in_opclass_conf == OPCLASSES_SUPPORTED_BY_CUR_HWMODE ||
+		     in_opclass_conf == OPCLASSES_SUPPORTED_BY_DOMAIN)) {
 			cap->sup_chan_list[n_sup_chans++] = cfi;
 			cap->num_supported_chan++;
 		} else {
@@ -1646,6 +1652,8 @@ static uint16_t reg_find_nearest_ieee_bw(uint16_t spacing)
  * @pdev: Pointer to pdev
  * @cap: Pointer to regdmn_ap_cap_opclass_t
  * @op_class_tbl: Pointer to op_class_tbl
+ * @in_opclass_conf: input opclass configuration
+ * Supported or not-supported by current HW mode
  *
  * Populate channels from opclass map to regdmn_ap_cap_opclass_t as supported
  * and non-supported channels for non-6Ghz.
@@ -1655,7 +1663,8 @@ static uint16_t reg_find_nearest_ieee_bw(uint16_t spacing)
 static void reg_get_cfis_from_opclassmap_for_non6g(
 			struct wlan_objmgr_pdev *pdev,
 			struct regdmn_ap_cap_opclass_t *cap,
-			const struct reg_dmn_op_class_map_t *op_class_tbl)
+			const struct reg_dmn_op_class_map_t *op_class_tbl,
+			enum opclass_config in_opclass_conf)
 {
 	qdf_freq_t start_freq = op_class_tbl->start_freq;
 	uint8_t chan_idx = 0, n_sup_chans = 0, n_unsup_chans = 0;
@@ -1680,12 +1689,14 @@ static void reg_get_cfis_from_opclassmap_for_non6g(
 						     0,
 						     ch_width);
 
-		if (!is_supported) {
-			cap->non_sup_chan_list[n_unsup_chans++] = op_cls_chan;
-			cap->num_non_supported_chan++;
-		} else {
+		if (is_supported &&
+		    (in_opclass_conf == OPCLASSES_SUPPORTED_BY_CUR_HWMODE ||
+		     in_opclass_conf == OPCLASSES_SUPPORTED_BY_DOMAIN)) {
 			cap->sup_chan_list[n_sup_chans++] = op_cls_chan;
 			cap->num_supported_chan++;
+		} else {
+			cap->non_sup_chan_list[n_unsup_chans++] = op_cls_chan;
+			cap->num_non_supported_chan++;
 		}
 	}
 }
@@ -1697,6 +1708,8 @@ static void reg_get_cfis_from_opclassmap_for_non6g(
  * @index: Pointer to index of reg_ap_cap
  * @op_class_tbl: Pointer to op_class_tbl
  * @is_opclass_operable: Set true if opclass is operable, else set false
+ * @in_opclass_conf: input opclass configuration
+ * Supported or not-supported by current HW mode
  *
  * Populate channels from opclass map to reg_ap_cap as supported and
  * non-supported channels.
@@ -1709,18 +1722,21 @@ reg_get_channels_from_opclassmap(
 		struct regdmn_ap_cap_opclass_t *reg_ap_cap,
 		uint8_t index,
 		const struct reg_dmn_op_class_map_t *op_class_tbl,
-		bool *is_opclass_operable)
+		bool *is_opclass_operable,
+		enum opclass_config in_opclass_conf)
 {
 	struct regdmn_ap_cap_opclass_t *cap = &reg_ap_cap[index];
 
 	if (reg_is_6ghz_op_class(pdev, op_class_tbl->op_class)) {
 		reg_get_cfis_from_opclassmap_for_6g(pdev,
 						    cap,
-						    op_class_tbl);
+						    op_class_tbl,
+						    in_opclass_conf);
 	} else {
 		reg_get_cfis_from_opclassmap_for_non6g(pdev,
 						       cap,
-						       op_class_tbl);
+						       op_class_tbl,
+						       in_opclass_conf);
 	}
 
 	if (cap->num_supported_chan >= 1)
@@ -1736,6 +1752,7 @@ QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
 	uint8_t max_reg_power = 0;
 	const struct reg_dmn_op_class_map_t *op_class_tbl;
 	uint8_t index = 0;
+	enum opclass_config opclass_conf = OPCLASSES_SUPPORTED_BY_DOMAIN;
 
 	if (global_tbl_lookup)
 		op_class_tbl = global_op_class;
@@ -1757,7 +1774,8 @@ QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
 						 reg_ap_cap,
 						 index,
 						 op_class_tbl,
-						 &is_opclass_operable);
+						 &is_opclass_operable,
+						 opclass_conf);
 		if (is_opclass_operable) {
 			reg_ap_cap[index].op_class = op_class_tbl->op_class;
 			reg_ap_cap[index].ch_width =
@@ -1835,4 +1853,132 @@ bool reg_is_2ghz_op_class(const uint8_t *country, uint8_t op_class)
 {
 	return reg_is_opclass_band_found(country, op_class, BIT(REG_BAND_2G));
 }
+
+/**
+ * reg_convert_chan_spacing_to_width() - Convert channel spacing to
+ * channel width.
+ * @chan_spacing: Channel spacing
+ * @opclass_chwidth: Opclass channel width
+ * Return - None
+ */
+#ifdef WLAN_FEATURE_11BE
+static void reg_convert_chan_spacing_to_width(uint16_t chan_spacing,
+					      uint16_t *opclass_chwidth)
+{
+	switch (chan_spacing) {
+	case BW_20_MHZ:
+	case BW_25_MHZ:
+		*opclass_chwidth = BW_20_MHZ;
+		break;
+	case BW_40_MHZ:
+		*opclass_chwidth = BW_40_MHZ;
+		break;
+	case BW_80_MHZ:
+		*opclass_chwidth = BW_80_MHZ;
+		break;
+	case BW_160_MHZ:
+		*opclass_chwidth = BW_160_MHZ;
+		break;
+	case BW_320_MHZ:
+		*opclass_chwidth = BW_320_MHZ;
+		break;
+	default:
+		*opclass_chwidth = 0;
+	}
+}
+#else
+static void reg_convert_chan_spacing_to_width(uint16_t chan_spacing,
+					      uint16_t *opclass_chwidth)
+{
+	switch (chan_spacing) {
+	case BW_20_MHZ:
+	case BW_25_MHZ:
+		*opclass_chwidth = BW_20_MHZ;
+		break;
+	case BW_40_MHZ:
+		*opclass_chwidth = BW_40_MHZ;
+		break;
+	case BW_80_MHZ:
+		*opclass_chwidth = BW_80_MHZ;
+		break;
+	case BW_160_MHZ:
+		*opclass_chwidth = BW_160_MHZ;
+		break;
+	default:
+		*opclass_chwidth = 0;
+	}
+}
+#endif
+
+QDF_STATUS
+reg_get_opclass_for_cur_hwmode(struct wlan_objmgr_pdev *pdev,
+			       struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+			       uint8_t *n_opclasses,
+			       uint8_t max_supp_op_class,
+			       bool global_tbl_lookup,
+			       enum phy_ch_width max_chwidth,
+			       bool is_80p80_supp)
+{
+	uint8_t max_reg_power = 0;
+	const struct reg_dmn_op_class_map_t *op_class_tbl;
+	uint8_t index = 0;
+	uint16_t out_width;
+
+	if (global_tbl_lookup)
+		op_class_tbl = global_op_class;
+	else
+		reg_get_op_class_tbl_by_chan_map(&op_class_tbl);
+
+	max_reg_power = reg_get_max_tx_power(pdev);
+
+	out_width = reg_get_bw_value(max_chwidth);
+
+	while (op_class_tbl->op_class && (index < max_supp_op_class)) {
+		bool is_opclass_operable = false;
+		enum opclass_config opclass_in_config =
+		    OPCLASSES_SUPPORTED_BY_CUR_HWMODE;
+		uint16_t opclass_width;
+
+		qdf_mem_zero(reg_ap_cap[index].sup_chan_list,
+			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
+		reg_ap_cap[index].num_supported_chan = 0;
+		qdf_mem_zero(reg_ap_cap[index].non_sup_chan_list,
+			     REG_MAX_CHANNELS_PER_OPERATING_CLASS);
+		reg_ap_cap[index].num_non_supported_chan = 0;
+
+		reg_convert_chan_spacing_to_width(op_class_tbl->chan_spacing,
+						  &opclass_width);
+
+		if ((opclass_width > out_width) ||
+		    ((op_class_tbl->behav_limit == BIT(BEHAV_BW80_PLUS)) &&
+		     !is_80p80_supp))
+			opclass_in_config =
+			    OPCLASSES_NOT_SUPPORTED_BY_CUR_HWMODE;
+
+		reg_get_channels_from_opclassmap(pdev,
+						 reg_ap_cap,
+						 index,
+						 op_class_tbl,
+						 &is_opclass_operable,
+						 opclass_in_config);
+
+		if (is_opclass_operable && opclass_in_config ==
+		    OPCLASSES_SUPPORTED_BY_CUR_HWMODE) {
+			reg_ap_cap[index].op_class = op_class_tbl->op_class;
+			reg_ap_cap[index].ch_width =
+				op_class_tbl->chan_spacing;
+			reg_ap_cap[index].start_freq =
+				op_class_tbl->start_freq;
+			reg_ap_cap[index].max_tx_pwr_dbm = max_reg_power;
+			reg_ap_cap[index].behav_limit =
+				op_class_tbl->behav_limit;
+			index++;
+		}
+		op_class_tbl++;
+	}
+
+	*n_opclasses = index;
+
+	return QDF_STATUS_SUCCESS;
+}
 #endif

+ 33 - 0
umac/regulatory/core/src/reg_opclass.h

@@ -126,6 +126,27 @@ QDF_STATUS reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
 				   uint8_t max_supp_op_class,
 				   bool global_tbl_lookup);
 
+/**
+ * reg_get_opclass_for_cur_hwmode() - Get details about the opclasses for
+ * the current hwmode.
+ * @pdev: Pointer to pdev.
+ * @reg_ap_cap: Pointer to reg_ap_cap.
+ * @n_opclasses: Pointer to number of opclasses.
+ * @max_supp_op_class: Maximum number of operating classes supported.
+ * @global_tbl_lookup: Whether to lookup global op class table.
+ * @max_chwidth: Max channel width supported by cur hwmode
+ * @is_80p80_supp: Bool to indicate if 80p80 is supported
+ *
+ * Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE.
+ */
+QDF_STATUS
+reg_get_opclass_for_cur_hwmode(struct wlan_objmgr_pdev *pdev,
+			       struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+			       uint8_t *n_opclasses,
+			       uint8_t max_supp_op_class,
+			       bool global_tbl_lookup,
+			       enum phy_ch_width max_chwidth,
+			       bool is_80p80_supp);
 /**
  * reg_is_5ghz_op_class() - Check if the input opclass is a 5GHz opclass.
  * @country: Country code.
@@ -355,6 +376,18 @@ bool reg_is_2ghz_op_class(const uint8_t *country, uint8_t op_class)
 	return false;
 }
 
+static inline QDF_STATUS
+reg_get_opclass_for_cur_hwmode(struct wlan_objmgr_pdev *pdev,
+			       struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+			       uint8_t *n_opclasses,
+			       uint8_t max_supp_op_class,
+			       bool global_tbl_lookup,
+			       enum phy_ch_width max_ch_width,
+			       bool is_80p80_supp)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+
 #ifdef CONFIG_CHAN_FREQ_API
 
 static inline void

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

@@ -748,6 +748,21 @@ struct reg_dmn_op_class_map_t {
 	const struct c_freq_lst *p_cfi_lst_obj;
 };
 
+/**
+ * enum opclass_config: Opclass configuration
+ * @OPCLASSES_SUPPORTED_BY_CUR_HWMODE: Retrieve opclasses that is supported
+ * by the current hw mode.
+ * @OPCLASSES_NOT_SUPPORTED_BY_CUR_HWMODE: Retrieve opclasses that are not
+ * supported by the current hw mode.
+ * OPCLASSES_SUPPORTED_BY_DOMAIN: Populate the opclass supported by the radio
+ * without considering the capability of current hwmode.
+ */
+enum opclass_config {
+	OPCLASSES_SUPPORTED_BY_CUR_HWMODE = 1,
+	OPCLASSES_NOT_SUPPORTED_BY_CUR_HWMODE = 2,
+	OPCLASSES_SUPPORTED_BY_DOMAIN = 3
+};
+
 /**
  * struct regdmn_ap_cap_opclass_t: AP Cap operation class table
  * @op_class: operating class number

+ 21 - 0
umac/regulatory/dispatcher/inc/wlan_reg_services_api.h

@@ -994,6 +994,27 @@ wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
 			     uint8_t max_supp_op_class,
 			     bool global_tbl_lookup);
 
+/**
+ * wlan_reg_get_opclass_for_cur_hwmode() - Get details about the
+ * opclass table for the current hwmode.
+ * @pdev: Pointer to pdev.
+ * @reg_ap_cap: Pointer to reg_ap_cap.
+ * @n_opclasses: Pointer to number of opclasses.
+ * @max_supp_op_class: Maximum number of operating classes supported.
+ * @global_tbl_lookup: Whether to lookup global op class tbl.
+ * @max_chwidth: Maximum channel width supported by cur hwmode
+ * @is_80p80_supp: Bool to indicate if 80p80 is supported.
+ *
+ * Return: QDF_STATUS_SUCCESS if success, else return QDF_STATUS_FAILURE.
+ */
+QDF_STATUS
+wlan_reg_get_opclass_for_cur_hwmode(struct wlan_objmgr_pdev *pdev,
+				    struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+				    uint8_t *n_opclasses,
+				    uint8_t max_supp_op_class,
+				    bool global_tbl_lookup,
+				    enum phy_ch_width max_chwidth,
+				    bool is_80p80_supp);
 /**
  * wlan_reg_get_cc_and_src () - get country code and src
  * @psoc: psoc ptr

+ 16 - 0
umac/regulatory/dispatcher/src/wlan_reg_services_api.c

@@ -300,6 +300,22 @@ wlan_reg_get_opclass_details(struct wlan_objmgr_pdev *pdev,
 				       global_tbl_lookup);
 }
 
+QDF_STATUS
+wlan_reg_get_opclass_for_cur_hwmode(struct wlan_objmgr_pdev *pdev,
+				    struct regdmn_ap_cap_opclass_t *reg_ap_cap,
+				    uint8_t *n_opclasses,
+				    uint8_t max_supp_op_class,
+				    bool global_tbl_lookup,
+				    enum phy_ch_width max_chwidth,
+				    bool is_80p80_supp)
+{
+	return reg_get_opclass_for_cur_hwmode(pdev, reg_ap_cap, n_opclasses,
+					      max_supp_op_class,
+					      global_tbl_lookup,
+					      max_chwidth,
+					      is_80p80_supp);
+}
+
 enum country_src wlan_reg_get_cc_and_src(struct wlan_objmgr_psoc *psoc,
 					 uint8_t *alpha)
 {