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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/google/gve/gve_tx.c
Extension
.c
Size
28134 bytes
Lines
1039
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 (info->xdp_frame) {
			xdp_return_frame(info->xdp_frame);
			info->xdp_frame = NULL;
		}
		space_freed += gve_tx_clear_buffer_state(info);
	}

	gve_tx_free_fifo(&tx->tx_fifo, space_freed);
	if (xsk_complete > 0 && tx->xsk_pool)
		xsk_tx_completed(tx->xsk_pool, xsk_complete);
	u64_stats_update_begin(&tx->statss);
	tx->bytes_done += bytes;
	tx->pkt_done += pkts;
	u64_stats_update_end(&tx->statss);
	return pkts;
}

static int gve_clean_tx_done(struct gve_priv *priv, struct gve_tx_ring *tx,
			     u32 to_do, bool try_to_wake);

void gve_tx_stop_ring_gqi(struct gve_priv *priv, int idx)
{
	int ntfy_idx = gve_tx_idx_to_ntfy(priv, idx);
	struct gve_tx_ring *tx = &priv->tx[idx];

	if (!gve_tx_was_added_to_block(priv, idx))
		return;

	gve_remove_napi(priv, ntfy_idx);
	if (tx->q_num < priv->tx_cfg.num_queues)
		gve_clean_tx_done(priv, tx, priv->tx_desc_cnt, false);
	else
		gve_clean_xdp_done(priv, tx, priv->tx_desc_cnt);
	netdev_tx_reset_queue(tx->netdev_txq);
	gve_tx_remove_from_block(priv, idx);
}

static void gve_tx_free_ring_gqi(struct gve_priv *priv, struct gve_tx_ring *tx,
				 struct gve_tx_alloc_rings_cfg *cfg)
{
	struct device *hdev = &priv->pdev->dev;
	int idx = tx->q_num;
	size_t bytes;
	u32 qpl_id;
	u32 slots;

	slots = tx->mask + 1;
	dma_free_coherent(hdev, sizeof(*tx->q_resources),
			  tx->q_resources, tx->q_resources_bus);
	tx->q_resources = NULL;

	if (tx->tx_fifo.qpl) {
		if (tx->tx_fifo.base)
			gve_tx_fifo_release(priv, &tx->tx_fifo);

		qpl_id = gve_tx_qpl_id(priv, tx->q_num);
		gve_free_queue_page_list(priv, tx->tx_fifo.qpl, qpl_id);
		tx->tx_fifo.qpl = NULL;
	}

	bytes = sizeof(*tx->desc) * slots;
	dma_free_coherent(hdev, bytes, tx->desc, tx->bus);
	tx->desc = NULL;

	vfree(tx->info);
	tx->info = NULL;

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

void gve_tx_start_ring_gqi(struct gve_priv *priv, int idx)
{
	int ntfy_idx = gve_tx_idx_to_ntfy(priv, idx);
	struct gve_tx_ring *tx = &priv->tx[idx];

	gve_tx_add_to_block(priv, idx);

	tx->netdev_txq = netdev_get_tx_queue(priv->dev, idx);
	gve_add_napi(priv, ntfy_idx, gve_napi_poll);
}

static int gve_tx_alloc_ring_gqi(struct gve_priv *priv,
				 struct gve_tx_alloc_rings_cfg *cfg,
				 struct gve_tx_ring *tx,
				 int idx)
{
	struct device *hdev = &priv->pdev->dev;
	u32 qpl_id = 0;
	size_t bytes;

Annotation

Implementation Notes