]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
base: soc: Handle custom soc information sysfs entries
authorMurali Nalajala <mnalajal@codeaurora.org>
Mon, 7 Oct 2019 20:37:42 +0000 (13:37 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2019 12:35:32 +0000 (14:35 +0200)
Soc framework exposed sysfs entries are not sufficient for some
of the h/w platforms. Currently there is no interface where soc
drivers can expose further information about their SoCs via soc
framework. This change address this limitation where clients can
pass their custom entries as attribute group and soc framework
would expose them as sysfs properties.

Signed-off-by: Murali Nalajala <mnalajal@codeaurora.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/1570480662-25252-1-git-send-email-mnalajal@codeaurora.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/base/soc.c
include/linux/sys_soc.h

index 7c0c5ca5953d20b63b849ec537ba999a328f212a..4af11a423475e5bb818d3b36b2410e25861b786a 100644 (file)
@@ -104,15 +104,12 @@ static const struct attribute_group soc_attr_group = {
        .is_visible = soc_attribute_mode,
 };
 
-static const struct attribute_group *soc_attr_groups[] = {
-       &soc_attr_group,
-       NULL,
-};
-
 static void soc_release(struct device *dev)
 {
        struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
 
+       ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
+       kfree(soc_dev->dev.groups);
        kfree(soc_dev);
 }
 
@@ -121,6 +118,7 @@ static struct soc_device_attribute *early_soc_dev_attr;
 struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
 {
        struct soc_device *soc_dev;
+       const struct attribute_group **soc_attr_groups;
        int ret;
 
        if (!soc_bus_type.p) {
@@ -136,10 +134,18 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
                goto out1;
        }
 
+       soc_attr_groups = kcalloc(3, sizeof(*soc_attr_groups), GFP_KERNEL);
+       if (!soc_attr_groups) {
+               ret = -ENOMEM;
+               goto out2;
+       }
+       soc_attr_groups[0] = &soc_attr_group;
+       soc_attr_groups[1] = soc_dev_attr->custom_attr_group;
+
        /* Fetch a unique (reclaimable) SOC ID. */
        ret = ida_simple_get(&soc_ida, 0, 0, GFP_KERNEL);
        if (ret < 0)
-               goto out2;
+               goto out3;
        soc_dev->soc_dev_num = ret;
 
        soc_dev->attr = soc_dev_attr;
@@ -150,15 +156,15 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
        dev_set_name(&soc_dev->dev, "soc%d", soc_dev->soc_dev_num);
 
        ret = device_register(&soc_dev->dev);
-       if (ret)
-               goto out3;
+       if (ret) {
+               put_device(&soc_dev->dev);
+               return ERR_PTR(ret);
+       }
 
        return soc_dev;
 
 out3:
-       ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
-       put_device(&soc_dev->dev);
-       soc_dev = NULL;
+       kfree(soc_attr_groups);
 out2:
        kfree(soc_dev);
 out1:
@@ -169,8 +175,6 @@ EXPORT_SYMBOL_GPL(soc_device_register);
 /* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */
 void soc_device_unregister(struct soc_device *soc_dev)
 {
-       ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
-
        device_unregister(&soc_dev->dev);
        early_soc_dev_attr = NULL;
 }
index 48ceea867dd65274cb0d17eb4a536439ac4d40d2..d9b3cf0f410c8cfb509a4c1a4d6c83fde6fe33c6 100644 (file)
@@ -15,6 +15,7 @@ struct soc_device_attribute {
        const char *serial_number;
        const char *soc_id;
        const void *data;
+       const struct attribute_group *custom_attr_group;
 };
 
 /**