/** * _commmon_choices_show - Show the available profile choices * @choices: The available profile choices * @buf: The buffer to write to * * Return: The number of bytes written
*/ static ssize_t _commmon_choices_show(unsignedlong *choices, char *buf)
{ int i, len = 0;
for_each_set_bit(i, choices, PLATFORM_PROFILE_LAST) { if (len == 0)
len += sysfs_emit_at(buf, len, "%s", profile_names[i]); else
len += sysfs_emit_at(buf, len, " %s", profile_names[i]);
}
len += sysfs_emit_at(buf, len, "\n");
return len;
}
/** * _store_class_profile - Set the profile for a class device * @dev: The class device * @data: The profile to set * * Return: 0 on success, -errno on failure
*/ staticint _store_class_profile(struct device *dev, void *data)
{ struct platform_profile_handler *handler; int *bit = (int *)data;
/** * get_class_profile - Show the current profile for a class device * @dev: The class device * @profile: The profile to return * * Return: 0 on success, -errno on failure
*/ staticint get_class_profile(struct device *dev, enum platform_profile_option *profile)
{ struct platform_profile_handler *handler; enum platform_profile_option val; int err;
lockdep_assert_held(&profile_lock);
handler = to_pprof_handler(dev);
err = handler->ops->profile_get(dev, &val); if (err) {
pr_err("Failed to get profile for handler %s\n", handler->name); return err;
}
if (WARN_ON(val >= PLATFORM_PROFILE_LAST)) return -EINVAL;
*profile = val;
return 0;
}
/** * name_show - Show the name of the profile handler * @dev: The device * @attr: The attribute * @buf: The buffer to write to * * Return: The number of bytes written
*/ static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf)
{ struct platform_profile_handler *handler = to_pprof_handler(dev);
/** * choices_show - Show the available profile choices * @dev: The device * @attr: The attribute * @buf: The buffer to write to * * Return: The number of bytes written
*/ static ssize_t choices_show(struct device *dev, struct device_attribute *attr, char *buf)
{ struct platform_profile_handler *handler = to_pprof_handler(dev);
/** * profile_show - Show the current profile for a class device * @dev: The device * @attr: The attribute * @buf: The buffer to write to * * Return: The number of bytes written
*/ static ssize_t profile_show(struct device *dev, struct device_attribute *attr, char *buf)
{ enum platform_profile_option profile = PLATFORM_PROFILE_LAST; int err;
/** * profile_store - Set the profile for a class device * @dev: The device * @attr: The attribute * @buf: The buffer to read from * @count: The number of bytes to read * * Return: The number of bytes read
*/ static ssize_t profile_store(struct device *dev, struct device_attribute *attr, constchar *buf, size_t count)
{ int index, ret;
index = sysfs_match_string(profile_names, buf); if (index < 0) return -EINVAL;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
ret = _store_class_profile(dev, &index); if (ret) return ret;
}
/** * platform_profile_choices_show - Show the available profile choices for legacy sysfs interface * @kobj: The kobject * @attr: The attribute * @buf: The buffer to write to * * Return: The number of bytes written
*/ static ssize_t platform_profile_choices_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{ struct aggregate_choices_data data = {
.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
.count = 0,
}; int err;
/** * _store_and_notify - Store and notify a class from legacy sysfs interface * @dev: The device * @data: The profile to return * * Return: 0 on success, -errno on failure
*/ staticint _store_and_notify(struct device *dev, void *data)
{ enum platform_profile_option *profile = data; int err;
/** * platform_profile_show - Show the current profile for legacy sysfs interface * @kobj: The kobject * @attr: The attribute * @buf: The buffer to write to * * Return: The number of bytes written
*/ static ssize_t platform_profile_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{ enum platform_profile_option profile = PLATFORM_PROFILE_LAST; int err;
/** * platform_profile_store - Set the profile for legacy sysfs interface * @kobj: The kobject * @attr: The attribute * @buf: The buffer to read from * @count: The number of bytes to read * * Return: The number of bytes read
*/ static ssize_t platform_profile_store(struct kobject *kobj, struct kobj_attribute *attr, constchar *buf, size_t count)
{ struct aggregate_choices_data data = {
.aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL },
.count = 0,
}; int ret; int i;
/* Scan for a matching profile */
i = sysfs_match_string(profile_names, buf); if (i < 0 || i == PLATFORM_PROFILE_CUSTOM) return -EINVAL;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
ret = class_for_each_device(&platform_profile_class, NULL,
&data, _aggregate_choices); if (ret) return ret; if (!test_bit(i, data.aggregate)) return -EOPNOTSUPP;
ret = class_for_each_device(&platform_profile_class, NULL, &i,
_store_and_notify); if (ret) return ret;
}
/** * platform_profile_register - Creates and registers a platform profile class device * @dev: Parent device * @name: Name of the class device * @drvdata: Driver data that will be attached to the class device * @ops: Platform profile's mandatory operations * * Return: pointer to the new class device on success, ERR_PTR on failure
*/ struct device *platform_profile_register(struct device *dev, constchar *name, void *drvdata, conststruct platform_profile_ops *ops)
{ struct device *ppdev; int minor; int err;
if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
dev_err(dev, "Failed to register platform_profile class device with empty choices\n"); return ERR_PTR(-EINVAL);
}
if (ops->hidden_choices) {
err = ops->hidden_choices(drvdata, pprof->hidden_choices); if (err) {
dev_err(dev, "platform_profile hidden_choices failed\n"); return ERR_PTR(err);
}
}
guard(mutex)(&profile_lock);
/* create class interface for individual handler */
minor = ida_alloc(&platform_profile_ida, GFP_KERNEL); if (minor < 0) return ERR_PTR(minor);
/** * devm_platform_profile_register - Device managed version of platform_profile_register * @dev: Parent device * @name: Name of the class device * @drvdata: Driver data that will be attached to the class device * @ops: Platform profile's mandatory operations * * Return: pointer to the new class device on success, ERR_PTR on failure
*/ struct device *devm_platform_profile_register(struct device *dev, constchar *name, void *drvdata, conststruct platform_profile_ops *ops)
{ struct device *ppdev; struct device **dr;
dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL); if (!dr) return ERR_PTR(-ENOMEM);
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.