drivers/net/ethernet/mediatek/mtk_wed_wo.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mediatek/mtk_wed_wo.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mediatek/mtk_wed_wo.c
Extension
.c
Size
10864 bytes
Lines
492
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

if (unlikely(dma_mapping_error(wo->hw->dev, addr))) {
			skb_free_frag(buf);
			break;
		}

		q->head = (q->head + 1) % q->n_desc;
		entry = &q->entry[q->head];
		entry->addr = addr;
		entry->len = q->buf_size;
		q->entry[q->head].buf = buf;

		if (rx) {
			struct mtk_wed_wo_queue_desc *desc = &q->desc[q->head];
			u32 ctrl = MTK_WED_WO_CTL_LAST_SEC0 |
				   FIELD_PREP(MTK_WED_WO_CTL_SD_LEN0,
					      entry->len);

			WRITE_ONCE(desc->buf0, cpu_to_le32(addr));
			WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
		}
		q->queued++;
		n_buf++;
	}

	return n_buf;
}

static void
mtk_wed_wo_rx_complete(struct mtk_wed_wo *wo)
{
	mtk_wed_wo_set_ack(wo, MTK_WED_WO_RXCH_INT_MASK);
	mtk_wed_wo_irq_enable(wo, MTK_WED_WO_RXCH_INT_MASK);
}

static void
mtk_wed_wo_rx_run_queue(struct mtk_wed_wo *wo, struct mtk_wed_wo_queue *q)
{
	for (;;) {
		struct mtk_wed_mcu_hdr *hdr;
		struct sk_buff *skb;
		void *data;
		u32 len;

		data = mtk_wed_wo_dequeue(wo, q, &len, false);
		if (!data)
			break;

		skb = build_skb(data, q->buf_size);
		if (!skb) {
			skb_free_frag(data);
			continue;
		}

		__skb_put(skb, len);
		if (mtk_wed_mcu_check_msg(wo, skb)) {
			dev_kfree_skb(skb);
			continue;
		}

		hdr = (struct mtk_wed_mcu_hdr *)skb->data;
		if (hdr->flag & cpu_to_le16(MTK_WED_WARP_CMD_FLAG_RSP))
			mtk_wed_mcu_rx_event(wo, skb);
		else
			mtk_wed_mcu_rx_unsolicited_event(wo, skb);
	}

	if (mtk_wed_wo_queue_refill(wo, q, true)) {
		u32 index = (q->head - 1) % q->n_desc;

		mtk_wed_wo_queue_kick(wo, q, index);
	}
}

static irqreturn_t
mtk_wed_wo_irq_handler(int irq, void *data)
{
	struct mtk_wed_wo *wo = data;

	mtk_wed_wo_set_isr(wo, 0);
	tasklet_schedule(&wo->mmio.irq_tasklet);

	return IRQ_HANDLED;
}

static void mtk_wed_wo_irq_tasklet(struct tasklet_struct *t)
{
	struct mtk_wed_wo *wo = from_tasklet(wo, t, mmio.irq_tasklet);
	u32 intr, mask;

	/* disable interrupts */

Annotation

Implementation Notes