Commit 0469a43b authored by Mike Turquette's avatar Mike Turquette

Merge branch 'clk-next-debugfs-lock' into clk-next

parents 2fed71e5 6314b679
...@@ -100,6 +100,8 @@ static void clk_enable_unlock(unsigned long flags) ...@@ -100,6 +100,8 @@ static void clk_enable_unlock(unsigned long flags)
static struct dentry *rootdir; static struct dentry *rootdir;
static int inited = 0; static int inited = 0;
static DEFINE_MUTEX(clk_debug_lock);
static HLIST_HEAD(clk_debug_list);
static struct hlist_head *all_lists[] = { static struct hlist_head *all_lists[] = {
&clk_root_list, &clk_root_list,
...@@ -300,28 +302,6 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) ...@@ -300,28 +302,6 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
return ret; return ret;
} }
/* caller must hold prepare_lock */
static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
{
struct clk *child;
int ret = -EINVAL;;
if (!clk || !pdentry)
goto out;
ret = clk_debug_create_one(clk, pdentry);
if (ret)
goto out;
hlist_for_each_entry(child, &clk->children, child_node)
clk_debug_create_subtree(child, pdentry);
ret = 0;
out:
return ret;
}
/** /**
* clk_debug_register - add a clk node to the debugfs clk tree * clk_debug_register - add a clk node to the debugfs clk tree
* @clk: the clk being added to the debugfs clk tree * @clk: the clk being added to the debugfs clk tree
...@@ -329,20 +309,21 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry) ...@@ -329,20 +309,21 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
* Dynamically adds a clk to the debugfs clk tree if debugfs has been * Dynamically adds a clk to the debugfs clk tree if debugfs has been
* initialized. Otherwise it bails out early since the debugfs clk tree * initialized. Otherwise it bails out early since the debugfs clk tree
* will be created lazily by clk_debug_init as part of a late_initcall. * will be created lazily by clk_debug_init as part of a late_initcall.
*
* Caller must hold prepare_lock. Only clk_init calls this function (so
* far) so this is taken care.
*/ */
static int clk_debug_register(struct clk *clk) static int clk_debug_register(struct clk *clk)
{ {
int ret = 0; int ret = 0;
mutex_lock(&clk_debug_lock);
hlist_add_head(&clk->debug_node, &clk_debug_list);
if (!inited) if (!inited)
goto out; goto unlock;
ret = clk_debug_create_subtree(clk, rootdir); ret = clk_debug_create_one(clk, rootdir);
unlock:
mutex_unlock(&clk_debug_lock);
out:
return ret; return ret;
} }
...@@ -353,12 +334,18 @@ static int clk_debug_register(struct clk *clk) ...@@ -353,12 +334,18 @@ static int clk_debug_register(struct clk *clk)
* Dynamically removes a clk and all it's children clk nodes from the * Dynamically removes a clk and all it's children clk nodes from the
* debugfs clk tree if clk->dentry points to debugfs created by * debugfs clk tree if clk->dentry points to debugfs created by
* clk_debug_register in __clk_init. * clk_debug_register in __clk_init.
*
* Caller must hold prepare_lock.
*/ */
static void clk_debug_unregister(struct clk *clk) static void clk_debug_unregister(struct clk *clk)
{ {
mutex_lock(&clk_debug_lock);
if (!clk->dentry)
goto out;
hlist_del_init(&clk->debug_node);
debugfs_remove_recursive(clk->dentry); debugfs_remove_recursive(clk->dentry);
clk->dentry = NULL;
out:
mutex_unlock(&clk_debug_lock);
} }
struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode, struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
...@@ -415,17 +402,12 @@ static int __init clk_debug_init(void) ...@@ -415,17 +402,12 @@ static int __init clk_debug_init(void)
if (!d) if (!d)
return -ENOMEM; return -ENOMEM;
clk_prepare_lock(); mutex_lock(&clk_debug_lock);
hlist_for_each_entry(clk, &clk_debug_list, debug_node)
hlist_for_each_entry(clk, &clk_root_list, child_node) clk_debug_create_one(clk, rootdir);
clk_debug_create_subtree(clk, rootdir);
hlist_for_each_entry(clk, &clk_orphan_list, child_node)
clk_debug_create_subtree(clk, rootdir);
inited = 1; inited = 1;
mutex_unlock(&clk_debug_lock);
clk_prepare_unlock();
return 0; return 0;
} }
...@@ -2090,11 +2072,13 @@ void clk_unregister(struct clk *clk) ...@@ -2090,11 +2072,13 @@ void clk_unregister(struct clk *clk)
if (!clk || WARN_ON_ONCE(IS_ERR(clk))) if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
return; return;
clk_debug_unregister(clk);
clk_prepare_lock(); clk_prepare_lock();
if (clk->ops == &clk_nodrv_ops) { if (clk->ops == &clk_nodrv_ops) {
pr_err("%s: unregistered clock: %s\n", __func__, clk->name); pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
goto out; return;
} }
/* /*
* Assign empty clock ops for consumers that might still hold * Assign empty clock ops for consumers that might still hold
...@@ -2113,16 +2097,13 @@ void clk_unregister(struct clk *clk) ...@@ -2113,16 +2097,13 @@ void clk_unregister(struct clk *clk)
clk_set_parent(child, NULL); clk_set_parent(child, NULL);
} }
clk_debug_unregister(clk);
hlist_del_init(&clk->child_node); hlist_del_init(&clk->child_node);
if (clk->prepare_count) if (clk->prepare_count)
pr_warn("%s: unregistering prepared clock: %s\n", pr_warn("%s: unregistering prepared clock: %s\n",
__func__, clk->name); __func__, clk->name);
kref_put(&clk->ref, __clk_release); kref_put(&clk->ref, __clk_release);
out:
clk_prepare_unlock(); clk_prepare_unlock();
} }
EXPORT_SYMBOL_GPL(clk_unregister); EXPORT_SYMBOL_GPL(clk_unregister);
......
...@@ -48,6 +48,7 @@ struct clk { ...@@ -48,6 +48,7 @@ struct clk {
unsigned long accuracy; unsigned long accuracy;
struct hlist_head children; struct hlist_head children;
struct hlist_node child_node; struct hlist_node child_node;
struct hlist_node debug_node;
unsigned int notifier_count; unsigned int notifier_count;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *dentry; struct dentry *dentry;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment