Merge "clk: qcom: Add an atomic version for clock debug_suspend"

This commit is contained in:
qctecmdr 2022-06-20 16:53:36 -07:00 committed by Gerrit - the friendly Code Review server
commit 913d8197ed

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016, 2019-2021, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */
#include <linux/clk.h>
#include <linux/export.h>
@ -23,7 +24,9 @@
static struct clk_hw *measure;
static bool debug_suspend;
static bool debug_suspend_atomic;
static struct dentry *clk_debugfs_suspend;
static struct dentry *clk_debugfs_suspend_atomic;
struct hw_debug_clk {
struct list_head list;
@ -788,7 +791,8 @@ static int clock_debug_print_clock(struct hw_debug_clk *dclk, struct seq_file *s
struct clk_hw *clk_hw;
unsigned long clk_rate;
bool clk_prepared, clk_enabled;
int vdd_level;
int vdd_level = 0;
bool atomic;
if (!dclk || !dclk->clk_hw) {
pr_err("clk param error\n");
@ -802,13 +806,23 @@ static int clock_debug_print_clock(struct hw_debug_clk *dclk, struct seq_file *s
clk = dclk->clk_hw->clk;
/*
* In order to prevent running into "scheduling while atomic"
* due to grabbing contested mutexes, avoid making any calls
* that grab a mutex in the debug_suspend path when the
* variable atomic is true.
*/
atomic = debug_suspend_atomic && !s;
do {
clk_hw = __clk_get_hw(clk);
if (!clk_hw)
break;
clk_rate = clk_hw_get_rate(clk_hw);
vdd_level = clk_list_rate_vdd_level(clk_hw, clk_rate);
if (!atomic)
vdd_level = clk_list_rate_vdd_level(clk_hw, clk_rate);
if (s) {
/*
@ -847,6 +861,9 @@ static int clock_debug_print_clock(struct hw_debug_clk *dclk, struct seq_file *s
clk_rate);
}
if (atomic)
break;
start = " -> ";
} while ((clk = clk_get_parent(clk_hw->clk)));
@ -981,6 +998,24 @@ static int clk_debug_suspend_enable_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(clk_debug_suspend_enable_fops,
clk_debug_suspend_enable_get, clk_debug_suspend_enable_set, "%llu\n");
static int clk_debug_suspend_atomic_enable_get(void *data, u64 *val)
{
*val = debug_suspend_atomic;
return 0;
}
static int clk_debug_suspend_atomic_enable_set(void *data, u64 val)
{
debug_suspend_atomic = !!val;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(clk_debug_suspend_atomic_enable_fops,
clk_debug_suspend_atomic_enable_get, clk_debug_suspend_atomic_enable_set, "%llu\n");
static void clk_hw_debug_remove(struct hw_debug_clk *dclk)
{
if (dclk) {
@ -1053,6 +1088,11 @@ int clk_debug_init(void)
clk_debugfs_suspend = debugfs_create_file_unsafe("debug_suspend",
0644, rootdir, NULL,
&clk_debug_suspend_enable_fops);
clk_debugfs_suspend_atomic = debugfs_create_file_unsafe("debug_suspend_atomic",
0644, rootdir, NULL,
&clk_debug_suspend_atomic_enable_fops);
dput(rootdir);
if (IS_ERR(clk_debugfs_suspend)) {
ret = PTR_ERR(clk_debugfs_suspend);
@ -1060,15 +1100,23 @@ int clk_debug_init(void)
__func__, ret);
}
if (IS_ERR(clk_debugfs_suspend_atomic)) {
ret = PTR_ERR(clk_debugfs_suspend_atomic);
pr_err("%s: unable to create clock debug_suspend_atomic debugfs directory, ret=%d\n",
__func__, ret);
}
return ret;
}
void clk_debug_exit(void)
{
debugfs_remove(clk_debugfs_suspend);
debugfs_remove(clk_debugfs_suspend_atomic);
if (debug_suspend)
unregister_trace_suspend_resume(
clk_debug_suspend_trace_probe, NULL);
clk_debug_unregister();
}