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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/mediatek/mt76/npu.c
Extension
.c
Size
12304 bytes
Lines
529
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

if (!FIELD_GET(NPU_RX_DMA_DESC_DONE_MASK, desc[index].ctrl)) {
			dev_kfree_skb(skb);
			return NULL;
		}

		dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0],
					e->dma_len[0],
					page_pool_get_dma_dir(q->page_pool));

		if (!skb) {
			skb = napi_build_skb(e->buf, q->buf_size);
			if (!skb)
				return NULL;

			__skb_put(skb, len);
			skb_reset_mac_header(skb);
			skb_mark_for_recycle(skb);
		} else {
			struct skb_shared_info *shinfo = skb_shinfo(skb);
			struct page *page = virt_to_head_page(e->buf);
			int nr_frags = shinfo->nr_frags;

			if (nr_frags < ARRAY_SIZE(shinfo->frags))
				skb_add_rx_frag(skb, nr_frags, page,
						e->buf - page_address(page),
						len, q->buf_size);
		}

		*info = desc[index].info;
		index = (index + 1) % q->ndesc;
	}
	q->tail = index;
	q->queued -= i;
	Q_WRITE(q, dma_idx, q->tail);

	return skb;
}

void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb,
			u32 info)
{
	struct airoha_ppe_dev *ppe_dev;
	u16 reason, hash;

	if (!mt76_npu_device_active(dev))
		return;

	rcu_read_lock();

	ppe_dev = rcu_dereference(dev->mmio.ppe_dev);
	if (!ppe_dev)
		goto out;

	hash = FIELD_GET(NPU_RX_DMA_FOE_ID_MASK, info);
	skb_set_hash(skb, hash, PKT_HASH_TYPE_L4);

	reason = FIELD_GET(NPU_RX_DMA_CRSN_MASK, info);
	if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
		skb_set_mac_header(skb, 0);
		airoha_ppe_dev_check_skb(ppe_dev, skb, hash, true);
	}
out:
	rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(mt76_npu_check_ppe);

static int mt76_npu_rx_poll(struct napi_struct *napi, int budget)
{
	struct mt76_dev *dev = mt76_priv(napi->dev);
	enum mt76_rxq_id qid = napi - dev->napi;
	struct airoha_npu *npu;
	int done = 0;

	rcu_read_lock();

	npu = rcu_dereference(dev->mmio.npu);
	if (!npu)
		goto out;

	while (done < budget) {
		struct sk_buff *skb;
		u32 info = 0;

		skb = mt76_npu_dequeue(dev, &dev->q_rx[qid], &info);
		if (!skb)
			break;

		dev->drv->rx_skb(dev, qid, skb, &info);
		mt76_rx_poll_complete(dev, qid, napi);
		done++;

Annotation

Implementation Notes