drivers/net/ethernet/mellanox/mlx5/core/en_rx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
Extension
.c
Size
75578 bytes
Lines
2738
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 (no_xdp_xmit || !test_bit(i, wi->skip_release_bitmap)) {
				struct mlx5e_frag_page *frag_page;

				frag_page = &wi->alloc_units.frag_pages[i];
				mlx5e_page_release_fragmented(rq->page_pool,
							      frag_page);
			}
		}
	}
}

static void mlx5e_post_rx_mpwqe(struct mlx5e_rq *rq, u8 n)
{
	struct mlx5_wq_ll *wq = &rq->mpwqe.wq;

	do {
		u16 next_wqe_index = mlx5_wq_ll_get_wqe_next_ix(wq, wq->head);

		mlx5_wq_ll_push(wq, next_wqe_index);
	} while (--n);

	/* ensure wqes are visible to device before updating doorbell record */
	dma_wmb();

	mlx5_wq_ll_update_db_record(wq);
}

static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix)
{
	struct mlx5e_mpw_info *wi = mlx5e_get_mpw_info(rq, ix);
	struct mlx5e_icosq *sq = rq->icosq;
	struct mlx5e_frag_page *frag_page;
	struct mlx5_wq_cyc *wq = &sq->wq;
	struct mlx5e_umr_wqe *umr_wqe;
	u32 offset; /* 17-bit value with MTT. */
	bool sync_locked;
	u16 pi;
	int err;
	int i;

	sync_locked = mlx5e_icosq_sync_lock(sq);
	pi = mlx5e_icosq_get_next_pi(sq, rq->mpwqe.umr_wqebbs);
	umr_wqe = mlx5_wq_cyc_get_wqe(wq, pi);
	memcpy(umr_wqe, &rq->mpwqe.umr_wqe, sizeof(struct mlx5e_umr_wqe));

	frag_page = &wi->alloc_units.frag_pages[0];

	for (i = 0; i < rq->mpwqe.pages_per_wqe; i++, frag_page++) {
		dma_addr_t addr;

		err = mlx5e_page_alloc_fragmented(rq->page_pool, frag_page);
		if (unlikely(err))
			goto err_unmap;

		addr = page_pool_get_dma_addr_netmem(frag_page->netmem);
		umr_wqe->inline_mtts[i] = (struct mlx5_mtt) {
			.ptag = cpu_to_be64(addr | MLX5_EN_WR),
		};
	}

	/* Pad if needed, in case the value set to ucseg->xlt_octowords
	 * in mlx5e_build_umr_wqe() needed alignment.
	 */
	if (rq->mpwqe.pages_per_wqe & (MLX5_UMR_MTT_NUM_ENTRIES_ALIGNMENT - 1)) {
		int pad = ALIGN(rq->mpwqe.pages_per_wqe, MLX5_UMR_MTT_NUM_ENTRIES_ALIGNMENT) -
			rq->mpwqe.pages_per_wqe;

		memset(&umr_wqe->inline_mtts[rq->mpwqe.pages_per_wqe], 0,
		       sizeof(*umr_wqe->inline_mtts) * pad);
	}

	bitmap_zero(wi->skip_release_bitmap, rq->mpwqe.pages_per_wqe);
	wi->consumed_strides = 0;

	umr_wqe->hdr.ctrl.opmod_idx_opcode =
		cpu_to_be32((sq->pc << MLX5_WQE_CTRL_WQE_INDEX_SHIFT) |
			    MLX5_OPCODE_UMR);

	offset = (ix * rq->mpwqe.mtts_per_wqe) * sizeof(struct mlx5_mtt) / MLX5_OCTWORD;
	umr_wqe->hdr.uctrl.xlt_offset = cpu_to_be16(offset);

	sq->db.wqe_info[pi] = (struct mlx5e_icosq_wqe_info) {
		.wqe_type   = MLX5E_ICOSQ_WQE_UMR_RX,
		.num_wqebbs = rq->mpwqe.umr_wqebbs,
		.umr.rq     = rq,
	};

	sq->pc += rq->mpwqe.umr_wqebbs;
	mlx5e_icosq_sync_unlock(sq, sync_locked);

Annotation

Implementation Notes