drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
Extension
.c
Size
25030 bytes
Lines
1023
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 (dcb_buf->use_skb) {
			dma_unmap_single(lan966x->dev,
					 dcb_buf->dma_addr,
					 dcb_buf->len,
					 DMA_TO_DEVICE);

			if (!dcb_buf->ptp)
				napi_consume_skb(dcb_buf->data.skb, weight);
		} else {
			if (dcb_buf->xdp_ndo)
				dma_unmap_single(lan966x->dev,
						 dcb_buf->dma_addr,
						 dcb_buf->len,
						 DMA_TO_DEVICE);

			if (dcb_buf->xdp_ndo)
				xdp_return_frame_bulk(dcb_buf->data.xdpf, &bq);
			else
				page_pool_recycle_direct(rx->page_pool,
							 dcb_buf->data.page);
		}

		clear = true;
	}

	xdp_flush_frame_bulk(&bq);

	if (clear)
		lan966x_fdma_wakeup_netdev(lan966x);

	spin_unlock_irqrestore(&lan966x->tx_lock, flags);
}

static int lan966x_fdma_rx_check_frame(struct lan966x_rx *rx, u64 *src_port)
{
	struct lan966x *lan966x = rx->lan966x;
	struct fdma *fdma = &rx->fdma;
	struct lan966x_port *port;
	struct fdma_db *db;
	struct page *page;

	db = fdma_db_next_get(fdma);
	page = rx->page[fdma->dcb_index][fdma->db_index];
	if (unlikely(!page))
		return FDMA_ERROR;

	dma_sync_single_for_cpu(lan966x->dev,
				(dma_addr_t)db->dataptr + XDP_PACKET_HEADROOM,
				FDMA_DCB_STATUS_BLOCKL(db->status),
				DMA_FROM_DEVICE);

	lan966x_ifh_get_src_port(page_address(page) + XDP_PACKET_HEADROOM,
				 src_port);
	if (WARN_ON(*src_port >= lan966x->num_phys_ports))
		return FDMA_ERROR;

	port = lan966x->ports[*src_port];
	if (!lan966x_xdp_port_present(port))
		return FDMA_PASS;

	return lan966x_xdp_run(port, page, FDMA_DCB_STATUS_BLOCKL(db->status));
}

static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx,
						 u64 src_port)
{
	struct lan966x *lan966x = rx->lan966x;
	struct fdma *fdma = &rx->fdma;
	struct sk_buff *skb;
	struct fdma_db *db;
	struct page *page;
	u64 timestamp;

	/* Get the received frame and unmap it */
	db = fdma_db_next_get(fdma);
	page = rx->page[fdma->dcb_index][fdma->db_index];

	skb = build_skb(page_address(page), fdma->db_size);
	if (unlikely(!skb))
		goto free_page;

	skb_mark_for_recycle(skb);

	skb_reserve(skb, XDP_PACKET_HEADROOM);
	skb_put(skb, FDMA_DCB_STATUS_BLOCKL(db->status));

	lan966x_ifh_get_timestamp(skb->data, &timestamp);

	skb->dev = lan966x->ports[src_port]->dev;
	skb_pull(skb, IFH_LEN_BYTES);

Annotation

Implementation Notes