Commit 11553d88 authored by Felix Fietkau's avatar Felix Fietkau
Browse files

mt76: mt7915: query station rx rate from firmware



When per-packet rate reporting is enabled, the hardware can get stuck under
some conditions. It self-recovers quickly, but in practice this leads to
reduced performance.
In order to avoid running into this issue, disable per-packet rate reporting
by default and query the rx rate from firmware instead, unless monitor mode
is enabled.

Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 99de49fc
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -43,8 +43,8 @@ static void mt7915_mac_init(struct mt7915_dev *dev)

	mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_MAX_RX_LEN, 1536);
	mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
	/* enable rx rate report */
	mt76_set(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN);
	/* disable rx rate report by default due to hw issues */
	mt76_clear(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN);
	/* disable hardware de-agg */
	mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);

+8 −1
Original line number Diff line number Diff line
@@ -362,11 +362,14 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
	mutex_lock(&dev->mt76.mutex);

	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
		if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
		bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);

		if (!enabled)
			phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
		else
			phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;

		mt76_rmw_field(dev, MT_DMA_DCR0, MT_DMA_DCR0_RXD_G5_EN, enabled);
		mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
	}

@@ -794,9 +797,13 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw,
				  struct ieee80211_sta *sta,
				  struct station_info *sinfo)
{
	struct mt7915_phy *phy = mt7915_hw_phy(hw);
	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
	struct mt7915_sta_stats *stats = &msta->stats;

	if (mt7915_mcu_get_rx_rate(phy, vif, sta, &sinfo->rxrate) == 0)
		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);

	if (!stats->tx_rate.legacy && !stats->tx_rate.flags)
		return;

+94 −0
Original line number Diff line number Diff line
@@ -3404,3 +3404,97 @@ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
	return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, &req,
				 sizeof(req), true);
}

int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
			   struct ieee80211_sta *sta, struct rate_info *rate)
{
	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
	struct mt7915_dev *dev = phy->dev;
	struct mt76_phy *mphy = phy->mt76;
	struct {
		u8 category;
		u8 band;
		__le16 wcid;
	} __packed req = {
		.category = MCU_PHY_STATE_CONTENTION_RX_RATE,
		.band = mvif->band_idx,
		.wcid = cpu_to_le16(msta->wcid.idx),
	};
	struct ieee80211_supported_band *sband;
	struct mt7915_mcu_phy_rx_info *res;
	struct sk_buff *skb;
	u16 flags = 0;
	int ret;
	int i;

	ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD_PHY_STAT_INFO,
					&req, sizeof(req), true, &skb);
	if (ret)
		return ret;

	res = (struct mt7915_mcu_phy_rx_info *)skb->data;

	rate->mcs = res->rate;
	rate->nss = res->nsts + 1;

	switch (res->mode) {
	case MT_PHY_TYPE_CCK:
	case MT_PHY_TYPE_OFDM:
		if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
			sband = &mphy->sband_5g.sband;
		else
			sband = &mphy->sband_2g.sband;

		for (i = 0; i < sband->n_bitrates; i++) {
			if (rate->mcs != (sband->bitrates[i].hw_value & 0xf))
				continue;

			rate->legacy = sband->bitrates[i].bitrate;
			break;
		}
		break;
	case MT_PHY_TYPE_HT:
	case MT_PHY_TYPE_HT_GF:
		rate->mcs += (rate->nss - 1) * 8;
		flags |= RATE_INFO_FLAGS_MCS;

		if (res->gi)
			flags |= RATE_INFO_FLAGS_SHORT_GI;
		break;
	case MT_PHY_TYPE_VHT:
		flags |= RATE_INFO_FLAGS_VHT_MCS;

		if (res->gi)
			flags |= RATE_INFO_FLAGS_SHORT_GI;
		break;
	case MT_PHY_TYPE_HE_SU:
	case MT_PHY_TYPE_HE_EXT_SU:
	case MT_PHY_TYPE_HE_TB:
	case MT_PHY_TYPE_HE_MU:
		rate->he_gi = res->gi;

		flags |= RATE_INFO_FLAGS_HE_MCS;
		break;
	default:
		break;
	}
	rate->flags = flags;

	switch (res->bw) {
	case IEEE80211_STA_RX_BW_160:
		rate->bw = RATE_INFO_BW_160;
		break;
	case IEEE80211_STA_RX_BW_80:
		rate->bw = RATE_INFO_BW_80;
		break;
	case IEEE80211_STA_RX_BW_40:
		rate->bw = RATE_INFO_BW_40;
		break;
	default:
		rate->bw = RATE_INFO_BW_20;
		break;
	}

	return 0;
}
+21 −0
Original line number Diff line number Diff line
@@ -153,6 +153,18 @@ struct mt7915_mcu_ra_info {
	u8 prob_down_pending;
} __packed;


struct mt7915_mcu_phy_rx_info {
	u8 category;
	u8 rate;
	u8 mode;
	u8 nsts;
	u8 gi;
	u8 coding;
	u8 stbc;
	u8 bw;
};

#define MT_RA_RATE_NSS			GENMASK(8, 6)
#define MT_RA_RATE_MCS			GENMASK(3, 0)
#define MT_RA_RATE_TX_MODE		GENMASK(12, 9)
@@ -217,6 +229,7 @@ enum {
	MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
	MCU_EXT_CMD_SET_RDD_TH = 0x9d,
	MCU_EXT_CMD_SET_SPR = 0xa8,
	MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
};

enum {
@@ -250,6 +263,14 @@ enum {
	EE_FORMAT_MULTIPLE,
};

enum {
	MCU_PHY_STATE_TX_RATE,
	MCU_PHY_STATE_RX_RATE,
	MCU_PHY_STATE_RSSI,
	MCU_PHY_STATE_CONTENTION_RX_RATE,
	MCU_PHY_STATE_OFDMLQ_CNINFO,
};

#define STA_TYPE_STA			BIT(0)
#define STA_TYPE_AP			BIT(1)
#define STA_TYPE_ADHOC			BIT(2)
+2 −0
Original line number Diff line number Diff line
@@ -321,6 +321,8 @@ int mt7915_mcu_set_radar_th(struct mt7915_dev *dev, int index,
			    const struct mt7915_dfs_pattern *pattern);
int mt7915_mcu_get_rate_info(struct mt7915_dev *dev, u32 cmd, u16 wlan_idx);
int mt7915_mcu_get_temperature(struct mt7915_dev *dev, int index);
int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
			   struct ieee80211_sta *sta, struct rate_info *rate);
int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd,
		       u8 index, u8 rx_sel, u8 val);
int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl);