driver core: Add device_show_string() helper for sysfs attributes
authorLukas Wunner <lukas@wunner.de>
Sat, 20 Apr 2024 20:00:01 +0000 (22:00 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 May 2024 15:37:03 +0000 (17:37 +0200)
For drivers wishing to expose an unsigned long, int or bool at a static
memory location in sysfs, the driver core provides ready-made helpers
such as device_show_ulong() to be used as ->show() callback.

Some drivers need to expose a string and so far they all provide their
own ->show() implementation.  arch/powerpc/perf/hv-24x7.c went so far
as to create a device_show_string() helper but kept it private.

Make it public for reuse by other drivers.  The pattern seems to be
sufficiently frequent to merit a public helper.

Add a DEVICE_STRING_ATTR_RO() macro in line with the existing
DEVICE_ULONG_ATTR() and similar macros to ease declaration of string
attributes.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/2e3eaaf2600bb55c0415c23ba301e809403a7aa2.1713608122.git.lukas@wunner.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/powerpc/perf/hv-24x7.c
drivers/base/core.c
include/linux/device.h

index 057ec2e3451d19cb81d41668ca86e9649dc9c5e3..d400fa391c2765cf201ee4dc754007e655cc74ca 100644 (file)
@@ -425,16 +425,6 @@ static char *memdup_to_str(char *maybe_str, int max_len, gfp_t gfp)
        return kasprintf(gfp, "%.*s", max_len, maybe_str);
 }
 
-static ssize_t device_show_string(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct dev_ext_attribute *d;
-
-       d = container_of(attr, struct dev_ext_attribute, attr);
-
-       return sprintf(buf, "%s\n", (char *)d->var);
-}
-
 static ssize_t cpumask_show(struct device *dev,
                            struct device_attribute *attr, char *buf)
 {
index 4d51928c4088700d930a62b3e24b75c71f026659..131d96c6090be49e01db82af4709d045ff2450fc 100644 (file)
@@ -2538,6 +2538,15 @@ ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
 }
 EXPORT_SYMBOL_GPL(device_show_bool);
 
+ssize_t device_show_string(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+
+       return sysfs_emit(buf, "%s\n", (char *)ea->var);
+}
+EXPORT_SYMBOL_GPL(device_show_string);
+
 /**
  * device_release - free device structure.
  * @kobj: device's kobject.
index 07f4d2af1e3c474fbe2c24081b5e7f177108447e..b6b6ff881a3fd1ec32a80fd384ac580328364e21 100644 (file)
@@ -132,6 +132,8 @@ ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
                        char *buf);
 ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
                         const char *buf, size_t count);
+ssize_t device_show_string(struct device *dev, struct device_attribute *attr,
+                          char *buf);
 
 /**
  * DEVICE_ATTR - Define a device attribute.
@@ -251,6 +253,19 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
        struct dev_ext_attribute dev_attr_##_name = \
                { __ATTR(_name, _mode, device_show_bool, device_store_bool), &(_var) }
 
+/**
+ * DEVICE_STRING_ATTR_RO - Define a device attribute backed by a r/o string.
+ * @_name: Attribute name.
+ * @_mode: File mode.
+ * @_var: Identifier of string.
+ *
+ * Like DEVICE_ULONG_ATTR(), but @_var is a string. Because the length of the
+ * string allocation is unknown, the attribute must be read-only.
+ */
+#define DEVICE_STRING_ATTR_RO(_name, _mode, _var) \
+       struct dev_ext_attribute dev_attr_##_name = \
+               { __ATTR(_name, (_mode) & ~0222, device_show_string, NULL), (_var) }
+
 #define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
        struct device_attribute dev_attr_##_name =              \
                __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)