drivers/base/firmware_loader/main.c

Source file repositories/reference/linux-study-clean/drivers/base/firmware_loader/main.c

File Facts

System
Linux kernel
Corpus path
drivers/base/firmware_loader/main.c
Extension
.c
Size
44500 bytes
Lines
1746
Domain
Driver Families
Bucket
drivers/base
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 firmware_cache {
	/* firmware_buf instance will be added into the below list */
	spinlock_t lock;
	struct list_head head;
	int state;

#ifdef CONFIG_FW_CACHE
	/*
	 * Names of firmware images which have been cached successfully
	 * will be added into the below list so that device uncache
	 * helper can trace which firmware images have been cached
	 * before.
	 */
	spinlock_t name_lock;
	struct list_head fw_names;

	struct delayed_work work;

	struct notifier_block   pm_notify;
#endif
};

struct fw_cache_entry {
	struct list_head list;
	const char *name;
};

struct fw_name_devm {
	unsigned long magic;
	const char *name;
};

static inline struct fw_priv *to_fw_priv(struct kref *ref)
{
	return container_of(ref, struct fw_priv, ref);
}

#define	FW_LOADER_NO_CACHE	0
#define	FW_LOADER_START_CACHE	1

/* fw_lock could be moved to 'struct fw_sysfs' but since it is just
 * guarding for corner cases a global lock should be OK */
DEFINE_MUTEX(fw_lock);

struct firmware_cache fw_cache;
bool fw_load_abort_all;

void fw_state_init(struct fw_priv *fw_priv)
{
	struct fw_state *fw_st = &fw_priv->fw_st;

	init_completion(&fw_st->completion);
	fw_st->status = FW_STATUS_UNKNOWN;
}

static inline int fw_state_wait(struct fw_priv *fw_priv)
{
	return __fw_state_wait_common(fw_priv, MAX_SCHEDULE_TIMEOUT);
}

static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv);

static struct fw_priv *__allocate_fw_priv(const char *fw_name,
					  struct firmware_cache *fwc,
					  void *dbuf,
					  size_t size,
					  size_t offset,
					  u32 opt_flags)
{
	struct fw_priv *fw_priv;

	/* For a partial read, the buffer must be preallocated. */
	if ((opt_flags & FW_OPT_PARTIAL) && !dbuf)
		return NULL;

	/* Only partial reads are allowed to use an offset. */
	if (offset != 0 && !(opt_flags & FW_OPT_PARTIAL))
		return NULL;

	fw_priv = kzalloc_obj(*fw_priv, GFP_ATOMIC);
	if (!fw_priv)
		return NULL;

	fw_priv->fw_name = kstrdup_const(fw_name, GFP_ATOMIC);
	if (!fw_priv->fw_name) {
		kfree(fw_priv);
		return NULL;
	}

	kref_init(&fw_priv->ref);

Annotation

Implementation Notes