drivers/tee/optee/notif.c

Source file repositories/reference/linux-study-clean/drivers/tee/optee/notif.c

File Facts

System
Linux kernel
Corpus path
drivers/tee/optee/notif.c
Extension
.c
Size
2620 bytes
Lines
131
Domain
Driver Families
Bucket
drivers/tee
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 notif_entry {
	struct list_head link;
	struct completion c;
	u_int key;
};

static bool have_key(struct optee *optee, u_int key)
{
	struct notif_entry *entry;

	list_for_each_entry(entry, &optee->notif.db, link)
		if (entry->key == key)
			return true;

	return false;
}

int optee_notif_wait(struct optee *optee, u_int key, u32 timeout)
{
	unsigned long flags;
	struct notif_entry *entry;
	int rc = 0;

	if (key > optee->notif.max_key)
		return -EINVAL;

	entry = kmalloc_obj(*entry);
	if (!entry)
		return -ENOMEM;
	init_completion(&entry->c);
	entry->key = key;

	spin_lock_irqsave(&optee->notif.lock, flags);

	/*
	 * If the bit is already set it means that the key has already
	 * been posted and we must not wait.
	 */
	if (test_bit(key, optee->notif.bitmap)) {
		clear_bit(key, optee->notif.bitmap);
		goto out;
	}

	/*
	 * Check if someone is already waiting for this key. If there is
	 * it's a programming error.
	 */
	if (have_key(optee, key)) {
		rc = -EBUSY;
		goto out;
	}

	list_add_tail(&entry->link, &optee->notif.db);

	/*
	 * Unlock temporarily and wait for completion.
	 */
	spin_unlock_irqrestore(&optee->notif.lock, flags);
	if (timeout != 0) {
		if (!wait_for_completion_timeout(&entry->c, timeout))
			rc = -ETIMEDOUT;
	} else {
		wait_for_completion(&entry->c);
	}
	spin_lock_irqsave(&optee->notif.lock, flags);

	list_del(&entry->link);
out:
	spin_unlock_irqrestore(&optee->notif.lock, flags);

	kfree(entry);

	return rc;
}

int optee_notif_send(struct optee *optee, u_int key)
{
	unsigned long flags;
	struct notif_entry *entry;

	if (key > optee->notif.max_key)
		return -EINVAL;

	spin_lock_irqsave(&optee->notif.lock, flags);

	list_for_each_entry(entry, &optee->notif.db, link)
		if (entry->key == key) {
			complete(&entry->c);
			goto out;
		}

Annotation

Implementation Notes