Commit 43eaa368 authored by Ryder Lee's avatar Ryder Lee Committed by Felix Fietkau
Browse files

wifi: mt76: add PPDU based TxS support for WED device



Given that there's no data coming from network stack for binding flows,
hence driver counts and reports station's statistics directly through
NL80211_STA_INFO_* based on active PPDU based TxS for offloading data.

Apart from that, WA firmware and its offloading engine (SDO) have hardcoded
"2" as PID, so we introduce MT_PACKET_ID_WED to differentiate WED reporting.

Note that PPDU format TxS is mutually exclusive with MT_TXD5_TX_STATUS_HOST.

Co-developed-by: default avatarYi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Signed-off-by: default avatarYi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent dc877523
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -270,6 +270,10 @@ struct mt76_sta_stats {
	u64 tx_bw[4];		/* 20, 40, 80, 160 */
	u64 tx_nss[4];		/* 1, 2, 3, 4 */
	u64 tx_mcs[16];		/* mcs idx */
	u64 tx_bytes;
	u32 tx_packets;
	u32 tx_retries;
	u32 tx_failed;
};

enum mt76_wcid_flags {
@@ -364,7 +368,8 @@ struct mt76_rx_tid {
#define MT_PACKET_ID_MASK		GENMASK(6, 0)
#define MT_PACKET_ID_NO_ACK		0
#define MT_PACKET_ID_NO_SKB		1
#define MT_PACKET_ID_FIRST		2
#define MT_PACKET_ID_WED		2
#define MT_PACKET_ID_FIRST		3
#define MT_PACKET_ID_HAS_RATE		BIT(7)
/* This is timer for when to give up when waiting for TXS callback,
 * with starting time being the time at which the DMA_DONE callback
+2 −0
Original line number Diff line number Diff line
@@ -354,6 +354,8 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
				 struct sk_buff *skb, struct mt76_wcid *wcid,
				 struct ieee80211_key_conf *key, int pid,
				 enum mt76_txq_id qid, u32 changed);
bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
			       __le32 *txs_data);
bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
				  int pid, __le32 *txs_data);
void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
+8 −0
Original line number Diff line number Diff line
@@ -158,6 +158,14 @@ enum {

#define MT_TXS4_TIMESTAMP		GENMASK(31, 0)

/* PPDU based TXS */
#define MT_TXS5_MPDU_TX_BYTE		GENMASK(22, 0)
#define MT_TXS5_MPDU_TX_CNT		GENMASK(31, 23)

#define MT_TXS6_MPDU_FAIL_CNT		GENMASK(31, 23)

#define MT_TXS7_MPDU_RETRY_CNT		GENMASK(31, 23)

/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX		GENMASK(9, 0)
#define MT_RXD1_NORMAL_GROUP_1		BIT(11)
+48 −26
Original line number Diff line number Diff line
@@ -490,6 +490,10 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
		p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
		q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS +
			mt76_connac_lmac_mapping(skb_get_queue_mapping(skb));

		/* counting non-offloading skbs */
		wcid->stats.tx_bytes += skb->len;
		wcid->stats.tx_packets++;
	}

	val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
@@ -550,35 +554,29 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_write_txwi);

bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
				  int pid, __le32 *txs_data)
bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
			       __le32 *txs_data)
{
	struct mt76_sta_stats *stats = &wcid->stats;
	struct ieee80211_supported_band *sband;
	struct mt76_phy *mphy;
	struct ieee80211_tx_info *info;
	struct sk_buff_head list;
	struct rate_info rate = {};
	struct sk_buff *skb;
	bool cck = false;
	u32 txrate, txs, mode;

	mt76_tx_status_lock(dev, &list);
	skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
	if (!skb)
		goto out;

	txs = le32_to_cpu(txs_data[0]);

	info = IEEE80211_SKB_CB(skb);
	if (!(txs & MT_TXS0_ACK_ERROR_MASK))
		info->flags |= IEEE80211_TX_STAT_ACK;

	info->status.ampdu_len = 1;
	info->status.ampdu_ack_len = !!(info->flags &
					IEEE80211_TX_STAT_ACK);

	info->status.rates[0].idx = -1;
	/* PPDU based reporting */
	if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) {
		stats->tx_bytes +=
			le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE);
		stats->tx_packets +=
			le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT);
		stats->tx_failed +=
			le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
		stats->tx_retries +=
			le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT);
	}

	txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);

@@ -613,7 +611,7 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
	case MT_PHY_TYPE_HT:
	case MT_PHY_TYPE_HT_GF:
		if (rate.mcs > 31)
			goto out;
			return false;

		rate.flags = RATE_INFO_FLAGS_MCS;
		if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
@@ -621,7 +619,7 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
		break;
	case MT_PHY_TYPE_VHT:
		if (rate.mcs > 9)
			goto out;
			return false;

		rate.flags = RATE_INFO_FLAGS_VHT_MCS;
		break;
@@ -630,14 +628,14 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
	case MT_PHY_TYPE_HE_TB:
	case MT_PHY_TYPE_HE_MU:
		if (rate.mcs > 11)
			goto out;
			return false;

		rate.he_gi = wcid->rate.he_gi;
		rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
		rate.flags = RATE_INFO_FLAGS_HE_MCS;
		break;
	default:
		goto out;
		return false;
	}

	stats->tx_mode[mode]++;
@@ -662,10 +660,34 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
	}
	wcid->rate = rate;

out:
	if (skb)
		mt76_tx_status_skb_done(dev, skb, &list);
	return true;
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_txs);

bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
				  int pid, __le32 *txs_data)
{
	struct sk_buff_head list;
	struct sk_buff *skb;

	mt76_tx_status_lock(dev, &list);
	skb = mt76_tx_status_skb_get(dev, wcid, pid, &list);
	if (skb) {
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
		bool noacked = !(info->flags & IEEE80211_TX_STAT_ACK);

		if (!(le32_to_cpu(txs_data[0]) & MT_TXS0_ACK_ERROR_MASK))
			info->flags |= IEEE80211_TX_STAT_ACK;

		info->status.ampdu_len = 1;
		info->status.ampdu_ack_len = !noacked;
		info->status.rates[0].idx = -1;

		wcid->stats.tx_failed += noacked;

		mt76_connac2_mac_fill_txs(dev, wcid, txs_data);
		mt76_tx_status_skb_done(dev, skb, &list);
	}
	mt76_tx_status_unlock(dev, &list);

	return !!skb;
+9 −5
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
		/*
		 * We don't support reading GI info from txs packets.
		 * For accurate tx status reporting and AQL improvement,
		  we need to make sure that flags match so polling GI
		 * we need to make sure that flags match so polling GI
		 * from per-sta counters directly.
		 */
		rate = &msta->wcid.rate;
@@ -1001,7 +1001,7 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
	wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
	pid = le32_get_bits(txs_data[3], MT_TXS3_PID);

	if (pid < MT_PACKET_ID_FIRST)
	if (pid < MT_PACKET_ID_WED)
		return;

	if (wcidx >= mt7915_wtbl_size(dev))
@@ -1015,7 +1015,11 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)

	msta = container_of(wcid, struct mt7915_sta, wcid);

	if (pid == MT_PACKET_ID_WED)
		mt76_connac2_mac_fill_txs(&dev->mt76, wcid, txs_data);
	else
		mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data);

	if (!wcid->sta)
		goto out;

Loading