static void plt_clk_free_parent_names_loop(const char **parent_names, unsigned int i) { while (i--) kfree_const(parent_names[i]); kfree(parent_names); }
/** * kernfs_put - put a reference count on a kernfs_node * @kn: the target kernfs_node * * Put a reference count of @kn and destroy it if it reached zero. */ void kernfs_put(struct kernfs_node *kn) { struct kernfs_node *parent; struct kernfs_root *root; if (!kn || !atomic_dec_and_test(&kn->count)) return; root = kernfs_root(kn); repeat: /* * Moving/renaming is always done while holding reference. * kn->parent won't change beneath us. */ parent = kn->parent; WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS, "kernfs_put: %s/%s: released with incorrect active_ref %d\n", parent ? parent->name : "", kn->name, atomic_read(&kn->active)); if (kernfs_type(kn) == KERNFS_LINK) kernfs_put(kn->symlink.target_kn); kfree_const(kn->name); if (kn->iattr) { if (kn->iattr->ia_secdata) security_release_secctx(kn->iattr->ia_secdata, kn->iattr->ia_secdata_len); simple_xattrs_free(&kn->iattr->xattrs); } kfree(kn->iattr); ida_simple_remove(&root->ino_ida, kn->ino); kmem_cache_free(kernfs_node_cache, kn); kn = parent; if (kn) { if (atomic_dec_and_test(&kn->count)) goto repeat; } else { /* just released the root kn, free @root too */ ida_destroy(&root->ino_ida); kfree(root); } }
static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, const char *name, umode_t mode, unsigned flags) { struct kernfs_node *kn; int ret; name = kstrdup_const(name, GFP_KERNEL); if (!name) return NULL; kn = kmem_cache_zalloc(kernfs_node_cache, GFP_KERNEL); if (!kn) goto err_out1; /* * If the ino of the sysfs entry created for a kmem cache gets * allocated from an ida layer, which is accounted to the memcg that * owns the cache, the memcg will get pinned forever. So do not account * ino ida allocations. */ ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL | __GFP_NOACCOUNT); if (ret < 0) goto err_out2; kn->ino = ret; atomic_set(&kn->count, 1); atomic_set(&kn->active, KN_DEACTIVATED_BIAS); RB_CLEAR_NODE(&kn->rb); kn->name = name; kn->mode = mode; kn->flags = flags; return kn; err_out2: kmem_cache_free(kernfs_node_cache, kn); err_out1: kfree_const(name); return NULL; }
static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, const char *name, umode_t mode, unsigned flags) { struct kernfs_node *kn; int ret; name = kstrdup_const(name, GFP_KERNEL); if (!name) return NULL; kn = kmem_cache_zalloc(kernfs_node_cache, GFP_KERNEL); if (!kn) goto err_out1; ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL); if (ret < 0) goto err_out2; kn->ino = ret; atomic_set(&kn->count, 1); atomic_set(&kn->active, KN_DEACTIVATED_BIAS); RB_CLEAR_NODE(&kn->rb); kn->name = name; kn->mode = mode; kn->flags = flags; return kn; err_out2: kmem_cache_free(kernfs_node_cache, kn); err_out1: kfree_const(name); return NULL; }
/** * kernfs_rename_ns - move and rename a kernfs_node * @kn: target node * @new_parent: new parent to put @sd under * @new_name: new name * @new_ns: new namespace tag */ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, const char *new_name, const void *new_ns) { struct kernfs_node *old_parent; const char *old_name = NULL; int error; /* can't move or rename root */ if (!kn->parent) return -EINVAL; mutex_lock(&kernfs_mutex); error = -ENOENT; if (!kernfs_active(kn) || !kernfs_active(new_parent) || (new_parent->flags & KERNFS_EMPTY_DIR)) goto out; error = 0; if ((kn->parent == new_parent) && (kn->ns == new_ns) && (strcmp(kn->name, new_name) == 0)) goto out; /* nothing to rename */ error = -EEXIST; if (kernfs_find_ns(new_parent, new_name, new_ns)) goto out; /* rename kernfs_node */ if (strcmp(kn->name, new_name) != 0) { error = -ENOMEM; new_name = kstrdup_const(new_name, GFP_KERNEL); if (!new_name) goto out; } else { new_name = NULL; } /* * Move to the appropriate place in the appropriate directories rbtree. */ kernfs_unlink_sibling(kn); kernfs_get(new_parent); /* rename_lock protects ->parent and ->name accessors */ spin_lock_irq(&kernfs_rename_lock); old_parent = kn->parent; kn->parent = new_parent; kn->ns = new_ns; if (new_name) { old_name = kn->name; kn->name = new_name; } spin_unlock_irq(&kernfs_rename_lock); kn->hash = kernfs_name_hash(kn->name, kn->ns); kernfs_link_sibling(kn); kernfs_put(old_parent); kfree_const(old_name); error = 0; out: mutex_unlock(&kernfs_mutex); return error; }
static int __init meson_mx_socinfo_init(void) { struct soc_device_attribute *soc_dev_attr; struct soc_device *soc_dev; struct device_node *np; struct regmap *assist_regmap, *bootrom_regmap, *analog_top_regmap; unsigned int major_ver, misc_ver, metal_rev = 0; int ret; assist_regmap = syscon_regmap_lookup_by_compatible("amlogic,meson-mx-assist"); if (IS_ERR(assist_regmap)) return PTR_ERR(assist_regmap); bootrom_regmap = syscon_regmap_lookup_by_compatible("amlogic,meson-mx-bootrom"); if (IS_ERR(bootrom_regmap)) return PTR_ERR(bootrom_regmap); np = of_find_matching_node(NULL, meson_mx_socinfo_analog_top_ids); if (np) { analog_top_regmap = syscon_node_to_regmap(np); if (IS_ERR(analog_top_regmap)) return PTR_ERR(analog_top_regmap); ret = regmap_read(analog_top_regmap, MESON_MX_ANALOG_TOP_METAL_REVISION, &metal_rev); if (ret) return ret; } ret = regmap_read(assist_regmap, MESON_MX_ASSIST_HW_REV, &major_ver); if (ret < 0) return ret; ret = regmap_read(bootrom_regmap, MESON_MX_BOOTROM_MISC_VER, &misc_ver); if (ret < 0) return ret; soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); if (!soc_dev_attr) return -ENODEV; soc_dev_attr->family = "Amlogic Meson"; np = of_find_node_by_path("/"); of_property_read_string(np, "model", &soc_dev_attr->machine); of_node_put(np); soc_dev_attr->revision = meson_mx_socinfo_revision(major_ver, misc_ver, metal_rev); soc_dev_attr->soc_id = meson_mx_socinfo_soc_id(major_ver, metal_rev); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { kfree_const(soc_dev_attr->revision); kfree_const(soc_dev_attr->soc_id); kfree(soc_dev_attr); return PTR_ERR(soc_dev); } dev_info(soc_device_to_device(soc_dev), "Amlogic %s %s detected\n", soc_dev_attr->soc_id, soc_dev_attr->revision); return 0; }
int __init meson_gx_socinfo_init(void) { struct soc_device_attribute *soc_dev_attr; struct soc_device *soc_dev; struct device_node *np; struct regmap *regmap; unsigned int socinfo; struct device *dev; int ret; /* look up for chipid node */ np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gx-ao-secure"); if (!np) return -ENODEV; /* check if interface is enabled */ if (!of_device_is_available(np)) return -ENODEV; /* check if chip-id is available */ if (!of_property_read_bool(np, "amlogic,has-chip-id")) return -ENODEV; /* node should be a syscon */ regmap = syscon_node_to_regmap(np); of_node_put(np); if (IS_ERR(regmap)) { pr_err("%s: failed to get regmap\n", __func__); return -ENODEV; } ret = regmap_read(regmap, AO_SEC_SOCINFO_OFFSET, &socinfo); if (ret < 0) return ret; if (!socinfo) { pr_err("%s: invalid chipid value\n", __func__); return -EINVAL; } soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); if (!soc_dev_attr) return -ENODEV; soc_dev_attr->family = "Amlogic Meson"; np = of_find_node_by_path("/"); of_property_read_string(np, "model", &soc_dev_attr->machine); of_node_put(np); soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x:%x - %x:%x", socinfo_to_major(socinfo), socinfo_to_minor(socinfo), socinfo_to_pack(socinfo), socinfo_to_misc(socinfo)); soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%s (%s)", socinfo_to_soc_id(socinfo), socinfo_to_package_id(socinfo)); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { kfree(soc_dev_attr->revision); kfree_const(soc_dev_attr->soc_id); kfree(soc_dev_attr); return PTR_ERR(soc_dev); } dev = soc_device_to_device(soc_dev); dev_info(dev, "Amlogic Meson %s Revision %x:%x (%x:%x) Detected\n", soc_dev_attr->soc_id, socinfo_to_major(socinfo), socinfo_to_minor(socinfo), socinfo_to_pack(socinfo), socinfo_to_misc(socinfo)); return 0; }