drivers/of/overlay.c

Source file repositories/reference/linux-study-clean/drivers/of/overlay.c

File Facts

System
Linux kernel
Corpus path
drivers/of/overlay.c
Extension
.c
Size
36572 bytes
Lines
1299
Domain
Driver Families
Bucket
drivers/of
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 target {
	struct device_node *np;
	bool in_livetree;
};

/**
 * struct fragment - info about fragment nodes in overlay expanded device tree
 * @overlay:	pointer to the __overlay__ node
 * @target:	target of the overlay operation
 */
struct fragment {
	struct device_node *overlay;
	struct device_node *target;
};

/**
 * struct overlay_changeset
 * @id:			changeset identifier
 * @ovcs_list:		list on which we are located
 * @new_fdt:		Memory allocated to hold unflattened aligned FDT
 * @overlay_mem:	the memory chunk that contains @overlay_root
 * @overlay_root:	expanded device tree that contains the fragment nodes
 * @notify_state:	most recent notify action used on overlay
 * @count:		count of fragment structures
 * @fragments:		fragment nodes in the overlay expanded device tree
 * @symbols_fragment:	last element of @fragments[] is the  __symbols__ node
 * @cset:		changeset to apply fragments to live device tree
 */
struct overlay_changeset {
	int id;
	struct list_head ovcs_list;
	const void *new_fdt;
	const void *overlay_mem;
	struct device_node *overlay_root;
	enum of_overlay_notify_action notify_state;
	int count;
	struct fragment *fragments;
	bool symbols_fragment;
	struct of_changeset cset;
};

/* flags are sticky - once set, do not reset */
static int devicetree_state_flags;
#define DTSF_APPLY_FAIL		0x01
#define DTSF_REVERT_FAIL	0x02

static int of_prop_val_eq(const struct property *p1, const struct property *p2)
{
	return p1->length == p2->length &&
	       !memcmp(p1->value, p2->value, (size_t)p1->length);
}

/*
 * If a changeset apply or revert encounters an error, an attempt will
 * be made to undo partial changes, but may fail.  If the undo fails
 * we do not know the state of the devicetree.
 */
static int devicetree_corrupt(void)
{
	return devicetree_state_flags &
		(DTSF_APPLY_FAIL | DTSF_REVERT_FAIL);
}

static int build_changeset_next_level(struct overlay_changeset *ovcs,
		struct target *target, const struct device_node *overlay_node);

/*
 * of_resolve_phandles() finds the largest phandle in the live tree.
 * of_overlay_apply() may add a larger phandle to the live tree.
 * Do not allow race between two overlays being applied simultaneously:
 *    mutex_lock(&of_overlay_phandle_mutex)
 *    of_resolve_phandles()
 *    of_overlay_apply()
 *    mutex_unlock(&of_overlay_phandle_mutex)
 */
static DEFINE_MUTEX(of_overlay_phandle_mutex);

void of_overlay_mutex_lock(void)
{
	mutex_lock(&of_overlay_phandle_mutex);
}

void of_overlay_mutex_unlock(void)
{
	mutex_unlock(&of_overlay_phandle_mutex);
}

static LIST_HEAD(ovcs_list);
static DEFINE_IDR(ovcs_idr);

Annotation

Implementation Notes