drivers/infiniband/sw/rdmavt/mr.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/sw/rdmavt/mr.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/sw/rdmavt/mr.c
Extension
.c
Size
21409 bytes
Lines
923
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (!tmr) {
			mr->lkey_published = 1;
			/* Insure published written first */
			rcu_assign_pointer(dev->dma_mr, mr);
			rvt_get_mr(mr);
		}
		goto success;
	}

	/* Find the next available LKEY */
	r = rkt->next;
	n = r;
	for (;;) {
		if (!rcu_access_pointer(rkt->table[r]))
			break;
		r = (r + 1) & (rkt->max - 1);
		if (r == n)
			goto bail;
	}
	rkt->next = (r + 1) & (rkt->max - 1);
	/*
	 * Make sure lkey is never zero which is reserved to indicate an
	 * unrestricted LKEY.
	 */
	rkt->gen++;
	/*
	 * bits are capped to ensure enough bits for generation number
	 */
	mr->lkey = (r << (32 - dev->dparms.lkey_table_size)) |
		((((1 << (24 - dev->dparms.lkey_table_size)) - 1) & rkt->gen)
		 << 8);
	if (mr->lkey == 0) {
		mr->lkey |= 1 << 8;
		rkt->gen++;
	}
	mr->lkey_published = 1;
	/* Insure published written first */
	rcu_assign_pointer(rkt->table[r], mr);
success:
	spin_unlock_irqrestore(&rkt->lock, flags);
out:
	return ret;
bail:
	rvt_put_mr(mr);
	spin_unlock_irqrestore(&rkt->lock, flags);
	ret = -ENOMEM;
	goto out;
}

/**
 * rvt_free_lkey - free an lkey
 * @mr: mr to free from tables
 */
static void rvt_free_lkey(struct rvt_mregion *mr)
{
	unsigned long flags;
	u32 lkey = mr->lkey;
	u32 r;
	struct rvt_dev_info *dev = ib_to_rvt(mr->pd->device);
	struct rvt_lkey_table *rkt = &dev->lkey_table;
	int freed = 0;

	spin_lock_irqsave(&rkt->lock, flags);
	if (!lkey) {
		if (mr->lkey_published) {
			mr->lkey_published = 0;
			/* insure published is written before pointer */
			rcu_assign_pointer(dev->dma_mr, NULL);
			rvt_put_mr(mr);
		}
	} else {
		if (!mr->lkey_published)
			goto out;
		r = lkey >> (32 - dev->dparms.lkey_table_size);
		mr->lkey_published = 0;
		/* insure published is written before pointer */
		rcu_assign_pointer(rkt->table[r], NULL);
	}
	freed++;
out:
	spin_unlock_irqrestore(&rkt->lock, flags);
	if (freed)
		percpu_ref_kill(&mr->refcount);
}

static struct rvt_mr *__rvt_alloc_mr(int count, struct ib_pd *pd)
{
	struct rvt_mr *mr;
	int rval = -ENOMEM;
	int m;

Annotation

Implementation Notes