^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * File attributes for Mediated devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Neo Jia <cjia@nvidia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Kirti Wankhede <kwankhede@nvidia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/uuid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "mdev_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* Static functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static ssize_t mdev_type_attr_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct attribute *__attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct mdev_type_attribute *attr = to_mdev_type_attr(__attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct mdev_type *type = to_mdev_type(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ssize_t ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (attr->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ret = attr->show(kobj, type->parent->dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static ssize_t mdev_type_attr_store(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct attribute *__attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct mdev_type_attribute *attr = to_mdev_type_attr(__attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct mdev_type *type = to_mdev_type(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) ssize_t ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (attr->store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ret = attr->store(&type->kobj, type->parent->dev, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static const struct sysfs_ops mdev_type_sysfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .show = mdev_type_attr_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .store = mdev_type_attr_store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static ssize_t create_store(struct kobject *kobj, struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) guid_t uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if ((count < UUID_STRING_LEN) || (count > UUID_STRING_LEN + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) str = kstrndup(buf, count, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ret = guid_parse(str, &uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) kfree(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = mdev_device_create(kobj, dev, &uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static MDEV_TYPE_ATTR_WO(create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void mdev_type_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct mdev_type *type = to_mdev_type(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pr_debug("Releasing group %s\n", kobj->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) kfree(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct kobj_type mdev_type_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .sysfs_ops = &mdev_type_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .release = mdev_type_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct attribute_group *group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct mdev_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!group->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pr_err("%s: Type name empty!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) type = kzalloc(sizeof(*type), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) type->kobj.kset = parent->mdev_types_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) type->parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) "%s-%s", dev_driver_string(parent->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) group->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) kobject_put(&type->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) goto attr_create_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) type->devices_kobj = kobject_create_and_add("devices", &type->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!type->devices_kobj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto attr_devices_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ret = sysfs_create_files(&type->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) (const struct attribute **)group->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto attrs_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) type->group = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) attrs_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) kobject_put(type->devices_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) attr_devices_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) attr_create_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) kobject_del(&type->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) kobject_put(&type->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static void remove_mdev_supported_type(struct mdev_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) sysfs_remove_files(&type->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) (const struct attribute **)type->group->attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) kobject_put(type->devices_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) kobject_del(&type->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) kobject_put(&type->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int add_mdev_supported_type_groups(struct mdev_parent *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (i = 0; parent->ops->supported_type_groups[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct mdev_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) type = add_mdev_supported_type(parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) parent->ops->supported_type_groups[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (IS_ERR(type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct mdev_type *ltype, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) list_for_each_entry_safe(ltype, tmp, &parent->type_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) list_del(<ype->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) remove_mdev_supported_type(ltype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return PTR_ERR(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) list_add(&type->next, &parent->type_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* mdev sysfs functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) void parent_remove_sysfs_files(struct mdev_parent *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct mdev_type *type, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) list_for_each_entry_safe(type, tmp, &parent->type_list, next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) list_del(&type->next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) remove_mdev_supported_type(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) sysfs_remove_groups(&parent->dev->kobj, parent->ops->dev_attr_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) kset_unregister(parent->mdev_types_kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int parent_create_sysfs_files(struct mdev_parent *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) parent->mdev_types_kset = kset_create_and_add("mdev_supported_types",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) NULL, &parent->dev->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!parent->mdev_types_kset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) INIT_LIST_HEAD(&parent->type_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ret = sysfs_create_groups(&parent->dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) parent->ops->dev_attr_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) goto create_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ret = add_mdev_supported_type_groups(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) sysfs_remove_groups(&parent->dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) parent->ops->dev_attr_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) create_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) kset_unregister(parent->mdev_types_kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (kstrtoul(buf, 0, &val) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (val && device_remove_file_self(dev, attr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = mdev_device_remove(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static DEVICE_ATTR_WO(remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static const struct attribute *mdev_device_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) &dev_attr_remove.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ret = sysfs_create_link(type->devices_kobj, &dev->kobj, dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ret = sysfs_create_link(&dev->kobj, &type->kobj, "mdev_type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) goto type_link_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret = sysfs_create_files(&dev->kobj, mdev_device_attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) goto create_files_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) create_files_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) sysfs_remove_link(&dev->kobj, "mdev_type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) type_link_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) sysfs_remove_link(type->devices_kobj, dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) sysfs_remove_files(&dev->kobj, mdev_device_attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) sysfs_remove_link(&dev->kobj, "mdev_type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) sysfs_remove_link(type->devices_kobj, dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }