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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx4/profile.c
Extension
.c
Size
8848 bytes
Lines
271
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_resource {
		u64 size;
		u64 start;
		int type;
		u32 num;
		int log_num;
	};

	u64 total_size = 0;
	struct mlx4_resource *profile;
	struct sysinfo si;
	int i, j;

	profile = kzalloc_objs(*profile, MLX4_RES_NUM);
	if (!profile)
		return -ENOMEM;

	/*
	 * We want to scale the number of MTTs with the size of the
	 * system memory, since it makes sense to register a lot of
	 * memory on a system with a lot of memory.  As a heuristic,
	 * make sure we have enough MTTs to cover twice the system
	 * memory (with PAGE_SIZE entries).
	 *
	 * This number has to be a power of two and fit into 32 bits
	 * due to device limitations, so cap this at 2^31 as well.
	 * That limits us to 8TB of memory registration per HCA with
	 * 4KB pages, which is probably OK for the next few months.
	 */
	si_meminfo(&si);
	request->num_mtt =
		roundup_pow_of_two(max_t(unsigned, request->num_mtt,
					 min(1UL << (31 - log_mtts_per_seg),
					     (si.totalram << 1) >> log_mtts_per_seg)));


	profile[MLX4_RES_QP].size     = dev_cap->qpc_entry_sz;
	profile[MLX4_RES_RDMARC].size = dev_cap->rdmarc_entry_sz;
	profile[MLX4_RES_ALTC].size   = dev_cap->altc_entry_sz;
	profile[MLX4_RES_AUXC].size   = dev_cap->aux_entry_sz;
	profile[MLX4_RES_SRQ].size    = dev_cap->srq_entry_sz;
	profile[MLX4_RES_CQ].size     = dev_cap->cqc_entry_sz;
	profile[MLX4_RES_EQ].size     = dev_cap->eqc_entry_sz;
	profile[MLX4_RES_DMPT].size   = dev_cap->dmpt_entry_sz;
	profile[MLX4_RES_CMPT].size   = dev_cap->cmpt_entry_sz;
	profile[MLX4_RES_MTT].size    = dev_cap->mtt_entry_sz;
	profile[MLX4_RES_MCG].size    = mlx4_get_mgm_entry_size(dev);

	profile[MLX4_RES_QP].num      = request->num_qp;
	profile[MLX4_RES_RDMARC].num  = request->num_qp * request->rdmarc_per_qp;
	profile[MLX4_RES_ALTC].num    = request->num_qp;
	profile[MLX4_RES_AUXC].num    = request->num_qp;
	profile[MLX4_RES_SRQ].num     = request->num_srq;
	profile[MLX4_RES_CQ].num      = request->num_cq;
	profile[MLX4_RES_EQ].num = mlx4_is_mfunc(dev) ? dev->phys_caps.num_phys_eqs :
					min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
	profile[MLX4_RES_DMPT].num    = request->num_mpt;
	profile[MLX4_RES_CMPT].num    = MLX4_NUM_CMPTS;
	profile[MLX4_RES_MTT].num     = request->num_mtt * (1 << log_mtts_per_seg);
	profile[MLX4_RES_MCG].num     = request->num_mcg;

	for (i = 0; i < MLX4_RES_NUM; ++i) {
		profile[i].type     = i;
		profile[i].num      = roundup_pow_of_two(profile[i].num);
		profile[i].log_num  = ilog2(profile[i].num);
		profile[i].size    *= profile[i].num;
		profile[i].size     = max(profile[i].size, (u64) PAGE_SIZE);
	}

	/*
	 * Sort the resources in decreasing order of size.  Since they
	 * all have sizes that are powers of 2, we'll be able to keep
	 * resources aligned to their size and pack them without gaps
	 * using the sorted order.
	 */
	for (i = MLX4_RES_NUM; i > 0; --i)
		for (j = 1; j < i; ++j) {
			if (profile[j].size > profile[j - 1].size)
				swap(profile[j], profile[j - 1]);
		}

	for (i = 0; i < MLX4_RES_NUM; ++i) {
		if (profile[i].size) {
			profile[i].start = total_size;
			total_size	+= profile[i].size;
		}

		if (total_size > dev_cap->max_icm_sz) {
			mlx4_err(dev, "Profile requires 0x%llx bytes; won't fit in 0x%llx bytes of context memory\n",
				 (unsigned long long) total_size,

Annotation

Implementation Notes