]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
firmware: arm_scmi: Add support for multiple device per protocol
authorSudeep Holla <sudeep.holla@arm.com>
Fri, 21 Dec 2018 18:08:08 +0000 (18:08 +0000)
committerSudeep Holla <sudeep.holla@arm.com>
Tue, 24 Dec 2019 11:35:48 +0000 (11:35 +0000)
Currently only one scmi device is created for each protocol enumerated.
However, there is requirement to make use of some procotols by multiple
kernel subsystems/frameworks. One such example is SCMI PERFORMANCE
protocol which can be used by both cpufreq and devfreq drivers.
Similarly, SENSOR protocol may be used by hwmon and iio subsystems,
and POWER protocol may be used by genpd and regulator drivers.

In order to achieve that, let us extend the scmi bus to match based
not only protocol id but also the scmi device name if one is available.

Reviewed-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_scmi/bus.c
drivers/firmware/arm_scmi/driver.c
include/linux/scmi_protocol.h

index 7a30952b463d58329edd05980409b40b6b856c74..3714e6307b05908416e4ad636d96a7ef9b26945a 100644 (file)
@@ -28,8 +28,12 @@ scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
                return NULL;
 
        for (; id->protocol_id; id++)
-               if (id->protocol_id == scmi_dev->protocol_id)
-                       return id;
+               if (id->protocol_id == scmi_dev->protocol_id) {
+                       if (!id->name)
+                               return id;
+                       else if (!strcmp(id->name, scmi_dev->name))
+                               return id;
+               }
 
        return NULL;
 }
@@ -125,7 +129,8 @@ static void scmi_device_release(struct device *dev)
 }
 
 struct scmi_device *
-scmi_device_create(struct device_node *np, struct device *parent, int protocol)
+scmi_device_create(struct device_node *np, struct device *parent, int protocol,
+                  const char *name)
 {
        int id, retval;
        struct scmi_device *scmi_dev;
@@ -134,8 +139,15 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
        if (!scmi_dev)
                return NULL;
 
+       scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
+       if (!scmi_dev->name) {
+               kfree(scmi_dev);
+               return NULL;
+       }
+
        id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
        if (id < 0) {
+               kfree_const(scmi_dev->name);
                kfree(scmi_dev);
                return NULL;
        }
@@ -154,6 +166,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 
        return scmi_dev;
 put_dev:
+       kfree_const(scmi_dev->name);
        put_device(&scmi_dev->dev);
        ida_simple_remove(&scmi_bus_id, id);
        return NULL;
@@ -161,6 +174,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 
 void scmi_device_destroy(struct scmi_device *scmi_dev)
 {
+       kfree_const(scmi_dev->name);
        scmi_handle_put(scmi_dev->handle);
        ida_simple_remove(&scmi_bus_id, scmi_dev->id);
        device_unregister(&scmi_dev->dev);
index 3eb0382491cebbc973de870eda7fc43ec244eee2..dee7ce3bd8156cd356bbd40b1dad56fdae2bbad3 100644 (file)
@@ -803,11 +803,11 @@ scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)
 
 static inline void
 scmi_create_protocol_device(struct device_node *np, struct scmi_info *info,
-                           int prot_id)
+                           int prot_id, const char *name)
 {
        struct scmi_device *sdev;
 
-       sdev = scmi_device_create(np, info->dev, prot_id);
+       sdev = scmi_device_create(np, info->dev, prot_id, name);
        if (!sdev) {
                dev_err(info->dev, "failed to create %d protocol device\n",
                        prot_id);
@@ -892,7 +892,7 @@ static int scmi_probe(struct platform_device *pdev)
                        continue;
                }
 
-               scmi_create_protocol_device(child, info, prot_id);
+               scmi_create_protocol_device(child, info, prot_id, NULL);
        }
 
        return 0;
index 881fea47c83d3dcc13d1e552f66b633aae8439f7..5c873a59b38710ccccf079bf61a30ae263e17404 100644 (file)
@@ -257,6 +257,7 @@ enum scmi_std_protocol {
 struct scmi_device {
        u32 id;
        u8 protocol_id;
+       const char *name;
        struct device dev;
        struct scmi_handle *handle;
 };
@@ -264,11 +265,13 @@ struct scmi_device {
 #define to_scmi_dev(d) container_of(d, struct scmi_device, dev)
 
 struct scmi_device *
-scmi_device_create(struct device_node *np, struct device *parent, int protocol);
+scmi_device_create(struct device_node *np, struct device *parent, int protocol,
+                  const char *name);
 void scmi_device_destroy(struct scmi_device *scmi_dev);
 
 struct scmi_device_id {
        u8 protocol_id;
+       const char *name;
 };
 
 struct scmi_driver {