summaryrefslogtreecommitdiffstats
path: root/drivers/interconnect
diff options
context:
space:
mode:
authorGeorgi Djakov <georgi.djakov@linaro.org>2019-01-16 18:11:03 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-01-22 13:37:25 +0100
commitdce6d406669b56506192e726ffbb238e409a7120 (patch)
treeb0319d905210066a51b3d4bdf9ecda5663d395a3 /drivers/interconnect
parentecfbed0c5ccc0df25cf213c710417ebc1d17aad7 (diff)
downloadlinux-dce6d406669b56506192e726ffbb238e409a7120.tar.bz2
interconnect: Revert to previous config if any request fails
When consumers report their bandwidth needs with icc_set_bw(), it's possible that the requested amount of bandwidth is not available or just the new configuration fails to apply on some path. In this case revert to the previous configuration and propagate the error back to the consumers to let them know that bandwidth is not available, hardware is busy or whatever error is returned by the interconnect platform driver. Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/interconnect')
-rw-r--r--drivers/interconnect/core.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 8091d998549a..6005a1c189f6 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -414,14 +414,18 @@ EXPORT_SYMBOL_GPL(of_icc_get);
int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
{
struct icc_node *node;
+ u32 old_avg, old_peak;
size_t i;
int ret;
- if (!path)
+ if (!path || !path->num_nodes)
return 0;
mutex_lock(&icc_lock);
+ old_avg = path->reqs[0].avg_bw;
+ old_peak = path->reqs[0].peak_bw;
+
for (i = 0; i < path->num_nodes; i++) {
node = path->reqs[i].node;
@@ -434,10 +438,19 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
}
ret = apply_constraints(path);
- if (ret)
+ if (ret) {
pr_debug("interconnect: error applying constraints (%d)\n",
ret);
+ for (i = 0; i < path->num_nodes; i++) {
+ node = path->reqs[i].node;
+ path->reqs[i].avg_bw = old_avg;
+ path->reqs[i].peak_bw = old_peak;
+ aggregate_requests(node);
+ }
+ apply_constraints(path);
+ }
+
mutex_unlock(&icc_lock);
return ret;