Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
// SPDX-License-Identifier: GPL-2.0-only
/*
* File attributes for Mediated devices
*
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
* Author: Neo Jia <cjia@nvidia.com>
* Kirti Wankhede <kwankhede@nvidia.com>
*/
#include <linux/sysfs.h>
#include <linux/ctype.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uuid.h>
#include <linux/mdev.h>
#include "mdev_private.h"
/* Static functions */
static ssize_t mdev_type_attr_show(struct kobject *kobj,
<------><------><------><------> struct attribute *__attr, char *buf)
{
<------>struct mdev_type_attribute *attr = to_mdev_type_attr(__attr);
<------>struct mdev_type *type = to_mdev_type(kobj);
<------>ssize_t ret = -EIO;
<------>if (attr->show)
<------><------>ret = attr->show(kobj, type->parent->dev, buf);
<------>return ret;
}
static ssize_t mdev_type_attr_store(struct kobject *kobj,
<------><------><------><------> struct attribute *__attr,
<------><------><------><------> const char *buf, size_t count)
{
<------>struct mdev_type_attribute *attr = to_mdev_type_attr(__attr);
<------>struct mdev_type *type = to_mdev_type(kobj);
<------>ssize_t ret = -EIO;
<------>if (attr->store)
<------><------>ret = attr->store(&type->kobj, type->parent->dev, buf, count);
<------>return ret;
}
static const struct sysfs_ops mdev_type_sysfs_ops = {
<------>.show = mdev_type_attr_show,
<------>.store = mdev_type_attr_store,
};
static ssize_t create_store(struct kobject *kobj, struct device *dev,
<------><------><------> const char *buf, size_t count)
{
<------>char *str;
<------>guid_t uuid;
<------>int ret;
<------>if ((count < UUID_STRING_LEN) || (count > UUID_STRING_LEN + 1))
<------><------>return -EINVAL;
<------>str = kstrndup(buf, count, GFP_KERNEL);
<------>if (!str)
<------><------>return -ENOMEM;
<------>ret = guid_parse(str, &uuid);
<------>kfree(str);
<------>if (ret)
<------><------>return ret;
<------>ret = mdev_device_create(kobj, dev, &uuid);
<------>if (ret)
<------><------>return ret;
<------>return count;
}
static MDEV_TYPE_ATTR_WO(create);
static void mdev_type_release(struct kobject *kobj)
{
<------>struct mdev_type *type = to_mdev_type(kobj);
<------>pr_debug("Releasing group %s\n", kobj->name);
<------>kfree(type);
}
static struct kobj_type mdev_type_ktype = {
<------>.sysfs_ops = &mdev_type_sysfs_ops,
<------>.release = mdev_type_release,
};
static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
<------><------><------><------><------><------> struct attribute_group *group)
{
<------>struct mdev_type *type;
<------>int ret;
<------>if (!group->name) {
<------><------>pr_err("%s: Type name empty!\n", __func__);
<------><------>return ERR_PTR(-EINVAL);
<------>}
<------>type = kzalloc(sizeof(*type), GFP_KERNEL);
<------>if (!type)
<------><------>return ERR_PTR(-ENOMEM);
<------>type->kobj.kset = parent->mdev_types_kset;
<------>type->parent = parent;
<------>ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
<------><------><------><------> "%s-%s", dev_driver_string(parent->dev),
<------><------><------><------> group->name);
<------>if (ret) {
<------><------>kobject_put(&type->kobj);
<------><------>return ERR_PTR(ret);
<------>}
<------>ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr);
<------>if (ret)
<------><------>goto attr_create_failed;
<------>type->devices_kobj = kobject_create_and_add("devices", &type->kobj);
<------>if (!type->devices_kobj) {
<------><------>ret = -ENOMEM;
<------><------>goto attr_devices_failed;
<------>}
<------>ret = sysfs_create_files(&type->kobj,
<------><------><------><------> (const struct attribute **)group->attrs);
<------>if (ret) {
<------><------>ret = -ENOMEM;
<------><------>goto attrs_failed;
<------>}
<------>type->group = group;
<------>return type;
attrs_failed:
<------>kobject_put(type->devices_kobj);
attr_devices_failed:
<------>sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
attr_create_failed:
<------>kobject_del(&type->kobj);
<------>kobject_put(&type->kobj);
<------>return ERR_PTR(ret);
}
static void remove_mdev_supported_type(struct mdev_type *type)
{
<------>sysfs_remove_files(&type->kobj,
<------><------><------> (const struct attribute **)type->group->attrs);
<------>kobject_put(type->devices_kobj);
<------>sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
<------>kobject_del(&type->kobj);
<------>kobject_put(&type->kobj);
}
static int add_mdev_supported_type_groups(struct mdev_parent *parent)
{
<------>int i;
<------>for (i = 0; parent->ops->supported_type_groups[i]; i++) {
<------><------>struct mdev_type *type;
<------><------>type = add_mdev_supported_type(parent,
<------><------><------><------><------>parent->ops->supported_type_groups[i]);
<------><------>if (IS_ERR(type)) {
<------><------><------>struct mdev_type *ltype, *tmp;
<------><------><------>list_for_each_entry_safe(ltype, tmp, &parent->type_list,
<------><------><------><------><------><------> next) {
<------><------><------><------>list_del(&ltype->next);
<------><------><------><------>remove_mdev_supported_type(ltype);
<------><------><------>}
<------><------><------>return PTR_ERR(type);
<------><------>}
<------><------>list_add(&type->next, &parent->type_list);
<------>}
<------>return 0;
}
/* mdev sysfs functions */
void parent_remove_sysfs_files(struct mdev_parent *parent)
{
<------>struct mdev_type *type, *tmp;
<------>list_for_each_entry_safe(type, tmp, &parent->type_list, next) {
<------><------>list_del(&type->next);
<------><------>remove_mdev_supported_type(type);
<------>}
<------>sysfs_remove_groups(&parent->dev->kobj, parent->ops->dev_attr_groups);
<------>kset_unregister(parent->mdev_types_kset);
}
int parent_create_sysfs_files(struct mdev_parent *parent)
{
<------>int ret;
<------>parent->mdev_types_kset = kset_create_and_add("mdev_supported_types",
<------><------><------><------><------> NULL, &parent->dev->kobj);
<------>if (!parent->mdev_types_kset)
<------><------>return -ENOMEM;
<------>INIT_LIST_HEAD(&parent->type_list);
<------>ret = sysfs_create_groups(&parent->dev->kobj,
<------><------><------><------> parent->ops->dev_attr_groups);
<------>if (ret)
<------><------>goto create_err;
<------>ret = add_mdev_supported_type_groups(parent);
<------>if (ret)
<------><------>sysfs_remove_groups(&parent->dev->kobj,
<------><------><------><------> parent->ops->dev_attr_groups);
<------>else
<------><------>return ret;
create_err:
<------>kset_unregister(parent->mdev_types_kset);
<------>return ret;
}
static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
<------><------><------> const char *buf, size_t count)
{
<------>unsigned long val;
<------>if (kstrtoul(buf, 0, &val) < 0)
<------><------>return -EINVAL;
<------>if (val && device_remove_file_self(dev, attr)) {
<------><------>int ret;
<------><------>ret = mdev_device_remove(dev);
<------><------>if (ret)
<------><------><------>return ret;
<------>}
<------>return count;
}
static DEVICE_ATTR_WO(remove);
static const struct attribute *mdev_device_attrs[] = {
<------>&dev_attr_remove.attr,
<------>NULL,
};
int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type)
{
<------>int ret;
<------>ret = sysfs_create_link(type->devices_kobj, &dev->kobj, dev_name(dev));
<------>if (ret)
<------><------>return ret;
<------>ret = sysfs_create_link(&dev->kobj, &type->kobj, "mdev_type");
<------>if (ret)
<------><------>goto type_link_failed;
<------>ret = sysfs_create_files(&dev->kobj, mdev_device_attrs);
<------>if (ret)
<------><------>goto create_files_failed;
<------>return ret;
create_files_failed:
<------>sysfs_remove_link(&dev->kobj, "mdev_type");
type_link_failed:
<------>sysfs_remove_link(type->devices_kobj, dev_name(dev));
<------>return ret;
}
void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type)
{
<------>sysfs_remove_files(&dev->kobj, mdev_device_attrs);
<------>sysfs_remove_link(&dev->kobj, "mdev_type");
<------>sysfs_remove_link(type->devices_kobj, dev_name(dev));
}