drivers/net/ethernet/mellanox/mlx4/en_rx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx4/en_rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx4/en_rx.c
Extension
.c
Size
36349 bytes
Lines
1313
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 mlx4_en_xdp_buff {
	struct xdp_buff xdp;
	struct mlx4_cqe *cqe;
	struct mlx4_en_dev *mdev;
	struct mlx4_en_rx_ring *ring;
	struct net_device *dev;
};

int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
{
	struct mlx4_en_xdp_buff *_ctx = (void *)ctx;

	if (unlikely(_ctx->ring->hwtstamp_rx_filter != HWTSTAMP_FILTER_ALL))
		return -ENODATA;

	*timestamp = mlx4_en_get_hwtstamp(_ctx->mdev,
					  mlx4_en_get_cqe_ts(_ctx->cqe));
	return 0;
}

int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
			enum xdp_rss_hash_type *rss_type)
{
	struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
	struct mlx4_cqe *cqe = _ctx->cqe;
	enum xdp_rss_hash_type xht = 0;
	__be16 status;

	if (unlikely(!(_ctx->dev->features & NETIF_F_RXHASH)))
		return -ENODATA;

	*hash = be32_to_cpu(cqe->immed_rss_invalid);
	status = cqe->status;
	if (status & cpu_to_be16(MLX4_CQE_STATUS_TCP))
		xht = XDP_RSS_L4_TCP;
	if (status & cpu_to_be16(MLX4_CQE_STATUS_UDP))
		xht = XDP_RSS_L4_UDP;
	if (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 | MLX4_CQE_STATUS_IPV4F))
		xht |= XDP_RSS_L3_IPV4;
	if (status & cpu_to_be16(MLX4_CQE_STATUS_IPV6)) {
		xht |= XDP_RSS_L3_IPV6;
		if (cqe->ipv6_ext_mask)
			xht |= XDP_RSS_L3_DYNHDR;
	}
	*rss_type = xht;

	return 0;
}

int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	struct mlx4_en_xdp_buff mxbuf = {};
	int factor = priv->cqe_factor;
	struct mlx4_en_rx_ring *ring;
	struct bpf_prog *xdp_prog;
	int cq_ring = cq->ring;
	bool doorbell_pending;
	bool xdp_redir_flush;
	struct mlx4_cqe *cqe;
	int polled = 0;
	int index;

	if (unlikely(!priv->port_up || budget <= 0))
		return 0;

	ring = priv->rx_ring[cq_ring];

	xdp_prog = rcu_dereference_bh(ring->xdp_prog);
	xdp_init_buff(&mxbuf.xdp, priv->frag_info[0].frag_stride, &ring->xdp_rxq);
	doorbell_pending = false;
	xdp_redir_flush = false;

	/* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
	 * descriptor offset can be deduced from the CQE index instead of
	 * reading 'cqe->index' */
	index = cq->mcq.cons_index & ring->size_mask;
	cqe = mlx4_en_get_cqe(cq->buf, index, priv->cqe_size) + factor;

	/* Process all completed CQEs */
	while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
		    cq->mcq.cons_index & cq->size)) {
		struct mlx4_en_rx_alloc *frags;
		enum pkt_hash_types hash_type;
		struct sk_buff *skb;
		unsigned int length;
		int ip_summed;
		void *va;
		int nr;

Annotation

Implementation Notes