Skip to contentSkip to conversation

wifi: rtw89: regd: add regd table with more fields to firmware file

PATCH In review Ping-Ke Shih 1 participant 5 messages Jan 20, 2025 – Feb 3, 2025 Realtek wireless driver (rtw89)

lore
Share & tools
lore

Ping-Ke Shih

author maintainer
#0 lore raw

cover wifi: rtw89: regd: add regd table with more fields to firmware file

The regd table is to map country code to tables of TX power limit and added support of two functions TAS and DAG. Append this table to firmware file as well, and then we can update the changes of regd table via firmware file in the future.

The patch 3/3 is to refactor initial flow of regd, and correct the naming by the way.

Zong-Zhe Yang (3):
wifi: rtw89: regd: support loading regd table from fw element
wifi: rtw89: regd: handle supported regulatory functions by country
wifi: rtw89: regd: refactor init/setup flow and prototype

 drivers/net/wireless/realtek/rtw89/core.c |   2 +-
 drivers/net/wireless/realtek/rtw89/core.h |  26 +-
 drivers/net/wireless/realtek/rtw89/fw.c   |  98 ++++
 drivers/net/wireless/realtek/rtw89/fw.h   |  23 +
 drivers/net/wireless/realtek/rtw89/regd.c | 566 +++++++++++-----------
 5 files changed, 440 insertions(+), 275 deletions(-)
Signature · 1 line
2.25.1
author maintainer
#1 lore raw

PATCH 1/3 wifi: rtw89: regd: support loading regd table from fw element

From: Zong-Zhe Yang <[email protected]>

Regd table is a table that we use to describe how to map Realtek RF TX power settings on different countries. Originally, a common regd table for all chips is implemented in driver. However, in order to work on all chips, the common regd table might have some trade-off. So now, there are also an individual regd table for some chips. And, we support loading it from FW element.

---
 drivers/net/wireless/realtek/rtw89/core.h | 14 ++++
 drivers/net/wireless/realtek/rtw89/fw.c   | 86 +++++++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/fw.h   | 22 ++++++
 drivers/net/wireless/realtek/rtw89/regd.c | 66 +++++++++++------
 4 files changed, 166 insertions(+), 22 deletions(-)
drivers/net/wireless/realtek/rtw89/core.h +14 -0
index 0f2a46e36b04..7257b5dc1cbc 100644
@@ -22,6 +22,7 @@ struct rtw89_h2c_rf_tssi;
 struct rtw89_fw_txpwr_track_cfg;
 struct rtw89_phy_rfk_log_fmt;
 struct rtw89_debugfs;
+struct rtw89_regd_data;
 
 extern const struct ieee80211_ops rtw89_ops;
 
@@ -718,6 +719,7 @@ enum rtw89_ofdma_type {
 	RTW89_OFDMA_NUM,
 };
 
+/* neither insert new in the middle, nor change any given definition */
 enum rtw89_regulation_type {
 	RTW89_WW	= 0,
 	RTW89_ETSI	= 1,
@@ -4537,6 +4539,7 @@ struct rtw89_fw_elm_info {
 	struct rtw89_phy_table *rf_nctl;
 	struct rtw89_fw_txpwr_track_cfg *txpwr_trk;
 	struct rtw89_phy_rfk_log_fmt *rfk_log_fmt;
+	const struct rtw89_regd_data *regd;
 };
 
 enum rtw89_fw_mss_dev_type {
@@ -5152,11 +5155,22 @@ struct rtw89_regd {
 	u8 txpwr_regd[RTW89_BAND_NUM];
 };
 
+struct rtw89_regd_data {
+	unsigned int nr;
+	struct rtw89_regd map[] __counted_by(nr);
+};
+
+struct rtw89_regd_ctrl {
+	unsigned int nr;
+	const struct rtw89_regd *map;
+};
+
 #define RTW89_REGD_MAX_COUNTRY_NUM U8_MAX
 #define RTW89_5GHZ_UNII4_CHANNEL_NUM 3
 #define RTW89_5GHZ_UNII4_START_INDEX 25
 
 struct rtw89_regulatory_info {
+	struct rtw89_regd_ctrl ctrl;
 	const struct rtw89_regd *regd;
 	enum rtw89_reg_6ghz_power reg_6ghz_power;
 	struct rtw89_reg_6ghz_tpe reg_6ghz_tpe;
drivers/net/wireless/realtek/rtw89/fw.c +86 -0

98 lines not on this page · raw message

drivers/net/wireless/realtek/rtw89/fw.h +22 -0
index 2026bc2fd2ac..c55eabe0138d 100644
@@ -3882,6 +3882,7 @@ enum rtw89_fw_element_id {
 	RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU = 17,
 	RTW89_FW_ELEMENT_ID_TXPWR_TRK = 18,
 	RTW89_FW_ELEMENT_ID_RFKLOG_FMT = 19,
+	RTW89_FW_ELEMENT_ID_REGD = 20,
 
 	RTW89_FW_ELEMENT_ID_NUM,
 };
@@ -3925,6 +3926,15 @@ struct __rtw89_fw_txpwr_element {
 	u8 content[];
 } __packed;
 
+struct __rtw89_fw_regd_element {
+	u8 rsvd0;
+	u8 rsvd1;
+	u8 rsvd2;
+	u8 ent_sz;
+	__le32 num_ents;
+	u8 content[];
+} __packed;
+
 enum rtw89_fw_txpwr_trk_type {
 	__RTW89_FW_TXPWR_TRK_TYPE_6GHZ_START = 0,
 	RTW89_FW_TXPWR_TRK_TYPE_6GB_N = 0,
@@ -4016,6 +4026,7 @@ struct rtw89_fw_element_hdr {
 			__le16 offset[];
 		} __packed rfk_log_fmt;
 		struct __rtw89_fw_txpwr_element txpwr;
+		struct __rtw89_fw_regd_element regd;
 	} __packed u;
 } __packed;
 
@@ -4874,6 +4885,17 @@ int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
 	return 0;
 }
 
+/* Must consider compatibility; don't insert new in the mid.
+ * Fill each field's default value in rtw89_regd_entcpy().
+ */
+struct rtw89_fw_regd_entry {
+	u8 alpha2_0;
+	u8 alpha2_1;
+	u8 rule_2ghz;
+	u8 rule_5ghz;
+	u8 rule_6ghz;
+} __packed;
+
 /* must consider compatibility; don't insert new in the mid */
 struct rtw89_fw_txpwr_byrate_entry {
 	u8 band;
drivers/net/wireless/realtek/rtw89/regd.c +44 -22

166 lines not on this page · raw message

Signature · 1 line
2.25.1
author maintainer
#2 lore raw

Re: [PATCH 1/3] wifi: rtw89: regd: support loading regd table from fw element

Quoted 11 lines · Ping-Ke Shih

From: Zong-Zhe Yang <[email protected]>

Regd table is a table that we use to describe how to map Realtek RF TX power settings on different countries. Originally, a common regd table for all chips is implemented in driver. However, in order to work on all chips, the common regd table might have some trade-off. So now, there are also an individual regd table for some chips. And, we support loading it from FW element.

3 patch(es) applied to rtw-next branch of rtw.git, thanks.

e7196b32a43d wifi: rtw89: regd: support loading regd table from fw element 79a36fc56bea wifi: rtw89: regd: handle supported regulatory functions by country b45acf245596 wifi: rtw89: regd: refactor init/setup flow and prototype

---
https://github.com/pkshih/rtw.git

author maintainer
#3 lore raw

PATCH 2/3 wifi: rtw89: regd: handle supported regulatory functions by country

In reply to Ping-Ke Shih

From: Zong-Zhe Yang <[email protected]>

There are two regulatory functions including TAS (Time Average SAR) and DAG (Dynamic Antenna Gain) for now. They are used to improve RF behavior. But, availability depends on country. Extend regd map to record the status of whether a country allows to enable certain regulatory functions.

Also, extend the handling of loading regd map via FW element for this.

---
 drivers/net/wireless/realtek/rtw89/core.h |   8 +
 drivers/net/wireless/realtek/rtw89/fw.c   |  12 +
 drivers/net/wireless/realtek/rtw89/fw.h   |   1 +
 drivers/net/wireless/realtek/rtw89/regd.c | 489 +++++++++++-----------
 4 files changed, 266 insertions(+), 244 deletions(-)
drivers/net/wireless/realtek/rtw89/core.h +8 -0
index 7257b5dc1cbc..7417dcd68f3d 100644
@@ -5150,9 +5150,17 @@ struct rtw89_power_trim_info {
 	u8 pad_bias_trim[RF_PATH_MAX];
 };
 
+enum rtw89_regd_func {
+	RTW89_REGD_FUNC_TAS = 0, /* TAS (Time Average SAR) */
+	RTW89_REGD_FUNC_DAG = 1, /* DAG (Dynamic Antenna Gain) */
+
+	NUM_OF_RTW89_REGD_FUNC,
+};
+
 struct rtw89_regd {
 	char alpha2[3];
 	u8 txpwr_regd[RTW89_BAND_NUM];
+	DECLARE_BITMAP(func_bitmap, NUM_OF_RTW89_REGD_FUNC);
 };
 
 struct rtw89_regd_data {
drivers/net/wireless/realtek/rtw89/fw.c +12 -0
index 7b7994b8e1aa..cb5ccd9df364 100644
@@ -1064,8 +1064,11 @@ static bool rtw89_regd_entcpy(struct rtw89_regd *regd, const void *cursor,
 		.rule_2ghz = RTW89_NA,
 		.rule_5ghz = RTW89_NA,
 		.rule_6ghz = RTW89_NA,
+		.fmap = cpu_to_le32(0x0),
 	};
 	u8 valid_size = min_t(u8, sizeof(entry), cursor_size);
+	unsigned int i;
+	u32 fmap;
 
 	memcpy(&entry, cursor, valid_size);
 	memset(regd, 0, sizeof(*regd));
@@ -1082,6 +1085,15 @@ static bool rtw89_regd_entcpy(struct rtw89_regd *regd, const void *cursor,
 	regd->txpwr_regd[RTW89_BAND_6G] = entry.rule_6ghz < RTW89_REGD_NUM ?
 					  entry.rule_6ghz : RTW89_NA;
 
+	BUILD_BUG_ON(sizeof(fmap) != sizeof(entry.fmap));
+	BUILD_BUG_ON(sizeof(fmap) * 8 < NUM_OF_RTW89_REGD_FUNC);
+
+	fmap = le32_to_cpu(entry.fmap);
+	for (i = 0; i < NUM_OF_RTW89_REGD_FUNC; i++) {
+		if (fmap & BIT(i))
+			set_bit(i, regd->func_bitmap);
+	}
+
 	return true;
 }
 
drivers/net/wireless/realtek/rtw89/fw.h +1 -0
index c55eabe0138d..5546c05fb428 100644
@@ -4894,6 +4894,7 @@ struct rtw89_fw_regd_entry {
 	u8 rule_2ghz;
 	u8 rule_5ghz;
 	u8 rule_6ghz;
+	__le32 fmap;
 } __packed;
 
 /* must consider compatibility; don't insert new in the mid */
drivers/net/wireless/realtek/rtw89/regd.c +245 -244

505 lines not on this page · raw message

Signature · 1 line
2.25.1
author maintainer
#4 lore raw

PATCH 3/3 wifi: rtw89: regd: refactor init/setup flow and prototype

In reply to Ping-Ke Shih

From: Zong-Zhe Yang <[email protected]>

The regulatory and wiphy setup should be done in rtw89_regd_setup(). And, what rtw89_regd_init() should do is to initialize target regulatory domain (regd), if and only if one is programmed in efuse. Since HW is registered after rtw89_regd_setup() and before rtw89_regd_init(), do not fill fields of regulatory in rtw89_regd_init(). So, move the regulatory->reg_6ghz_power assignment into rtw89_regd_setup().

Besides, rtw89_regd_notifier is assigned in rtw89_regd_setup() instead of rtw89_regd_init(). To reduce confusion, stop passing rtw89_regd_notifier to rtw89_regd_init(). And, rename rtw89_regd_init() to rtw89_regd_init_hint().

---
 drivers/net/wireless/realtek/rtw89/core.c |  2 +-
 drivers/net/wireless/realtek/rtw89/core.h |  4 +---
 drivers/net/wireless/realtek/rtw89/regd.c | 13 +++++++------
 3 files changed, 9 insertions(+), 10 deletions(-)
drivers/net/wireless/realtek/rtw89/core.c +1 -1
index 85f739f1173d..8b322581ba4f 100644
@@ -5296,7 +5296,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
 		goto err_free_supported_band;
 	}
 
-	ret = rtw89_regd_init(rtwdev, rtw89_regd_notifier);
+	ret = rtw89_regd_init_hint(rtwdev);
 	if (ret) {
 		rtw89_err(rtwdev, "failed to init regd\n");
 		goto err_unregister_hw;
drivers/net/wireless/realtek/rtw89/core.h +1 -3
index 7417dcd68f3d..73f0fe6bb934 100644
@@ -7115,9 +7115,7 @@ void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
 				       struct rtw89_vif_link *rtwvif_link);
 bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate);
 int rtw89_regd_setup(struct rtw89_dev *rtwdev);
-int rtw89_regd_init(struct rtw89_dev *rtwdev,
-		    void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request));
-void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request);
+int rtw89_regd_init_hint(struct rtw89_dev *rtwdev);
 void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev,
 			      struct rtw89_traffic_stats *stats);
 int rtw89_wait_for_cond(struct rtw89_wait_info *wait, unsigned int cond);
drivers/net/wireless/realtek/rtw89/regd.c +7 -6
index 50a7f6ff4b5b..5b9d3b78c24e 100644
@@ -7,6 +7,9 @@
 #include "ps.h"
 #include "util.h"
 
+static
+void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request);
+
 #define COUNTRY_REGD(_alpha2, _rule_2ghz, _rule_5ghz, _rule_6ghz, _fmap) \
 	{							\
 		.alpha2 = _alpha2,				\
@@ -598,6 +601,8 @@ int rtw89_regd_setup(struct rtw89_dev *rtwdev)
 		regulatory->ctrl.map = rtw89_regd_map;
 	}
 
+	regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
+
 	if (!wiphy)
 		return -EINVAL;
 
@@ -608,17 +613,12 @@ int rtw89_regd_setup(struct rtw89_dev *rtwdev)
 	return 0;
 }
 
-int rtw89_regd_init(struct rtw89_dev *rtwdev,
-		    void (*reg_notifier)(struct wiphy *wiphy,
-					 struct regulatory_request *request))
+int rtw89_regd_init_hint(struct rtw89_dev *rtwdev)
 {
-	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
 	const struct rtw89_regd *chip_regd;
 	struct wiphy *wiphy = rtwdev->hw->wiphy;
 	int ret;
 
-	regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
-
 	if (!wiphy)
 		return -EINVAL;
 
@@ -738,6 +738,7 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
 	rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
 }
 
+static
 void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 {
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
Signature · 1 line
2.25.1