Commit d60e73e5 authored by Ping-Ke Shih's avatar Ping-Ke Shih Committed by Kalle Valo
Browse files

wifi: rtw89: fw: load TX power track tables from fw_element



The TX power track tables are used to define compensation power reflected
to thermal value. Currently, we have 16 (2 * 4 * 2) tables made by
combinations of
  {negative/positive thermal value, 2GHz/2GHz-CCK/5GHz/6GHz, path A/B}

Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20231213005054.10568-2-pkshih@realtek.com
parent f0dd488e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ struct rtw89_pci_info;
struct rtw89_mac_gen_def;
struct rtw89_phy_gen_def;
struct rtw89_efuse_block_cfg;
struct rtw89_fw_txpwr_track_cfg;

extern const struct ieee80211_ops rtw89_ops;

@@ -38,6 +39,8 @@ extern const struct ieee80211_ops rtw89_ops;
#define RSSI_FACTOR 1
#define RTW89_RSSI_RAW_TO_DBM(rssi) ((s8)((rssi) >> RSSI_FACTOR) - MAX_RSSI)
#define RTW89_TX_DIV_RSSI_RAW_TH (2 << RSSI_FACTOR)
#define DELTA_SWINGIDX_SIZE 30

#define RTW89_RADIOTAP_ROOM_HE sizeof(struct ieee80211_radiotap_he)
#define RTW89_RADIOTAP_ROOM_EHT \
	(sizeof(struct ieee80211_radiotap_tlv) + \
@@ -3948,6 +3951,7 @@ struct rtw89_fw_elm_info {
	struct rtw89_phy_table *bb_gain;
	struct rtw89_phy_table *rf_radio[RF_PATH_MAX];
	struct rtw89_phy_table *rf_nctl;
	struct rtw89_fw_txpwr_track_cfg *txpwr_trk;
};

struct rtw89_fw_info {
+71 −0
Original line number Diff line number Diff line
@@ -659,6 +659,72 @@ int rtw89_fw_recognize_txpwr_from_elm(struct rtw89_dev *rtwdev,
	return 0;
}

static
int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
				       const struct rtw89_fw_element_hdr *elm,
				       const union rtw89_fw_element_arg arg)
{
	struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
	const struct rtw89_chip_info *chip = rtwdev->chip;
	u32 needed_bitmap = 0;
	u32 offset = 0;
	int subband;
	u32 bitmap;
	int type;

	if (chip->support_bands & BIT(NL80211_BAND_6GHZ))
		needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_6GHZ;
	if (chip->support_bands & BIT(NL80211_BAND_5GHZ))
		needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_5GHZ;
	if (chip->support_bands & BIT(NL80211_BAND_2GHZ))
		needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_2GHZ;

	bitmap = le32_to_cpu(elm->u.txpwr_trk.bitmap);

	if ((bitmap & needed_bitmap) != needed_bitmap) {
		rtw89_warn(rtwdev, "needed txpwr trk bitmap %08x but %0x8x\n",
			   needed_bitmap, bitmap);
		return -ENOENT;
	}

	elm_info->txpwr_trk = kzalloc(sizeof(*elm_info->txpwr_trk), GFP_KERNEL);
	if (!elm_info->txpwr_trk)
		return -ENOMEM;

	for (type = 0; bitmap; type++, bitmap >>= 1) {
		if (!(bitmap & BIT(0)))
			continue;

		if (type >= __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_START &&
		    type <= __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_MAX)
			subband = 4;
		else if (type >= __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_START &&
			 type <= __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_MAX)
			subband = 3;
		else if (type >= __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_START &&
			 type <= __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_MAX)
			subband = 1;
		else
			break;

		elm_info->txpwr_trk->delta[type] = &elm->u.txpwr_trk.contents[offset];

		offset += subband;
		if (offset * DELTA_SWINGIDX_SIZE > le32_to_cpu(elm->size))
			goto err;
	}

	return 0;

err:
	rtw89_warn(rtwdev, "unexpected txpwr trk offset %d over size %d\n",
		   offset, le32_to_cpu(elm->size));
	kfree(elm_info->txpwr_trk);
	elm_info->txpwr_trk = NULL;

	return -EFAULT;
}

static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
	[RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
					{ .fw_type = RTW89_FW_BBMCU0 }, NULL},
@@ -711,6 +777,9 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
		rtw89_fw_recognize_txpwr_from_elm,
		{ .offset = offsetof(struct rtw89_rfe_data, tx_shape_lmt_ru.conf) }, NULL,
	},
	[RTW89_FW_ELEMENT_ID_TXPWR_TRK] = {
		rtw89_build_txpwr_trk_tbl_from_elm, {}, "PWR_TRK",
	},
};

int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
@@ -1144,6 +1213,8 @@ static void rtw89_unload_firmware_elements(struct rtw89_dev *rtwdev)
	for (i = 0; i < ARRAY_SIZE(elm_info->rf_radio); i++)
		rtw89_free_phy_tbl_from_elm(elm_info->rf_radio[i]);
	rtw89_free_phy_tbl_from_elm(elm_info->rf_nctl);

	kfree(elm_info->txpwr_trk);
}

void rtw89_unload_firmware(struct rtw89_dev *rtwdev)
+60 −0
Original line number Diff line number Diff line
@@ -3426,6 +3426,7 @@ enum rtw89_fw_element_id {
	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_TXPWR_TRK = 18,

	RTW89_FW_ELEMENT_ID_NUM,
};
@@ -3446,6 +3447,7 @@ enum rtw89_fw_element_id {
					     BIT(RTW89_FW_ELEMENT_ID_RADIO_A) | \
					     BIT(RTW89_FW_ELEMENT_ID_RADIO_B) | \
					     BIT(RTW89_FW_ELEMENT_ID_RF_NCTL) | \
					     BIT(RTW89_FW_ELEMENT_ID_TXPWR_TRK) | \
					     BITS_OF_RTW89_TXPWR_FW_ELEMENTS)

struct __rtw89_fw_txpwr_element {
@@ -3457,6 +3459,59 @@ struct __rtw89_fw_txpwr_element {
	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,
	RTW89_FW_TXPWR_TRK_TYPE_6GB_P = 1,
	RTW89_FW_TXPWR_TRK_TYPE_6GA_N = 2,
	RTW89_FW_TXPWR_TRK_TYPE_6GA_P = 3,
	__RTW89_FW_TXPWR_TRK_TYPE_6GHZ_MAX = 3,

	__RTW89_FW_TXPWR_TRK_TYPE_5GHZ_START = 4,
	RTW89_FW_TXPWR_TRK_TYPE_5GB_N = 4,
	RTW89_FW_TXPWR_TRK_TYPE_5GB_P = 5,
	RTW89_FW_TXPWR_TRK_TYPE_5GA_N = 6,
	RTW89_FW_TXPWR_TRK_TYPE_5GA_P = 7,
	__RTW89_FW_TXPWR_TRK_TYPE_5GHZ_MAX = 7,

	__RTW89_FW_TXPWR_TRK_TYPE_2GHZ_START = 8,
	RTW89_FW_TXPWR_TRK_TYPE_2GB_N = 8,
	RTW89_FW_TXPWR_TRK_TYPE_2GB_P = 9,
	RTW89_FW_TXPWR_TRK_TYPE_2GA_N = 10,
	RTW89_FW_TXPWR_TRK_TYPE_2GA_P = 11,
	RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_N = 12,
	RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_P = 13,
	RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N = 14,
	RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P = 15,
	__RTW89_FW_TXPWR_TRK_TYPE_2GHZ_MAX = 15,

	RTW89_FW_TXPWR_TRK_TYPE_NR,
};

struct rtw89_fw_txpwr_track_cfg {
	const s8 (*delta[RTW89_FW_TXPWR_TRK_TYPE_NR])[DELTA_SWINGIDX_SIZE];
};

#define RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_6GHZ \
	(BIT(RTW89_FW_TXPWR_TRK_TYPE_6GB_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_6GB_P) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_6GA_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_6GA_P))
#define RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_5GHZ \
	(BIT(RTW89_FW_TXPWR_TRK_TYPE_5GB_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_5GB_P) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_5GA_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_5GA_P))
#define RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_2GHZ \
	(BIT(RTW89_FW_TXPWR_TRK_TYPE_2GB_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_2GB_P) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_2GA_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_2GA_P) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_P) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N) | \
	 BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P))

struct rtw89_fw_element_hdr {
	__le32 id; /* enum rtw89_fw_element_id */
	__le32 size; /* exclude header size */
@@ -3477,6 +3532,11 @@ struct rtw89_fw_element_hdr {
				__le32 data;
			} __packed regs[];
		} __packed reg2;
		struct {
			__le32 bitmap; /* bitmap of enum rtw89_fw_txpwr_trk_type */
			__le32 rsvd;
			s8 contents[][DELTA_SWINGIDX_SIZE];
		} __packed txpwr_trk;
		struct __rtw89_fw_txpwr_element txpwr;
	} __packed u;
} __packed;
+0 −2
Original line number Diff line number Diff line
@@ -291,8 +291,6 @@ struct rtw89_txpwr_byrate_cfg {
	u32 data;
};

#define DELTA_SWINGIDX_SIZE 30

struct rtw89_txpwr_track_cfg {
	const s8 (*delta_swingidx_6gb_n)[DELTA_SWINGIDX_SIZE];
	const s8 (*delta_swingidx_6gb_p)[DELTA_SWINGIDX_SIZE];