clk: Remove global clk traversal on fetch parent index
authorDerek Basehore <dbasehore@chromium.org>
Fri, 21 Dec 2018 00:31:00 +0000 (16:31 -0800)
committerStephen Boyd <sboyd@kernel.org>
Thu, 24 Jan 2019 19:13:28 +0000 (11:13 -0800)
It's not required to traverse the entire clk tree when the parents array
contains a NULL value. We already have the parent clk_core pointer, so
we can just compare the parent->name and parent_names[i] pointers.

This can be a substantial power improvement in cases where the parent
clk isn't known and that clk is never registered, because a mux having
an unregistered parent name may traverse the clk tree on every
clk_set_rate() call in clk_mux_determine_rate_flags(). This can happen
hundreds of times a second for CPU clks.

This patch is the combination of reverting commit 470b5e2f97cf ("clk:
simplify clk_fetch_parent_index() function") and optimizing the
resulting code to never call __clk_lookup() because we already have the
clk_core pointer we're looking for. That optimization went unnoticed
even after commit da0f0b2c3ad2 ("clk: Correct lookup logic in
clk_fetch_parent_index()") tried to optimize this path.

Signed-off-by: Derek Basehore <dbasehore@chromium.org>
[sboyd@kernel.org: More description in commit text]
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/clk.c

index 6ccdbed..d2477a5 100644 (file)
@@ -1513,9 +1513,19 @@ static int clk_fetch_parent_index(struct clk_core *core,
        if (!parent)
                return -EINVAL;
 
-       for (i = 0; i < core->num_parents; i++)
-               if (clk_core_get_parent_by_index(core, i) == parent)
+       for (i = 0; i < core->num_parents; i++) {
+               if (core->parents[i] == parent)
+                       return i;
+
+               if (core->parents[i])
+                       continue;
+
+               /* Fallback to comparing globally unique names */
+               if (!strcmp(parent->name, core->parent_names[i])) {
+                       core->parents[i] = parent;
                        return i;
+               }
+       }
 
        return -EINVAL;
 }