/** * class_to_subsys - Turn a struct class into a struct subsys_private * * @class: pointer to the struct bus_type to look up * * The driver core internals need to work on the subsys_private structure, not * the external struct class pointer. This function walks the list of * registered classes in the system and finds the matching one and returns the * internal struct subsys_private that relates to that class. * * Note, the reference count of the return value is INCREMENTED if it is not * NULL. A call to subsys_put() must be done when finished with the pointer in * order for it to be properly freed.
*/ struct subsys_private *class_to_subsys(conststructclass *class)
{ struct subsys_private *sp = NULL; struct kobject *kobj;
int class_register(conststructclass *cls)
{ struct subsys_private *cp; struct lock_class_key *key; int error;
pr_debug("device class '%s': registering\n", cls->name);
if (cls->ns_type && !cls->namespace) {
pr_err("%s: class '%s' does not have namespace\n",
__func__, cls->name); return -EINVAL;
} if (!cls->ns_type && cls->namespace) {
pr_err("%s: class '%s' does not have ns_type\n",
__func__, cls->name); return -EINVAL;
}
staticvoid class_create_release(conststructclass *cls)
{
pr_debug("%s called for %s\n", __func__, cls->name);
kfree(cls);
}
/** * class_create - create a struct class structure * @name: pointer to a string for the name of this class. * * This is used to create a struct class pointer that can then be used * in calls to device_create(). * * Returns &struct class pointer on success, or ERR_PTR() on error. * * Note, the pointer created here is to be destroyed when finished by * making a call to class_destroy().
*/ structclass *class_create(constchar *name)
{ structclass *cls; int retval;
/** * class_destroy - destroys a struct class structure * @cls: pointer to the struct class that is to be destroyed * * Note, the pointer to be destroyed must have been created with a call * to class_create().
*/ void class_destroy(conststructclass *cls)
{ if (IS_ERR_OR_NULL(cls)) return;
/** * class_dev_iter_init - initialize class device iterator * @iter: class iterator to initialize * @class: the class we wanna iterate over * @start: the device to start iterating from, if any * @type: device_type of the devices to iterate over, NULL for all * * Initialize class iterator @iter such that it iterates over devices * of @class. If @start is set, the list iteration will start there, * otherwise if it is NULL, the iteration starts at the beginning of * the list.
*/ void class_dev_iter_init(struct class_dev_iter *iter, conststructclass *class, conststruct device *start, conststruct device_type *type)
{ struct subsys_private *sp = class_to_subsys(class); struct klist_node *start_knode = NULL;
memset(iter, 0, sizeof(*iter)); if (!sp) {
pr_crit("%s: class %p was not registered yet\n",
__func__, class); return;
}
/** * class_dev_iter_next - iterate to the next device * @iter: class iterator to proceed * * Proceed @iter to the next device and return it. Returns NULL if * iteration is complete. * * The returned device is referenced and won't be released till * iterator is proceed to the next device or exited. The caller is * free to do whatever it wants to do with the device including * calling back into class code.
*/ struct device *class_dev_iter_next(struct class_dev_iter *iter)
{ struct klist_node *knode; struct device *dev;
if (!iter->sp) return NULL;
while (1) {
knode = klist_next(&iter->ki); if (!knode) return NULL;
dev = klist_class_to_dev(knode); if (!iter->type || iter->type == dev->type) return dev;
}
}
EXPORT_SYMBOL_GPL(class_dev_iter_next);
/** * class_dev_iter_exit - finish iteration * @iter: class iterator to finish * * Finish an iteration. Always call this function after iteration is * complete whether the iteration ran till the end or not.
*/ void class_dev_iter_exit(struct class_dev_iter *iter)
{
klist_iter_exit(&iter->ki);
subsys_put(iter->sp);
}
EXPORT_SYMBOL_GPL(class_dev_iter_exit);
/** * class_for_each_device - device iterator * @class: the class we're iterating * @start: the device to start with in the list, if any. * @data: data for the callback * @fn: function to be called for each device * * Iterate over @class's list of devices, and call @fn for each, * passing it @data. If @start is set, the list iteration will start * there, otherwise if it is NULL, the iteration starts at the * beginning of the list. * * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * * @fn is allowed to do anything including calling back into class * code. There's no locking restriction.
*/ int class_for_each_device(conststructclass *class, conststruct device *start, void *data, device_iter_t fn)
{ struct subsys_private *sp = class_to_subsys(class); struct class_dev_iter iter; struct device *dev; int error = 0;
if (!class) return -EINVAL; if (!sp) {
WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name); return -EINVAL;
}
class_dev_iter_init(&iter, class, start, NULL); while ((dev = class_dev_iter_next(&iter))) {
error = fn(dev, data); if (error) break;
}
class_dev_iter_exit(&iter);
subsys_put(sp);
/** * class_find_device - device iterator for locating a particular device * @class: the class we're iterating * @start: Device to begin with * @data: data for the match function * @match: function to check device * * This is similar to the class_for_each_dev() function above, but it * returns a reference to a device that is 'found' for later use, as * determined by the @match callback. * * The callback should return 0 if the device doesn't match and non-zero * if it does. If the callback returns non-zero, this function will * return to the caller and not iterate over any more devices. * * Note, you will need to drop the reference with put_device() after use. * * @match is allowed to do anything including calling back into class * code. There's no locking restriction.
*/ struct device *class_find_device(conststructclass *class, conststruct device *start, constvoid *data, device_match_t match)
{ struct subsys_private *sp = class_to_subsys(class); struct class_dev_iter iter; struct device *dev;
if (!class) return NULL; if (!sp) {
WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name); return NULL;
}
class_dev_iter_init(&iter, class, start, NULL); while ((dev = class_dev_iter_next(&iter))) { if (match(dev, data)) {
get_device(dev); break;
}
}
class_dev_iter_exit(&iter);
subsys_put(sp);
mutex_lock(&sp->mutex);
list_del_init(&class_intf->node); if (class_intf->remove_dev) {
class_dev_iter_init(&iter, parent, NULL, NULL); while ((dev = class_dev_iter_next(&iter)))
class_intf->remove_dev(dev);
class_dev_iter_exit(&iter);
}
mutex_unlock(&sp->mutex);
/* * Decrement the reference count twice, once for the class_to_subsys() * call in the start of this function, and the second one from the * reference increment in class_interface_register()
*/
subsys_put(sp);
subsys_put(sp);
}
EXPORT_SYMBOL_GPL(class_interface_unregister);
/** * class_compat_register - register a compatibility class * @name: the name of the class * * Compatibility class are meant as a temporary user-space compatibility * workaround when converting a family of class devices to a bus devices.
*/ struct class_compat *class_compat_register(constchar *name)
{ struct class_compat *cls;
/** * class_compat_unregister - unregister a compatibility class * @cls: the class to unregister
*/ void class_compat_unregister(struct class_compat *cls)
{
kobject_put(cls->kobj);
kfree(cls);
}
EXPORT_SYMBOL_GPL(class_compat_unregister);
/** * class_compat_create_link - create a compatibility class device link to * a bus device * @cls: the compatibility class * @dev: the target bus device
*/ int class_compat_create_link(struct class_compat *cls, struct device *dev)
{ return sysfs_create_link(cls->kobj, &dev->kobj, dev_name(dev));
}
EXPORT_SYMBOL_GPL(class_compat_create_link);
/** * class_compat_remove_link - remove a compatibility class device link to * a bus device * @cls: the compatibility class * @dev: the target bus device
*/ void class_compat_remove_link(struct class_compat *cls, struct device *dev)
{
sysfs_remove_link(cls->kobj, dev_name(dev));
}
EXPORT_SYMBOL_GPL(class_compat_remove_link);
/** * class_is_registered - determine if at this moment in time, a class is * registered in the driver core or not. * @class: the class to check * * Returns a boolean to state if the class is registered in the driver core * or not. Note that the value could switch right after this call is made, * so only use this in places where you "know" it is safe to do so (usually * to determine if the specific class has been registered yet or not). * * Be careful in using this.
*/ bool class_is_registered(conststructclass *class)
{ struct subsys_private *sp = class_to_subsys(class); bool is_initialized = false;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.