drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
Extension
.c
Size
27913 bytes
Lines
977
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 mlx5e_xsk_tx_complete {
	struct mlx5_cqe64 *cqe;
	struct mlx5e_cq *cq;
};

static u64 mlx5e_xsk_fill_timestamp(void *_priv)
{
	struct mlx5e_xsk_tx_complete *priv = _priv;
	u64 ts;

	ts = get_cqe_ts(priv->cqe);

	if (mlx5_is_real_time_rq(priv->cq->mdev) || mlx5_is_real_time_sq(priv->cq->mdev))
		return mlx5_real_time_cyc2time(priv->cq->mdev->clock, ts);

	return  mlx5_timecounter_cyc2time(priv->cq->mdev->clock, ts);
}

static void mlx5e_xsk_request_checksum(u16 csum_start, u16 csum_offset, void *priv)
{
	struct mlx5_wqe_eth_seg *eseg = priv;

	/* HW/FW is doing parsing, so offsets are largely ignored. */
	eseg->cs_flags |= MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM;
}

const struct xsk_tx_metadata_ops mlx5e_xsk_tx_metadata_ops = {
	.tmo_fill_timestamp		= mlx5e_xsk_fill_timestamp,
	.tmo_request_checksum		= mlx5e_xsk_request_checksum,
};

/* returns true if packet was consumed by xdp */
bool mlx5e_xdp_handle(struct mlx5e_rq *rq,
		      struct bpf_prog *prog, struct mlx5e_xdp_buff *mxbuf)
{
	struct xdp_buff *xdp = &mxbuf->xdp;
	u32 act;
	int err;

	act = bpf_prog_run_xdp(prog, xdp);
	switch (act) {
	case XDP_PASS:
		return false;
	case XDP_TX:
		if (unlikely(!mlx5e_xmit_xdp_buff(rq->xdpsq, rq, xdp)))
			goto xdp_abort;
		__set_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags); /* non-atomic */
		return true;
	case XDP_REDIRECT:
		/* When XDP enabled then page-refcnt==1 here */
		err = xdp_do_redirect(rq->netdev, xdp, prog);
		if (unlikely(err))
			goto xdp_abort;
		__set_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags);
		__set_bit(MLX5E_RQ_FLAG_XDP_REDIRECT, rq->flags);
		rq->stats->xdp_redirect++;
		return true;
	default:
		bpf_warn_invalid_xdp_action(rq->netdev, prog, act);
		fallthrough;
	case XDP_ABORTED:
xdp_abort:
		trace_xdp_exception(rq->netdev, prog, act);
		fallthrough;
	case XDP_DROP:
		rq->stats->xdp_drop++;
		return true;
	}
}

static u16 mlx5e_xdpsq_get_next_pi(struct mlx5e_xdpsq *sq, u16 size)
{
	struct mlx5_wq_cyc *wq = &sq->wq;
	u16 pi, contig_wqebbs;

	pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
	contig_wqebbs = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
	if (unlikely(contig_wqebbs < size)) {
		struct mlx5e_xdp_wqe_info *wi, *edge_wi;

		wi = &sq->db.wqe_info[pi];
		edge_wi = wi + contig_wqebbs;

		/* Fill SQ frag edge with NOPs to avoid WQE wrapping two pages. */
		for (; wi < edge_wi; wi++) {
			*wi = (struct mlx5e_xdp_wqe_info) {
				.num_wqebbs = 1,
				.num_pkts = 0,
			};
			mlx5e_post_nop(wq, sq->sqn, &sq->pc);

Annotation

Implementation Notes