Skip to content

Commit

Permalink
sh: clock framework update, fix count and kill off kref
Browse files Browse the repository at this point in the history
This patch updates the clock framework use count code.
With this patch the enable() and disable() callbacks
only get called when counting from and to zero.
While at it the kref stuff gets replaced with an int.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
Magnus Damm authored and Paul Mundt committed May 8, 2009
1 parent 7d170b1 commit 4f5ecaa
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 34 deletions.
4 changes: 2 additions & 2 deletions arch/sh/include/asm/clock.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef __ASM_SH_CLOCK_H
#define __ASM_SH_CLOCK_H

#include <linux/kref.h>
#include <linux/list.h>
#include <linux/seq_file.h>
#include <linux/clk.h>
Expand All @@ -28,7 +27,7 @@ struct clk {
struct clk *parent;
struct clk_ops *ops;

struct kref kref;
int usecount;

unsigned long rate;
unsigned long flags;
Expand All @@ -37,6 +36,7 @@ struct clk {

#define CLK_ALWAYS_ENABLED (1 << 0)
#define CLK_RATE_PROPAGATES (1 << 1)
#define CLK_NEEDS_INIT (1 << 2)

/* Should be defined by processor-specific code */
void arch_init_clk_ops(struct clk_ops **, int type);
Expand Down
69 changes: 37 additions & 32 deletions arch/sh/kernel/cpu/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/kref.h>
#include <linux/kobject.h>
#include <linux/sysdev.h>
#include <linux/seq_file.h>
Expand Down Expand Up @@ -90,7 +89,7 @@ static void propagate_rate(struct clk *clk)
}
}

static int __clk_enable(struct clk *clk)
static void __clk_init(struct clk *clk)
{
/*
* See if this is the first time we're enabling the clock, some
Expand All @@ -100,19 +99,33 @@ static int __clk_enable(struct clk *clk)
* divisors to use before it can effectively recalc.
*/

if (clk->flags & CLK_ALWAYS_ENABLED) {
kref_get(&clk->kref);
return 0;
}

if (unlikely(atomic_read(&clk->kref.refcount) == 1))
if (clk->flags & CLK_NEEDS_INIT) {
if (clk->ops && clk->ops->init)
clk->ops->init(clk);

kref_get(&clk->kref);
clk->flags &= ~CLK_NEEDS_INIT;
}
}

static int __clk_enable(struct clk *clk)
{
if (!clk)
return -EINVAL;

clk->usecount++;

/* nothing to do if always enabled */
if (clk->flags & CLK_ALWAYS_ENABLED)
return 0;

if (clk->usecount == 1) {
__clk_init(clk);

if (likely(clk->ops && clk->ops->enable))
clk->ops->enable(clk);
__clk_enable(clk->parent);

if (clk->ops && clk->ops->enable)
clk->ops->enable(clk);
}

return 0;
}
Expand All @@ -122,11 +135,6 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret;

if (!clk)
return -EINVAL;

clk_enable(clk->parent);

spin_lock_irqsave(&clock_lock, flags);
ret = __clk_enable(clk);
spin_unlock_irqrestore(&clock_lock, flags);
Expand All @@ -135,36 +143,33 @@ int clk_enable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_enable);

static void clk_kref_release(struct kref *kref)
{
/* Nothing to do */
}

static void __clk_disable(struct clk *clk)
{
int count = kref_put(&clk->kref, clk_kref_release);
if (!clk)
return;

clk->usecount--;

WARN_ON(clk->usecount < 0);

if (clk->flags & CLK_ALWAYS_ENABLED)
return;

if (!count) { /* count reaches zero, disable the clock */
if (clk->usecount == 0) {
if (likely(clk->ops && clk->ops->disable))
clk->ops->disable(clk);

__clk_disable(clk->parent);
}
}

void clk_disable(struct clk *clk)
{
unsigned long flags;

if (!clk)
return;

spin_lock_irqsave(&clock_lock, flags);
__clk_disable(clk);
spin_unlock_irqrestore(&clock_lock, flags);

clk_disable(clk->parent);
}
EXPORT_SYMBOL_GPL(clk_disable);

Expand All @@ -173,14 +178,14 @@ int clk_register(struct clk *clk)
mutex_lock(&clock_list_sem);

list_add(&clk->node, &clock_list);
kref_init(&clk->kref);
clk->usecount = 0;
clk->flags |= CLK_NEEDS_INIT;

mutex_unlock(&clock_list_sem);

if (clk->flags & CLK_ALWAYS_ENABLED) {
__clk_init(clk);
pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name);
if (clk->ops && clk->ops->init)
clk->ops->init(clk);
if (clk->ops && clk->ops->enable)
clk->ops->enable(clk);
pr_debug( "Enabled.");
Expand Down Expand Up @@ -356,7 +361,7 @@ static int show_clocks(char *buf, char **start, off_t off,
p += sprintf(p, "%-12s\t: %ld.%02ldMHz\t%s\n", clk->name,
rate / 1000000, (rate % 1000000) / 10000,
((clk->flags & CLK_ALWAYS_ENABLED) ||
(atomic_read(&clk->kref.refcount) != 1)) ?
clk->usecount > 0) ?
"enabled" : "disabled");
}

Expand Down

0 comments on commit 4f5ecaa

Please sign in to comment.