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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/google/gve/gve_rx.c
Extension
.c
Size
28709 bytes
Lines
1095
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 (!rx->data.raw_addressing) {
			struct page *page = rx->data.qpl->pages[i];
			dma_addr_t addr = i * PAGE_SIZE;

			gve_setup_rx_buffer(rx, &rx->data.page_info[i], addr,
					    page,
					    &rx->data.data_ring[i].qpl_offset);
			continue;
		}
		err = gve_rx_alloc_buffer(priv, &priv->pdev->dev,
					  &rx->data.page_info[i],
					  &rx->data.data_ring[i], rx);
		if (err)
			goto alloc_err_rda;
	}

	if (!rx->data.raw_addressing) {
		for (j = 0; j < rx->qpl_copy_pool_mask + 1; j++) {
			struct page *page = alloc_pages_node(priv->numa_node,
							     GFP_KERNEL, 0);

			if (!page) {
				err = -ENOMEM;
				goto alloc_err_qpl;
			}

			rx->qpl_copy_pool[j].page = page;
			rx->qpl_copy_pool[j].page_offset = 0;
			rx->qpl_copy_pool[j].page_address = page_address(page);
			rx->qpl_copy_pool[j].buf_size = rx->packet_buffer_size;

			/* The page already has 1 ref. */
			page_ref_add(page, INT_MAX - 1);
			rx->qpl_copy_pool[j].pagecnt_bias = INT_MAX;
		}
	}

	return slots;

alloc_err_qpl:
	/* Fully free the copy pool pages. */
	while (j--) {
		page_ref_sub(rx->qpl_copy_pool[j].page,
			     rx->qpl_copy_pool[j].pagecnt_bias - 1);
		put_page(rx->qpl_copy_pool[j].page);
	}

	/* Do not fully free QPL pages - only remove the bias added in this
	 * function with gve_setup_rx_buffer.
	 */
	while (i--)
		page_ref_sub(rx->data.page_info[i].page,
			     rx->data.page_info[i].pagecnt_bias - 1);

	return err;

alloc_err_rda:
	while (i--)
		gve_rx_free_buffer(&priv->pdev->dev,
				   &rx->data.page_info[i],
				   &rx->data.data_ring[i]);
	return err;
}

void gve_rx_start_ring_gqi(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);
}

int gve_rx_alloc_ring_gqi(struct gve_priv *priv,
			  struct gve_rx_alloc_rings_cfg *cfg,
			  struct gve_rx_ring *rx,
			  int idx)
{
	struct device *hdev = &priv->pdev->dev;
	u32 slots = cfg->ring_size;
	int filled_pages;
	u32 qpl_id = 0;
	size_t bytes;
	int err;

	netif_dbg(priv, drv, priv->dev, "allocating rx ring\n");
	/* Make sure everything is zeroed to start with */
	memset(rx, 0, sizeof(*rx));

	rx->gve = priv;
	rx->q_num = idx;

Annotation

Implementation Notes