From: "Kurt Borja" <kuurtb@gmail.com>
To: "Thomas Weißschuh" <linux@weissschuh.net>,
"Hans de Goede" <hdegoede@redhat.com>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Armin Wolf" <W_Armin@gmx.de>
Cc: <platform-driver-x86@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
"Joshua Grisham" <josh@joshuagrisham.com>
Subject: Re: [PATCH 1/2] platform/x86: firmware_attributes_class: Provide a highlevel interface
Date: Wed, 23 Apr 2025 05:05:35 -0300 [thread overview]
Message-ID: <D9DV2VOCWEK3.TQ96Z41CV0P4@gmail.com> (raw)
In-Reply-To: <20250107-pdx86-firmware-attributes-v1-1-9d75c04a3b52@weissschuh.net>
On Tue Jan 7, 2025 at 2:05 PM -03, Thomas Weißschuh wrote:
> Currently each user of firmware_attributes_class has to manually set up
> kobjects, devices, etc.
> Provide a higher level API which takes care of the low-level details.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> drivers/platform/x86/firmware_attributes_class.c | 146 +++++++++++++++++++++++
> drivers/platform/x86/firmware_attributes_class.h | 37 ++++++
> 2 files changed, 183 insertions(+)
>
> diff --git a/drivers/platform/x86/firmware_attributes_class.c b/drivers/platform/x86/firmware_attributes_class.c
> index 736e96c186d9dc6d945517f090e9af903e93bbf4..70ceae5215820098b017bfda991a3c2a7824c98e 100644
> --- a/drivers/platform/x86/firmware_attributes_class.c
> +++ b/drivers/platform/x86/firmware_attributes_class.c
> @@ -2,6 +2,9 @@
>
> /* Firmware attributes class helper module */
>
> +#include <linux/device/class.h>
> +#include <linux/device.h>
> +#include <linux/kobject.h>
> #include <linux/module.h>
> #include "firmware_attributes_class.h"
>
> @@ -22,6 +25,149 @@ static __exit void fw_attributes_class_exit(void)
> }
> module_exit(fw_attributes_class_exit);
>
> +static ssize_t fw_attributes_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buf)
> +{
> + struct firmware_attributes_device *fwadev = to_firmware_attribute_device(kobj);
> + const struct firmware_attribute *fw_attr = to_firmware_attribute(attr);
> +
> + if (!fw_attr->show)
> + return -EIO;
> +
> + return fw_attr->show(fwadev, fw_attr, buf);
> +}
> +
> +static ssize_t fw_attributes_sysfs_store(struct kobject *kobj, struct attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct firmware_attributes_device *fwadev = to_firmware_attribute_device(kobj);
> + const struct firmware_attribute *fw_attr = to_firmware_attribute(attr);
> +
> + if (!fw_attr->store)
> + return -EIO;
> +
> + return fw_attr->store(fwadev, fw_attr, buf, count);
> +}
> +
> +static const struct sysfs_ops fw_attributes_sysfs_ops = {
> + .show = fw_attributes_sysfs_show,
> + .store = fw_attributes_sysfs_store,
> +};
> +
> +static void fw_attributes_attr_release(struct kobject *kobj)
> +{
> + struct firmware_attributes_device *fwadev = to_firmware_attribute_device(kobj);
> + struct device *cdev;
> +
> + cdev = fwadev->dev;
> +
> + kfree(fwadev);
> + device_unregister(cdev);
> +}
> +
> +static const struct kobj_type fw_attributes_attr_type = {
> + .sysfs_ops = &fw_attributes_sysfs_ops,
> + .release = fw_attributes_attr_release,
> +};
> +
> +DEFINE_FREE(firmware_attributes_device_unregister, struct firmware_attributes_device *,
> + if (_T) firmware_attributes_device_unregister(_T))
> +
> +struct firmware_attributes_device *
> +firmware_attributes_device_register(struct device *parent, const char *name,
> + const struct attribute_group **groups, void *data)
> +{
> + struct firmware_attributes_device *fwadev = NULL;
> + struct device *cdev = NULL;
> + int ret;
> +
> + fwadev = kzalloc(sizeof(*fwadev), GFP_KERNEL);
> + if (!fwadev)
> + return ERR_PTR(-ENOMEM);
> +
> + cdev = device_create(&firmware_attributes_class, parent, MKDEV(0, 0), "%s", name);
> + if (IS_ERR(cdev))
> + return ERR_CAST(cdev);
> +
> + fwadev->data = data;
> + fwadev->dev = cdev;
> +
> + ret = kobject_init_and_add(&fwadev->attributes, &fw_attributes_attr_type, &cdev->kobj,
> + "attributes");
> + if (ret) {
> + device_del(cdev);
> + return ERR_PTR(ret);
> + }
> +
> + if (groups) {
> + ret = sysfs_create_groups(&fwadev->attributes, groups);
> + if (ret) {
> + firmware_attributes_device_unregister(fwadev);
> + return ERR_PTR(ret);
> + }
> +
> + kobject_uevent(&fwadev->dev->kobj, KOBJ_CHANGE);
> + }
> +
> + return fwadev;
> +}
> +EXPORT_SYMBOL_GPL(firmware_attributes_device_register);
> +
> +void firmware_attributes_device_unregister(struct firmware_attributes_device *fwadev)
> +{
> + kobject_del(&fwadev->attributes);
> + kobject_put(&fwadev->attributes);
> +}
> +EXPORT_SYMBOL_GPL(firmware_attributes_device_unregister);
> +
> +static void devm_firmware_attributes_device_release(void *data)
> +{
> + struct firmware_attributes_device *fwadev = data;
> +
> + firmware_attributes_device_unregister(fwadev);
> +}
> +
> +struct firmware_attributes_device *
> +devm_firmware_attributes_device_register(struct device *parent, const char *name,
> + const struct attribute_group **groups, void *data)
> +{
> + struct firmware_attributes_device *fwadev;
> + int ret;
> +
> + fwadev = firmware_attributes_device_register(parent, name, groups, data);
> + if (IS_ERR(fwadev))
> + return fwadev;
> +
> + ret = devm_add_action_or_reset(parent, devm_firmware_attributes_device_release, fwadev);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return fwadev;
> +}
> +EXPORT_SYMBOL_GPL(devm_firmware_attributes_device_register);
> +
> +static ssize_t firmware_attributes_type_show(struct firmware_attributes_device *fwadev,
> + const struct firmware_attribute *attr, char *buf)
> +{
> + if (attr == &_firmware_attribute_type_string)
> + return sysfs_emit(buf, "string\n");
> + else if (attr == &_firmware_attribute_type_enumeration)
> + return sysfs_emit(buf, "enumeration\n");
> + else if (attr == &_firmware_attribute_type_integer)
> + return sysfs_emit(buf, "integer\n");
> + else
> + return -EIO;
> +}
> +
> +#define __FW_TYPE_ATTR __ATTR(type, 0444, firmware_attributes_type_show, NULL)
> +
> +const struct firmware_attribute _firmware_attribute_type_string = __FW_TYPE_ATTR;
> +EXPORT_SYMBOL_GPL(_firmware_attribute_type_string);
> +const struct firmware_attribute _firmware_attribute_type_enumeration = __FW_TYPE_ATTR;
> +EXPORT_SYMBOL_GPL(_firmware_attribute_type_enumeration);
> +const struct firmware_attribute _firmware_attribute_type_integer = __FW_TYPE_ATTR;
> +EXPORT_SYMBOL_GPL(_firmware_attribute_type_integer);
> +
> MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>");
> +MODULE_AUTHOR("Thomas Weißschuh <linux@weissschuh.net>");
> MODULE_DESCRIPTION("Firmware attributes class helper module");
> MODULE_LICENSE("GPL");
> diff --git a/drivers/platform/x86/firmware_attributes_class.h b/drivers/platform/x86/firmware_attributes_class.h
> index d27abe54fcf9812a2f0868eec5426bbc8e7eb21c..66837ad9f65b8ca501dee73f48c01f2710d86bf5 100644
> --- a/drivers/platform/x86/firmware_attributes_class.h
> +++ b/drivers/platform/x86/firmware_attributes_class.h
> @@ -5,8 +5,45 @@
> #ifndef FW_ATTR_CLASS_H
> #define FW_ATTR_CLASS_H
>
> +#include <linux/device.h>
> #include <linux/device/class.h>
> +#include <linux/sysfs.h>
>
> extern const struct class firmware_attributes_class;
>
> +struct firmware_attributes_device {
> + struct device *dev;
> + struct kobject attributes;
> + void *data;
> +};
> +
> +struct firmware_attribute {
> + struct attribute attr;
> + ssize_t (*show)(struct firmware_attributes_device *fwadev,
> + const struct firmware_attribute *attr, char *buf);
> + ssize_t (*store)(struct firmware_attributes_device *fwadev,
> + const struct firmware_attribute *attr, const char *buf, size_t count);
> +};
> +
> +#define to_firmware_attribute(_a) container_of_const(_a, struct firmware_attribute, attr)
> +#define to_firmware_attribute_device(_s) \
> + container_of_const(_s, struct firmware_attributes_device, attributes)
> +
> +extern const struct firmware_attribute _firmware_attribute_type_string;
> +#define firmware_attribute_type_string ((struct attribute *)&_firmware_attribute_type_string.attr)
> +extern const struct firmware_attribute _firmware_attribute_type_enumeration;
> +#define firmware_attribute_type_enumeration ((struct attribute *)&_firmware_attribute_type_enumeration.attr)
> +extern const struct firmware_attribute _firmware_attribute_type_integer;
> +#define firmware_attribute_type_integer ((struct attribute *)&_firmware_attribute_type_integer.attr)
> +
> +struct firmware_attributes_device * __must_check
> +firmware_attributes_device_register(struct device *parent, const char *name,
> + const struct attribute_group **groups, void *data);
> +
> +void firmware_attributes_device_unregister(struct firmware_attributes_device *fwadev);
> +
> +struct firmware_attributes_device * __must_check
> +devm_firmware_attributes_device_register(struct device *parent, const char *name,
> + const struct attribute_group **groups, void *data);
> +
> #endif /* FW_ATTR_CLASS_H */
Hi Thomas,
Are you still working on this patchset?
If you don't mind I can take it from here. I'm planning on fixing a
couple memory leaks of this patch and extend it a bit more with some
helper macros for ABI compliant drivers. I might drop the test driver
though.
I ask this because I want to use this class in another series I'm
to do, and I think this patch is a great starting point.
Let me know what you think!
--
~ Kurt
next prev parent reply other threads:[~2025-04-23 8:05 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-07 17:05 [PATCH 0/2] platform/x86: firmware_attributes_class: Provide a highlevel interface Thomas Weißschuh
2025-01-07 17:05 ` [PATCH 1/2] " Thomas Weißschuh
2025-04-23 8:05 ` Kurt Borja [this message]
2025-04-23 16:57 ` Thomas Weißschuh
2025-01-07 17:05 ` [PATCH 2/2] platform/x86: firmware_attributes_class: Add test driver Thomas Weißschuh
2025-01-07 19:29 ` Mario Limonciello
2025-01-07 20:50 ` Thomas Weißschuh
2025-01-07 21:18 ` Mario Limonciello
2025-01-07 22:13 ` Thomas Weißschuh
2025-01-07 22:20 ` Mario Limonciello
2025-01-07 22:47 ` Thomas Weißschuh
2025-01-08 9:30 ` Ilpo Järvinen
2025-01-09 15:17 ` Thomas Weißschuh
2025-01-09 15:37 ` Mario Limonciello
2025-01-09 16:19 ` Thomas Weißschuh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=D9DV2VOCWEK3.TQ96Z41CV0P4@gmail.com \
--to=kuurtb@gmail.com \
--cc=W_Armin@gmx.de \
--cc=hdegoede@redhat.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=josh@joshuagrisham.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@weissschuh.net \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.