Commit 5ee7b2ea authored by Zong-Zhe Yang's avatar Zong-Zhe Yang Committed by Kalle Valo

wifi: rtw89: load TX power related tables from FW elements

The following FW elements are recognized, and then the valid entries
in them are loaded into SW struct case by case.
* TX power by rate
* TX power limit 2 GHz
* TX power limit 5 GHz
* TX power limit 6 GHz
* TX power limit RU 2 GHz
* TX power limit RU 5 GHz
* TX power limit RU 6 GHz
* TX shape limit
* TX shape limit RU
One single firmware file can contain multiples of each of the above FW
elements. Each of them is configured with a target RFE (RF front end)
type. We choose one of the multiples to load based on RFE type. If there
are multiples of the same FW elements with the same target RFE type. The
last one will be applied.

We don't want to have many loading variants for above FW elements. Even if
between different chips or between different generations, we would like to
maintain only one single set of loadings. So, the loadings are designed to
consider compatibility. The main concepts are listed below.
* The driver structures, which are used to cast binary entry from FW,
  cannot insert new members in the middle. If there are something new,
  they should always be appended at the tail.
* Each binary entry from FW uses a dictionary way containing a key set
  and a data. The keys in the key set indicate where to put the data.
* If size of driver struct and size of binary entry do not match when
  loading, it means the number of keys in the key set are different.
  Then, we deal with compatibility. No matter which one has more keys,
  we take/use zero on those mismatched keys.
  If driver struct is bigger (backward compatibility):
  	e.g. SW uses two keys, but FW is built with one key.
	Then, put the data of FW(keyX) into SW[keyX][0].
  If binary entry is bigger (forward compatibility):
  	e.g. FW is built with two keys, but SW uses one key.
  	Then, only take the data of FW(keyX, keyY = 0) into SW[keyX]

Besides, chip info setup flow is tweaked a bit for the following.
* Before loading FW elements, we need to determine chip RFE via efuse.
* Setting up RFE parameters depends on loading FW elements ahead.
Signed-off-by: default avatarZong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230920074322.42898-8-pkshih@realtek.com
parent f6d601c7
......@@ -4027,8 +4027,8 @@ static void rtw89_core_setup_rfe_parms(struct rtw89_dev *rtwdev)
sel = chip->dflt_parms;
out:
rtwdev->rfe_parms = sel;
rtw89_load_txpwr_table(rtwdev, sel->byr_tbl);
rtwdev->rfe_parms = rtw89_load_rfe_data_from_fw(rtwdev, sel);
rtw89_load_txpwr_table(rtwdev, rtwdev->rfe_parms->byr_tbl);
}
static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev)
......@@ -4052,7 +4052,6 @@ static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev)
return ret;
rtw89_core_setup_phycap(rtwdev);
rtw89_core_setup_rfe_parms(rtwdev);
rtw89_mac_pwr_off(rtwdev);
......@@ -4084,20 +4083,21 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
return ret;
}
ret = rtw89_chip_efuse_info_setup(rtwdev);
if (ret)
return ret;
ret = rtw89_fw_recognize_elements(rtwdev);
if (ret) {
rtw89_err(rtwdev, "failed to recognize firmware elements\n");
return ret;
}
ret = rtw89_chip_efuse_info_setup(rtwdev);
if (ret)
return ret;
ret = rtw89_chip_board_info_setup(rtwdev);
if (ret)
return ret;
rtw89_core_setup_rfe_parms(rtwdev);
rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev);
return 0;
......@@ -4309,6 +4309,7 @@ EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw);
void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev)
{
kfree(rtwdev->ops);
kfree(rtwdev->rfe_data);
release_firmware(rtwdev->fw.req.firmware);
ieee80211_free_hw(rtwdev->hw);
}
......
......@@ -3400,6 +3400,95 @@ struct rtw89_rfe_parms_conf {
u8 rfe_type;
};
#define RTW89_TXPWR_CONF_DFLT_RFE_TYPE 0x0
struct rtw89_txpwr_conf {
u8 rfe_type;
u8 ent_sz;
u32 num_ents;
const void *data;
};
#define rtw89_txpwr_conf_valid(conf) (!!(conf)->data)
#define rtw89_for_each_in_txpwr_conf(entry, cursor, conf) \
for (typecheck(const void *, cursor), (cursor) = (conf)->data, \
memcpy(&(entry), cursor, \
min_t(u8, sizeof(entry), (conf)->ent_sz)); \
(cursor) < (conf)->data + (conf)->num_ents * (conf)->ent_sz; \
(cursor) += (conf)->ent_sz, \
memcpy(&(entry), cursor, \
min_t(u8, sizeof(entry), (conf)->ent_sz)))
struct rtw89_txpwr_byrate_data {
struct rtw89_txpwr_conf conf;
struct rtw89_txpwr_table tbl;
};
struct rtw89_txpwr_lmt_2ghz_data {
struct rtw89_txpwr_conf conf;
s8 v[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM];
};
struct rtw89_txpwr_lmt_5ghz_data {
struct rtw89_txpwr_conf conf;
s8 v[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][RTW89_5G_CH_NUM];
};
struct rtw89_txpwr_lmt_6ghz_data {
struct rtw89_txpwr_conf conf;
s8 v[RTW89_6G_BW_NUM][RTW89_NTX_NUM]
[RTW89_RS_LMT_NUM][RTW89_BF_NUM]
[RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
[RTW89_6G_CH_NUM];
};
struct rtw89_txpwr_lmt_ru_2ghz_data {
struct rtw89_txpwr_conf conf;
s8 v[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_2G_CH_NUM];
};
struct rtw89_txpwr_lmt_ru_5ghz_data {
struct rtw89_txpwr_conf conf;
s8 v[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][RTW89_5G_CH_NUM];
};
struct rtw89_txpwr_lmt_ru_6ghz_data {
struct rtw89_txpwr_conf conf;
s8 v[RTW89_RU_NUM][RTW89_NTX_NUM]
[RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER]
[RTW89_6G_CH_NUM];
};
struct rtw89_tx_shape_lmt_data {
struct rtw89_txpwr_conf conf;
u8 v[RTW89_BAND_NUM][RTW89_RS_TX_SHAPE_NUM][RTW89_REGD_NUM];
};
struct rtw89_tx_shape_lmt_ru_data {
struct rtw89_txpwr_conf conf;
u8 v[RTW89_BAND_NUM][RTW89_REGD_NUM];
};
struct rtw89_rfe_data {
struct rtw89_txpwr_byrate_data byrate;
struct rtw89_txpwr_lmt_2ghz_data lmt_2ghz;
struct rtw89_txpwr_lmt_5ghz_data lmt_5ghz;
struct rtw89_txpwr_lmt_6ghz_data lmt_6ghz;
struct rtw89_txpwr_lmt_ru_2ghz_data lmt_ru_2ghz;
struct rtw89_txpwr_lmt_ru_5ghz_data lmt_ru_5ghz;
struct rtw89_txpwr_lmt_ru_6ghz_data lmt_ru_6ghz;
struct rtw89_tx_shape_lmt_data tx_shape_lmt;
struct rtw89_tx_shape_lmt_ru_data tx_shape_lmt_ru;
struct rtw89_rfe_parms rfe_parms;
};
struct rtw89_page_regs {
u32 hci_fc_ctrl;
u32 ch_page_ctrl;
......@@ -4582,6 +4671,7 @@ struct rtw89_dev {
struct rtw89_hci_info hci;
struct rtw89_efuse efuse;
struct rtw89_traffic_stats stats;
struct rtw89_rfe_data *rfe_data;
/* ensures exclusive access from mac80211 callbacks */
struct mutex mutex;
......
This diff is collapsed.
......@@ -3417,10 +3417,46 @@ enum rtw89_fw_element_id {
RTW89_FW_ELEMENT_ID_RADIO_C = 6,
RTW89_FW_ELEMENT_ID_RADIO_D = 7,
RTW89_FW_ELEMENT_ID_RF_NCTL = 8,
RTW89_FW_ELEMENT_ID_TXPWR_BYRATE = 9,
RTW89_FW_ELEMENT_ID_TXPWR_LMT_2GHZ = 10,
RTW89_FW_ELEMENT_ID_TXPWR_LMT_5GHZ = 11,
RTW89_FW_ELEMENT_ID_TXPWR_LMT_6GHZ = 12,
RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_2GHZ = 13,
RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_5GHZ = 14,
RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_6GHZ = 15,
RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT = 16,
RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU = 17,
RTW89_FW_ELEMENT_ID_NUM,
};
#define BITS_OF_RTW89_TXPWR_FW_ELEMENTS \
(BIT(RTW89_FW_ELEMENT_ID_TXPWR_BYRATE) | \
BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_2GHZ) | \
BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_5GHZ) | \
BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_6GHZ) | \
BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_2GHZ) | \
BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_5GHZ) | \
BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_6GHZ) | \
BIT(RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT) | \
BIT(RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU))
#define RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS (BIT(RTW89_FW_ELEMENT_ID_BBMCU0) | \
BIT(RTW89_FW_ELEMENT_ID_BB_REG) | \
BIT(RTW89_FW_ELEMENT_ID_RADIO_A) | \
BIT(RTW89_FW_ELEMENT_ID_RADIO_B) | \
BIT(RTW89_FW_ELEMENT_ID_RF_NCTL) | \
BITS_OF_RTW89_TXPWR_FW_ELEMENTS)
struct __rtw89_fw_txpwr_element {
u8 rsvd0;
u8 rsvd1;
u8 rfe_type;
u8 ent_sz;
__le32 num_ents;
u8 content[];
} __packed;
struct rtw89_fw_element_hdr {
__le32 id; /* enum rtw89_fw_element_id */
__le32 size; /* exclude header size */
......@@ -3441,6 +3477,7 @@ struct rtw89_fw_element_hdr {
__le32 data;
} __packed regs[];
} __packed reg2;
struct __rtw89_fw_txpwr_element txpwr;
} __packed u;
} __packed;
......@@ -3778,4 +3815,97 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(rtwdev);
}
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_txpwr_byrate_entry {
u8 band;
u8 nss;
u8 rs;
u8 shf;
u8 len;
__le32 data;
u8 bw;
u8 ofdma;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_txpwr_lmt_2ghz_entry {
u8 bw;
u8 nt;
u8 rs;
u8 bf;
u8 regd;
u8 ch_idx;
s8 v;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_txpwr_lmt_5ghz_entry {
u8 bw;
u8 nt;
u8 rs;
u8 bf;
u8 regd;
u8 ch_idx;
s8 v;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_txpwr_lmt_6ghz_entry {
u8 bw;
u8 nt;
u8 rs;
u8 bf;
u8 regd;
u8 reg_6ghz_power;
u8 ch_idx;
s8 v;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_txpwr_lmt_ru_2ghz_entry {
u8 ru;
u8 nt;
u8 regd;
u8 ch_idx;
s8 v;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_txpwr_lmt_ru_5ghz_entry {
u8 ru;
u8 nt;
u8 regd;
u8 ch_idx;
s8 v;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_txpwr_lmt_ru_6ghz_entry {
u8 ru;
u8 nt;
u8 regd;
u8 reg_6ghz_power;
u8 ch_idx;
s8 v;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_tx_shape_lmt_entry {
u8 band;
u8 tx_shape_rs;
u8 regd;
u8 v;
} __packed;
/* must consider compatibility; don't insert new in the mid */
struct rtw89_fw_tx_shape_lmt_ru_entry {
u8 band;
u8 regd;
u8 v;
} __packed;
const struct rtw89_rfe_parms *
rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev,
const struct rtw89_rfe_parms *init);
#endif
......@@ -1535,7 +1535,6 @@ static const u8 rtw89_rs_nss_num[] = {
[RTW89_RS_OFFSET] = 1,
};
static
s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
struct rtw89_txpwr_byrate *head,
const struct rtw89_rate_desc *desc)
......
......@@ -613,6 +613,9 @@ void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
u32 data, enum rtw89_phy_idx phy_idx);
u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
enum rtw89_phy_idx phy_idx);
s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
struct rtw89_txpwr_byrate *head,
const struct rtw89_rate_desc *desc);
void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl);
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment