aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGeorgi Djakov <georgi.djakov@linaro.org>2019-01-16 11:11:03 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-01-22 07:37:25 -0500
commitdce6d406669b56506192e726ffbb238e409a7120 (patch)
treeb0319d905210066a51b3d4bdf9ecda5663d395a3 /drivers
parentecfbed0c5ccc0df25cf213c710417ebc1d17aad7 (diff)
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')
-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);
414int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) 414int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
415{ 415{
416 struct icc_node *node; 416 struct icc_node *node;
417 u32 old_avg, old_peak;
417 size_t i; 418 size_t i;
418 int ret; 419 int ret;
419 420
420 if (!path) 421 if (!path || !path->num_nodes)
421 return 0; 422 return 0;
422 423
423 mutex_lock(&icc_lock); 424 mutex_lock(&icc_lock);
424 425
426 old_avg = path->reqs[0].avg_bw;
427 old_peak = path->reqs[0].peak_bw;
428
425 for (i = 0; i < path->num_nodes; i++) { 429 for (i = 0; i < path->num_nodes; i++) {
426 node = path->reqs[i].node; 430 node = path->reqs[i].node;
427 431
@@ -434,10 +438,19 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
434 } 438 }
435 439
436 ret = apply_constraints(path); 440 ret = apply_constraints(path);
437 if (ret) 441 if (ret) {
438 pr_debug("interconnect: error applying constraints (%d)\n", 442 pr_debug("interconnect: error applying constraints (%d)\n",
439 ret); 443 ret);
440 444
445 for (i = 0; i < path->num_nodes; i++) {
446 node = path->reqs[i].node;
447 path->reqs[i].avg_bw = old_avg;
448 path->reqs[i].peak_bw = old_peak;
449 aggregate_requests(node);
450 }
451 apply_constraints(path);
452 }
453
441 mutex_unlock(&icc_lock); 454 mutex_unlock(&icc_lock);
442 455
443 return ret; 456 return ret;