In message: Re: [linux-yocto][v5.15/standard/preempt-rt/base][PATCH] OF: DT-Overlay configfs interface (v8) on 30/05/2023 Quanyang Wang wrote:
> Hi Bruce, > > I wrote the wrong branch information. It should be: > > v6.1/standard/preempt-rt/base > > v6.1/standard/base > > And this patch will conflict with another patch ("Revert "OF: DT-Overlay > configfs interface (v8)" I just sent which is > > https://lists.yoctoproject.org/g/linux-yocto/topic/v6_1_standard_preempt_rt_sdkv6_1_xlnx_soc_patch/99215104?p=,,,20,0,0,0::recentpostdate/sticky,,,20,2,0,99215104,previd%3D1685429439939095335,nextid%3D1684520876284512837&previd=1685429439939095335&nextid=1684520876284512837 > > So the patch in the above URL should be applied first and then this patch. > > Sorry for the inconvenience. No problem! I have it sorted out and the functionality should now be on all BSP branches. The rpi branches carry a similar change, but I reverted the rpi version, otherwise the conflicts are a mess. Bruce > > Thanks, > > Quanyang > > On 5/30/23 14:43, quanyang.wang via lists.yoctoproject.org wrote: > > From: Pantelis Antoniou <pantelis.anton...@konsulko.com> > > > > commit 999eb1a8fdc4512412c7bc519c895bc2a6fabbe0 from > > https://github.com/Xilinx/linux-xlnx.git > > > > Add a runtime interface to using configfs for generic device tree overlay > > usage. With it its possible to use device tree overlays without having > > to use a per-platform overlay manager. > > > > Please see Documentation/devicetree/configfs-overlays.txt for more info. > > > > Changes since v7: > > - Xilinx alignment > > - of: configfs: Fix error handling from of_overlay_create() > > - of: configfs: lock while resolving and applying > > - of: configfs: Fix memory leak in create overlay > > - of: configfs: Fix compilation warning > > - of: configfs: Use of_overlay_fdt_apply API call > > > > Changes since v6: > > - Default groups properties API changed. > > > > Changes since v5: > > - New style configfs. > > > > Changes since v4: > > - Loading fix for multiple overlays as found out by > > Geert Uytterhoeven <ge...@linux-m68k.org> > > > > Changes since v3: > > - Fixed compilation on SPARC & Xtensa > > > > Changes since v2: > > - Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) > > - Created a documentation entry > > - Slight rewording in Kconfig > > > > Changes since v1: > > - of_resolve() -> of_resolve_phandles(). > > > > Signed-off-by: Pantelis Antoniou <pantelis.anton...@konsulko.com> > > Signed-off-by: Nava kishore Manne <nava.ma...@xilinx.com> > > Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pan...@xilinx.com> > > State: not-upstreamable > > Signed-off-by: Liwei Song <liwei.s...@windriver.com> > > [Liwei: remove overlay_lock to fix "unused-variable" warning.] > > Signed-off-by: Bruce Ashfield <bruce.ashfi...@gmail.com> > > --- > > Hi Bruce, > > Would you please help merge this patch to the branches: > > v5.15/standard/preempt-rt/base > > v5.15/standard/base > > Thanks, > > Quanyang > > --- > > .../devicetree/configfs-overlays.txt | 31 ++ > > drivers/of/Kconfig | 11 + > > drivers/of/Makefile | 1 + > > drivers/of/configfs.c | 292 ++++++++++++++++++ > > 4 files changed, 335 insertions(+) > > create mode 100644 Documentation/devicetree/configfs-overlays.txt > > create mode 100644 drivers/of/configfs.c > > > > diff --git a/Documentation/devicetree/configfs-overlays.txt > > b/Documentation/devicetree/configfs-overlays.txt > > new file mode 100644 > > index 0000000000000..5fa43e0643072 > > --- /dev/null > > +++ b/Documentation/devicetree/configfs-overlays.txt > > @@ -0,0 +1,31 @@ > > +Howto use the configfs overlay interface. > > + > > +A device-tree configfs entry is created in /config/device-tree/overlays > > +and and it is manipulated using standard file system I/O. > > +Note that this is a debug level interface, for use by developers and > > +not necessarily something accessed by normal users due to the > > +security implications of having direct access to the kernel's device tree. > > + > > +* To create an overlay you mkdir the directory: > > + > > + # mkdir /config/device-tree/overlays/foo > > + > > +* Either you echo the overlay firmware file to the path property file. > > + > > + # echo foo.dtbo >/config/device-tree/overlays/foo/path > > + > > +* Or you cat the contents of the overlay to the dtbo file > > + > > + # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo > > + > > +The overlay file will be applied, and devices will be created/destroyed > > +as required. > > + > > +To remove it simply rmdir the directory. > > + > > + # rmdir /config/device-tree/overlays/foo > > + > > +The rationalle of the dual interface (firmware & direct copy) is that each > > is > > +better suited to different use patterns. The firmware interface is what's > > +intended to be used by hardware managers in the kernel, while the copy > > interface > > +make sense for developers (since it avoids problems with namespaces). > > diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig > > index 80b5fd44ab1c7..da62bc6766952 100644 > > --- a/drivers/of/Kconfig > > +++ b/drivers/of/Kconfig > > @@ -94,4 +94,15 @@ config OF_DMA_DEFAULT_COHERENT > > # arches should select this if DMA is coherent by default for OF devices > > bool > > +config OF_CONFIGFS > > + bool "Device Tree Overlay ConfigFS interface" > > + select CONFIGFS_FS > > + depends on OF_OVERLAY > > + help > > + Select this option to enable simple user-space driven DT overlay > > + interface to support device tree manipulated at runtime. > > + Say Y here to include this support. > > + > > + If unsure, say N. > > + > > endif # OF > > diff --git a/drivers/of/Makefile b/drivers/of/Makefile > > index e0360a44306e2..90c92ced24e62 100644 > > --- a/drivers/of/Makefile > > +++ b/drivers/of/Makefile > > @@ -1,6 +1,7 @@ > > # SPDX-License-Identifier: GPL-2.0 > > obj-y = base.o device.o platform.o property.o > > obj-$(CONFIG_OF_KOBJ) += kobj.o > > +obj-$(CONFIG_OF_CONFIGFS) += configfs.o > > obj-$(CONFIG_OF_DYNAMIC) += dynamic.o > > obj-$(CONFIG_OF_FLATTREE) += fdt.o > > obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o > > diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c > > new file mode 100644 > > index 0000000000000..64caba77a7193 > > --- /dev/null > > +++ b/drivers/of/configfs.c > > @@ -0,0 +1,292 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Configfs entries for device-tree > > + * > > + * Copyright (C) 2013 - Pantelis Antoniou <pa...@antoniou-consulting.com> > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License > > + * as published by the Free Software Foundation; either version > > + * 2 of the License, or (at your option) any later version. > > + */ > > +#include <linux/ctype.h> > > +#include <linux/cpu.h> > > +#include <linux/module.h> > > +#include <linux/of.h> > > +#include <linux/of_fdt.h> > > +#include <linux/spinlock.h> > > +#include <linux/sizes.h> > > +#include <linux/slab.h> > > +#include <linux/proc_fs.h> > > +#include <linux/configfs.h> > > +#include <linux/types.h> > > +#include <linux/stat.h> > > +#include <linux/limits.h> > > +#include <linux/file.h> > > +#include <linux/vmalloc.h> > > +#include <linux/firmware.h> > > + > > +#include "of_private.h" > > + > > +struct cfs_overlay_item { > > + struct config_item item; > > + > > + char path[PATH_MAX]; > > + > > + const struct firmware *fw; > > + struct device_node *overlay; > > + int ov_id; > > + > > + void *dtbo; > > + int dtbo_size; > > + > > + void *mem; > > +}; > > + > > +static int create_overlay(struct cfs_overlay_item *overlay, void *blob) > > +{ > > + int err; > > + > > + /* FIXME */ > > + err = of_overlay_fdt_apply(blob, overlay->dtbo_size, &overlay->ov_id); > > + if (err < 0) { > > + pr_err("%s: Failed to create overlay (err=%d)\n", > > + __func__, err); > > + return err; > > + } > > + > > + return err; > > +} > > + > > +static inline struct cfs_overlay_item > > + *to_cfs_overlay_item(struct config_item *item) > > +{ > > + return item ? container_of(item, struct cfs_overlay_item, item) : NULL; > > +} > > + > > +static ssize_t cfs_overlay_item_path_show(struct config_item *item, char > > *page) > > +{ > > + return sprintf(page, "%s\n", to_cfs_overlay_item(item)->path); > > +} > > + > > +static ssize_t cfs_overlay_item_path_store(struct config_item *item, > > + const char *page, size_t count) > > +{ > > + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); > > + const char *p = page; > > + char *s; > > + int err; > > + > > + /* if it's set do not allow changes */ > > + if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) > > + return -EPERM; > > + > > + /* copy to path buffer (and make sure it's always zero terminated */ > > + count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); > > + overlay->path[sizeof(overlay->path) - 1] = '\0'; > > + > > + /* strip trailing newlines */ > > + s = overlay->path + strlen(overlay->path); > > + while (s > overlay->path && *--s == '\n') > > + *s = '\0'; > > + > > + pr_debug("%s: path is '%s'\n", __func__, overlay->path); > > + > > + err = request_firmware(&overlay->fw, overlay->path, NULL); > > + if (err != 0) > > + goto out_err; > > + > > + overlay->dtbo_size = overlay->fw->size; > > + err = create_overlay(overlay, (void *)overlay->fw->data); > > + if (err < 0) > > + goto out_err; > > + > > + return count; > > + > > +out_err: > > + > > + release_firmware(overlay->fw); > > + overlay->fw = NULL; > > + > > + overlay->path[0] = '\0'; > > + > > + return count; > > +} > > + > > +static ssize_t cfs_overlay_item_status_show(struct config_item *item, > > + char *page) > > +{ > > + return sprintf(page, "%s\n", to_cfs_overlay_item(item)->ov_id >= 0 ? > > + "applied" : "unapplied"); > > +} > > + > > +CONFIGFS_ATTR(cfs_overlay_item_, path); > > +CONFIGFS_ATTR_RO(cfs_overlay_item_, status); > > + > > +static struct configfs_attribute *cfs_overlay_attrs[] = { > > + &cfs_overlay_item_attr_path, > > + &cfs_overlay_item_attr_status, > > + NULL, > > +}; > > + > > +ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, > > + void *buf, size_t max_count) > > +{ > > + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); > > + > > + pr_debug("%s: buf=%p max_count=%zu\n", __func__, buf, max_count); > > + > > + if (!overlay->dtbo) > > + return 0; > > + > > + /* copy if buffer provided */ > > + if (buf) { > > + /* the buffer must be large enough */ > > + if (overlay->dtbo_size > max_count) > > + return -ENOSPC; > > + > > + memcpy(buf, overlay->dtbo, overlay->dtbo_size); > > + } > > + > > + return overlay->dtbo_size; > > +} > > + > > +ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, > > + const void *buf, size_t count) > > +{ > > + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); > > + int err; > > + > > + /* if it's set do not allow changes */ > > + if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) > > + return -EPERM; > > + > > + /* copy the contents */ > > + overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); > > + if (!overlay->dtbo) > > + return -ENOMEM; > > + > > + overlay->dtbo_size = count; > > + > > + err = create_overlay(overlay, overlay->dtbo); > > + if (err < 0) > > + goto out_err; > > + > > + return count; > > + > > +out_err: > > + kfree(overlay->dtbo); > > + overlay->dtbo = NULL; > > + overlay->dtbo_size = 0; > > + > > + return err; > > +} > > + > > +CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); > > + > > +static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { > > + &cfs_overlay_item_attr_dtbo, > > + NULL, > > +}; > > + > > +static void cfs_overlay_release(struct config_item *item) > > +{ > > + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); > > + > > + if (overlay->ov_id >= 0) > > + of_overlay_remove(&overlay->ov_id); > > + if (overlay->fw) > > + release_firmware(overlay->fw); > > + /* kfree with NULL is safe */ > > + kfree(overlay->dtbo); > > + kfree(overlay->mem); > > + kfree(overlay); > > +} > > + > > +static struct configfs_item_operations cfs_overlay_item_ops = { > > + .release = cfs_overlay_release, > > +}; > > + > > +static struct config_item_type cfs_overlay_type = { > > + .ct_item_ops = &cfs_overlay_item_ops, > > + .ct_attrs = cfs_overlay_attrs, > > + .ct_bin_attrs = cfs_overlay_bin_attrs, > > + .ct_owner = THIS_MODULE, > > +}; > > + > > +static struct config_item > > + *cfs_overlay_group_make_item(struct config_group *group, > > + const char *name) > > +{ > > + struct cfs_overlay_item *overlay; > > + > > + overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); > > + if (!overlay) > > + return ERR_PTR(-ENOMEM); > > + overlay->ov_id = -1; > > + config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); > > + > > + return &overlay->item; > > +} > > + > > +static void cfs_overlay_group_drop_item(struct config_group *group, > > + struct config_item *item) > > +{ > > + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); > > + > > + config_item_put(&overlay->item); > > +} > > + > > +static struct configfs_group_operations overlays_ops = { > > + .make_item = cfs_overlay_group_make_item, > > + .drop_item = cfs_overlay_group_drop_item, > > +}; > > + > > +static struct config_item_type overlays_type = { > > + .ct_group_ops = &overlays_ops, > > + .ct_owner = THIS_MODULE, > > +}; > > + > > +static struct configfs_group_operations of_cfs_ops = { > > + /* empty - we don't allow anything to be created */ > > +}; > > + > > +static struct config_item_type of_cfs_type = { > > + .ct_group_ops = &of_cfs_ops, > > + .ct_owner = THIS_MODULE, > > +}; > > + > > +struct config_group of_cfs_overlay_group; > > + > > +static struct configfs_subsystem of_cfs_subsys = { > > + .su_group = { > > + .cg_item = { > > + .ci_namebuf = "device-tree", > > + .ci_type = &of_cfs_type, > > + }, > > + }, > > + .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), > > +}; > > + > > +static int __init of_cfs_init(void) > > +{ > > + int ret; > > + > > + pr_info("%s\n", __func__); > > + > > + config_group_init(&of_cfs_subsys.su_group); > > + config_group_init_type_name(&of_cfs_overlay_group, "overlays", > > + &overlays_type); > > + configfs_add_default_group(&of_cfs_overlay_group, > > + &of_cfs_subsys.su_group); > > + > > + ret = configfs_register_subsystem(&of_cfs_subsys); > > + if (ret != 0) { > > + pr_err("%s: failed to register subsys\n", __func__); > > + goto out; > > + } > > + pr_info("%s: OK\n", __func__); > > +out: > > + return ret; > > +} > > +late_initcall(of_cfs_init); > > > > > >
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#12668): https://lists.yoctoproject.org/g/linux-yocto/message/12668 Mute This Topic: https://lists.yoctoproject.org/mt/99215065/21656 Group Owner: linux-yocto+ow...@lists.yoctoproject.org Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/leave/6687884/21656/624485779/xyzzy [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-