drivers/tee/qcomtee/user_obj.c

Source file repositories/reference/linux-study-clean/drivers/tee/qcomtee/user_obj.c

File Facts

System
Linux kernel
Corpus path
drivers/tee/qcomtee/user_obj.c
Extension
.c
Size
19107 bytes
Lines
693
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 qcomtee_user_object {
	struct qcomtee_object object;
	struct tee_context *ctx;
	u64 object_id;
	bool notify;
};

#define to_qcomtee_user_object(o) \
	container_of((o), struct qcomtee_user_object, object)

static struct qcomtee_object_operations qcomtee_user_object_ops;

/* Is it a user object? */
int is_qcomtee_user_object(struct qcomtee_object *object)
{
	return object != NULL_QCOMTEE_OBJECT &&
	       typeof_qcomtee_object(object) == QCOMTEE_OBJECT_TYPE_CB &&
	       object->ops == &qcomtee_user_object_ops;
}

/* Set the user object's 'notify on release' flag. */
void qcomtee_user_object_set_notify(struct qcomtee_object *object, bool notify)
{
	if (is_qcomtee_user_object(object))
		to_qcomtee_user_object(object)->notify = notify;
}

/* Supplicant Requests: */

/**
 * enum qcomtee_req_state - Current state of request.
 * @QCOMTEE_REQ_QUEUED: Request is waiting for supplicant.
 * @QCOMTEE_REQ_PROCESSING: Request has been picked by the supplicant.
 * @QCOMTEE_REQ_PROCESSED: Response has been submitted for the request.
 */
enum qcomtee_req_state {
	QCOMTEE_REQ_QUEUED = 1,
	QCOMTEE_REQ_PROCESSING,
	QCOMTEE_REQ_PROCESSED,
};

/* User requests sent to supplicants. */
struct qcomtee_ureq {
	enum qcomtee_req_state state;

	/* User Request: */
	int req_id;
	u64 object_id;
	u32 op;
	struct qcomtee_arg *args;
	int errno;

	struct list_head node;
	struct completion c; /* Completion for whoever wait. */
};

/*
 * Placeholder for a PROCESSING request in qcomtee_context.reqs_idr.
 *
 * If the thread that calls qcomtee_object_invoke() dies and the supplicant
 * is processing the request, replace the entry in qcomtee_context.reqs_idr
 * with empty_ureq. This ensures that (1) the req_id remains busy and is not
 * reused, and (2) the supplicant fails to submit the response and performs
 * the necessary rollback.
 */
static struct qcomtee_ureq empty_ureq = { .state = QCOMTEE_REQ_PROCESSING };

/* Enqueue a user request for a context and assign a request ID. */
static int ureq_enqueue(struct qcomtee_context_data *ctxdata,
			struct qcomtee_ureq *ureq)
{
	int ret;

	guard(mutex)(&ctxdata->reqs_lock);
	/* Supplicant is dying. */
	if (ctxdata->released)
		return -ENODEV;

	/* Allocate an ID and queue the request. */
	ret = idr_alloc(&ctxdata->reqs_idr, ureq, 0, 0, GFP_KERNEL);
	if (ret < 0)
		return ret;

	ureq->req_id = ret;
	ureq->state = QCOMTEE_REQ_QUEUED;
	list_add_tail(&ureq->node, &ctxdata->reqs_list);

	return 0;
}

Annotation

Implementation Notes