drivers/net/ethernet/google/gve/gve_rx_dqo.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/google/gve/gve_rx_dqo.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/google/gve/gve_rx_dqo.c
Extension
.c
Size
29959 bytes
Lines
1144
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 (gve_buf_state_is_allocated(rx, bs) && bs->xsk_buff) {
			xsk_buff_free(bs->xsk_buff);
			bs->xsk_buff = NULL;
		}
	}

	if (rx->dqo.qpl) {
		qpl_id = gve_get_rx_qpl_id(cfg->qcfg_tx, rx->q_num);
		gve_free_queue_page_list(priv, rx->dqo.qpl, qpl_id);
		rx->dqo.qpl = NULL;
	}

	if (rx->dqo.bufq.desc_ring) {
		size = sizeof(rx->dqo.bufq.desc_ring[0]) * buffer_queue_slots;
		dma_free_coherent(hdev, size, rx->dqo.bufq.desc_ring,
				  rx->dqo.bufq.bus);
		rx->dqo.bufq.desc_ring = NULL;
	}

	if (rx->dqo.complq.desc_ring) {
		size = sizeof(rx->dqo.complq.desc_ring[0]) *
			completion_queue_slots;
		dma_free_coherent(hdev, size, rx->dqo.complq.desc_ring,
				  rx->dqo.complq.bus);
		rx->dqo.complq.desc_ring = NULL;
	}

	kvfree(rx->dqo.buf_states);
	rx->dqo.buf_states = NULL;

	if (rx->dqo.page_pool) {
		page_pool_destroy(rx->dqo.page_pool);
		rx->dqo.page_pool = NULL;
	}

	gve_rx_free_hdr_bufs(priv, rx);

	netif_dbg(priv, drv, priv->dev, "freed rx ring %d\n", idx);
}

static int gve_rx_alloc_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx,
				 const u32 buf_count)
{
	struct device *hdev = &priv->pdev->dev;

	rx->dqo.hdr_bufs.data = dma_alloc_coherent(hdev, priv->header_buf_size * buf_count,
						   &rx->dqo.hdr_bufs.addr, GFP_KERNEL);
	if (!rx->dqo.hdr_bufs.data)
		return -ENOMEM;

	return 0;
}

void gve_rx_start_ring_dqo(struct gve_priv *priv, int idx)
{
	int ntfy_idx = gve_rx_idx_to_ntfy(priv, idx);

	gve_rx_add_to_block(priv, idx);
	gve_add_napi(priv, ntfy_idx, gve_napi_poll_dqo);
}

int gve_rx_alloc_ring_dqo(struct gve_priv *priv,
			  struct gve_rx_alloc_rings_cfg *cfg,
			  struct gve_rx_ring *rx,
			  int idx)
{
	struct device *hdev = &priv->pdev->dev;
	struct page_pool *pool;
	size_t size;
	u32 qpl_id;

	const u32 buffer_queue_slots = cfg->ring_size;
	const u32 completion_queue_slots = cfg->ring_size;

	netif_dbg(priv, drv, priv->dev, "allocating rx ring DQO\n");

	memset(rx, 0, sizeof(*rx));
	rx->gve = priv;
	rx->q_num = idx;
	rx->packet_buffer_size = cfg->packet_buffer_size;

	if (cfg->xdp) {
		rx->packet_buffer_truesize = GVE_XDP_RX_BUFFER_SIZE_DQO;
		rx->rx_headroom = XDP_PACKET_HEADROOM;
	} else {
		rx->packet_buffer_truesize = rx->packet_buffer_size;
		rx->rx_headroom = 0;
	}

	/* struct gve_xdp_buff is overlaid on struct xdp_buff_xsk and utilizes

Annotation

Implementation Notes