drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
Extension
.c
Size
7750 bytes
Lines
287
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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: BSD-3-Clause-Clear
/*
 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
 */

#include "mt76x02_usb.h"

static void mt76x02u_remove_dma_hdr(struct sk_buff *skb)
{
	int hdr_len;

	skb_pull(skb, sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN);
	hdr_len = ieee80211_get_hdrlen_from_skb(skb);
	if (hdr_len % 4)
		mt76x02_remove_hdr_pad(skb, 2);
}

void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
{
	mt76x02u_remove_dma_hdr(e->skb);
	mt76_tx_complete_skb(mdev, e->wcid, e->skb);
}
EXPORT_SYMBOL_GPL(mt76x02u_tx_complete_skb);

int mt76x02u_mac_start(struct mt76x02_dev *dev)
{
	mt76x02_mac_reset_counters(dev);

	mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
	if (!mt76x02_wait_for_wpdma(&dev->mt76, 200000))
		return -ETIMEDOUT;

	mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);

	mt76_wr(dev, MT_MAC_SYS_CTRL,
		MT_MAC_SYS_CTRL_ENABLE_TX |
		MT_MAC_SYS_CTRL_ENABLE_RX);

	if (!mt76x02_wait_for_wpdma(&dev->mt76, 50))
		return -ETIMEDOUT;

	return 0;
}
EXPORT_SYMBOL_GPL(mt76x02u_mac_start);

int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
{
	u32 info, pad;

	/* Buffer layout:
	 *	|   4B   | xfer len |      pad       |  4B  |
	 *	| TXINFO | pkt/cmd  | zero pad to 4B | zero |
	 *
	 * length field of TXINFO should be set to 'xfer len'.
	 */
	info = FIELD_PREP(MT_TXD_INFO_LEN, round_up(skb->len, 4)) |
	       FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags;
	put_unaligned_le32(info, skb_push(skb, sizeof(info)));

	pad = round_up(skb->len, 4) + 4 - skb->len;
	return mt76_skb_adjust_pad(skb, pad);
}

int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
			    enum mt76_txq_id qid, struct mt76_wcid *wcid,
			    struct ieee80211_sta *sta,
			    struct mt76_tx_info *tx_info)
{
	struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
	int pid, len = tx_info->skb->len, ep = dev->mphy.q_tx[qid]->ep;
	struct mt76x02_txwi *txwi;
	bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU;
	enum mt76_qsel qsel;
	u32 flags;
	int err;

	mt76_insert_hdr_pad(tx_info->skb);

	txwi = (struct mt76x02_txwi *)(tx_info->skb->data - sizeof(*txwi));
	mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len);
	skb_push(tx_info->skb, sizeof(*txwi));

	pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);

	/* encode packet rate for no-skb packet id to fix up status reporting */
	if (pid == MT_PACKET_ID_NO_SKB)
		pid = MT_PACKET_ID_HAS_RATE |
		      (le16_to_cpu(txwi->rate) & MT_PKTID_RATE) |
		      FIELD_PREP(MT_PKTID_AC,
				 skb_get_queue_mapping(tx_info->skb));

Annotation

Implementation Notes