drivers/firmware/arm_sdei.c

Source file repositories/reference/linux-study-clean/drivers/firmware/arm_sdei.c

File Facts

System
Linux kernel
Corpus path
drivers/firmware/arm_sdei.c
Extension
.c
Size
24455 bytes
Lines
1122
Domain
Driver Families
Bucket
drivers/firmware
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 sdei_event {
	/* These three are protected by the sdei_list_lock */
	struct list_head	list;
	bool			reregister;
	bool			reenable;

	u32			event_num;
	u8			type;
	u8			priority;

	/* This pointer is handed to firmware as the event argument. */
	union {
		/* Shared events */
		struct sdei_registered_event *registered;

		/* CPU private events */
		struct sdei_registered_event __percpu *private_registered;
	};
};

/* Take the mutex for any API call or modification. Take the mutex first. */
static DEFINE_MUTEX(sdei_events_lock);

/* and then hold this when modifying the list */
static DEFINE_SPINLOCK(sdei_list_lock);
static LIST_HEAD(sdei_list);

/* Private events are registered/enabled via IPI passing one of these */
struct sdei_crosscall_args {
	struct sdei_event *event;
	atomic_t errors;
	int first_error;
};

#define CROSSCALL_INIT(arg, event)		\
	do {					\
		arg.event = event;		\
		arg.first_error = 0;		\
		atomic_set(&arg.errors, 0);	\
	} while (0)

static inline int sdei_do_local_call(smp_call_func_t fn,
				     struct sdei_event *event)
{
	struct sdei_crosscall_args arg;

	CROSSCALL_INIT(arg, event);
	fn(&arg);

	return arg.first_error;
}

static inline int sdei_do_cross_call(smp_call_func_t fn,
				     struct sdei_event *event)
{
	struct sdei_crosscall_args arg;

	CROSSCALL_INIT(arg, event);
	on_each_cpu(fn, &arg, true);

	return arg.first_error;
}

static inline void
sdei_cross_call_return(struct sdei_crosscall_args *arg, int err)
{
	if (err && (atomic_inc_return(&arg->errors) == 1))
		arg->first_error = err;
}

static int sdei_to_linux_errno(unsigned long sdei_err)
{
	switch (sdei_err) {
	case SDEI_NOT_SUPPORTED:
		return -EOPNOTSUPP;
	case SDEI_INVALID_PARAMETERS:
		return -EINVAL;
	case SDEI_DENIED:
		return -EPERM;
	case SDEI_PENDING:
		return -EINPROGRESS;
	case SDEI_OUT_OF_RESOURCE:
		return -ENOMEM;
	}

	return 0;
}

static int invoke_sdei_fn(unsigned long function_id, unsigned long arg0,
			  unsigned long arg1, unsigned long arg2,

Annotation

Implementation Notes