Commit 254ab81f authored by StanleyYP Wang's avatar StanleyYP Wang Committed by Felix Fietkau
Browse files

wifi: mt76: connac: add beacon duplicate TX mode support for mt7996



For connac3 chipsets, setting of spe_idx is moved from TX descriptor to
the fixed rate table. This patch implements the setting to support
duplicate TX mode for beacon.

Signed-off-by: default avatarStanleyYP Wang <StanleyYP.Wang@mediatek.com>
Signed-off-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 6879b2e9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1242,6 +1242,7 @@ enum {
	MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
	MCU_UNI_CMD_THERMAL = 0x35,
	MCU_UNI_CMD_VOW = 0x37,
	MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
	MCU_UNI_CMD_RRO = 0x57,
	MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
	MCU_UNI_CMD_PER_STA_INFO = 0x6d,
+4 −2
Original line number Diff line number Diff line
@@ -354,6 +354,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;

	phy->slottime = 9;
	phy->beacon_rate = -1;

	hw->sta_data_size = sizeof(struct mt7996_sta);
	hw->vif_data_size = sizeof(struct mt7996_vif);
@@ -468,11 +469,12 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)

	for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
		u16 rate = mt76_rates[i].hw_value;
		u16 idx = MT7996_BASIC_RATES_TBL + i;
		/* odd index for driver, even index for firmware */
		u16 idx = MT7996_BASIC_RATES_TBL + 2 * i;

		rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
		       FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
		mt7996_mac_set_fixed_rate_table(dev, idx, rate);
		mt7996_mcu_set_fixed_rate_table(&dev->phy, idx, rate, false);
	}
}

+0 −11
Original line number Diff line number Diff line
@@ -248,17 +248,6 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
		mt76_clear(dev, addr, BIT(5));
}

void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
				     u8 tbl_idx, u16 rate_idx)
{
	u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;

	mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
	/* use wtbl spe idx */
	mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
	mt76_wr(dev, MT_WTBL_ITCR, ctrl);
}

/* The HW does not translate the mac header to 802.3 for mesh point */
static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
{
+9 −9
Original line number Diff line number Diff line
@@ -522,24 +522,25 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
	struct mt76_phy *mphy = hw->priv;
	u16 rate;
	u8 i, idx, ht;
	u8 i, idx;

	rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);
	ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;

	if (beacon && ht) {
		struct mt7996_dev *dev = mt7996_hw_dev(hw);
	if (beacon) {
		struct mt7996_phy *phy = mphy->priv;

		/* odd index for driver, even index for firmware */
		idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx;
		if (phy->beacon_rate != rate)
			mt7996_mcu_set_fixed_rate_table(phy, idx, rate, beacon);

		/* must odd index */
		idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
		mt7996_mac_set_fixed_rate_table(dev, idx, rate);
		return idx;
	}

	idx = FIELD_GET(MT_TX_RATE_IDX, rate);
	for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
		if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
			return MT7996_BASIC_RATES_TBL + i;
			return MT7996_BASIC_RATES_TBL + 2 * i;

	return mvif->basic_rates_idx;
}
@@ -965,7 +966,6 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
	mt7996_set_stream_vht_txbf_caps(phy);
	mt7996_set_stream_he_eht_caps(phy);

	/* TODO: update bmc_wtbl spe_idx when antenna changes */
	mutex_unlock(&dev->mt76.mutex);

	return 0;
+29 −0
Original line number Diff line number Diff line
@@ -4179,6 +4179,35 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
				     MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
}

int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
				    u16 rate_idx, bool beacon)
{
#define UNI_FIXED_RATE_TABLE_SET	0
#define SPE_IXD_SELECT_TXD		0
#define SPE_IXD_SELECT_BMC_WTBL		1
	struct mt7996_dev *dev = phy->dev;
	struct fixed_rate_table_ctrl req = {
		.tag = cpu_to_le16(UNI_FIXED_RATE_TABLE_SET),
		.len = cpu_to_le16(sizeof(req) - 4),
		.table_idx = table_idx,
		.rate_idx = cpu_to_le16(rate_idx),
		.gi = 1,
		.he_ltf = 1,
	};
	u8 band_idx = phy->mt76->band_idx;

	if (beacon) {
		req.spe_idx_sel = SPE_IXD_SELECT_TXD;
		req.spe_idx = 24 + band_idx;
		phy->beacon_rate = rate_idx;
	} else {
		req.spe_idx_sel = SPE_IXD_SELECT_BMC_WTBL;
	}

	return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(FIXED_RATE_TABLE),
				 &req, sizeof(req), false);
}

int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
{
	struct {
Loading