drivers/base/swnode.c

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

File Facts

System
Linux kernel
Corpus path
drivers/base/swnode.c
Extension
.c
Size
27706 bytes
Lines
1144
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 swnode {
	struct kobject kobj;
	struct fwnode_handle fwnode;
	const struct software_node *node;
	int id;

	/* hierarchy */
	struct ida child_ids;
	struct list_head entry;
	struct list_head children;
	struct swnode *parent;

	unsigned int allocated:1;
	unsigned int managed:1;
};

static DEFINE_IDA(swnode_root_ids);
static struct kset *swnode_kset;

#define kobj_to_swnode(_kobj_) container_of(_kobj_, struct swnode, kobj)

static const struct fwnode_operations software_node_ops;

bool is_software_node(const struct fwnode_handle *fwnode)
{
	return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops;
}
EXPORT_SYMBOL_GPL(is_software_node);

#define to_swnode(__fwnode)						\
	({								\
		typeof(__fwnode) __to_swnode_fwnode = __fwnode;		\
									\
		is_software_node(__to_swnode_fwnode) ?			\
			container_of(__to_swnode_fwnode,		\
				     struct swnode, fwnode) : NULL;	\
	})

static inline struct swnode *dev_to_swnode(struct device *dev)
{
	struct fwnode_handle *fwnode = dev_fwnode(dev);

	if (!fwnode)
		return NULL;

	if (!is_software_node(fwnode))
		fwnode = fwnode->secondary;

	return to_swnode(fwnode);
}

static struct swnode *
software_node_to_swnode(const struct software_node *node)
{
	struct swnode *swnode = NULL;
	struct kobject *k;

	if (!node)
		return NULL;

	spin_lock(&swnode_kset->list_lock);

	list_for_each_entry(k, &swnode_kset->list, entry) {
		swnode = kobj_to_swnode(k);
		if (swnode->node == node)
			break;
		swnode = NULL;
	}

	spin_unlock(&swnode_kset->list_lock);

	return swnode;
}

const struct software_node *to_software_node(const struct fwnode_handle *fwnode)
{
	const struct swnode *swnode = to_swnode(fwnode);

	return swnode ? swnode->node : NULL;
}
EXPORT_SYMBOL_GPL(to_software_node);

struct fwnode_handle *software_node_fwnode(const struct software_node *node)
{
	struct swnode *swnode = software_node_to_swnode(node);

	return swnode ? &swnode->fwnode : NULL;
}
EXPORT_SYMBOL_GPL(software_node_fwnode);

Annotation

Implementation Notes