drivers/misc/bcm-vk/bcm_vk_msg.c

Source file repositories/reference/linux-study-clean/drivers/misc/bcm-vk/bcm_vk_msg.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/bcm-vk/bcm_vk_msg.c
Extension
.c
Size
35330 bytes
Lines
1357
Domain
Driver Families
Bucket
drivers/misc
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 (!vk->ctx[i].in_use) {
			vk->ctx[i].in_use = true;
			ctx = &vk->ctx[i];
			break;
		}
	}

	if (!ctx) {
		dev_err(&vk->pdev->dev, "All context in use\n");

		goto all_in_use_exit;
	}

	/* set the pid and insert it to hash table */
	ctx->pid = pid;
	ctx->hash_idx = hash_idx;
	list_add_tail(&ctx->node, &vk->pid_ht[hash_idx].head);

	/* increase kref */
	kref_get(&vk->kref);

	/* clear counter */
	atomic_set(&ctx->pend_cnt, 0);
	atomic_set(&ctx->dma_cnt, 0);
	init_waitqueue_head(&ctx->rd_wq);

all_in_use_exit:
in_reset_exit:
	spin_unlock(&vk->ctx_lock);

	return ctx;
}

static u16 bcm_vk_get_msg_id(struct bcm_vk *vk)
{
	u16 rc = VK_MSG_ID_OVERFLOW;
	u16 test_bit_count = 0;

	spin_lock(&vk->msg_id_lock);
	while (test_bit_count < (VK_MSG_ID_BITMAP_SIZE - 1)) {
		/*
		 * first time come in this loop, msg_id will be 0
		 * and the first one tested will be 1.  We skip
		 * VK_SIMPLEX_MSG_ID (0) for one way host2vk
		 * communication
		 */
		vk->msg_id++;
		if (vk->msg_id == VK_MSG_ID_BITMAP_SIZE)
			vk->msg_id = 1;

		if (test_bit(vk->msg_id, vk->bmap)) {
			test_bit_count++;
			continue;
		}
		rc = vk->msg_id;
		bitmap_set(vk->bmap, vk->msg_id, 1);
		break;
	}
	spin_unlock(&vk->msg_id_lock);

	return rc;
}

static int bcm_vk_free_ctx(struct bcm_vk *vk, struct bcm_vk_ctx *ctx)
{
	u32 idx;
	u32 hash_idx;
	pid_t pid;
	struct bcm_vk_ctx *entry;
	int count = 0;

	if (!ctx) {
		dev_err(&vk->pdev->dev, "NULL context detected\n");
		return -EINVAL;
	}
	idx = ctx->idx;
	pid = ctx->pid;

	spin_lock(&vk->ctx_lock);

	if (!vk->ctx[idx].in_use) {
		dev_err(&vk->pdev->dev, "context[%d] not in use!\n", idx);
	} else {
		vk->ctx[idx].in_use = false;
		vk->ctx[idx].miscdev = NULL;

		/* Remove it from hash list and see if it is the last one. */
		list_del(&ctx->node);
		hash_idx = ctx->hash_idx;
		list_for_each_entry(entry, &vk->pid_ht[hash_idx].head, node) {

Annotation

Implementation Notes