Commit 3de4cb17 authored by Felix Fietkau's avatar Felix Fietkau
Browse files

mt76: mt7915: add support for tx status reporting



For now, this only reports ACK status

Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 223fd4f8
Loading
Loading
Loading
Loading
+96 −28
Original line number Diff line number Diff line
@@ -887,7 +887,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
}

void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
			   struct sk_buff *skb, struct mt76_wcid *wcid,
			   struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
			   struct ieee80211_key_conf *key, bool beacon)
{
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -946,7 +946,12 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,

	txwi[3] = cpu_to_le32(val);
	txwi[4] = 0;
	txwi[5] = 0;

	val = FIELD_PREP(MT_TXD5_PID, pid);
	if (pid >= MT_PACKET_ID_FIRST)
		val |= MT_TXD5_TX_STATUS_HOST;
	txwi[5] = cpu_to_le32(val);

	txwi[6] = 0;
	txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;

@@ -986,11 +991,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
	struct ieee80211_key_conf *key = info->control.hw_key;
	struct ieee80211_vif *vif = info->control.vif;
	struct mt76_tx_cb *cb = mt76_tx_skb_cb(tx_info->skb);
	struct mt76_txwi_cache *t;
	struct mt7915_txp *txp;
	int id, i, nbuf = tx_info->nbuf - 1;
	u8 *txwi = (u8 *)txwi_ptr;
	int pid;

	if (unlikely(tx_info->skb->len <= ETH_HLEN))
		return -EINVAL;
@@ -998,10 +1003,10 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
	if (!wcid)
		wcid = &dev->mt76.global_wcid;

	mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
			      false);
	pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);

	cb->wcid = wcid->idx;
	mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
			      false);

	txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
	for (i = 0; i < nbuf; i++) {
@@ -1088,9 +1093,7 @@ static void
mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
		 struct ieee80211_sta *sta, struct list_head *free_list)
{
	struct ieee80211_tx_status status = {};
	struct mt76_dev *mdev = &dev->mt76;
	struct ieee80211_tx_info *info;
	struct mt76_wcid *wcid;
	__le32 *txwi;
	u16 wcid_idx;
@@ -1110,26 +1113,6 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
		wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
	}

	info = IEEE80211_SKB_CB(t->skb);
	if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
		struct ieee80211_hw *hw;

		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
			info->flags |= IEEE80211_TX_STAT_ACK;

		info->status.rates[0].count = 0;
		info->status.rates[0].idx = -1;

		status.skb = t->skb;
		status.sta = sta;
		status.info = info;

		hw = mt76_tx_status_get_hw(mdev, t->skb);
		ieee80211_tx_status_ext(hw, &status);

		goto out;
	}

	__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);

out:
@@ -1221,11 +1204,89 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb)
	}
}

static bool
mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
		       __le32 *txs_data)
{
	struct mt76_dev *mdev = &dev->mt76;
	struct ieee80211_tx_info *info;
	struct sk_buff_head list;
	struct sk_buff *skb;

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

	info = IEEE80211_SKB_CB(skb);
	if (!(txs_data[0] & le32_to_cpu(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;
	mt76_tx_status_skb_done(mdev, skb, &list);

out:
	mt76_tx_status_unlock(mdev, &list);

	return !!skb;
}

static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
{
	struct mt7915_sta *msta = NULL;
	struct mt76_wcid *wcid;
	__le32 *txs_data = data;
	u16 wcidx;
	u32 txs;
	u8 pid;

	txs = le32_to_cpu(txs_data[0]);
	if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
		return;

	txs = le32_to_cpu(txs_data[2]);
	wcidx = FIELD_GET(MT_TXS2_WCID, txs);

	txs = le32_to_cpu(txs_data[3]);
	pid = FIELD_GET(MT_TXS3_PID, txs);

	if (pid < MT_PACKET_ID_FIRST)
		return;

	if (wcidx >= MT7915_WTBL_SIZE)
		return;

	rcu_read_lock();

	wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
	if (!wcid)
		goto out;

	mt7915_mac_add_txs_skb(dev, wcid, pid, txs_data);

	if (!wcid->sta)
		goto out;

	msta = container_of(wcid, struct mt7915_sta, wcid);
	spin_lock_bh(&dev->sta_poll_lock);
	if (list_empty(&msta->poll_list))
		list_add_tail(&msta->poll_list, &dev->sta_poll_list);
	spin_unlock_bh(&dev->sta_poll_lock);

out:
	rcu_read_unlock();
}

void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
			 struct sk_buff *skb)
{
	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
	__le32 *rxd = (__le32 *)skb->data;
	__le32 *end = (__le32 *)&skb->data[skb->len];
	enum rx_pkt_type type;

	type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
@@ -1240,6 +1301,11 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
	case PKT_TYPE_TXRXV:
		mt7915_mac_fill_rx_vector(dev, skb);
		break;
	case PKT_TYPE_TXS:
		for (rxd += 2; rxd + 8 <= end; rxd += 8)
		    mt7915_mac_add_txs(dev, rxd);
		dev_kfree_skb(skb);
		break;
	case PKT_TYPE_NORMAL:
		if (!mt7915_mac_fill_rx(dev, skb)) {
			mt76_rx(&dev->mt76, q, skb);
@@ -1775,6 +1841,8 @@ void mt7915_mac_work(struct work_struct *work)

	mutex_unlock(&mphy->dev->mutex);

	mt76_tx_status_check(mphy->dev, NULL, false);

	ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
				     MT7915_WATCHDOG_TIME);
}
+56 −0
Original line number Diff line number Diff line
@@ -304,6 +304,62 @@ struct mt7915_tx_free {
/* will support this field in further revision */
#define MT_TX_FREE_RATE			GENMASK(13, 0)

#define MT_TXS0_FIXED_RATE		BIT(31)
#define MT_TXS0_BW			GENMASK(30, 29)
#define MT_TXS0_TID			GENMASK(28, 26)
#define MT_TXS0_AMPDU			BIT(25)
#define MT_TXS0_TXS_FORMAT		GENMASK(24, 23)
#define MT_TXS0_BA_ERROR		BIT(22)
#define MT_TXS0_PS_FLAG			BIT(21)
#define MT_TXS0_TXOP_TIMEOUT		BIT(20)
#define MT_TXS0_BIP_ERROR		BIT(19)

#define MT_TXS0_QUEUE_TIMEOUT		BIT(18)
#define MT_TXS0_RTS_TIMEOUT		BIT(17)
#define MT_TXS0_ACK_TIMEOUT		BIT(16)
#define MT_TXS0_ACK_ERROR_MASK		GENMASK(18, 16)

#define MT_TXS0_TX_STATUS_HOST		BIT(15)
#define MT_TXS0_TX_STATUS_MCU		BIT(14)
#define MT_TXS0_TX_RATE			GENMASK(13, 0)

#define MT_TXS1_SEQNO			GENMASK(31, 20)
#define MT_TXS1_RESP_RATE		GENMASK(19, 16)
#define MT_TXS1_RXV_SEQNO		GENMASK(15, 8)
#define MT_TXS1_TX_POWER_DBM		GENMASK(7, 0)

#define MT_TXS2_BF_STATUS		GENMASK(31, 30)
#define MT_TXS2_LAST_TX_RATE		GENMASK(29, 27)
#define MT_TXS2_SHARED_ANTENNA		BIT(26)
#define MT_TXS2_WCID			GENMASK(25, 16)
#define MT_TXS2_TX_DELAY		GENMASK(15, 0)

#define MT_TXS3_PID			GENMASK(31, 24)
#define MT_TXS3_ANT_ID			GENMASK(23, 0)

#define MT_TXS4_TIMESTAMP		GENMASK(31, 0)

#define MT_TXS5_F0_FINAL_MPDU		BIT(31)
#define MT_TXS5_F0_QOS			BIT(30)
#define MT_TXS5_F0_TX_COUNT		GENMASK(29, 25)
#define MT_TXS5_F0_FRONT_TIME		GENMASK(24, 0)
#define MT_TXS5_F1_MPDU_TX_COUNT	GENMASK(31, 24)
#define MT_TXS5_F1_MPDU_TX_BYTES	GENMASK(23, 0)

#define MT_TXS6_F0_NOISE_3		GENMASK(31, 24)
#define MT_TXS6_F0_NOISE_2		GENMASK(23, 16)
#define MT_TXS6_F0_NOISE_1		GENMASK(15, 8)
#define MT_TXS6_F0_NOISE_0		GENMASK(7, 0)
#define MT_TXS6_F1_MPDU_FAIL_COUNT	GENMASK(31, 24)
#define MT_TXS6_F1_MPDU_FAIL_BYTES	GENMASK(23, 0)

#define MT_TXS7_F0_RCPI_3		GENMASK(31, 24)
#define MT_TXS7_F0_RCPI_2		GENMASK(23, 16)
#define MT_TXS7_F0_RCPI_1		GENMASK(15, 8)
#define MT_TXS7_F0_RCPI_0		GENMASK(7, 0)
#define MT_TXS7_F1_MPDU_RETRY_COUNT	GENMASK(31, 24)
#define MT_TXS7_F1_MPDU_RETRY_BYTES	GENMASK(23, 0)

struct mt7915_dfs_pulse {
	u32 max_width;		/* us */
	int max_pwr;		/* dbm */
+1 −1
Original line number Diff line number Diff line
@@ -2440,7 +2440,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct sk_buff *rskb,
		cont->csa_ofs = cpu_to_le16(offs->cntdwn_counter_offs[0] - 4);

	buf = (u8 *)tlv + sizeof(*cont);
	mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL,
	mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
			      true);
	memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
}
+1 −1
Original line number Diff line number Diff line
@@ -395,7 +395,7 @@ void mt7915_mac_reset_counters(struct mt7915_phy *phy);
void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
			   struct sk_buff *skb, struct mt76_wcid *wcid,
			   struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
			   struct ieee80211_key_conf *key, bool beacon);
void mt7915_mac_set_timing(struct mt7915_phy *phy);
int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,