Jelajahi Sumber

qcacmn: Add regulatory API for phymode change

Add new enum in regulatory to hold all current phymodes.
Add a new API to get max allowed phymode which is not more than the
user provided phymode.

This change simplifies the phymode selection process when starting
or updating the parameters of a vdev.

Change-Id: I12c15e357b80faf2f5272800e55179f02755a263
CRs-fixed: 2658290
Lincoln Tran 5 tahun lalu
induk
melakukan
0779b77211

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

@@ -3795,3 +3795,74 @@ reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap)
 	return QDF_STATUS_SUCCESS;
 }
 #endif
+
+#ifdef CHECK_REG_PHYMODE
+/**
+ * reg_is_phymode_allowed() - Check if requested phymode is unallowed
+ * @phy_in: phymode that the user requested
+ * @phymode_bitmap: bitmap of unallowed phymodes for specific country
+ *
+ * Return: true if phymode is not allowed, else false
+ */
+static bool reg_is_phymode_unallowed(enum reg_phymode phy_in,
+				     uint32_t phymode_bitmap)
+{
+	if (!phymode_bitmap)
+		return false;
+
+	if (phy_in == REG_PHYMODE_11AX)
+		return phymode_bitmap & REGULATORY_PHYMODE_NO11AX;
+	else if (phy_in == REG_PHYMODE_11AC)
+		return phymode_bitmap & REGULATORY_PHYMODE_NO11AC;
+	else if (phy_in == REG_PHYMODE_11N)
+		return phymode_bitmap & REGULATORY_CHAN_NO11N;
+	else if (phy_in == REG_PHYMODE_11G)
+		return phymode_bitmap & REGULATORY_PHYMODE_NO11G;
+	else if (phy_in == REG_PHYMODE_11A)
+		return phymode_bitmap & REGULATORY_PHYMODE_NO11A;
+	else if (phy_in == REG_PHYMODE_11B)
+		return phymode_bitmap & REGULATORY_PHYMODE_NO11B;
+	else
+		return true;
+
+}
+
+enum reg_phymode reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
+				     enum reg_phymode phy_in,
+				     qdf_freq_t freq)
+{
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+	uint32_t phymode_bitmap;
+	enum reg_phymode current_phymode = phy_in;
+
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("pdev reg component is NULL");
+		return REG_PHYMODE_INVALID;
+	}
+
+	phymode_bitmap = pdev_priv_obj->phybitmap;
+
+	while (1) {
+		if (reg_is_phymode_unallowed(current_phymode, phymode_bitmap)) {
+			if (current_phymode == REG_PHYMODE_11N) {
+				if (REG_IS_24GHZ_CH_FREQ(freq))
+					current_phymode = REG_PHYMODE_11G;
+				else
+					current_phymode = REG_PHYMODE_11A;
+			} else if (current_phymode == REG_PHYMODE_11A ||
+				   current_phymode == REG_PHYMODE_11B) {
+				reg_err("Couldn't find a suitable phymode");
+				return REG_PHYMODE_INVALID;
+			} else if (current_phymode > REG_PHYMODE_MAX) {
+				reg_err("Unknown phymode");
+				return REG_PHYMODE_INVALID;
+			} else {
+				current_phymode--;
+			}
+		} else {
+			return current_phymode;
+		}
+	}
+}
+#endif /* CHECK_REG_PHYMODE */

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

@@ -1098,4 +1098,27 @@ QDF_STATUS
 reg_get_unii_5g_bitmap(struct wlan_objmgr_pdev *pdev, uint8_t *bitmap);
 #endif
 
+#ifdef CHECK_REG_PHYMODE
+/**
+ * reg_get_max_phymode() - Recursively find the best possible phymode given a
+ * phymode, a frequency, and per-country regulations
+ * @pdev: pdev pointer
+ * @phy_in: phymode that the user requested
+ * @freq: current operating center frequency
+ *
+ * Return: maximum phymode allowed in current country that is <= phy_in
+ */
+enum reg_phymode reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
+				     enum reg_phymode phy_in,
+				     qdf_freq_t freq);
+#else
+static inline enum reg_phymode
+reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
+		    enum reg_phymode phy_in,
+		    qdf_freq_t freq)
+{
+	return REG_PHYMODE_INVALID;
+}
+#endif /* CHECK_REG_PHYMODE */
+
 #endif

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

@@ -1137,4 +1137,26 @@ struct reg_ctl_params {
 	uint8_t ctl_5g;
 };
 
+/**
+ * enum reg_phymode - Regulatory phymode
+ * @REG_PHYMODE_INVALID: Invalid phymode
+ * @REG_PHYMODE_11B: 802.11b phymode
+ * @REG_PHYMODE_11G: 802.11g phymode
+ * @REG_PHYMODE_11A: 802.11a phymode
+ * @REG_PHYMODE_11N: 802.11n phymode
+ * @REG_PHYMODE_11AC: 802.11ac phymode
+ * @REG_PHYMODE_11AX: 802.11ax phymode
+ * @REG_PHYMODE_MAX: placeholder for future phymodes
+ */
+enum reg_phymode {
+	REG_PHYMODE_INVALID,
+	REG_PHYMODE_11B,
+	REG_PHYMODE_11G,
+	REG_PHYMODE_11A,
+	REG_PHYMODE_11N,
+	REG_PHYMODE_11AC,
+	REG_PHYMODE_11AX,
+	REG_PHYMODE_MAX,
+};
+
 #endif

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

@@ -1402,4 +1402,28 @@ uint16_t wlan_reg_chan_opclass_to_freq(uint8_t chan,
 
 qdf_freq_t wlan_reg_chan_opclass_to_freq_auto(uint8_t chan, uint8_t op_class,
 					      bool global_tbl_lookup);
+
+#ifdef CHECK_REG_PHYMODE
+/**
+ * wlan_reg_get_max_phymode() - Find the best possible phymode given a
+ * phymode, a frequency, and per-country regulations
+ * @pdev: pdev pointer
+ * @phy_in: phymode that the user requested
+ * @freq: current operating center frequency
+ *
+ * Return: maximum phymode allowed in current country that is <= phy_in
+ */
+enum reg_phymode wlan_reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
+					  enum reg_phymode phy_in,
+					  qdf_freq_t freq);
+#else
+static inline enum reg_phymode
+wlan_reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
+			 enum reg_phymode phy_in,
+			 qdf_freq_t freq)
+{
+	return REG_PHYMODE_INVALID;
+}
+#endif /* CHECK_REG_PHYMODE */
+
 #endif

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

@@ -1155,3 +1155,12 @@ qdf_freq_t wlan_reg_chan_opclass_to_freq_auto(uint8_t chan, uint8_t op_class,
 
 	return reg_chan_opclass_to_freq_auto(chan, op_class, global_tbl_lookup);
 }
+
+#ifdef CHECK_REG_PHYMODE
+enum reg_phymode wlan_reg_get_max_phymode(struct wlan_objmgr_pdev *pdev,
+					  enum reg_phymode phy_in,
+					  qdf_freq_t freq)
+{
+	return reg_get_max_phymode(pdev, phy_in, freq);
+}
+#endif /* CHECK_REG_PHYMODE */