drivers/net/ethernet/alibaba/eea/eea_rx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/alibaba/eea/eea_rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/alibaba/eea/eea_rx.c
Extension
.c
Size
16956 bytes
Lines
815
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

struct eea_rx_ctx {
	u32 len;
	u32 hdr_len;

	u16 flags;
	bool more;

	struct eea_rx_meta *meta;

	struct eea_rx_ctx_stats stats;
};

static struct eea_rx_meta *eea_rx_meta_get(struct eea_net_rx *rx)
{
	struct eea_rx_meta *meta;

	if (!rx->free)
		return NULL;

	meta = rx->free;
	rx->free = meta->next;

	return meta;
}

static void eea_rx_meta_put(struct eea_net_rx *rx, struct eea_rx_meta *meta)
{
	meta->next = rx->free;
	rx->free = meta;
}

static void eea_free_rx_buffer(struct eea_net_rx *rx, struct eea_rx_meta *meta,
			       bool allow_direct)
{
	u32 drain_count;

	drain_count = EEA_PAGE_FRAGS_NUM - meta->frags;

	if (page_pool_unref_page(meta->page, drain_count) == 0)
		page_pool_put_unrefed_page(rx->pp, meta->page, -1,
					   allow_direct);

	meta->page = NULL;
}

static void eea_rx_meta_dma_sync_for_device(struct eea_net_rx *rx,
					    struct eea_rx_meta *meta)
{
	u32 len;

	if (meta->sync_for_cpu <= meta->offset + rx->headroom)
		return;

	len = meta->sync_for_cpu - meta->offset - rx->headroom;

	dma_sync_single_for_device(rx->enet->edev->dma_dev,
				   meta->dma + meta->offset + rx->headroom,
				   len, DMA_FROM_DEVICE);
	meta->sync_for_cpu = 0;
}

static void meta_align_offset(struct eea_net_rx *rx, struct eea_rx_meta *meta)
{
	int h, b;

	h = rx->headroom;
	b = meta->offset + h;

	/* For better performance, we align the buffer address to
	 * EEA_RX_BUF_ALIGN, as required by the device design.
	 */
	b = ALIGN(b, EEA_RX_BUF_ALIGN);

	meta->offset = b - h;
}

static int eea_alloc_rx_buffer(struct eea_net_rx *rx, struct eea_rx_meta *meta)
{
	struct page *page;

	if (meta->page) {
		eea_rx_meta_dma_sync_for_device(rx, meta);
		return 0;
	}

	page = page_pool_dev_alloc_pages(rx->pp);
	if (!page)
		return -ENOMEM;

	page_pool_fragment_page(page, EEA_PAGE_FRAGS_NUM);

Annotation

Implementation Notes