drivers/infiniband/hw/hfi1/sdma.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/hfi1/sdma.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/hfi1/sdma.c
Extension
.c
Size
89721 bytes
Lines
3367
Domain
Driver Families
Bucket
drivers/infiniband
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 sdma_rht_map_elem {
	u32 mask;
	u8 ctr;
	struct sdma_engine *sde[];
};

struct sdma_rht_node {
	unsigned long cpu_id;
	struct sdma_rht_map_elem *map[HFI1_MAX_VLS_SUPPORTED];
	struct rhash_head node;
};

#define NR_CPUS_HINT 192

static const struct rhashtable_params sdma_rht_params = {
	.nelem_hint = NR_CPUS_HINT,
	.head_offset = offsetof(struct sdma_rht_node, node),
	.key_offset = offsetof(struct sdma_rht_node, cpu_id),
	.key_len = sizeof_field(struct sdma_rht_node, cpu_id),
	.max_size = NR_CPUS,
	.min_size = 8,
	.automatic_shrinking = true,
};

/*
 * sdma_select_user_engine() - select sdma engine based on user setup
 * @dd: devdata
 * @selector: a spreading factor
 * @vl: this vl
 *
 * This function returns an sdma engine for a user sdma request.
 * User defined sdma engine affinity setting is honored when applicable,
 * otherwise system default sdma engine mapping is used. To ensure correct
 * ordering, the mapping from <selector, vl> to sde must remain unchanged.
 */
struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd,
					    u32 selector, u8 vl)
{
	struct sdma_rht_node *rht_node;
	struct sdma_engine *sde = NULL;
	unsigned long cpu_id;

	/*
	 * To ensure that always the same sdma engine(s) will be
	 * selected make sure the process is pinned to this CPU only.
	 */
	if (current->nr_cpus_allowed != 1)
		goto out;

	rcu_read_lock();
	cpu_id = smp_processor_id();
	rht_node = rhashtable_lookup(dd->sdma_rht, &cpu_id,
				     sdma_rht_params);

	if (rht_node && rht_node->map[vl]) {
		struct sdma_rht_map_elem *map = rht_node->map[vl];

		sde = map->sde[selector & map->mask];
	}
	rcu_read_unlock();

	if (sde)
		return sde;

out:
	return sdma_select_engine_vl(dd, selector, vl);
}

static void sdma_populate_sde_map(struct sdma_rht_map_elem *map)
{
	int i;

	for (i = 0; i < roundup_pow_of_two(map->ctr ? : 1) - map->ctr; i++)
		map->sde[map->ctr + i] = map->sde[i];
}

static void sdma_cleanup_sde_map(struct sdma_rht_map_elem *map,
				 struct sdma_engine *sde)
{
	unsigned int i, pow;

	/* only need to check the first ctr entries for a match */
	for (i = 0; i < map->ctr; i++) {
		if (map->sde[i] == sde) {
			memmove(&map->sde[i], &map->sde[i + 1],
				(map->ctr - i - 1) * sizeof(map->sde[0]));
			map->ctr--;
			pow = roundup_pow_of_two(map->ctr ? : 1);
			map->mask = pow - 1;
			sdma_populate_sde_map(map);

Annotation

Implementation Notes