* [PATCH v2 1/2] clk: Sort include statements
@ 2025-08-14 3:53 Chen-Yu Tsai
2025-08-14 3:53 ` [PATCH v2 2/2] clk: Use hashtable for global clk lookups Chen-Yu Tsai
2025-08-22 13:26 ` [PATCH v2 1/2] clk: Sort include statements Brian Masney
0 siblings, 2 replies; 4+ messages in thread
From: Chen-Yu Tsai @ 2025-08-14 3:53 UTC (permalink / raw)
To: Stephen Boyd; +Cc: Chen-Yu Tsai, linux-clk, linux-arm-kernel, linux-kernel
The clk core has its include statements in some random order.
Clean it up before we add more.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/clk/clk.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b821b2cdb155..2eb63d610cbb 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -6,21 +6,21 @@
* Standard functionality for the common clock API. See Documentation/driver-api/clk.rst
*/
+#include <linux/clk/clk-conf.h>
+#include <linux/clkdev.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
-#include <linux/clk/clk-conf.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
+#include <linux/device.h>
#include <linux/err.h>
+#include <linux/init.h>
#include <linux/list.h>
-#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of.h>
-#include <linux/device.h>
-#include <linux/init.h>
#include <linux/pm_runtime.h>
#include <linux/sched.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
#include "clk.h"
--
2.51.0.rc1.163.g2494970778-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] clk: Use hashtable for global clk lookups
2025-08-14 3:53 [PATCH v2 1/2] clk: Sort include statements Chen-Yu Tsai
@ 2025-08-14 3:53 ` Chen-Yu Tsai
2025-08-22 13:20 ` Brian Masney
2025-08-22 13:26 ` [PATCH v2 1/2] clk: Sort include statements Brian Masney
1 sibling, 1 reply; 4+ messages in thread
From: Chen-Yu Tsai @ 2025-08-14 3:53 UTC (permalink / raw)
To: Stephen Boyd; +Cc: Chen-Yu Tsai, linux-clk, linux-arm-kernel, linux-kernel
A clk lookup using clk_core_lookup() is currently somewhat expensive
since it has to walk the whole clk tree to find a match. This is
extremely bad in the clk_core_init() function where it is used to look
for clk name conflicts, which is always the worst case of walking the
whole tree. Moreover, the number of clks checked increases as more
clks are registered, causing each subsequent clk registration becoming
slower.
Add a hashtable for doing clk lookups to replace the tree walk method.
On arm64 this increases kernel memory usage by 4 KB for the hashtable,
and 16 bytes (2 pointers) for |struct hlist_node| in each clk. On a
platform with around 800 clks, this reduces the time spent in
clk_core_lookup() significantly:
| PID 0 | kworker |
| before | after | before | after |
-------------------------------------------
avg | 203 us | 2.7 us | 123 us | 1.5 us |
-------------------------------------------
min | 4.7 us | 2.3 us | 102 us | 0.9 us |
-------------------------------------------
max | 867 us | 4.8 us | 237 us | 3.5 us |
-------------------------------------------
culm | 109 ms | 1.5 ms | 21 ms | 0.3 ms |
This in turn reduces the time spent in clk_hw_register(), and
ultimately, boot time. On a different system with close to 700 clks,
This reduces boot time by around 110 ms. While this doesn't seem like
a lot, this helps in cases where minimizing boot time is important.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Changes since v1:
- marked hash table as static
---
drivers/clk/clk.c | 50 +++++++++++++++++------------------------------
1 file changed, 18 insertions(+), 32 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 2eb63d610cbb..85d2f2481acf 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -12,6 +12,7 @@
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/hashtable.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -21,6 +22,8 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/stringhash.h>
#include "clk.h"
@@ -33,6 +36,9 @@ static struct task_struct *enable_owner;
static int prepare_refcnt;
static int enable_refcnt;
+#define CLK_HASH_BITS 9
+static DEFINE_HASHTABLE(clk_hashtable, CLK_HASH_BITS);
+
static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
@@ -87,6 +93,7 @@ struct clk_core {
struct clk_duty duty;
struct hlist_head children;
struct hlist_node child_node;
+ struct hlist_node hashtable_node;
struct hlist_head clks;
unsigned int notifier_count;
#ifdef CONFIG_DEBUG_FS
@@ -395,45 +402,20 @@ struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(clk_hw_get_parent);
-static struct clk_core *__clk_lookup_subtree(const char *name,
- struct clk_core *core)
-{
- struct clk_core *child;
- struct clk_core *ret;
-
- if (!strcmp(core->name, name))
- return core;
-
- hlist_for_each_entry(child, &core->children, child_node) {
- ret = __clk_lookup_subtree(name, child);
- if (ret)
- return ret;
- }
-
- return NULL;
-}
-
static struct clk_core *clk_core_lookup(const char *name)
{
- struct clk_core *root_clk;
- struct clk_core *ret;
+ struct clk_core *core;
+ u32 hash;
if (!name)
return NULL;
- /* search the 'proper' clk tree first */
- hlist_for_each_entry(root_clk, &clk_root_list, child_node) {
- ret = __clk_lookup_subtree(name, root_clk);
- if (ret)
- return ret;
- }
+ hash = full_name_hash(NULL, name, strlen(name));
- /* if not found, then search the orphan tree */
- hlist_for_each_entry(root_clk, &clk_orphan_list, child_node) {
- ret = __clk_lookup_subtree(name, root_clk);
- if (ret)
- return ret;
- }
+ /* search the hashtable */
+ hash_for_each_possible(clk_hashtable, core, hashtable_node, hash)
+ if (!strcmp(core->name, name))
+ return core;
return NULL;
}
@@ -4013,6 +3995,8 @@ static int __clk_core_init(struct clk_core *core)
hlist_add_head(&core->child_node, &clk_orphan_list);
core->orphan = true;
}
+ hash_add(clk_hashtable, &core->hashtable_node,
+ full_name_hash(NULL, core->name, strlen(core->name)));
/*
* Set clk's accuracy. The preferred method is to use
@@ -4089,6 +4073,7 @@ static int __clk_core_init(struct clk_core *core)
clk_pm_runtime_put(core);
unlock:
if (ret) {
+ hash_del(&core->hashtable_node);
hlist_del_init(&core->child_node);
core->hw->core = NULL;
}
@@ -4610,6 +4595,7 @@ void clk_unregister(struct clk *clk)
clk_core_evict_parent_cache(clk->core);
+ hash_del(&clk->core->hashtable_node);
hlist_del_init(&clk->core->child_node);
if (clk->core->prepare_count)
--
2.51.0.rc1.163.g2494970778-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 2/2] clk: Use hashtable for global clk lookups
2025-08-14 3:53 ` [PATCH v2 2/2] clk: Use hashtable for global clk lookups Chen-Yu Tsai
@ 2025-08-22 13:20 ` Brian Masney
0 siblings, 0 replies; 4+ messages in thread
From: Brian Masney @ 2025-08-22 13:20 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: Stephen Boyd, linux-clk, linux-arm-kernel, linux-kernel
On Thu, Aug 14, 2025 at 11:53:16AM +0800, Chen-Yu Tsai wrote:
> A clk lookup using clk_core_lookup() is currently somewhat expensive
> since it has to walk the whole clk tree to find a match. This is
> extremely bad in the clk_core_init() function where it is used to look
> for clk name conflicts, which is always the worst case of walking the
> whole tree. Moreover, the number of clks checked increases as more
> clks are registered, causing each subsequent clk registration becoming
> slower.
>
> Add a hashtable for doing clk lookups to replace the tree walk method.
> On arm64 this increases kernel memory usage by 4 KB for the hashtable,
> and 16 bytes (2 pointers) for |struct hlist_node| in each clk. On a
> platform with around 800 clks, this reduces the time spent in
> clk_core_lookup() significantly:
>
> | PID 0 | kworker |
> | before | after | before | after |
> -------------------------------------------
> avg | 203 us | 2.7 us | 123 us | 1.5 us |
> -------------------------------------------
> min | 4.7 us | 2.3 us | 102 us | 0.9 us |
> -------------------------------------------
> max | 867 us | 4.8 us | 237 us | 3.5 us |
> -------------------------------------------
> culm | 109 ms | 1.5 ms | 21 ms | 0.3 ms |
>
> This in turn reduces the time spent in clk_hw_register(), and
> ultimately, boot time. On a different system with close to 700 clks,
> This reduces boot time by around 110 ms. While this doesn't seem like
> a lot, this helps in cases where minimizing boot time is important.
>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Tested-by: Brian Masney <bmasney@redhat.com>
I tested this on my Thinkpad x13s laptop, and clk_core_lookup() is
called 684 times on normal boot up of my system. Only 4 of those are
duplicate lookups.
Brian
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] clk: Sort include statements
2025-08-14 3:53 [PATCH v2 1/2] clk: Sort include statements Chen-Yu Tsai
2025-08-14 3:53 ` [PATCH v2 2/2] clk: Use hashtable for global clk lookups Chen-Yu Tsai
@ 2025-08-22 13:26 ` Brian Masney
1 sibling, 0 replies; 4+ messages in thread
From: Brian Masney @ 2025-08-22 13:26 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: Stephen Boyd, linux-clk, linux-arm-kernel, linux-kernel
On Thu, Aug 14, 2025 at 11:53:15AM +0800, Chen-Yu Tsai wrote:
> The clk core has its include statements in some random order.
>
> Clean it up before we add more.
>
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> ---
> drivers/clk/clk.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index b821b2cdb155..2eb63d610cbb 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -6,21 +6,21 @@
> * Standard functionality for the common clock API. See Documentation/driver-api/clk.rst
> */
>
> +#include <linux/clk/clk-conf.h>
> +#include <linux/clkdev.h>
> #include <linux/clk.h>
> #include <linux/clk-provider.h>
> -#include <linux/clk/clk-conf.h>
> -#include <linux/module.h>
> -#include <linux/mutex.h>
> -#include <linux/spinlock.h>
> +#include <linux/device.h>
> #include <linux/err.h>
> +#include <linux/init.h>
> #include <linux/list.h>
> -#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> #include <linux/of.h>
> -#include <linux/device.h>
> -#include <linux/init.h>
> #include <linux/pm_runtime.h>
> #include <linux/sched.h>
> -#include <linux/clkdev.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
Reviewed-by: Brian Masney <bmasney@redhat.com>
Just a note that vim will sort the four linux/clk* includes at the top
slightly differently, however I like what you have better.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-08-22 13:26 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-14 3:53 [PATCH v2 1/2] clk: Sort include statements Chen-Yu Tsai
2025-08-14 3:53 ` [PATCH v2 2/2] clk: Use hashtable for global clk lookups Chen-Yu Tsai
2025-08-22 13:20 ` Brian Masney
2025-08-22 13:26 ` [PATCH v2 1/2] clk: Sort include statements Brian Masney
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).