git: ca4ce6a56f9c - main - linuxkpi: Add `sysfs_create_bin_file()` and `sysfs_remove_bin_file()`
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 07 Apr 2025 18:01:24 UTC
The branch main has been updated by dumbbell: URL: https://cgit.FreeBSD.org/src/commit/?id=ca4ce6a56f9c174917ab33191d367a850fc15c89 commit ca4ce6a56f9c174917ab33191d367a850fc15c89 Author: Jean-Sébastien Pédron <dumbbell@FreeBSD.org> AuthorDate: 2025-02-08 20:28:10 +0000 Commit: Jean-Sébastien Pédron <dumbbell@FreeBSD.org> CommitDate: 2025-04-07 17:34:40 +0000 linuxkpi: Add `sysfs_create_bin_file()` and `sysfs_remove_bin_file()` They are used by the i915 DRM driver for quite some time, but that code was commented out. It was moved around in Linux 6.8, so instead of figuring out what should be commented out now, let's add an implementation of these functions. Reviewed by: bz Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D49068 --- sys/compat/linuxkpi/common/include/linux/sysfs.h | 83 ++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/sys/compat/linuxkpi/common/include/linux/sysfs.h b/sys/compat/linuxkpi/common/include/linux/sysfs.h index b5ad73e4460b..c6692b803789 100644 --- a/sys/compat/linuxkpi/common/include/linux/sysfs.h +++ b/sys/compat/linuxkpi/common/include/linux/sysfs.h @@ -50,6 +50,15 @@ struct attribute_group { struct attribute **attrs; }; +struct bin_attribute { + struct attribute attr; + size_t size; + ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); + ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *, + char *, loff_t, size_t); +}; + #define __ATTR(_name, _mode, _show, _store) { \ .attr = { .name = __stringify(_name), .mode = _mode }, \ .show = _show, .store = _store, \ @@ -155,6 +164,80 @@ sysfs_remove_file(struct kobject *kobj, const struct attribute *attr) sysctl_remove_name(kobj->oidp, attr->name, 1, 1); } +static inline int +sysctl_handle_bin_attr(SYSCTL_HANDLER_ARGS) +{ + struct kobject *kobj; + struct bin_attribute *attr; + char *buf; + int error; + ssize_t len; + + kobj = arg1; + attr = (struct bin_attribute *)(intptr_t)arg2; + if (kobj->ktype == NULL || kobj->ktype->sysfs_ops == NULL) + return (ENODEV); + buf = (char *)get_zeroed_page(GFP_KERNEL); + if (buf == NULL) + return (ENOMEM); + + if (attr->read) { + len = attr->read( + NULL, /* <-- struct file, unimplemented */ + kobj, attr, buf, req->oldidx, PAGE_SIZE); + if (len < 0) { + error = -len; + if (error != EIO) + goto out; + } + } + + error = sysctl_handle_opaque(oidp, buf, PAGE_SIZE, req); + if (error != 0 || req->newptr == NULL || attr->write == NULL) + goto out; + + len = attr->write( + NULL, /* <-- struct file, unimplemented */ + kobj, attr, buf, req->newidx, req->newlen); + if (len < 0) + error = -len; +out: + free_page((unsigned long)buf); + + return (error); +} + +static inline int +sysfs_create_bin_file(struct kobject *kobj, const struct bin_attribute *attr) +{ + struct sysctl_oid *oid; + int ctlflags; + + ctlflags = CTLTYPE_OPAQUE | CTLFLAG_MPSAFE; + if (attr->attr.mode & (S_IRUSR | S_IWUSR)) + ctlflags |= CTLFLAG_RW; + else if (attr->attr.mode & S_IRUSR) + ctlflags |= CTLFLAG_RD; + else if (attr->attr.mode & S_IWUSR) + ctlflags |= CTLFLAG_WR; + + oid = SYSCTL_ADD_OID(NULL, SYSCTL_CHILDREN(kobj->oidp), OID_AUTO, + attr->attr.name, ctlflags, kobj, + (uintptr_t)attr, sysctl_handle_bin_attr, "", ""); + if (oid == NULL) + return (-ENOMEM); + + return (0); +} + +static inline void +sysfs_remove_bin_file(struct kobject *kobj, const struct bin_attribute *attr) +{ + + if (kobj->oidp) + sysctl_remove_name(kobj->oidp, attr->attr.name, 1, 1); +} + static inline int sysfs_create_link(struct kobject *kobj __unused, struct kobject *target __unused, const char *name __unused)