]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_scmi: add option for polling based performance domain operations
authorSudeep Holla <sudeep.holla@arm.com>
Fri, 21 Jul 2017 10:42:24 +0000 (11:42 +0100)
committerSudeep Holla <sudeep.holla@arm.com>
Wed, 28 Feb 2018 16:37:57 +0000 (16:37 +0000)
In order to implement fast CPU DVFS switching, we need to perform all
DVFS operations atomically. Since SCMI transfer already provide option
to choose between pooling vs interrupt driven(default), we can opt for
polling based transfers for set,get performance domain operations.

This patch adds option to choose between polling vs interrupt driven
SCMI transfers for set,get performance level operations.

Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_scmi/perf.c
include/linux/scmi_protocol.h

index 9c56ea503890638aed890655e813d4544c4dc047..987c64d198010962a492919905878b928334fb6d 100644 (file)
@@ -292,8 +292,8 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
        return ret;
 }
 
-static int
-scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
+static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
+                              u32 level, bool poll)
 {
        int ret;
        struct scmi_xfer *t;
@@ -304,6 +304,7 @@ scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
        if (ret)
                return ret;
 
+       t->hdr.poll_completion = poll;
        lvl = t->tx.buf;
        lvl->domain = cpu_to_le32(domain);
        lvl->level = cpu_to_le32(level);
@@ -314,8 +315,8 @@ scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level)
        return ret;
 }
 
-static int
-scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
+static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
+                              u32 *level, bool poll)
 {
        int ret;
        struct scmi_xfer *t;
@@ -325,6 +326,7 @@ scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level)
        if (ret)
                return ret;
 
+       t->hdr.poll_completion = poll;
        *(__le32 *)t->tx.buf = cpu_to_le32(domain);
 
        ret = scmi_do_xfer(handle, t);
@@ -400,23 +402,24 @@ static int scmi_dvfs_get_transition_latency(const struct scmi_handle *handle,
 }
 
 static int scmi_dvfs_freq_set(const struct scmi_handle *handle, u32 domain,
-                             unsigned long freq)
+                             unsigned long freq, bool poll)
 {
        struct scmi_perf_info *pi = handle->perf_priv;
        struct perf_dom_info *dom = pi->dom_info + domain;
 
-       return scmi_perf_level_set(handle, domain, freq / dom->mult_factor);
+       return scmi_perf_level_set(handle, domain, freq / dom->mult_factor,
+                                  poll);
 }
 
 static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain,
-                             unsigned long *freq)
+                             unsigned long *freq, bool poll)
 {
        int ret;
        u32 level;
        struct scmi_perf_info *pi = handle->perf_priv;
        struct perf_dom_info *dom = pi->dom_info + domain;
 
-       ret = scmi_perf_level_get(handle, domain, &level);
+       ret = scmi_perf_level_get(handle, domain, &level, poll);
        if (!ret)
                *freq = level * dom->mult_factor;
 
index 5d63da9435ba3bbee91c0ada1825d242192ff8f9..b458c87b866cb14d3489f63c0f95e2ec161d7259 100644 (file)
@@ -98,18 +98,18 @@ struct scmi_perf_ops {
        int (*limits_get)(const struct scmi_handle *handle, u32 domain,
                          u32 *max_perf, u32 *min_perf);
        int (*level_set)(const struct scmi_handle *handle, u32 domain,
-                        u32 level);
+                        u32 level, bool poll);
        int (*level_get)(const struct scmi_handle *handle, u32 domain,
-                        u32 *level);
+                        u32 *level, bool poll);
        int (*device_domain_id)(struct device *dev);
        int (*get_transition_latency)(const struct scmi_handle *handle,
                                      struct device *dev);
        int (*add_opps_to_device)(const struct scmi_handle *handle,
                                  struct device *dev);
        int (*freq_set)(const struct scmi_handle *handle, u32 domain,
-                       unsigned long rate);
+                       unsigned long rate, bool poll);
        int (*freq_get)(const struct scmi_handle *handle, u32 domain,
-                       unsigned long *rate);
+                       unsigned long *rate, bool poll);
 };
 
 /**