drivers/acpi/device_sysfs.c

Source file repositories/reference/linux-study-clean/drivers/acpi/device_sysfs.c

File Facts

System
Linux kernel
Corpus path
drivers/acpi/device_sysfs.c
Extension
.c
Size
16402 bytes
Lines
652
Domain
Driver Families
Bucket
drivers/acpi
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 acpi_data_node_attr {
	struct attribute attr;
	ssize_t (*show)(struct acpi_data_node *, char *);
	ssize_t (*store)(struct acpi_data_node *, const char *, size_t count);
};

#define DATA_NODE_ATTR(_name)			\
	static struct acpi_data_node_attr data_node_##_name =	\
		__ATTR(_name, 0444, data_node_show_##_name, NULL)

static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf)
{
	return dn->handle ? acpi_object_path(dn->handle, buf) : 0;
}

DATA_NODE_ATTR(path);

static struct attribute *acpi_data_node_default_attrs[] = {
	&data_node_path.attr,
	NULL
};
ATTRIBUTE_GROUPS(acpi_data_node_default);

#define to_data_node(k) container_of(k, struct acpi_data_node, kobj)
#define to_attr(a) container_of(a, struct acpi_data_node_attr, attr)

static ssize_t acpi_data_node_attr_show(struct kobject *kobj,
					struct attribute *attr, char *buf)
{
	struct acpi_data_node *dn = to_data_node(kobj);
	struct acpi_data_node_attr *dn_attr = to_attr(attr);

	return dn_attr->show ? dn_attr->show(dn, buf) : -ENXIO;
}

static const struct sysfs_ops acpi_data_node_sysfs_ops = {
	.show	= acpi_data_node_attr_show,
};

static void acpi_data_node_release(struct kobject *kobj)
{
	struct acpi_data_node *dn = to_data_node(kobj);

	complete(&dn->kobj_done);
}

static const struct kobj_type acpi_data_node_ktype = {
	.sysfs_ops = &acpi_data_node_sysfs_ops,
	.default_groups = acpi_data_node_default_groups,
	.release = acpi_data_node_release,
};

static void acpi_expose_nondev_subnodes(struct kobject *kobj,
					struct acpi_device_data *data)
{
	struct list_head *list = &data->subnodes;
	struct acpi_data_node *dn;

	if (list_empty(list))
		return;

	list_for_each_entry(dn, list, sibling) {
		int ret;

		init_completion(&dn->kobj_done);
		ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype,
					   kobj, "%s", dn->name);
		if (!ret)
			acpi_expose_nondev_subnodes(&dn->kobj, &dn->data);
		else if (dn->handle)
			acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
	}
}

static void acpi_hide_nondev_subnodes(struct acpi_device_data *data)
{
	struct list_head *list = &data->subnodes;
	struct acpi_data_node *dn;

	if (list_empty(list))
		return;

	list_for_each_entry_reverse(dn, list, sibling) {
		acpi_hide_nondev_subnodes(&dn->data);
		kobject_put(&dn->kobj);
	}
}

/**
 * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent

Annotation

Implementation Notes