Commit 15ee62e7 authored by Ryder Lee's avatar Ryder Lee Committed by Felix Fietkau
Browse files

wifi: mt76: mt7996: enable BSS_CHANGED_BASIC_RATES support



The connac3 removes fixed rate fields to reduce txd size and introduces
global rate tables (64 entries) for rate setting. Driver needs to fill
the corresponding idx in MT_TXD6_TX_RATE while tx, and push mt76_rate
into predifined table at bootup stage so that  mvif->basic_rates_idx
can immediately switch out once setting changes.

spe_idx is also needed for fixed rate frames, and will be updated by
future patches.

Note that all table entries are shared across driver and firmware
(i.e.TxBF), hence adding MT7996_BASIC_RATES_TBL to reflect mapping
status.

Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 9c54548b
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -255,6 +255,20 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
	mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
}

static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
		u16 rate = mt76_rates[i].hw_value;
		u16 idx = MT7996_BASIC_RATES_TBL + 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);
	}
}

void mt7996_mac_init(struct mt7996_dev *dev)
{
#define HIF_TXD_V2_1	4
@@ -287,6 +301,8 @@ void mt7996_mac_init(struct mt7996_dev *dev)

	for (i = MT_BAND0; i <= MT_BAND2; i++)
		mt7996_mac_init_band(dev, i);

	mt7996_mac_init_basic_rates(dev);
}

int mt7996_txbf_init(struct mt7996_dev *dev)
+15 −17
Original line number Diff line number Diff line
@@ -252,6 +252,17 @@ 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);
}

static void
mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
				 struct ieee80211_radiotap_he *he,
@@ -985,7 +996,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
{
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_vif *vif = info->control.vif;
	struct mt76_phy *mphy = &dev->mphy;
	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
	u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
	u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
	bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
@@ -997,15 +1008,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
					 BSS_CHANGED_FILS_DISCOVERY));

	if (vif) {
		struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;

		omac_idx = mvif->mt76.omac_idx;
		wmm_idx = mvif->mt76.wmm_idx;
		band_idx = mvif->mt76.band_idx;
	}

	mphy = mt76_dev_phy(&dev->mt76, band_idx);

	if (inband_disc) {
		p_fmt = MT_TX_TYPE_FW;
		q_idx = MT_LMAC_ALTX0;
@@ -1063,18 +1070,9 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
		mt7996_mac_write_txwi_80211(dev, txwi, skb, key);

	if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
		/* Fixed rata is available just for 802.11 txd */
		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
		bool multicast = is_multicast_ether_addr(hdr->addr1);
		u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
							multicast);

		/* fix to bw 20 */
		val = MT_TXD6_FIXED_BW |
		      FIELD_PREP(MT_TXD6_BW, 0) |
		      FIELD_PREP(MT_TXD6_TX_RATE, rate);
		u8 idx = mvif->basic_rates_idx;

		txwi[6] |= cpu_to_le32(val);
		txwi[6] |= FIELD_PREP(MT_TXD6_TX_RATE, idx);
		txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
	}
}
+2 −5
Original line number Diff line number Diff line
@@ -224,14 +224,11 @@ enum tx_mgnt_type {

#define MT_TXD6_TX_SRC			GENMASK(31, 30)
#define MT_TXD6_VTA			BIT(28)
#define MT_TXD6_FIXED_BW		BIT(25)
#define MT_TXD6_BW			GENMASK(24, 22)
#define MT_TXD6_BW			GENMASK(25, 22)
#define MT_TXD6_TX_RATE			GENMASK(21, 16)
#define MT_TXD6_TIMESTAMP_OFS_EN	BIT(15)
#define MT_TXD6_TIMESTAMP_OFS_IDX	GENMASK(14, 10)
#define MT_TXD6_MSDU_CNT		GENMASK(9, 4)
#define MT_TXD6_SPE_ID_IDX		BIT(10)
#define MT_TXD6_ANT_ID			GENMASK(7, 4)
#define MT_TXD6_DIS_MAT			BIT(3)
#define MT_TXD6_DAS			BIT(2)
#define MT_TXD6_AMSDU_CAP		BIT(1)
@@ -245,7 +242,7 @@ enum tx_mgnt_type {
#define MT_TXD7_UDP_TCP_SUM		BIT(15)
#define MT_TXD7_TX_TIME			GENMASK(9, 0)

#define MT_TX_RATE_STBC			BIT(13)
#define MT_TX_RATE_STBC			BIT(14)
#define MT_TX_RATE_NSS			GENMASK(13, 10)
#define MT_TX_RATE_MODE			GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE		BIT(5)
+29 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@

#include "mt7996.h"
#include "mcu.h"
#include "mac.h"

static bool mt7996_dev_running(struct mt7996_dev *dev)
{
@@ -219,6 +220,11 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
		vif->offload_flags = 0;
	vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;

	if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
		mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
	else
		mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL;

	mt7996_init_bitrate_mask(vif);

	mt7996_mcu_add_bss_info(phy, vif, true);
@@ -496,11 +502,30 @@ mt7996_update_bss_color(struct ieee80211_hw *hw,
	}
}

static u8
mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
	struct mt76_phy *mphy = hw->priv;
	u16 rate;
	u8 i, idx;

	rate = mt76_connac2_mac_tx_rate_val(mphy, vif, false, false);

	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 mvif->basic_rates_idx;
}

static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif,
				    struct ieee80211_bss_conf *info,
				    u64 changed)
{
	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
	struct mt7996_phy *phy = mt7996_hw_phy(hw);
	struct mt7996_dev *dev = mt7996_hw_dev(hw);

@@ -532,6 +557,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
		}
	}

	if (changed & BSS_CHANGED_BASIC_RATES)
		mvif->basic_rates_idx = mt7996_get_rates_table(hw, vif);

	if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
		mt7996_mcu_add_bss_info(phy, vif, true);
		mt7996_mcu_add_sta(dev, vif, NULL, true);
@@ -891,6 +919,7 @@ 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;
+9 −11
Original line number Diff line number Diff line
@@ -597,25 +597,23 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
}

static void
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt7996_phy *phy)
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
		       struct mt7996_phy *phy)
{
	struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
	struct bss_rate_tlv *bmc;
	struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
	enum nl80211_band band = chandef->chan->band;
	struct tlv *tlv;
	u8 idx = mvif->basic_rates_idx;

	tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_RATE, sizeof(*bmc));

	bmc = (struct bss_rate_tlv *)tlv;
	if (band == NL80211_BAND_2GHZ) {
		bmc->short_preamble = true;
	} else {
		bmc->bc_trans = cpu_to_le16(0x8080);
		bmc->mc_trans = cpu_to_le16(0x8080);
		bmc->bc_fixed_rate = 1;
		bmc->mc_fixed_rate = 1;
		bmc->short_preamble = 1;
	}

	bmc->short_preamble = (band == NL80211_BAND_2GHZ);
	bmc->bc_fixed_rate = idx;
	bmc->mc_fixed_rate = idx;
}

static void
@@ -823,7 +821,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,

	if (enable) {
		mt7996_mcu_bss_rfch_tlv(skb, vif, phy);
		mt7996_mcu_bss_bmc_tlv(skb, phy);
		mt7996_mcu_bss_bmc_tlv(skb, vif, phy);
		mt7996_mcu_bss_ra_tlv(skb, vif, phy);
		mt7996_mcu_bss_txcmd_tlv(skb, true);

Loading