18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * class.c - basic device class management
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2002-3 Patrick Mochel
68c2ecf20Sopenharmony_ci * Copyright (c) 2002-3 Open Source Development Labs
78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2004 Greg Kroah-Hartman
88c2ecf20Sopenharmony_ci * Copyright (c) 2003-2004 IBM Corp.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/device/class.h>
128c2ecf20Sopenharmony_ci#include <linux/device.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/init.h>
158c2ecf20Sopenharmony_ci#include <linux/string.h>
168c2ecf20Sopenharmony_ci#include <linux/kdev_t.h>
178c2ecf20Sopenharmony_ci#include <linux/err.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/genhd.h>
208c2ecf20Sopenharmony_ci#include <linux/mutex.h>
218c2ecf20Sopenharmony_ci#include "base.h"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
268c2ecf20Sopenharmony_ci			       char *buf)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	struct class_attribute *class_attr = to_class_attr(attr);
298c2ecf20Sopenharmony_ci	struct subsys_private *cp = to_subsys_private(kobj);
308c2ecf20Sopenharmony_ci	ssize_t ret = -EIO;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	if (class_attr->show)
338c2ecf20Sopenharmony_ci		ret = class_attr->show(cp->class, class_attr, buf);
348c2ecf20Sopenharmony_ci	return ret;
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
388c2ecf20Sopenharmony_ci				const char *buf, size_t count)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	struct class_attribute *class_attr = to_class_attr(attr);
418c2ecf20Sopenharmony_ci	struct subsys_private *cp = to_subsys_private(kobj);
428c2ecf20Sopenharmony_ci	ssize_t ret = -EIO;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	if (class_attr->store)
458c2ecf20Sopenharmony_ci		ret = class_attr->store(cp->class, class_attr, buf, count);
468c2ecf20Sopenharmony_ci	return ret;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic void class_release(struct kobject *kobj)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	struct subsys_private *cp = to_subsys_private(kobj);
528c2ecf20Sopenharmony_ci	struct class *class = cp->class;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	pr_debug("class '%s': release.\n", class->name);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	if (class->class_release)
578c2ecf20Sopenharmony_ci		class->class_release(class);
588c2ecf20Sopenharmony_ci	else
598c2ecf20Sopenharmony_ci		pr_debug("class '%s' does not have a release() function, "
608c2ecf20Sopenharmony_ci			 "be careful\n", class->name);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	kfree(cp);
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic const struct kobj_ns_type_operations *class_child_ns_type(struct kobject *kobj)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	struct subsys_private *cp = to_subsys_private(kobj);
688c2ecf20Sopenharmony_ci	struct class *class = cp->class;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return class->ns_type;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic const struct sysfs_ops class_sysfs_ops = {
748c2ecf20Sopenharmony_ci	.show	   = class_attr_show,
758c2ecf20Sopenharmony_ci	.store	   = class_attr_store,
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic struct kobj_type class_ktype = {
798c2ecf20Sopenharmony_ci	.sysfs_ops	= &class_sysfs_ops,
808c2ecf20Sopenharmony_ci	.release	= class_release,
818c2ecf20Sopenharmony_ci	.child_ns_type	= class_child_ns_type,
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/* Hotplug events for classes go to the class subsys */
858c2ecf20Sopenharmony_cistatic struct kset *class_kset;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ciint class_create_file_ns(struct class *cls, const struct class_attribute *attr,
898c2ecf20Sopenharmony_ci			 const void *ns)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	int error;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (cls)
948c2ecf20Sopenharmony_ci		error = sysfs_create_file_ns(&cls->p->subsys.kobj,
958c2ecf20Sopenharmony_ci					     &attr->attr, ns);
968c2ecf20Sopenharmony_ci	else
978c2ecf20Sopenharmony_ci		error = -EINVAL;
988c2ecf20Sopenharmony_ci	return error;
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_civoid class_remove_file_ns(struct class *cls, const struct class_attribute *attr,
1028c2ecf20Sopenharmony_ci			  const void *ns)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	if (cls)
1058c2ecf20Sopenharmony_ci		sysfs_remove_file_ns(&cls->p->subsys.kobj, &attr->attr, ns);
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic struct class *class_get(struct class *cls)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	if (cls)
1118c2ecf20Sopenharmony_ci		kset_get(&cls->p->subsys);
1128c2ecf20Sopenharmony_ci	return cls;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic void class_put(struct class *cls)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	if (cls)
1188c2ecf20Sopenharmony_ci		kset_put(&cls->p->subsys);
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic struct device *klist_class_to_dev(struct klist_node *n)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	struct device_private *p = to_device_private_class(n);
1248c2ecf20Sopenharmony_ci	return p->device;
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic void klist_class_dev_get(struct klist_node *n)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	struct device *dev = klist_class_to_dev(n);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	get_device(dev);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic void klist_class_dev_put(struct klist_node *n)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	struct device *dev = klist_class_to_dev(n);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	put_device(dev);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic int class_add_groups(struct class *cls,
1428c2ecf20Sopenharmony_ci			    const struct attribute_group **groups)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	return sysfs_create_groups(&cls->p->subsys.kobj, groups);
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic void class_remove_groups(struct class *cls,
1488c2ecf20Sopenharmony_ci				const struct attribute_group **groups)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	return sysfs_remove_groups(&cls->p->subsys.kobj, groups);
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ciint __class_register(struct class *cls, struct lock_class_key *key)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	struct subsys_private *cp;
1568c2ecf20Sopenharmony_ci	int error;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	pr_debug("device class '%s': registering\n", cls->name);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
1618c2ecf20Sopenharmony_ci	if (!cp)
1628c2ecf20Sopenharmony_ci		return -ENOMEM;
1638c2ecf20Sopenharmony_ci	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
1648c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&cp->interfaces);
1658c2ecf20Sopenharmony_ci	kset_init(&cp->glue_dirs);
1668c2ecf20Sopenharmony_ci	__mutex_init(&cp->mutex, "subsys mutex", key);
1678c2ecf20Sopenharmony_ci	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
1688c2ecf20Sopenharmony_ci	if (error) {
1698c2ecf20Sopenharmony_ci		kfree(cp);
1708c2ecf20Sopenharmony_ci		return error;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	/* set the default /sys/dev directory for devices of this class */
1748c2ecf20Sopenharmony_ci	if (!cls->dev_kobj)
1758c2ecf20Sopenharmony_ci		cls->dev_kobj = sysfs_dev_char_kobj;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci#if defined(CONFIG_BLOCK)
1788c2ecf20Sopenharmony_ci	/* let the block class directory show up in the root of sysfs */
1798c2ecf20Sopenharmony_ci	if (!sysfs_deprecated || cls != &block_class)
1808c2ecf20Sopenharmony_ci		cp->subsys.kobj.kset = class_kset;
1818c2ecf20Sopenharmony_ci#else
1828c2ecf20Sopenharmony_ci	cp->subsys.kobj.kset = class_kset;
1838c2ecf20Sopenharmony_ci#endif
1848c2ecf20Sopenharmony_ci	cp->subsys.kobj.ktype = &class_ktype;
1858c2ecf20Sopenharmony_ci	cp->class = cls;
1868c2ecf20Sopenharmony_ci	cls->p = cp;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	error = kset_register(&cp->subsys);
1898c2ecf20Sopenharmony_ci	if (error) {
1908c2ecf20Sopenharmony_ci		kfree(cp);
1918c2ecf20Sopenharmony_ci		return error;
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci	error = class_add_groups(class_get(cls), cls->class_groups);
1948c2ecf20Sopenharmony_ci	class_put(cls);
1958c2ecf20Sopenharmony_ci	if (error) {
1968c2ecf20Sopenharmony_ci		kobject_del(&cp->subsys.kobj);
1978c2ecf20Sopenharmony_ci		kfree_const(cp->subsys.kobj.name);
1988c2ecf20Sopenharmony_ci		kfree(cp);
1998c2ecf20Sopenharmony_ci	}
2008c2ecf20Sopenharmony_ci	return error;
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__class_register);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_civoid class_unregister(struct class *cls)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	pr_debug("device class '%s': unregistering\n", cls->name);
2078c2ecf20Sopenharmony_ci	class_remove_groups(cls, cls->class_groups);
2088c2ecf20Sopenharmony_ci	kset_unregister(&cls->p->subsys);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic void class_create_release(struct class *cls)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	pr_debug("%s called for %s\n", __func__, cls->name);
2148c2ecf20Sopenharmony_ci	kfree(cls);
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci/**
2188c2ecf20Sopenharmony_ci * class_create - create a struct class structure
2198c2ecf20Sopenharmony_ci * @owner: pointer to the module that is to "own" this struct class
2208c2ecf20Sopenharmony_ci * @name: pointer to a string for the name of this class.
2218c2ecf20Sopenharmony_ci * @key: the lock_class_key for this class; used by mutex lock debugging
2228c2ecf20Sopenharmony_ci *
2238c2ecf20Sopenharmony_ci * This is used to create a struct class pointer that can then be used
2248c2ecf20Sopenharmony_ci * in calls to device_create().
2258c2ecf20Sopenharmony_ci *
2268c2ecf20Sopenharmony_ci * Returns &struct class pointer on success, or ERR_PTR() on error.
2278c2ecf20Sopenharmony_ci *
2288c2ecf20Sopenharmony_ci * Note, the pointer created here is to be destroyed when finished by
2298c2ecf20Sopenharmony_ci * making a call to class_destroy().
2308c2ecf20Sopenharmony_ci */
2318c2ecf20Sopenharmony_cistruct class *__class_create(struct module *owner, const char *name,
2328c2ecf20Sopenharmony_ci			     struct lock_class_key *key)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct class *cls;
2358c2ecf20Sopenharmony_ci	int retval;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	cls = kzalloc(sizeof(*cls), GFP_KERNEL);
2388c2ecf20Sopenharmony_ci	if (!cls) {
2398c2ecf20Sopenharmony_ci		retval = -ENOMEM;
2408c2ecf20Sopenharmony_ci		goto error;
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	cls->name = name;
2448c2ecf20Sopenharmony_ci	cls->owner = owner;
2458c2ecf20Sopenharmony_ci	cls->class_release = class_create_release;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	retval = __class_register(cls, key);
2488c2ecf20Sopenharmony_ci	if (retval)
2498c2ecf20Sopenharmony_ci		goto error;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	return cls;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cierror:
2548c2ecf20Sopenharmony_ci	kfree(cls);
2558c2ecf20Sopenharmony_ci	return ERR_PTR(retval);
2568c2ecf20Sopenharmony_ci}
2578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__class_create);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci/**
2608c2ecf20Sopenharmony_ci * class_destroy - destroys a struct class structure
2618c2ecf20Sopenharmony_ci * @cls: pointer to the struct class that is to be destroyed
2628c2ecf20Sopenharmony_ci *
2638c2ecf20Sopenharmony_ci * Note, the pointer to be destroyed must have been created with a call
2648c2ecf20Sopenharmony_ci * to class_create().
2658c2ecf20Sopenharmony_ci */
2668c2ecf20Sopenharmony_civoid class_destroy(struct class *cls)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	if ((cls == NULL) || (IS_ERR(cls)))
2698c2ecf20Sopenharmony_ci		return;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	class_unregister(cls);
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci/**
2758c2ecf20Sopenharmony_ci * class_dev_iter_init - initialize class device iterator
2768c2ecf20Sopenharmony_ci * @iter: class iterator to initialize
2778c2ecf20Sopenharmony_ci * @class: the class we wanna iterate over
2788c2ecf20Sopenharmony_ci * @start: the device to start iterating from, if any
2798c2ecf20Sopenharmony_ci * @type: device_type of the devices to iterate over, NULL for all
2808c2ecf20Sopenharmony_ci *
2818c2ecf20Sopenharmony_ci * Initialize class iterator @iter such that it iterates over devices
2828c2ecf20Sopenharmony_ci * of @class.  If @start is set, the list iteration will start there,
2838c2ecf20Sopenharmony_ci * otherwise if it is NULL, the iteration starts at the beginning of
2848c2ecf20Sopenharmony_ci * the list.
2858c2ecf20Sopenharmony_ci */
2868c2ecf20Sopenharmony_civoid class_dev_iter_init(struct class_dev_iter *iter, struct class *class,
2878c2ecf20Sopenharmony_ci			 struct device *start, const struct device_type *type)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	struct klist_node *start_knode = NULL;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	if (start)
2928c2ecf20Sopenharmony_ci		start_knode = &start->p->knode_class;
2938c2ecf20Sopenharmony_ci	klist_iter_init_node(&class->p->klist_devices, &iter->ki, start_knode);
2948c2ecf20Sopenharmony_ci	iter->type = type;
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_dev_iter_init);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci/**
2998c2ecf20Sopenharmony_ci * class_dev_iter_next - iterate to the next device
3008c2ecf20Sopenharmony_ci * @iter: class iterator to proceed
3018c2ecf20Sopenharmony_ci *
3028c2ecf20Sopenharmony_ci * Proceed @iter to the next device and return it.  Returns NULL if
3038c2ecf20Sopenharmony_ci * iteration is complete.
3048c2ecf20Sopenharmony_ci *
3058c2ecf20Sopenharmony_ci * The returned device is referenced and won't be released till
3068c2ecf20Sopenharmony_ci * iterator is proceed to the next device or exited.  The caller is
3078c2ecf20Sopenharmony_ci * free to do whatever it wants to do with the device including
3088c2ecf20Sopenharmony_ci * calling back into class code.
3098c2ecf20Sopenharmony_ci */
3108c2ecf20Sopenharmony_cistruct device *class_dev_iter_next(struct class_dev_iter *iter)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	struct klist_node *knode;
3138c2ecf20Sopenharmony_ci	struct device *dev;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	while (1) {
3168c2ecf20Sopenharmony_ci		knode = klist_next(&iter->ki);
3178c2ecf20Sopenharmony_ci		if (!knode)
3188c2ecf20Sopenharmony_ci			return NULL;
3198c2ecf20Sopenharmony_ci		dev = klist_class_to_dev(knode);
3208c2ecf20Sopenharmony_ci		if (!iter->type || iter->type == dev->type)
3218c2ecf20Sopenharmony_ci			return dev;
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_dev_iter_next);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci/**
3278c2ecf20Sopenharmony_ci * class_dev_iter_exit - finish iteration
3288c2ecf20Sopenharmony_ci * @iter: class iterator to finish
3298c2ecf20Sopenharmony_ci *
3308c2ecf20Sopenharmony_ci * Finish an iteration.  Always call this function after iteration is
3318c2ecf20Sopenharmony_ci * complete whether the iteration ran till the end or not.
3328c2ecf20Sopenharmony_ci */
3338c2ecf20Sopenharmony_civoid class_dev_iter_exit(struct class_dev_iter *iter)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	klist_iter_exit(&iter->ki);
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_dev_iter_exit);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci/**
3408c2ecf20Sopenharmony_ci * class_for_each_device - device iterator
3418c2ecf20Sopenharmony_ci * @class: the class we're iterating
3428c2ecf20Sopenharmony_ci * @start: the device to start with in the list, if any.
3438c2ecf20Sopenharmony_ci * @data: data for the callback
3448c2ecf20Sopenharmony_ci * @fn: function to be called for each device
3458c2ecf20Sopenharmony_ci *
3468c2ecf20Sopenharmony_ci * Iterate over @class's list of devices, and call @fn for each,
3478c2ecf20Sopenharmony_ci * passing it @data.  If @start is set, the list iteration will start
3488c2ecf20Sopenharmony_ci * there, otherwise if it is NULL, the iteration starts at the
3498c2ecf20Sopenharmony_ci * beginning of the list.
3508c2ecf20Sopenharmony_ci *
3518c2ecf20Sopenharmony_ci * We check the return of @fn each time. If it returns anything
3528c2ecf20Sopenharmony_ci * other than 0, we break out and return that value.
3538c2ecf20Sopenharmony_ci *
3548c2ecf20Sopenharmony_ci * @fn is allowed to do anything including calling back into class
3558c2ecf20Sopenharmony_ci * code.  There's no locking restriction.
3568c2ecf20Sopenharmony_ci */
3578c2ecf20Sopenharmony_ciint class_for_each_device(struct class *class, struct device *start,
3588c2ecf20Sopenharmony_ci			  void *data, int (*fn)(struct device *, void *))
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	struct class_dev_iter iter;
3618c2ecf20Sopenharmony_ci	struct device *dev;
3628c2ecf20Sopenharmony_ci	int error = 0;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	if (!class)
3658c2ecf20Sopenharmony_ci		return -EINVAL;
3668c2ecf20Sopenharmony_ci	if (!class->p) {
3678c2ecf20Sopenharmony_ci		WARN(1, "%s called for class '%s' before it was initialized",
3688c2ecf20Sopenharmony_ci		     __func__, class->name);
3698c2ecf20Sopenharmony_ci		return -EINVAL;
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	class_dev_iter_init(&iter, class, start, NULL);
3738c2ecf20Sopenharmony_ci	while ((dev = class_dev_iter_next(&iter))) {
3748c2ecf20Sopenharmony_ci		error = fn(dev, data);
3758c2ecf20Sopenharmony_ci		if (error)
3768c2ecf20Sopenharmony_ci			break;
3778c2ecf20Sopenharmony_ci	}
3788c2ecf20Sopenharmony_ci	class_dev_iter_exit(&iter);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	return error;
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_for_each_device);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci/**
3858c2ecf20Sopenharmony_ci * class_find_device - device iterator for locating a particular device
3868c2ecf20Sopenharmony_ci * @class: the class we're iterating
3878c2ecf20Sopenharmony_ci * @start: Device to begin with
3888c2ecf20Sopenharmony_ci * @data: data for the match function
3898c2ecf20Sopenharmony_ci * @match: function to check device
3908c2ecf20Sopenharmony_ci *
3918c2ecf20Sopenharmony_ci * This is similar to the class_for_each_dev() function above, but it
3928c2ecf20Sopenharmony_ci * returns a reference to a device that is 'found' for later use, as
3938c2ecf20Sopenharmony_ci * determined by the @match callback.
3948c2ecf20Sopenharmony_ci *
3958c2ecf20Sopenharmony_ci * The callback should return 0 if the device doesn't match and non-zero
3968c2ecf20Sopenharmony_ci * if it does.  If the callback returns non-zero, this function will
3978c2ecf20Sopenharmony_ci * return to the caller and not iterate over any more devices.
3988c2ecf20Sopenharmony_ci *
3998c2ecf20Sopenharmony_ci * Note, you will need to drop the reference with put_device() after use.
4008c2ecf20Sopenharmony_ci *
4018c2ecf20Sopenharmony_ci * @match is allowed to do anything including calling back into class
4028c2ecf20Sopenharmony_ci * code.  There's no locking restriction.
4038c2ecf20Sopenharmony_ci */
4048c2ecf20Sopenharmony_cistruct device *class_find_device(struct class *class, struct device *start,
4058c2ecf20Sopenharmony_ci				 const void *data,
4068c2ecf20Sopenharmony_ci				 int (*match)(struct device *, const void *))
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	struct class_dev_iter iter;
4098c2ecf20Sopenharmony_ci	struct device *dev;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	if (!class)
4128c2ecf20Sopenharmony_ci		return NULL;
4138c2ecf20Sopenharmony_ci	if (!class->p) {
4148c2ecf20Sopenharmony_ci		WARN(1, "%s called for class '%s' before it was initialized",
4158c2ecf20Sopenharmony_ci		     __func__, class->name);
4168c2ecf20Sopenharmony_ci		return NULL;
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	class_dev_iter_init(&iter, class, start, NULL);
4208c2ecf20Sopenharmony_ci	while ((dev = class_dev_iter_next(&iter))) {
4218c2ecf20Sopenharmony_ci		if (match(dev, data)) {
4228c2ecf20Sopenharmony_ci			get_device(dev);
4238c2ecf20Sopenharmony_ci			break;
4248c2ecf20Sopenharmony_ci		}
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci	class_dev_iter_exit(&iter);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	return dev;
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_find_device);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ciint class_interface_register(struct class_interface *class_intf)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	struct class *parent;
4358c2ecf20Sopenharmony_ci	struct class_dev_iter iter;
4368c2ecf20Sopenharmony_ci	struct device *dev;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	if (!class_intf || !class_intf->class)
4398c2ecf20Sopenharmony_ci		return -ENODEV;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	parent = class_get(class_intf->class);
4428c2ecf20Sopenharmony_ci	if (!parent)
4438c2ecf20Sopenharmony_ci		return -EINVAL;
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	mutex_lock(&parent->p->mutex);
4468c2ecf20Sopenharmony_ci	list_add_tail(&class_intf->node, &parent->p->interfaces);
4478c2ecf20Sopenharmony_ci	if (class_intf->add_dev) {
4488c2ecf20Sopenharmony_ci		class_dev_iter_init(&iter, parent, NULL, NULL);
4498c2ecf20Sopenharmony_ci		while ((dev = class_dev_iter_next(&iter)))
4508c2ecf20Sopenharmony_ci			class_intf->add_dev(dev, class_intf);
4518c2ecf20Sopenharmony_ci		class_dev_iter_exit(&iter);
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci	mutex_unlock(&parent->p->mutex);
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	return 0;
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_civoid class_interface_unregister(struct class_interface *class_intf)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	struct class *parent = class_intf->class;
4618c2ecf20Sopenharmony_ci	struct class_dev_iter iter;
4628c2ecf20Sopenharmony_ci	struct device *dev;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (!parent)
4658c2ecf20Sopenharmony_ci		return;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	mutex_lock(&parent->p->mutex);
4688c2ecf20Sopenharmony_ci	list_del_init(&class_intf->node);
4698c2ecf20Sopenharmony_ci	if (class_intf->remove_dev) {
4708c2ecf20Sopenharmony_ci		class_dev_iter_init(&iter, parent, NULL, NULL);
4718c2ecf20Sopenharmony_ci		while ((dev = class_dev_iter_next(&iter)))
4728c2ecf20Sopenharmony_ci			class_intf->remove_dev(dev, class_intf);
4738c2ecf20Sopenharmony_ci		class_dev_iter_exit(&iter);
4748c2ecf20Sopenharmony_ci	}
4758c2ecf20Sopenharmony_ci	mutex_unlock(&parent->p->mutex);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	class_put(parent);
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cissize_t show_class_attr_string(struct class *class,
4818c2ecf20Sopenharmony_ci			       struct class_attribute *attr, char *buf)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	struct class_attribute_string *cs;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	cs = container_of(attr, struct class_attribute_string, attr);
4868c2ecf20Sopenharmony_ci	return sysfs_emit(buf, "%s\n", cs->str);
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(show_class_attr_string);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistruct class_compat {
4928c2ecf20Sopenharmony_ci	struct kobject *kobj;
4938c2ecf20Sopenharmony_ci};
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci/**
4968c2ecf20Sopenharmony_ci * class_compat_register - register a compatibility class
4978c2ecf20Sopenharmony_ci * @name: the name of the class
4988c2ecf20Sopenharmony_ci *
4998c2ecf20Sopenharmony_ci * Compatibility class are meant as a temporary user-space compatibility
5008c2ecf20Sopenharmony_ci * workaround when converting a family of class devices to a bus devices.
5018c2ecf20Sopenharmony_ci */
5028c2ecf20Sopenharmony_cistruct class_compat *class_compat_register(const char *name)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct class_compat *cls;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	cls = kmalloc(sizeof(struct class_compat), GFP_KERNEL);
5078c2ecf20Sopenharmony_ci	if (!cls)
5088c2ecf20Sopenharmony_ci		return NULL;
5098c2ecf20Sopenharmony_ci	cls->kobj = kobject_create_and_add(name, &class_kset->kobj);
5108c2ecf20Sopenharmony_ci	if (!cls->kobj) {
5118c2ecf20Sopenharmony_ci		kfree(cls);
5128c2ecf20Sopenharmony_ci		return NULL;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci	return cls;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_compat_register);
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci/**
5198c2ecf20Sopenharmony_ci * class_compat_unregister - unregister a compatibility class
5208c2ecf20Sopenharmony_ci * @cls: the class to unregister
5218c2ecf20Sopenharmony_ci */
5228c2ecf20Sopenharmony_civoid class_compat_unregister(struct class_compat *cls)
5238c2ecf20Sopenharmony_ci{
5248c2ecf20Sopenharmony_ci	kobject_put(cls->kobj);
5258c2ecf20Sopenharmony_ci	kfree(cls);
5268c2ecf20Sopenharmony_ci}
5278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_compat_unregister);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci/**
5308c2ecf20Sopenharmony_ci * class_compat_create_link - create a compatibility class device link to
5318c2ecf20Sopenharmony_ci *			      a bus device
5328c2ecf20Sopenharmony_ci * @cls: the compatibility class
5338c2ecf20Sopenharmony_ci * @dev: the target bus device
5348c2ecf20Sopenharmony_ci * @device_link: an optional device to which a "device" link should be created
5358c2ecf20Sopenharmony_ci */
5368c2ecf20Sopenharmony_ciint class_compat_create_link(struct class_compat *cls, struct device *dev,
5378c2ecf20Sopenharmony_ci			     struct device *device_link)
5388c2ecf20Sopenharmony_ci{
5398c2ecf20Sopenharmony_ci	int error;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	error = sysfs_create_link(cls->kobj, &dev->kobj, dev_name(dev));
5428c2ecf20Sopenharmony_ci	if (error)
5438c2ecf20Sopenharmony_ci		return error;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	/*
5468c2ecf20Sopenharmony_ci	 * Optionally add a "device" link (typically to the parent), as a
5478c2ecf20Sopenharmony_ci	 * class device would have one and we want to provide as much
5488c2ecf20Sopenharmony_ci	 * backwards compatibility as possible.
5498c2ecf20Sopenharmony_ci	 */
5508c2ecf20Sopenharmony_ci	if (device_link) {
5518c2ecf20Sopenharmony_ci		error = sysfs_create_link(&dev->kobj, &device_link->kobj,
5528c2ecf20Sopenharmony_ci					  "device");
5538c2ecf20Sopenharmony_ci		if (error)
5548c2ecf20Sopenharmony_ci			sysfs_remove_link(cls->kobj, dev_name(dev));
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return error;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_compat_create_link);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci/**
5628c2ecf20Sopenharmony_ci * class_compat_remove_link - remove a compatibility class device link to
5638c2ecf20Sopenharmony_ci *			      a bus device
5648c2ecf20Sopenharmony_ci * @cls: the compatibility class
5658c2ecf20Sopenharmony_ci * @dev: the target bus device
5668c2ecf20Sopenharmony_ci * @device_link: an optional device to which a "device" link was previously
5678c2ecf20Sopenharmony_ci * 		 created
5688c2ecf20Sopenharmony_ci */
5698c2ecf20Sopenharmony_civoid class_compat_remove_link(struct class_compat *cls, struct device *dev,
5708c2ecf20Sopenharmony_ci			      struct device *device_link)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	if (device_link)
5738c2ecf20Sopenharmony_ci		sysfs_remove_link(&dev->kobj, "device");
5748c2ecf20Sopenharmony_ci	sysfs_remove_link(cls->kobj, dev_name(dev));
5758c2ecf20Sopenharmony_ci}
5768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_compat_remove_link);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ciint __init classes_init(void)
5798c2ecf20Sopenharmony_ci{
5808c2ecf20Sopenharmony_ci	class_kset = kset_create_and_add("class", NULL, NULL);
5818c2ecf20Sopenharmony_ci	if (!class_kset)
5828c2ecf20Sopenharmony_ci		return -ENOMEM;
5838c2ecf20Sopenharmony_ci	return 0;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_create_file_ns);
5878c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_remove_file_ns);
5888c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_unregister);
5898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_destroy);
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_interface_register);
5928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(class_interface_unregister);
593