drivers/net/wireless/mediatek/mt7601u/tx.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/mediatek/mt7601u/tx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/mediatek/mt7601u/tx.c
Extension
.c
Size
8994 bytes
Lines
317
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 */

#include "mt7601u.h"
#include "trace.h"

enum mt76_txq_id {
	MT_TXQ_VO = IEEE80211_AC_VO,
	MT_TXQ_VI = IEEE80211_AC_VI,
	MT_TXQ_BE = IEEE80211_AC_BE,
	MT_TXQ_BK = IEEE80211_AC_BK,
	MT_TXQ_PSD,
	MT_TXQ_MCU,
	__MT_TXQ_MAX
};

/* Hardware uses mirrored order of queues with Q0 having the highest priority */
static u8 q2hwq(u8 q)
{
	return q ^ 0x3;
}

/* Take mac80211 Q id from the skb and translate it to hardware Q id */
static u8 skb2q(struct sk_buff *skb)
{
	int qid = skb_get_queue_mapping(skb);

	if (WARN_ON(qid >= MT_TXQ_PSD)) {
		qid = MT_TXQ_BE;
		skb_set_queue_mapping(skb, qid);
	}

	return q2hwq(qid);
}

/* Note: TX retry reporting is a bit broken.
 *	 Retries are reported only once per AMPDU and often come a frame early
 *	 i.e. they are reported in the last status preceding the AMPDU. Apart
 *	 from the fact that it's hard to know the length of the AMPDU (which is
 *	 required to know to how many consecutive frames retries should be
 *	 applied), if status comes early on full FIFO it gets lost and retries
 *	 of the whole AMPDU become invisible.
 *	 As a work-around encode the desired rate in PKT_ID of TX descriptor
 *	 and based on that guess the retries (every rate is tried once).
 *	 Only downside here is that for MCS0 we have to rely solely on
 *	 transmission failures as no retries can ever be reported.
 *	 Not having to read EXT_FIFO has a nice effect of doubling the number
 *	 of reports which can be fetched.
 *	 Also the vendor driver never uses the EXT_FIFO register so it may be
 *	 undertested.
 */
static u8 mt7601u_tx_pktid_enc(struct mt7601u_dev *dev, u8 rate, bool is_probe)
{
	u8 encoded = (rate + 1) + is_probe *  8;

	/* Because PKT_ID 0 disables status reporting only 15 values are
	 * available but 16 are needed (8 MCS * 2 for encoding is_probe)
	 * - we need to cram together two rates. MCS0 and MCS7 with is_probe
	 * share PKT_ID 9.
	 */
	if (is_probe && rate == 7)
		return encoded - 7;

	return encoded;
}

static void
mt7601u_tx_pktid_dec(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
{
	u8 req_rate = stat->pktid;
	u8 eff_rate = stat->rate & 0x7;

	req_rate -= 1;

	if (req_rate > 7) {
		stat->is_probe = true;
		req_rate -= 8;

		/* Decide between MCS0 and MCS7 which share pktid 9 */
		if (!req_rate && eff_rate)
			req_rate = 7;
	}

	stat->retry = req_rate - eff_rate;
}

static void mt7601u_tx_skb_remove_dma_overhead(struct sk_buff *skb,

Annotation

Implementation Notes