drivers/infiniband/hw/cxgb4/resource.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/cxgb4/resource.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/cxgb4/resource.c
Extension
.c
Size
13581 bytes
Lines
517
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

if (!qid) {
			mutex_lock(&rdev->stats.lock);
			rdev->stats.qid.fail++;
			mutex_unlock(&rdev->stats.lock);
			goto out;
		}
		mutex_lock(&rdev->stats.lock);
		rdev->stats.qid.cur += rdev->qpmask + 1;
		mutex_unlock(&rdev->stats.lock);
		for (i = qid+1; i & rdev->qpmask; i++) {
			entry = kmalloc_obj(*entry);
			if (!entry)
				goto out;
			entry->qid = i;
			list_add_tail(&entry->entry, &uctx->qpids);
		}

		/*
		 * now put the same ids on the cq list since they all
		 * map to the same db/gts page.
		 */
		entry = kmalloc_obj(*entry);
		if (!entry)
			goto out;
		entry->qid = qid;
		list_add_tail(&entry->entry, &uctx->cqids);
		for (i = qid + 1; i & rdev->qpmask; i++) {
			entry = kmalloc_obj(*entry);
			if (!entry)
				goto out;
			entry->qid = i;
			list_add_tail(&entry->entry, &uctx->cqids);
		}
	}
out:
	mutex_unlock(&uctx->lock);
	pr_debug("qid 0x%x\n", qid);
	mutex_lock(&rdev->stats.lock);
	if (rdev->stats.qid.cur > rdev->stats.qid.max)
		rdev->stats.qid.max = rdev->stats.qid.cur;
	mutex_unlock(&rdev->stats.lock);
	return qid;
}

void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qid,
		   struct c4iw_dev_ucontext *uctx)
{
	struct c4iw_qid_list *entry;

	entry = kmalloc_obj(*entry);
	if (!entry)
		return;
	pr_debug("qid 0x%x\n", qid);
	entry->qid = qid;
	mutex_lock(&uctx->lock);
	list_add_tail(&entry->entry, &uctx->qpids);
	mutex_unlock(&uctx->lock);
}

void c4iw_destroy_resource(struct c4iw_resource *rscp)
{
	c4iw_id_table_free(&rscp->tpt_table);
	c4iw_id_table_free(&rscp->qid_table);
	c4iw_id_table_free(&rscp->pdid_table);
}

/*
 * PBL Memory Manager.  Uses Linux generic allocator.
 */

#define MIN_PBL_SHIFT 8			/* 256B == min PBL size (32 entries) */

u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
{
	unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
	pr_debug("addr 0x%x size %d\n", (u32)addr, size);
	mutex_lock(&rdev->stats.lock);
	if (addr) {
		rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT);
		if (rdev->stats.pbl.cur > rdev->stats.pbl.max)
			rdev->stats.pbl.max = rdev->stats.pbl.cur;
		kref_get(&rdev->pbl_kref);
	} else
		rdev->stats.pbl.fail++;
	mutex_unlock(&rdev->stats.lock);
	return (u32)addr;
}

static void destroy_pblpool(struct kref *kref)
{

Annotation

Implementation Notes